Post

๐Ÿ’Ž Websocket - STOMP ์ฑ„ํŒ… ์„œ๋ฒ„ ๊ตฌ์ถ•

๐Ÿ’Ž Websocket - STOMP ์ฑ„ํŒ… ์„œ๋ฒ„ ๊ตฌ์ถ•

Websocket - STOMP ๋„์ž… ๊ทผ๊ฑฐ

  • ์ฑ„ํŒ… ์„œ๋น„์Šค๋ฅผ ์œ„ํ•ด Websocket ์—ฐ๊ฒฐ ๋ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•ด์„œ MongoDB์— ๋ฐ์ดํ„ฐ๋ฅผ ๋“ฑ๋กํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.
  • ์ฑ„ํŒ…์€ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์ด๋ฏ€๋กœ SSE๋Š” ๋ถˆ๊ฐ€ํ•˜๊ณ , ํšจ์œจ์„ฑ์„ ์œ„ํ•ด Polling ๋ฐฉ์‹ ๋˜ํ•œ ๋ฐฐ์ œ๋˜์–ด Websocket์„ ๋„์ž…ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

์ž‘์„ฑ ์ฝ”๋“œ

โœ… ์„ค์ • ํŒŒ์ผ

1
2
3
4
5
6
7
8
9
10
/**
 * ์—”๋“œํฌ์ธํŠธ ์„ค์ •
 * @param registry
 */
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
	registry.addEndpoint("/ws")
		.setAllowedOriginPatterns("*");
		.withSockJS();
}

โœ… Controller

1
2
3
4
@MessageMapping("/chat.sendSystemMessage")
public void enterUser(Message message) {
	service.sendSystemMessage(message);
}

โœ… Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void sendSystemMessage(Message message) {
	MessageType type = message.getType();
	Long roomId = message.getRoomId();
	
	Message systemMessage = Message.builder()
		.type(type)
		.content(
			String.format(
				type.name().equals("ENTER") ? "[%s] %s ๋‹˜์ด ์ž…์žฅํ–ˆ์Šต๋‹ˆ๋‹ค." : "[%s] %s ๋‹˜์ด ํ‡ด์žฅํ–ˆ์Šต๋‹ˆ๋‹ค.",
				LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
				message.getSenderName()
			)
		)
		.senderId(message.getSenderId())
		.roomId(roomId)
		.sendAt(LocalDateTime.now())
		.build();
		
	repository.save(systemMessage);
	template.convertAndSend("/topic/room_" + roomId, systemMessage);
}
  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ์š”์ฒญํ•  ๊ฒฝ์šฐ DB์— ํ•ด๋‹น ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•˜๊ณ , ํ•ด๋‹น ์‚ฌ์šฉ์ž๊ฐ€ ๊ตฌ๋…ํ•œ Topic์— ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•œ๋‹ค.
  • SimpleMessagingTemplate์€ ๊ฐ„๋‹จํ•˜๊ฒŒ Topic์— ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

ํ…Œ์ŠคํŠธ

Websocket Debug Tool

  • Postman์—์„œ๋Š” STOMP ์„œ๋ธŒ ํ”„๋กœํ† ์ฝœ์„ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์œ„ ๋งํฌ๋ฅผ ํ™œ์šฉํ•ด์•ผ ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
2025-04-05T15:14:04.404+09:00 
DEBUG 23688 --- [nboundChannel-4] o.s.m.s.b.SimpleBrokerMessageHandlerย ย ย ย  
: Processing MESSAGE 
destination=/topic/room_2 
session=null 
payload={
	"senderId":1,
	"roomId":1,
	"senderName":null,
	"type":"ENTER",
	"send...(truncated)"
}
  • ์•ž์„œ ์ฒจ๋ถ€ํ•œ ๋งํฌ์—์„œ๋Š” CONNECT, SUBSCRIBE, SEND ๋“ฑ ์š”์ฒญ ํ”„๋ ˆ์ž„์„ ์ž‘์„ฑํ•  ํ•„์š” ์—†์ด ๊ฐ„๋‹จํ•˜๊ฒŒ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์‹ค์ œ ๋ชฉ์ ์ง€์— ์ œ๋Œ€๋กœ Broadcast ๋˜๋Š”์ง€๋Š” Frontend ์˜์—ญ์„ ๊ตฌํ˜„ํ•ด์•ผ ์•Œ ์ˆ˜ ์žˆ๊ธฐ๋Š” ํ•˜์ง€๋งŒ Backend ์˜์—ญ Logging์„ ํ™•์ธํ•˜๋Š” ์„ ์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ๋งˆ์ณค๋‹ค.ย 
  • Session์ด null ๊ฐ’์œผ๋กœ Logging๋˜๊ณ  ์žˆ๋Š”๋ฐ, ์ด๊ฑด SimpMessagingTemplate๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ Session ์ •๋ณด๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ๋ธŒ๋กœ์ปค๋กœ ๋ณด๋‚ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • SockJS๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ํ”„๋กœํ† ์ฝœ์— ws๊ฐ€ ์•„๋‹Œ http๋ฅผ ๊ธฐ์žฌํ•ด์•ผ ํ•œ๋‹ค.
This post is licensed under CC BY 4.0 by the author.