우리가 `Spring`의 `HTTP` 작업에서 예외처리를 하는 경우
`@RestControllerAdvice`와 `@ExceptionHandler`를 사용하면 아주 편하게 예외처리를 할 수 있다.
다행히(?)도 `STOMP`에도 `@ExceptionHandler`와 비슷한 기능을 지원하는 `@MessgeExceptionHandler`가 있다.
(대단하다.. SpringBoot!!)
하지만, 그냥 바로 사용하면 몇가지 문제가 존재한다.
우선, 여러 클라이언트가 특정 경로를 구독하고 있다고 가정해보자.
이때 만약, 특정 클라이언트가 `STOMP` 메시지 처리 관련해서 예외를 발생시키면(없는 메시지 수정, 없는 `Normal` 접근 등등)
해당 클라이언트에게만 예외 메시지를 전송해야 한다.
하지만, `STOMP`는 기본적으로 메시지 전송이 브로드캐스팅이다.
또한, `STOMP`가 자체적으로 메모리에 구독 정보와 `WebSocket` 세션에 관한 정보를 저장하고 관리해서
직접 `WebSocket` 세션에 접근하여 메시지를 보내는 것은 살짝 어려움이 있다.
즉,
- 예외 메시지를 브로드캐스팅하지 않아야 하며,
- 예외를 발생시킨 클라이언트에게만 예외 메시지를 전송하는 작업이 필요하다.
자, 이제 문제 상황을 인식했고 이걸 해결하는 과정을 살펴보자.
@MessageExceptionHandler
스프링에서는 `@MessageMapping` 메서드에서 발생한 예외를 처리하기 위해서
`@MessageExceptionHandler` 메서드를 지원한다.
발생한 예외는 `Method Argument`를 통해 접근할 수 있다.
이 `@MessageExceptionHandler`를 우리가 `WebSocket`이 아닌 예외처리 작업에서 하는 것처럼
`@RestControllerAdvice` 클래스 내부의 메소드로 사용하면 된다.
이렇게 하면 우선적으로 `STOMP`의 `@MessageMapping`에서 발생한 문제에 관해 공통 예외처리가 가능해진다.
이렇게 앞서 얘기한 2가지 작업을 해결하기 위한 초석을 마련했다.
결론적으로 어떻게 해결하느냐는 아래 방법을 따르면 된다.
- 따로 예외 메시지를 처리할 수 있는 경로를 구독하게 하는 것이다.
- 필자는 아래 코드처럼 `/queue/errors`라는 경로로 구독을 설정하게 했다.
- `@SendToUser`를 이용해 특정 사용자에게만 메시지를 전송하자.
- 또한, `broadcast = false` 옵션을 달아 하나의 세션에만 메시지를 전송하게 한다.
- 즉, 브로드캐스트를 하지 않게 하는 옵션이다
- 또한, `broadcast = false` 옵션을 달아 하나의 세션에만 메시지를 전송하게 한다.
관련 코드
@Slf4j
@RestControllerAdvice
public class StompExceptionHandler {
...
@MessageExceptionHandler(NormalChatException.class)
@SendToUser(destinations = "/queue/errors", broadcast = false)
public ErrorResponseDto normalChatExceptionHandler(NormalChatException e) {
log.error("NormalChatException: {}, detail: {}", e.getErrorCode().getMessage(), e.getMessage());
return ErrorResponseDto.of(e.getErrorCode(), e.getMessage());
}
}
참고
코드를 확인하고 싶다면?
https://github.com/HanYoonSoo/STOMP-Study
'Spring > WebSocket' 카테고리의 다른 글
[Spring WebSocket] 채팅 서비스에 Transactional Outbox Pattern 도입 (0) | 2024.11.11 |
---|---|
[Spring WebSocket] STOMP에서 Kafka 활용 Flow (0) | 2024.11.11 |
[Spring WebSocket] Spring Security + STOMP (0) | 2024.11.11 |
[Spring WebSocket] MongoDB Collection 설계 With Auto-Incremented Sequence (0) | 2024.11.10 |
[Spring WebSocket] 채팅 서비스 프로젝트에 Kafka 적용 (0) | 2024.11.10 |