JBoss EAP 6과 친해지기 16탄 - 웹 서비스 서브시스템
본문 바로가기
IT 이야기/JBoss EAP

JBoss EAP 6과 친해지기 16탄 - 웹 서비스 서브시스템

by 찬찬이 아빠 2020. 12. 21.
반응형
  1. 웹 서비스 개요

(1) 웹 서비스의 핵심 기술들

웹 서비스를 구성하는 여러 가지 많은 기술이 있지만, 그중에서도 핵심이 되는 것이 SOAP와 WSDL입니다.

웹 서비스의 개념도

 

(2) SOAP

SOAP(Simple Object Access Protocol)는 웹 서비스에 사용되는 메시지 형식 및 규칙 등을 정의한 규약입니다.

HTTP, HTTPS, SMTP 등을 사용하여 XML 기반의 메시지를 서버들 간에 교환하는 형태의 프로토콜입니다.

SOAP 메시지는 다음 그림과 같이 Envelope, Header, Body로 구성됩니다.

SOAP 메시지 포맷

 

 

(3) WSDL

SOAP 인터페이스는 XML 기반의 WSDL(Web Services Description Language)로 정의됩니다.

WSDL은 웹 서비스가 '어디에 있는지', '어떤 메시지 포맷을 이용하는지', '어떤 통신 프로토콜을 이용하는지' 등 웹 서비스를 사용하는데 필요한 정보가 들어 있습니다.

WSDL의 구조

 

(4) REST

최근에는 SOAP와 WSDL 대신 'REST(REpresentationl State Transfer)'라는 기술을 사용하는 경우가 많습니다.

REST는 HTTP를 사용하여 통신하는 방법이며, XML이나 JSON(JavaSCript Object Notation)을 메시지 포맷으로 사용하고 있습니다.

 

 

(5) UDDI

UDDI(Universal Description, Discovery and Intergration)는 필요한 웹 서비스를 찾아 보기 위한 검색 시스템입니다.

 

웹 서비스 제공자는 웹 서비스를 UDDI 시스템에 등록하고, 사용자는 UDDI에서 검색하여 웹 서비스를 이용하는 구조이지만, 현재는 거의 이용되지 않습니다. 그 이유는 접속할 대상을 알고 있으면 웹 서비스를 검색하여 사용하는 구조가 필요 없기 때문입니다.

 

또 UDDI는 웹 검색 엔진과 같이 웹 서비스에 대한 정보를 반환하는 역할만하며, 같은 웹 서비스도 공급자에 따라 인터페이스가 전혀 달라진다는 것이 더욱 사용하기 어렵게 만들었습니다.

 

 

 

  2. JAX-WS 웹 서비스

JAX-WS(Java API for XML Web Services)는 Java EE 플랫폼에 포함된 API를 사용하여 웹 서비스를 만드는 기술입니다. 웹 서비스는 주로 XML 및 구조화된 텍스트 형식으로 정보 교환 등 네트워크에서 통신할 수 있는 표준입니다. 웹 서비스는 플랫폼 독립적입니다. JAX-WS 애플리케이션은 클라이언트/서버 모델을 사용합니다. 서버 컴포넌트를 웹 서비스 엔드 포인트라고 합니다.

 

웹 서비스의 기능을 구현하기 위해 Java EE에서는 JSR-220 JAX-WS라는 표준 API를 제공합니다.

 

JAX-WS는 Java SE 5에서 도입된 어노테이션을 사용하여 웹 서비스 서버 모듈과 클라이언트 개발이 쉽습니다. JAX-WS는 JAX-RPC 표준을 발전시킨 것으로 XML의 바인딩을 위한 JAXB 표준과 표준 스트리밍 파싱 API인 StAX 표준, 기능이 향상된 새로운 SAaJ(SOAP with Attachments API for Java) 표준을 기반으로 통합한 API입니다.

 

JAX-WS는 XML 기반 통신에 SOAP와 REST를 사용한 웹 서비스를 처리하기 위한API입니다.

 

이전에는 JAX-RPC(Java API for XML Based RPC)라고 불리며, Java 플그램에서 RPC 원격 프로그램 호출을 위한 API 표준이었습니다. JAX-WS 버전은 2.0이며, JAX-RPC 1.1의 후속 표준이기 때문에 JAX-WS 버전 1.0은 없습니다.

JAX-WS 개념도

 

 

JAX-WS에서 주고받는 메시지는 java 객체에서 자동으로 생성됩니다. XML을 기반으로 하고 있기 때문에 다른 플랫폼과 연계하여 사용할 수 있습니다.

 

JAX-WS는 WS-Notification, WS-Addressing, WS-Policy, WS-Security, WS-Trust 등의 웹 서비스 프로토콜들을 지원하고 있습니다. 이런 프로토콜들은 메시지 구조 및 메시지 형식을 정의하는 XML 기반 SOAP 메시지를 사용하여 통신합니다.

 

웹 서비스 엔드 포인트는 웹 서비스 인터페이스와 웹 메서드 인터페이스를구현하는 클래스로 구성됩니다.

 

웹 서비스 클라이언트는 WSDL 정의를 사용하여 생성한 스텁이라는 클래스를 사용하여 작성합니다.

 

JBoss EAP 6에는 JAX-WS 웹 서비스 앤드 포인트의 배포를 지원하는 기능이 포함되어 있습니다. 이런 기능은 JBossWS에 의해 제공됩니다. 엔드 포인트 등을 설정하려면 웹 서비스 서브시스템을 사용합니다.

 

 

(1) JAXB

Java 및 XML 데이터의 맵핑은 'JAXB(Java Architecture for XML Binding)'가 이용됩니다. JAXB는 Java 오브젝트를 XML로 변환하는 표준이며, 반대로 XML에서 Java 객체로 변환도 가능합니다.

 

JAXB를 사용하면 특별히 신경쓰지 않고도 Java 객체와 XML 간의 상호 맵핑이 가능합니다. 따라서 웹 서비스를 구축할 경우, 사용자는 프로토콜을 전혀 의식하지 않고 메시지를 주고 받을 수 있어 개발 부담이 많이 줄어듭니다.

 

 

(2) Stub와 Tie

JAX-WS를 사용할 때 사용자의 Java 프로그램과 공급자 Java  프로그램의 통신을 위한 프로그램을 직접 코딩할 필요가 없습니다. 사용자 Java 프로그램의 Stub과 공급자 프로그램의 Tie가 서로 통신을 수행합니다. 이때 Tie가 Stub을 자동으로 생성하기 때문에 개발 시 통신에 대해서는 신경 쓸 필요가 없습니다. 일반적인 원격 메소드 호출뿐만 아니라 SOAP를 사용하여 XML 문서도 송수신할 수 있습니다. 다음 그림은 웹 서비스 공급자와 클라이언트 간의 통신 방식을 보여줍니다.

JAX-WS 웹 서비스와 클라이언트 간의 통신

 

 

  3. 확장 프로토콜 WS-* 표준

웹 서비스를 확장하는 WS-* 표준들은 다음과 같은 것이 있습니다.

 

  • WS-Security : 디지털 서명, 사용자 인증, 메시지의 암호화 메커니즘을 제공
  • WS-Addressing : 메시지 정보 헤더를 XML 메시지에 유지하는 방법을 제공
  • WS-Policy : XML 보안 정책 등의 정책 설명하고, 그것을 외부에 공개하는 방법을 제공
  • WS-Reliable Messaging : SOAP 메시지에서 안정적인 메시지 전달을 제공
  • WS-Coordination : 여러 웹 서비스를 연계하여 상호 연결하기 위한 구조를 제공

 

(1) JBossWS가 제공하는 기능

JBossWS가 지원하는 웹 서비스 표준들의 전체 구조를 설명하려고 합니다.

 

기본 표준인 XML이나 메시징 위에 확장 표준인 보안이나 트랜잭션 처리에 관한 표준들로 구성되어 있습니다.

또, 메타데이터는 웹 서비스들끼리 통신하기 위한 스키마를 제공하는 프로토콜들입니다.

 

다름 그림은 JBoss EAP 6가 지원하는 웹 서비스 표준들을 도식화한 것입니다.

JBoss EAP 6 웹 서비스 표준

 

 

<JBoss EAP 6의 주요 웹 서비스 표준>

구분 표준 설명
XML 표준 XML XML(eXtensible Markup Language)은 W3C에서 HTML과는 다른 특수 목적의 마크업 언어를 만드는 용도로 권장하는 다목적 마크업 언어입니다. XML은 SGML의 단순화된 부분 집합이지만, 수 많은 종류의 데이터를 기술하는데 사용할 수 있습니다. XML은 주로 다른 시스템, 특히 인터넷에 연결된 시스템 간에 데이터를 쉽게 주고받을 수있도록 만들어졌습니다.
XML Schema XML 문서의 구조와 엘리먼트, 속성 간의 관계를 정의하여 다양한 자료형을 만들어 사용할 수 있도록 정의된 문서 구조입니다.
메시징 표준 SOAP SOAP(Simple Object Access Protocol)은 일반적으로 널리 알려진 HTTP, HTTPS, SMTP 등을 사용하여 XML 기반으 ㅣ메시지를 컴퓨터 네트워크상에서 교환하는 형태의 프로토콜입니다. SOAP은 웹 서비스에서 메시지를 전달하는 기반이 됩니다.
MTOM MTOM(Message Transmission Optimization Mechanism, 메시지 전송 최적화 메커니즘)은 효율적인 전송을 위해 웹 서비스에서 이진 데이터를 전송하기 위한 표준으로 W3C에서 제정하였습니다.
MTOM에서는 이진 데이터 전송에 MIME이나 DIME가 아닌 XOP(XML-bianry Optimized Packaging)를 사용합니다.
WS-Addressing WS-Addressing은 WS-Routing과 WS-Referral의 기술을 대체하는 표준으로 2003년도에 새롭게 발표된 표준입니다.
WS-Addressing에서는 라우팅 경로뿐만 아니라 SOAP Envelope에 WS-Addressing에서는 라우팅 경로뿐만 아니라 SOAP Envelope에 To 및 From 헤더를 추가하여 사용하는 편리한 방식을 제공하고 있습니다.
전송보장 메시지 표준 WS-ReliableMessaging SOAP 메시지의 전달을 보장하는 프로토콜, SOAP 메시지를 교환할 때 전달 보증, 중복 방지, 메시지 순서 보장 등의 기능을 제공합니다.
웹 서비스 보안 표준 WS-Trust WS-Security 표준을 확장해 보안 토큰의 요구와 발행, 신뢰 관계를 관리를 지원하는 프로토콜입니다.
WS-Security 웹 서비스 환경에서 메시지를 암호화하여 안전한 SOAP 메시지의 송수신을 지원하기 위한 프로토콜입니다. SSL은 전송 계층 수준에서 전체 메시지를 암호화하는 방식이라면, WS-Security는 부분 메시지만 암호화하는 방식입니다.
트랜잭션 표준 WS-Coordination 웹 서비스에서 분산되어 실행되는 처리를 연동하기 위한 표준입니다. 상호 접속 가능한 웹 서비스를 제어할 수 있습니다.
WS-Transaction 오랫동안 실행되는 트랜잭션에서 애플리케이션 간에 일관성을 유지할 수 있도록 하는 표준입니다.
메타데이터 WSDL 웹 서비스의 위치, 메시지 포맷, 통신 프로토콜 등을 정의하는 표준입니다.

 

 

  4. JAX-RS 웹 서비스

JAX-RS(Java API for RESTful Web Services)는 Java  플랫폼에서 REST 방식의 웹 애플리케이션을 구현할 수 있도록 제공하는 Java API입니다. 

 

SOAP 기반의 연동은 Java 애플리케이션을 무겁게 한다는 비판이 많았습니다. 최근 웹 애플리케이션에서는 AJAX기반의 JSON이나 RSS와 같이 간결한 프로토콜을 사용하는 연동 방법이 개발에 많이 사용하고 있습니다. Java EE에서도 이런 방식을 쉽게 구현할 수 있ㄷ록 JAX-RS 표준을 제공합니다.

 

JBoss EAP 6에서는 JBoss RESTEasy(http://www.jboss.org/resteasy)를 사용하여 구현되어 있습니다. RESTEasy 프레임워크도 어노테이션을 사용하여 JAX-RS를 쉽게 구현할 수 있습니다.

 

 

 

  5. JBossWS 구성

JBoss EAP 6에서는 기본으로 Apache CXF 스택인 JBossWS-CXF를 사용하고 있지만 JBoss의 독자적인 구현 스택인 JBossWS-Native도 사용할 수 있습니다.

 

JBossWS-CXF는 JBossWS에서 Apache CXF를 사용하기 위한 모듈이며 Apache CXF의 WSDL 바인딩, WS-* 지원 기능을 사용합니다. 또 JBoss EAP 6에서 JAX-RPC를 지원하기 위해 JBossWS-Native 모듈을 함께 사용하고 있습니다.

 

JBoss EAP 6에 배포된 웹 서비스 동작으르 제어할 수 있습니다. 관리 콘솔에서 'Profile' → 'Web' → 'Web Services'에서 설정할 수 있습니다.

 

<웹 서비스의 주요 설정 항목>

파라미터 설명
modify-wsdl-address 기본적으로 JBoss IP주소가 WSDL의 주소가 됩니다.
웹 서버나 도메인 이름을 통해 웹 서비스를 제공하면 이 주소로 WSDL 주소를 변경해야 합니다.
true이면 <soap:address>의 값을 wsdl-host, wsdl-port의 값을 지정한 값으로 덮어 씁니다.
false이면 <soap:address>의 URL이 유효하지 않은 경우에만 덮어 씁니다.

/subsystem=webservices/:write-attribute(name=modify-wsdl-address, value=true)
wsdl-host <soap:address>를 덮어쓸 때 사용할 호스트 이름이나 IP 주소를 설정합니다.
jbossws.undefined.host로 설정하면 <soap:address> 요청자의 호스트가 사용됩니다.

/subsystem=webservices/:write-attribute(name=wsdl-host, value=192.168.0.100)
wsdl-port <soap:address>를 덮어쓸 때 사용하는 HRRP 포트 번호입니다.
정의하지 않으면, 설치된 HTTP 커넥터를 찾아 그 HTTP 포트를 사용합니다.

/subsystem=webservices/:write-attribute(name=wsdl-port, value=8080)
wsdl-secure-port <soap:address>를 덮어쓸 때 사용하는 HTTPS 포트 번호입니다.
정의하지 않으면 설치된 HTTPS 커넥터를 찾아 그 HTTPS 포트를 사용합니다.

/subsystem=webservices/:write-attribute(name=wsdl-secure-port, value=8443)

 

CLI를 사용하여 아래와 같이 JBossWS의 웹 서비스 서브시스템을 설정합니다.

[standalone:localhost:9999 /] cd /subsystem=webservices
[standalone:localhost:9999 subsystem=webservices] :write-attribute(name=modify-wsdl-address, value=true)
{
	"outcome" => "success",
    "response-headers" => {
    	"operation-requires-reload" => true,
        "process-state" => "reload-required"
    }
}

 

read-resource 명령으로 설정된 내용을 확인합니다.

[standalone@localhost:9999 subsystem=webservices] :read-resource
{
	"outcome" => "success",
    "result" => {
    	"endpoint" => {},
        "modify-wsdl-address" => true,
        "wsdl-host" => "jbossws.undefined.host",
        "wsdl-port" => 80,
        "wsdl-secure-port" => 443,
        "endpoint-config" => {
        	"Standard-Endpoint-Config" => undefined,
            "Recording-Endpoint-Config" => undefined
         }
   },
   "response-headers" -> {"process-state" => "reload-required"}
}      

 

 

 

  6. 웹 서비스 개발

웹 서비스를 개발하는 방법은 두 가지가 있습니다. 첫 번째 방법은 새로운 웹 서비스를 제공하기 위해 Java 코드로 개발하여 배포하고, 웹 서비스에 대한 WSDL을 제공하는 방법이 있습니다. 또 다른 방법은 웹 서비스가 제공해야 할 WSDL이 주어진 경우, 이에 맞는 웹 서비스를 개발해야 하는 경우 입니다.

 

Java  코드에서부터 개발하는 방식을 Bottom-up 개발 방식이라고 하며, WSDL에서 시작하는 방식을 Top-down 개발 방식이라고 합니다.

 

<Bottom-up을 사용하는 경우>

  • 이미 존재하는 EJB 3 빈을 웹 서비스로 제공하고자 할 때
  • 새로운 서비스를 제공하는 WSDL을 생성해야 할 때

 

<Top-down을 사용하는 경우>

  • 다른 언어로 개발된 기존의 웹 서비스를 Java로 다시 개발해야 할 때
  • 예전 클라이언트와 호환을 유지하며 재개발해야 할 때
  • 먼저 수동으로 개발된 WSDL과 XML 스키마를 준수하는 서비스를 만들 때

 

먼저 Java 코드에서 웹 서비스를 개발하는 방법을 살펴봅시다. 다음과 같이 문자열을 반환하는 간단한 Hello 웹 서비스를 개발합니다. Hello 웹 서비스는 @WebService 어노테이션을 사용하여 웹 서비스 클래스를 지정하였고, @WebMethod 어노테이션으로 웹 서비스의 메소드를 지정하였습니다.

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService()
public class Hello {
	private String message = new String("Hello, ");
    public void Hello() {
    }
    
    @WebMethod()
    public String sayHello(String name) {
    	return message + name + ".";
    }
}

 

이 웹 서비스를 WAR에 패키징하기 위하여 web.xml에 서블릿으로 등록합니다.

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/webapp_3_0.xsd">
	<servlet>
    	<servlet-name>HelloService</servlet-name>
        <servlet-class>com.wstest.Hello</servlet-class>
    </servlet>
    
    <servlet-mapping>
    	<servlet-name>HelloService</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

 

WAR로 패키징한 애플리케이션을 배포하면 'Runtime' → 'Status' → 'Subsystems' → 'Webservices'에서 WSDL URL을 확인할 수 있습니다.

 

제공하는 서비스에 대한 WSDL URL에 접근하면 웹 서비스에 대한 WSDL이 브라우저에 표시됩니다.

 

Hello 웹 서비스를 테스트하려면 웹 서비스에 접속하는 클라이언트가 필요합니다.

 

먼저 pom.xml 파일에 JBossWS의 클라이언트에서 필요한 jar파일인 jbossws-cxf-client를 <dependency>에 추가합니다.

<dependency>
	<groupId>org.jboss.ws.cxf</groupId>
    <artifactId>jbossws-cxf-client</artifactId>
    <version>4.2.3.Final</version>
</dependency>

 

또, Hello 웹 서비스가 제공하는 WSDL에서 Java 코드를 생성하여 사용하기 위해서 Hello 웹 서비스의 WSDL 파일을 이클립스 프로젝트의 src/test/resources/hellows.wsdl 파일로 저장합니다.

 

메이븐에서 WSDL에서 클라이너트 Java 코드를 생성하려면 아래와 같이 maven-jaxws-tools-plugin의 wsconsume을 사용하도록 pom.xml에 설정합니다.

<plugin>
	<groupId>org.jboss.ws.plugins</groupId>
    <artifactId>maven-jaxws-tools-plugin</artifactId>
    <version>1.1.1.Final</version>
    <executions>
    	<execution>
        	<id>My execution</id>
            <goals>
            	<goal>wsconsume</goal>
            </goals>
            <configuration>
            	<wsdls>
                	<wsdl>${basedir}/src/test/resources/hellows.wsdl</wsdl>
                </wsdls>
                <targetPackage>com.wstest</targetPackage>
                <sourceDirectory>${basedir}/src/test/java</sourceDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

 

메이븐으로 빌드하면 <sourceDirectory>에 지정한 src/test/java 디렉터리에 Java 파일이 생성됩니다. 이 파일을 사용하는 클라이언트를 다음과 같이 작성합니다.

package com.wsclient;

import javax.xml.ws.Service;

import com.wstest.Hello;
import com.wstest.HelloService;

public class HelloClient {
	public static void main(String{} args) [
    	try {
        	String name = "JBoss EAP 6";
            
            Service service = Service.create(
            	HelloService.WSDL_LOCATION,
                HelloService.SERVICE
            );
            Hello hello = service.getPort(hello.class);
            
            String message = hello.sayHello(name);
            System.out.println("message=" + message);
        } catch (Exception e) {
        	e.printStackTrace();
        }
    }
}

 

위 클라이언트 코드를 실행하면, Hello 웹 서비스를 호출하여 콘솔에 다음과 같은 메시지가 출력됩니다.

message=Hello, JBoss EAP 6.

 

Hello 웹 서비스에서는 WSDL에서 Java 클라이언트 코드를 생성하기 위해 wsconsume을 메이븐 플러그인으로 실행하였습니다. 예제에서는 WAR 애플리케이션을 배포하면 자동으로 생성되는 WSDL을 사용하였습니다. 만약 배포하지 않고 WSDL을 생성하려면 메이븐 플로그인의 골(goal)을 wsprovide로 변경하면 Java 코드에서 WSDL이 생성할 수 있을 것입니다.

 

또, 콘솔 명령으로 wsconsume, wsprovide를 제공하고 있습니다.

사용법은 다음과 같습니다.

명령 설명
wsprovide 웹 서비스로 제공될 Java  구현 클래스에서 WSDL과 Schema 파일을 생성합니다.
Bottom-up 개발에 사용됩니다.

$ ./wsprovide.sh -w com.wstest.Hello -c /home/jboss/workspaces/hellows/target/hellows/WEB-INF/classes
Cloud not find log4j.xml configuration, logging to console.

java2ws -s /home/jboss/eap/jboss-eap-6.2/bin/output -classdir /home/jboss/eap/jboss-eap-6.2/bin/output -d /home/jjeon/jboss/eap/jboss-eap-6.2/bin/output -verbose -wsdl -cp /hoem/jboss/workspaces/hellows/target/hellows/WEB-INF/classes/: -wrapperbean -createxsdimports com.wstest.Hello
java2ws - Apache CXF 2.6.6-redhat-3
wsconsume WSDL과 Schema 파일에서 서버 및 클라이언트에 사용할 수 있는 Java 파일을 생성합니다. 주로 웹 서비스의 클라이언트 프로그램을 생성할 때 사용하는 툴입니다.

$ ./wsconsume.sh -k hellows.xml
Could not find log4j.xml configuration, logging to console.
Loading FrontEnd jaxws ...
Lodiing DataBinding jaxb ...

wsdl2java -compile -exsh false -d /home/jboss/exp/jboss-eap-6.2/bin/output -verbose -classdir /home/jboss/eap/jboss-eap-6.2/bin/output -allowElementReferences file:/home/jboss/eap/jboss-eap-6.2/bin.hellows.xml

wsdl2java - Apache CXF 2.6.6-redhat-3

 

 

 

  7. 웹 서비스의 모듈 설정

JBoss EAP 6에 웹 서비스를 배포할 때, 모듈 의존성에 주의하여야 합니다. JBoss EAP 6의 웹 서비스가 구현된 애플리케이션도 모듈로 관리합니다. 웹 서비스 구현체인 JBossWS구현 모듈에 대해서 암시적인 의존성이 설정되지 않기 때문에 필요하면 명시적으로 의존성을 설정해야 합니다. 모듈의 명시적인 의존성의 설정은 jboss-deployment-structure.xml 또는 MANiFEST.MF를 사용해 설정합니다. jboss-deployment-structure.xml 파일의 예제는 다음과 같습니다.

<jboss-deployment-structure xmlns="'urn:jboss:deployment-structure:1.1">
	<deployment>
    	<dependencies>
        	<module name="org.jboss.ws.cxf.jbossws-cxf-client services export" />
            <module name="org.apache.ws.xmlschema services export" />
            <module name="org.apache.ws.security services export" />
        </dependencies>
    </deployment>
</jboss-deployment-structure>

 

또, 애플리케이션에서 JAX-RS 구현체로 JBoss RESTEasy가 아닌 Jersey를 사용하면 다음과 같이 jboss-deployment-structure.xml 파일에 모듈 의존성을 설정해야 합니다.

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
	<deployment>
    	<dependencies>
        	<system>
            	<paths>
                	<path name="com/sun/xml/bind/vv2/runtime/JAXBContextImpl" />
                </paths>
            </system>
        </dependencies>
    </deployment>
</jboss-deployment-structure>

 

 

참고 서적 : 거침없이 배우는 JBoss

반응형

댓글