Spring Stomp로 보는 직렬화/역직렬화

위와 같은 프로젝트 구성에서 Stomp 직렬화 역직렬화 예시를 보자.
테스트 환경은 서버가 시작할 때 StompClient를 생성하고 연결한다.
//StompClientConnect.java
@Component
@Slf4j
@RequiredArgsConstructor
public class StompClientConnect implements ApplicationRunner {
@NonNull
private CustomStompSessionHandler customStompSessionHandler;
@Override
public void run(ApplicationArguments args) throws Exception {
WebSocketStompClient webSocketStompClient = new WebSocketStompClient(new StandardWebSocketClient());
webSocketStompClient.connectAsync("ws://localhost:8080/ws-stomp", customStompSessionHandler);
}
}
연결하면 오버라이드한 afterConnect 메서드에서 stomp server에 messageDto를 전송한다.
//CustomStompSessionHandler.java
@Component
@RequiredArgsConstructor
@Slf4j
public class CustomStompSessionHandler implements StompSessionHandler {
@NonNull
private final ObjectMapper objectMapper;
@Override
public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
log.info("Connected");
MessageDto messageDto = new MessageDto();
messageDto.setUsername("choi");
messageDto.setMessage("hello");
try {
byte[] bytes = objectMapper.writeValueAsBytes(messageDto);
session.send("/pub/message", bytes);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
...
}
//StompController.java
public class StompController {
@NonNull
private final ObjectMapper objectMapper;
@Async
@MessageMapping("/message")
public void message(MessageDto messageDto) {
System.out.println(messageDto);
}
@Async
@MessageMapping("/message2")
public void message2(String s) throws JsonProcessingException {
MessageDto messageDto = objectMapper.readValue(s, MessageDto.class);
}
...
}
STOMP는 텍스트 기반 프로토콜이다. ( HTTP도 텍스트 기반 프로토콜 )
텍스트 기반 프로토콜에서는 텍스트 데이터를 특정 문자 인코딩(보통 UTF-8)을 사용하여 바이트로 변환한다.
( Although STOMP is a text-oriented protocol, message payloads can be either text or binary. ) --spring docs
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html
String httpRequest = "GET /index.html HTTP/1.1\r\nHost: www.example.com\r\nUser-Agent: Mozilla/5.0\r\nAccept: text/html\r\n\r\n";
byte[] byteArray = httpRequest.getBytes(StandardCharsets.UTF_8);
또 다른 프로토콜로, 바이너리 기반 프로토콜은 이미 데이터가 바이트 형식이므로, 데이터를 적절한 구조에 맞춰 전송한다.
ByteBuffer buffer = ByteBuffer.allocate(10);
buffer.put((byte) 0x01); // 명령어
buffer.putInt(12345); // 데이터 (예: 정수)
buffer.putShort((short) 0x6789); // 데이터 (예: 짧은 정수)
buffer.put((byte) 0x0A); // 종료 바이트
byte[] byteArray = buffer.array();
모든 네트워크 통신은 결국 바이트 스트림으로 이루어지며, 텍스트 기반 프로토콜도 마찬가지로 전송 전에 바이트 배열로 인코딩 된다.
결론
CustomStompSessionHandler.java 코드에서 messageDto를 bytes로 변환하여 전송하고 있다.
만약 messageDto 또는 String 객체를 전송하면 Stomp 서버에서 수신받지 못했다.
앞서 말했듯, 모든 네트워크 통신은 바이트 스트림으로 이루어지고, 다양한 언어/프레임워크들은 전송받은 바이트를 자기들의 타입으로 변환한다.
자바에선 이러한 과정을 직렬화/역직렬화 라고 한다.
역직렬화: 바이트 스트림을 원래의 객체로 복원하는 과정
직렬화: 객체를 바이트 스트림으로 변환하는 과정
Spring Boot는 기본으로 Jackson( 위의 예시에서 사용한 ObjectMapper ) 라이브러리를 포함하고 있고, 별다른 설정 없이 서버를 띄워도 JSON 형식의 직렬화/역직렬화 기능이 동작한다.
StompController.java 에 Stomp라우트(@MessageMapping)를 보면, 별다른 설정 없이 MessageDto, String 등 역직렬화된 자바 객체를 받을 수 있었다.
'back-end > spring' 카테고리의 다른 글
| Spring Data JPA - Cascade, orphanRemoval 차이 (0) | 2024.09.24 |
|---|---|
| Spring Security Session 인증 - REST API login (1) | 2024.09.07 |
| Spring) Client와 WebSocket Server 사이를 중계하기 (1) | 2023.12.04 |
| spring mapstruct (0) | 2023.10.15 |
| spring lombok SuperBuilder (0) | 2023.10.08 |