SockJS
SockJSλ μ΄ν리μΌμ΄μ
μ΄ WebSocket APIλ₯Ό μ¬μ©νλλ‘ νμ©νμ§λ§, λΈλΌμ°μ μμ WebSocketμ μ§μνμ§ μλ κ²½μ°μ λμμΌλ‘ μ΄ν리μΌμ΄μ
μ μ½λλ₯Ό λ³κ²½ν νμ μμ΄ λ°νμμ νμν λ λ체λ₯Ό νλ κ²μ΄λ€.
SockJSλ λ€μν κΈ°μ μ μ΄μ©ν΄ μΉμμΌμ μ§μνμ§ μλ λΈλΌμ°μ μμ μ μμ μΌλ‘ λμνλλ‘ ν΄μ€λ€. μ μ‘ νμ
μ ν¬κ² λ€μμ 3κ°μ§λ‘ λΆλ₯λλ€
β’
WebSocket
β’
HTTP Streaming
β’
HTTP Long Polling
STOMP (Simple/Stream Text Oriented Message Protocol)
WebSocket μμμ λμνλ λ¬Έμ κΈ°λ° λ©μμ§ νλ‘ν μ½, ν΄λΌμ΄μΈνΈμ μλ²κ° μ μ‘ν λ©μμ§μ μ ν, νμ, λ΄μ©λ€μ μ μνλ 맀컀λμ¦μ΄λ€.
κΈ°λ³Έμ μΌλ‘ pub/sub κ΅¬μ‘°λ‘ λμ΄μμ΄, λ©μμ§λ₯Ό μ μ‘νκ³ λ°μ μ²λ¦¬νλ λΆλΆμ΄ νμ€ν μ ν΄μ Έ μλ€.
httpμ λ§μ°¬κ°μ§λ‘ frameμ μ¬μ©ν΄ μ μ‘νλ νλ‘ν μ½μ΄λ€.
pub/sub ꡬ쑰λ?
STOMPμ Frame ꡬ쑰
COMMAND // λ©μμ§ νμ
μ λνλ΄λ λ¬Έμμ΄, SEND, SUBSCRIBE, UNSUBSCRIBE λ±μ΄ μλ€.
header1 : value1 // μΆκ° μ 보λ₯Ό μ 곡νλ ν€λ
header2 : value2 // μΆκ° μ 보λ₯Ό μ 곡νλ ν€λ
Body^@ // λ©μμ§μ λ΄μ©, ^@ : NULL λ¬Έμμ΄λ€. Bodyμ λμ λνλΈλ€.
Java
볡μ¬
SWAPSWAPμ Frame ꡬ쑰 μμ (μ±ν λ°© μ μ₯μ μμλλ‘)
1.
μΉ μμΌ μ°κ²° μ΄κΈ°ν, ν΄λΌμ΄μΈνΈκ° μλ²μκ² μΉ μμΌ μ°κ²°μ μμ²νλλ° μ¬μ©
2.
μΉ μμΌ μ°κ²°μ΄ μ±κ³΅μ μΌλ‘ μ€μ λμμμ λνλ
3.
ν΄λΌμ΄μΈνΈκ° νΉμ λμμ λν ꡬλ
μ μμ²νλ SUBSCRIBE νλ μ
4.
ν΄λΌμ΄μΈνΈκ° λ©μμ§λ₯Ό νΉμ λμμΌλ‘ 보λ΄λ λͺ
λ Ήμ΄
β’
destination : λ©μμ§κ° μ μ‘λλ λμμ λͺ©μ μ§
5.
νΉμ μ±ν
λ°©μΌλ‘λΆν° μμ λ μ€μ λ©μμ§ λ΄μ©μ λνλ΄λ MESSAGE νλ μ
β’
destination : λ©μμ§κ° μ μ‘λ λμμ λͺ©μ μ§
μ±ν λ°© μ μ₯ μ μ€νλλ μ€ν¬λ¦½νΈ
1.
chatroom.htmlκ° λ‘λλ λ μΉ μμΌ μ°κ²°μ μμ±. /ws/chatλ μΉ μμΌ μλν¬μΈνΈμ URL.
2.
Stomp.js λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ WebSocketμ Stomp νλ‘ν μ½λ‘ λν.
β’
onConnectλ μ°κ²° μ±κ³΅ μ , onErrorλ μ€ν¨ μ μ€νλλ μ½λ°± ν¨μ.
3.
μ°κ²° μ±κ³΅ μ /quere/chat/roomβ + chatRoomId μ λν ꡬλ
μ μ€μ νλ€.
4.
λ©μμ§λ₯Ό λ³΄λΌ λ μ€νλλ ν¨μ
β’
/app/chat/messageλ‘ λ©μμ§λ₯Ό 보λΈλ€.
5.
λ³΄λΈ λ©μμ§λ ν΄λΉ λ©μλλ‘ λ€μ΄μ chatRoomService.saveMessage(message)μμ μ²λ¦¬λ ν
6.
β/queue/chat/roomβ + message.roomId()λ‘ λ©μμ§λ₯Ό μ μ‘ β ν΄λΉ μ±λμ ꡬλ
νκ³ μλ ꡬλ
μλ λ©μμ§λ₯Ό λ°λλ€.
STOMPλ₯Ό μ¬μ©νμ§ μκ³ μμ μΉμμΌμ μΌμ λμ λ¬Έμ μ
μΉ μμΌμ κΈ°λ³Έμ μΌλ‘ Text, Binary νμ
μ λ©μμ§λ₯Ό μλ°©ν₯μΌλ‘ μ£Όκ³ λ°μ μ μλ νλ‘ν μ½μ΄λ€.
κ·Έλ°λ° μΉμμΌλ§ μ¬μ©νλ νλ‘μ νΈκ° 컀μ§λ©΄, μ£Όκ³ λ°λ λ©μμ§μ λν νμμ΄ μ€μνκ² λλ€.
μ¬κΈ°μ STOMPλ₯Ό μ¬μ©νλ©΄ μ΄λ ν μ₯μ μ λ릴 μ μμκΉ
STOMPλ 컀맨λ, ν€λ, λ°λλ‘ μ΄λ£¨μ΄μ§ νλ μ λ¨μλ₯Ό μ μν΄λμκΈ° λλ¬Έμ λ©μμ§ νλ‘ν μ½κ³Ό λ©μμ§ νμμ κ°λ°ν νμκ° μλ€. (μ¦ νμ νλ‘ν μ½κ³Ό λ©μμ§ μ»¨λ²€μ
μ μ μν νμκ° μλ€)
μ°κ²° μ£Όμλ§λ€ μλ‘μ΄ νΈλ€λ¬λ₯Ό ꡬννκ³ μ€μ ν΄μ€ νμκ° μλ€. WebSocketλ§ μ¬μ©νλ€λ©΄ ν
μ€νΈ κΈ°λ°μ μΉ μμΌ ν΅μ μ μ²λ¦¬νκΈ° μν΄μλ TextWebSocketHandlerλ₯Ό μμ λ°μ νΈλ€λ¬λ₯Ό ꡬνν΄ μ£Όμ΄μΌ νλ€.
λ©μμ§ λΈλ‘컀λ₯Ό μ¬μ©νλ©΄ ꡬλ
μ κ΄λ¦¬νκ³ λ©μμ§λ₯Ό Broadcast νλλ° μ¬μ©ν μ μλ€. λν μΈλΆ Messaging Queueλ₯Ό μ¬μ©ν μ μλ€.
μ κ·Έλ¦Όμ μμ μΉ μμΌμ μ¬μ©νμ λμ΄κ³ , μ€λ₯Έμͺ½μ STOMPλ₯Ό μ¬μ©νμ λμ΄λ€.
μΉ μμΌλ§ μ¬μ©νμ λλ λ κ²μ λ©μμ§λ§ μ€κ³ κ°λ λ°λ©΄μ STOMPλ₯Ό μ¬μ©νμ λλ COMMAND, header, bodyμ ννλ‘ μ€κ³ κ°λ κ²μ λ³Ό μ μλ€.
λμ νλ¦
β’
λ©μμ§λ₯Ό 보λ΄λ €λ λ°μ μ, λ©μμ§λ₯Ό λ°μΌλ €λ ꡬλ
μκ° μλ€. ꡬλ
μλ /topic μ΄λΌλ κ²½λ‘λ₯Ό ꡬλ
νκ³ μλ€.
β’
λ°μ μλ /topicμ destination ν€λλ‘ λ£μ΄ λ©μμ§λ₯Ό λ©μμ§ λΈλ‘컀λ₯Ό ν΅ν΄ ꡬλ
μλ€μκ² κ³§λ°λ‘ μ‘μ ν μ μλ€.
β’
νΉμ μλ² λ΄μμ μ΄λ€ κ°κ³΅μ²λ¦¬κ° νμνλ€λ©΄ /app κ²½λ‘λ‘ λ©μμ§λ₯Ό μ‘μ ν μλ μλ€.
β¦
μλ²κ° κ°κ³΅ μ²λ¦¬λ₯Ό λλΈ λ°μ΄ν°λ₯Ό /topicμ΄λΌλ κ²½λ‘λ₯Ό λ΄μ λ©μμ§ λΈλ‘컀μκ² μ λ¬νλ©΄ λ©μμ§ λΈλ‘컀λ μ λ¬λ°μ λ©μμ§λ₯Ό /topicμ ꡬλ
νλ ꡬλ
μλ€μκ² μ΅μ’
μ μΌλ‘ μ λ¬νλ€.
Springμμ STOMPλ₯Ό μ¬μ©νμ λ μ₯μ
β’
νμ νλ‘ν μ½, 컨벀μ
μ λ°λ‘ μ μν νμκ° μλ€.
β¦
STOMPκ° νλ μ λ¨μλ‘ μ μν΄μ€λ€.
β’
μ°κ²° μ£Όμλ§λ€ μλ‘μ΄ Handlerλ₯Ό ꡬννκ³ μ€μ ν΄μ€ νμκ° μλ€.
β¦
@Controller μ΄λ
Έν
μ΄μ
μ μ¬μ©νλ©΄ λλ€.
β’
μΈλΆ Messaging Queueλ₯Ό μ¬μ©ν μ μλ€.
β¦
Springμ΄ κΈ°λ³Έμ μΌλ‘ μ 곡νλ λ΄μ₯ λ©μμ§ λΈλ‘μ½κ° μλ μΈλΆ λ©μμ§ νλ₯Ό μ°λν΄μ μ¬μ©ν μ μλ€.
β’
Spring Securityλ₯Ό μ¬μ©ν μ μλ€.
β¦
μ€κ³ κ°λ λ©μμ§μ λν 보μ μ€μ μ ν μ μλ€.
μ¬κΈ°μ ChannelInterceptorλ λ©μμ§ μ μ‘ μ κ³Ό νμ νΉμ μμ
μ μνν μ μλλ‘ νλ μΈν°νμ΄μ€μ΄λ€. μ preSendλ©μλλ λ©μμ§κ° μ€μ λ‘ μ±λλ‘ μ μ‘λκΈ° μ μ νΈμΆλλλ°, μ΄λ₯Ό ν΅ν΄ λ©μμ§λ₯Ό κ°λ‘μ±κ³ μνλ μμ
μ μνν μ μλ€.
μ κ°μ κ²½μ°μλ STOMPμ Frameꡬ쑰μμ COMMANDκ° CONNECTμΌ λ, μ¦ ν΄λΌμ΄μΈνΈκ° μλ²μκ² μ°κ²°μ μμ²ν λ μ€νλλ λ©μλμ΄λ€. λ§μ½ ν΄λΉ if()λ¬Έ μμ JWT ν ν°μ validation νλ λ©μλλ λ£μ΄μ€λ€λ©΄ μ°κ²°μ μμ²νκΈ° μ μ JWT ν ν°μ κ²μ¦ν μ μμ κ²μ΄λ€.
















