Loading...
Spring Framework Reference Documentation 7.0.2의 Annotated Controllers의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
애플리케이션은 client로부터의 메시지를 처리하기 위해 어노테이션이 적용된 @Controller 클래스를 사용할 수 있습니다.
이러한 클래스는 다음 항목에서 설명하는 대로 @MessageMapping, @SubscribeMapping, 그리고 @ExceptionHandler
메서드를 선언할 수 있습니다:
@MessageMapping@MessageMapping을 사용하여 destination에 따라 메시지를 라우팅하는 메서드에 어노테이션을 적용할 수 있습니다.
이는 메서드 레벨뿐만 아니라 타입 레벨에서도 지원됩니다. 타입 레벨에서 @MessageMapping은
컨트롤러 내 모든 메서드에 걸쳐 공유되는 매핑을 표현하는 데 사용됩니다.
기본적으로 매핑 값은 Ant-style 경로 패턴(예: /thing*, /thing/**)이며,
템플릿 변수(예: /thing/{id})도 지원합니다. 값은 @DestinationVariable 메서드 인수를 통해
참조할 수 있습니다.
애플리케이션은 또한 Dots as Separators에 설명된 대로 매핑에 대해 dot-separated destination convention으로 전환할 수도 있습니다.
다음 표는 메서드 인수를 설명합니다:
| Method argument | Description |
|---|---|
Message | 전체 메시지에 대한 액세스를 제공합니다. |
MessageHeaders | Message 내의 헤더에 대한 액세스를 제공합니다. |
MessageHeaderAccessor, SimpMessageHeaderAccessor, and StompHeaderAccessor | 타입이 지정된 접근자 메서드를 통해 헤더에 대한 액세스를 제공합니다. |
@Payload | 메시지의 페이로드에 대한 액세스를 제공하며, 설정된 MessageConverter에 의해 (예: JSON에서)<br>변환됩니다.<br>이 어노테이션의 존재는 필수가 아닌데, 기본적으로 다른 인수가 매칭되지 않으면<br>가정되기 때문입니다.<br>페이로드 인수에 @jakarta.validation.Valid 또는 Spring의 @Validated를 어노테이션으로 적용하여,<br>페이로드 인수가 자동으로 검증되도록 할 수 있습니다. |
@Header | 특정 헤더 값에 대한 액세스를 제공하며, 필요하다면<br>org.springframework.core.convert.converter.Converter를 사용한 타입 변환도 수행합니다. |
@Headers | 메시지 내의 모든 헤더에 대한 액세스를 제공합니다. 이 인수는<br>java.util.Map에 할당 가능해야 합니다. |
@DestinationVariable | 메시지 destination에서 추출된 템플릿 변수에 대한 액세스를 제공합니다.<br>값은 필요에 따라 선언된 메서드 인수 타입으로 변환됩니다. |
java.security.Principal | WebSocket HTTP 핸드셰이크 시점에 로그인된 사용자를 반영합니다. |
기본적으로, @MessageMapping 메서드의 반환 값은 일치하는 MessageConverter를 통해 페이로드로
직렬화되고 brokerChannel로 Message로 전송되며, 그곳에서 구독자들에게 브로드캐스트됩니다.
아웃바운드 메시지의 destination은 인바운드 메시지와 동일하지만 /topic이 프리픽스로 붙습니다.
@SendTo와 @SendToUser 어노테이션을 사용하여 출력 메시지의 destination을 커스터마이즈할 수 있습니다.
@SendTo는 대상 destination을 커스터마이즈하거나 여러 destination을 지정하는 데 사용됩니다.
@SendToUser는 출력 메시지를 입력 메시지와 연관된 사용자에게만 전달하는 데 사용됩니다.
User Destinations를 참조하십시오.
동일한 메서드에 @SendTo와 @SendToUser를 동시에 사용할 수 있으며, 둘 다 클래스 레벨에서 지원되며,
이 경우 클래스 내 메서드의 기본값 역할을 합니다. 그러나 메서드 레벨의 @SendTo 또는
@SendToUser 어노테이션은 클래스 레벨의 그러한 어노테이션을 오버라이드한다는 점을 유념해야 합니다.
메시지는 비동기적으로 처리될 수 있으며 @MessageMapping 메서드는 ListenableFuture,
CompletableFuture, 또는 CompletionStage를 반환할 수 있습니다.
@SendTo와 @SendToUser는 단지 메시지를 보내기 위해 SimpMessagingTemplate을 사용하는 것에
해당하는 편의 기능일 뿐이라는 점에 유의하십시오. 필요하다면, 더 고급 시나리오에서
@MessageMapping 메서드는 직접 SimpMessagingTemplate을 사용하는 방식으로 되돌아갈 수 있습니다.
이는 값을 반환하는 대신에 또는 그와 더불어 수행될 수 있습니다. Sending Messages를 참조하십시오.
@SubscribeMapping@SubscribeMapping은 @MessageMapping과 비슷하지만 매핑을 subscription 메시지로만 한정합니다.
이는 @MessageMapping과 동일한
method arguments를 지원합니다.
그러나 반환 값의 경우, 기본적으로 메시지는 브로커(일치하는 subscription에 대한 브로드캐스트로
brokerChannel을 통해)가 아니라 client에게 직접(clientOutboundChannel을 통해, subscription에 대한
응답으로) 전송됩니다. @SendTo 또는 @SendToUser를 추가하면 이 동작이 오버라이드되어 대신 브로커로 전송됩니다.
언제 이것이 유용할까요? 브로커가 /topic 및 /queue에 매핑되고, 애플리케이션 컨트롤러는
/app에 매핑된다고 가정해 봅시다. 이 설정에서 브로커는 반복적인 브로드캐스트를 위한 /topic 및
/queue에 대한 모든 subscription을 저장하며, 애플리케이션이 관여할 필요가 없습니다.
client는 또한 일부 /app destination에 subscribe할 수 있고, 컨트롤러는 브로커를 관여시키지 않고 subscription에
대한 응답으로 값을 반환할 수 있으며, subscription을 다시 저장하거나 사용하지 않습니다
(사실상 one-time request-reply exchange). 한 가지 use case는 startup 시 UI를 초기 데이터로 채우는 것입니다.
언제 이것이 유용하지 않을까요? 어떤 이유로든 브로커와 컨트롤러가 subscription을 포함한 메시지를 각각 독립적으로 처리하기를 원하지 않는 한 동일한 destination 프리픽스에 브로커와 컨트롤러를 매핑하려고 하지 마십시오. 인바운드 메시지는 병렬로 처리됩니다.
주어진 메시지를 브로커가 먼저 처리하는지 컨트롤러가 먼저 처리하는지에 대한 보장은 없습니다. subscription이 저장되고 브로드캐스트를 위해 준비되었을 때 통지받는 것이 목표라면, client는 서버가 이를 지원한다면(simple 브로커는 지원하지 않음) receipt를 요청해야 합니다. 예를 들어 Java STOMP client를 사용하면 다음과 같이 receipt를 추가할 수 있습니다:
1@Autowired 2private TaskScheduler messageBrokerTaskScheduler; 3 4// During initialization.. 5stompClient.setTaskScheduler(this.messageBrokerTaskScheduler); 6 7// When subscribing.. 8StompHeaders headers = new StompHeaders(); 9headers.setDestination("/topic/..."); 10headers.setReceipt("r1"); 11FrameHandler handler = ...; 12stompSession.subscribe(headers, handler).addReceiptTask(receiptHeaders -> { 13 // Subscription ready... 14});
서버 사이드 옵션으로는 brokerChannel에 ExecutorChannelInterceptor를
등록하고,
subscription을 포함한 메시지가 처리된 후에 호출되는 afterMessageHandled
메서드를 구현하는 방법이 있습니다.
@MessageExceptionHandler애플리케이션은 @MessageMapping 메서드에서 발생한 예외를 처리하기 위해
@MessageExceptionHandler 메서드를 사용할 수 있습니다. 예외 인스턴스에 대한 액세스를
원하는 경우 어노테이션 자체 또는 메서드 인수를 통해 예외를 선언할 수 있습니다.
다음 예제는 메서드 인수를 통해 예외를 선언합니다:
1@Controller 2public class MyController { 3 4 // ... 5 6 @MessageExceptionHandler 7 public ApplicationError handleException(MyException exception) { 8 // ... 9 return appError; 10 } 11}
@MessageExceptionHandler 메서드는 유연한 메서드 시그니처를 지원하며,
@MessageMapping 메서드와 동일한
메서드 인수 타입과 반환 값을 지원합니다.
일반적으로 @MessageExceptionHandler 메서드는 선언된 @Controller 클래스
(또는 클래스 계층 구조) 내에서 적용됩니다. 이러한 메서드를 보다 전역적으로
(컨트롤러 전반에 걸쳐) 적용하고 싶다면 @ControllerAdvice가 표시된 클래스에
선언할 수 있습니다. 이는 Spring MVC에서 제공되는
유사한 지원과 비교할 수 있습니다.
Flow of Messages
Sending Messages