μΉμμΌ νλ‘ν μ½κ³Ό HTTP νλ‘ν μ½
νλ‘ν μ½
νλ‘ν μ½μ μ»΄ν¨ν° λ€νΈμν¬μμ λ°μ΄ν° κ΅νμ μν΄ μ¬μ©λλ κ·μΉκ³Ό νμ€μ μ§ν©μ
λλ€. μ¦, νλ‘ν μ½μ λ€νΈμν¬ μμμ λ°μ΄ν°κ° μ΄λ»κ², μ΄λ€ νμμΌλ‘ μ μ‘λμ΄μΌ νλμ§λ₯Ό μ μνλ κ·μ½μ
λλ€. μ»΄ν¨ν°λ λ€νΈμν¬ μ₯μΉκ° μλ‘ ν΅μ νκΈ° μν΄μλ λμΌν νλ‘ν μ½μ λ°λΌμΌ ν©λλ€. νλ‘ν μ½μ ν΅μ λ€νΈμν¬μ κΈ°λ³Έμ μΈ κ΅¬μ± μμλ‘, λ€μν λ€νΈμν¬ νκ²½κ³Ό μ ν리μΌμ΄μ
μμ ν¨μ¨μ μ΄κ³ μμ μ μΈ λ°μ΄ν° κ΅νμ κ°λ₯νκ² ν©λλ€.
μΉμμΌκ³Ό HTTP κ·Έλ¦¬κ³ TCP λ μ΄λ€ κ³μΈ΅μ μν΄μλμ?
μΉμμΌκ³Ό HTTP λͺ¨λ TCP λ₯Ό κΈ°λ°μΌλ‘ νμ§λ§, λ νλ‘ν μ½μ΄ TCP μ μνΈμμ© νλ λ°©μμ μλΉν λ€λ¦
λλ€. λ¨Όμ μΈ νλ‘ν μ½μ΄ μ΄λ€ λ€νΈμν¬ κ³μΈ΅μ μν΄μλμ§ λΆν° μμλ³΄κ² μ΅λλ€.
TCP μ HTTP μ μ°κ²°κ³Ό λ°μ΄ν° κ΅ν - 3 way handshake
β’
μ΄λ κ² μ°κ²°μ΄ μλ£λ νμ μμ²κ³Ό μλ΅μ΄ μ μ‘ λλ©°, κ° μμ²μ λ
립μ μ
λλ€.
β’
μ¬λ¬ HTTP μμ²μ νλμ TCP μ°κ²°λ‘ μ²λ¦¬ν μ μμ΅λλ€.
β’
HTTP λ μνλ₯Ό μ μ₯νμ§ μμΌλ―λ‘ μμ² κ°μ μν μ 보λ₯Ό μ μ§ νμ§ μμ΅λλ€.
β¦
λλ¬Έμ 맀 μμ² λ§λ€ μΈμ¦/μΈκ° λ₯Ό μν ν ν° λ±μ μ€μ΄λ³΄λ΄μΌ ν©λλ€.
μΉμμΌμ μμμ HTTP μ°κ²°!
μΉμμΌ μ°κ²°μ HTTP μ°κ²°μ ν΅ν΄ μμν©λλ€. μμ κ°μ΄ three way handshake λ₯Ό ν΅ν΄ μ°κ²°μ΄ λ νμ ν΄λΌμ΄μΈνΈλ μΉμμΌ μ°κ²°μ μμ²ν©λλ€. μλ²κ° μ΄λ₯Ό μΉμΈνλ©΄ HTTP μ°κ²°μ μΉμμΌ μ°κ²°λ‘ μ
κ·Έλ μ΄λ λ©λλ€. κ³Όμ μ μλμ κ°μ΅λλ€.
Β μ΄ κ³Όμ μ SockJS μ μ€νλ§ νλ μμν¬μ μΉμμΌ μ§μ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νλ©΄ λλΆλΆ μλμΌλ‘ μ²λ¦¬ λ©λλ€. λλ¬Έμ κ°λ°μλ λ©μΈμ§ μ²λ¦¬ λ° λΉμ¦λμ€ λ‘μ§ κ΅¬νμ μ§μ€νλ©΄ λ©λλ€.
β’
ν΄λΌμ΄μΈνΈλ Upgrade: websocket κ³Ό Connection:Upgrade λ₯Ό μμ² ν€λμ λ£μ΅λλ€.
β¦
μ΄λ ν΄λΌμ΄μΈνΈκ° νμ¬μ HTTP μ°κ²°μ μΉμμΌ μ°κ²°λ‘ μ ννκ³ μ ν¨μ λνλ
λλ€.
β¦
Sec-WebSocket-key λΌλ ν€λλ μλ²μ μλ΅μ κ²μ¦νλ λ° μ¬μ©νλ ν€λ μ
λλ€.
β’
μλ²κ° μ ν΄λΌμ΄μΈνΈμ μμ²μ μλ½νλ©΄ μλ΅μ ν΅ν΄ μ΄λ₯Ό μ립λλ€.
β¦
Upgrade: websocket κ³Ό Connection:Upgrade ν€λλ₯Ό ν¬ν¨ν΄μΌ ν©λλ€.
β¦
Sec-WebSocket-key λ₯Ό κΈ°λ°μΌλ‘ μμ±λ νΉλ³ν κ°μ Sec-WebSocket-Accept ν€λμ λ΄μ μλ΅ν©λλ€.
μ΄ κ³Όμ μ websocket handshake λΌκ³ νλ©°, μ΄ κ³Όμ μ΄ μλ£ λλ©΄ HTTP μ°κ²°μ μΉμμΌ μ°κ²°λ‘ μ
κ·Έλ μ΄λ λ©λλ€. μ¦, ν΄λΌμ΄μΈνΈμ μλ² μ¬μ΄μ ν΅μ μ μΉμμΌ νλ‘ν μ½μ ν΅ν΄ μ§νλ©λλ€. μ΄λ₯Ό ν΅ν΄ ν΄λΌμ΄μΈνΈμ μλ²λ μ°κ²°μ΄ μ’
λ£λ λκΉμ§ λ°μ΄ν° κ΅νμ ν¨μ¨μ μΌλ‘ μνν μ μκ² λ©λλ€.
HTTP μ μΉμμΌμ λ°μ΄ν° μ μ‘
λ νλ‘ν μ½μ TPC/IP νλ‘ν μ½μ μ΄μ©νκΈ° λλ¬Έμ λ°μ΄ν°λ ν¨ν·μ ννλ‘ μ μ‘λ©λλ€
HTTP νλ‘ν μ½ μμλ μ£Όλ‘ ν
μ€νΈ κΈ°λ°μ λ©μΈμ§ νμμ μ¬μ©νμ¬ λ°μ΄ν°λ₯Ό μ μ‘ν©λλ€. μμμ€, ν€λ, λ³Έλ¬ΈμΌλ‘ ꡬμ±λμ΄ μμ£ .
νμ§λ§ μΉμμΌμ κ²½μ° μΉμμΌ νλ μμ΄λΌλ ꡬ쑰λ₯Ό μ¬μ©νμ¬ λ°μ΄ν° μ μ‘μ΄ μ΄λ£¨μ΄ μ§λλ€. μ΄λ μ€μκ° λ°μ΄ν° ν΅μ μ μ΅μ νλ ν¬λ§·μ
λλ€.
μ€μ κ΅¬μ± μμ
β’
νλ μμ μμκ³Ό λμ λνλ΄λ νμμ
β’
νμ΄λ‘λ κΈΈμ΄
β’
λ§μ€νΉ
β’
νμ΄λ‘λ λ°μ΄ν°
νλ μ μ ν
1.
μ°μ νλ μ : κΈ΄ λ©μΈμ§λ₯Ό μ¬λ¬ νλ μμ λλμ΄ μ μ‘ν λ μ¬μ©ν©λλ€.
2.
ν
μ€νΈ νλ μ : UTF-8 ν
μ€νΈ λ°μ΄ν°λ₯Ό μ μ‘νλ λ° μ¬μ©λ©λλ€.
3.
λ°μ΄λ리 νλ μ : λ°μ΄λ리 λ°μ΄ν°λ₯Ό μ μ‘νλ λ° μ¬μ©λ©λλ€.
4.
μ μ΄ νλ μ : μ°κ²°μ λ«κ±°λ, ν/ν λ©μμ§λ₯Ό μ μ‘νλ λ° μ¬μ©λ©λλ€. μ΄ νλ μμ μ€κ°μ λ€λ₯Έ νλ μμ μ€λ¨νμ§ μκ³ μ μ‘λ μ μμ΅λλ€.
STOMP
STOMPλ Simple (or Streaming) Text Oriented Messaging Protocol μ μ½μλ‘, κ°λ¨ν ν
μ€νΈ κΈ°λ°μ λ©μμ§ νλ‘ν μ½μ
λλ€. STOMP λ HTTP μ μ μ¬ν νμμ νλ μμΌλ‘ ꡬμ±λμ΄ μλλ°μ, κ° νλ μμλ λͺ
λ Ήμ΄(CONNECT, SUBSCRIBE, SEND), ν€λ, λ°λκ° ν¬ν¨λ©λλ€. λν STOMPλ λ°ν/ꡬλ
(Publish/Subscribe) λ° μμ²/μλ΅(Request/Response) ν¨ν΄μ μ§μν©λλ€.
λμ κ³Όμ
WebSocket Client Messages
ν΄λΌμ΄μΈνΈκ° λ©μΈμ§λ₯Ό 보λ΄λ©΄(SEND) μ΄ λ©μΈμ§λ€μ μλ²μ νΉμ endpoint λ‘ λΌμ°ν
λ©λλ€. λ©μΈμ§μλ destination ν€λκ° ν¬ν¨λμ΄ μμ΄, λ©μΈμ§κ° μ΄λλ‘ λ³΄λ΄μ§μ§ μ§μ ν©λλ€. κ·Έλ¦Όμμμ /app/a λ μ ν리μΌμ΄μ
μ νΉμ μ‘μ
μ λνλ΄κ³ , /topic/a λ νΉμ μ£Όμ μ λν λ°νμ λνλ
λλ€.
Message handling
@SimpAnnotaionMehtodMessageHandler λ μ ν리μΌμ΄μ
λ©μλμ μ΄λ
Έν
μ΄μ
μ κΈ°λ°μΌλ‘ λ©μΈμ§λ₯Ό 맀ννλ νΈλ€λ¬ μ
λλ€. μλ₯Ό λ€μ΄, @MessageMapping μ΄λ
Έν
μ΄μ
μ΄ λΆμ λ©μλκ° /app/a λ‘ μ€λ λ©μΈμ§λ₯Ό μ²λ¦¬ν©λλ€. @StompBrokerRelayMessageHandler λ λ©μΈμ§λ₯Ό μΈλΆ λ©μΈμ§ λΈλ‘μ»€λ‘ λΌμ°ν
ν©λλ€. μ΄ κ²½μ° /topic μΌλ‘ μμνλ λͺ©μ μ§λ₯Ό κ°μ§ λ©μΈμ§λ μΈλΆ STOMP λ©μΈμ§ λΈλ‘μ»€λ‘ μ λ¬ λ©λλ€. λ©μΈμ§ λΈλ‘컀λΆν°μ μλ΅μ response channel μ ν΅ν΄ μλ²λ‘ λμμ€λ©°, νμ ν΄λΌμ΄μΈνΈμ μ λ¬λ©λλ€.
μ΄ν΄κ° μ μκ°λλ°μβ¦
μμ λ΄μ©μ΄ κΈλ‘λ§ λμ΄μμ΄μ μ μ΄ν΄κ° μκ° μ μμ΅λλ€. μ΄λ₯Ό μν΄ μ΄μ νλ‘μ νΈμ μ½λ μΌλΆλ₯Ό κ°μ Έμμ΅λλ€. ν΄λΉ κΈ°λ₯μ ν΅ν΄ νΉμ μ μ μ νλλμ μ΄λλ μ¬λ¬ μ μ λ€μ΄ μ€μκ°μΌλ‘ νλλλ₯Ό μμ±ν μ μμ΅λλ€.
WebSocketConfig.java
μΉμμΌ μ€μ κ³Ό κ΄λ ¨λ ν΄λμ€ μ
λλ€.
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
/*
destination μ /app/ μ΄ μμ λΆμΌλ©΄ μ μ¬κΈ°μ νΉμ μ‘μ
μ μννλ ꡬλ
νκ³ μκ°νλ©΄ λ κ² κ°μ΅λλ€.
destination μ /topic/ μ΄ μμ λΆμΌλ©΄ μ μ΄κ³³μ μ²λ¦¬λ λ°μ΄ν°κ° μ€λ ꡬλ
νκ³ μκ°νλ©΄ λ κ² κ°μ΅λλ€.
*/
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
...
}
Java
볡μ¬
νλ‘ νΈμλμμμ μΉμμΌ μ°κ²° μμ²
νλ‘ νΈμλμμ νΉμ νλλμ μΉμμΌ μ°κ²° μμ²μ νκ³ , μΉμμΌ μ°κ²°μ μ±κ³΅νλ©΄ μλμ κ°μ λ΄μ©μ΄ μ½μμ μ°νλλ€.
μ΄λ νΉμ μ μ μ νλλλ₯Ό μλ―Ένλ destination μ ꡬλ
νκ³ μλ€λ λ»μ
λλ€.
TodoListController.java
νλλμ λ€μ΄κ°μ μ¬νλ μ§λ₯Ό μμ±ν΄λ³΄κ² μ΅λλ€.
@Controller
@AllArgsConstructor
@RequestMapping("todolist")
public class TodoListController {
private final TodoListService todoListService;
private final SimpMessagingTemplate simpMessagingTemplate;
// λ©μΈμ§ λΈλ‘컀(/app/upload-todolist/{tpIdx}) μ 맀νμ ν©λλ€.
@MessageMapping("/upload-todolist/{tpIdx}")
public void upload(
@DestinationVariable("tpIdx") Long tpIdx,
TodoListRegistRequest dto
) throws Exception {
/*
κ΄νΈ μμ destination μ SUBSCRIBE νκ³ μλ λͺ¨λ μ¬λλ€μκ²
μμμ λ³΄λ΄ μ²λ¦¬λ λ°μ΄ν°λ₯Ό 보λ΄κ² λ€λ λ»μ
λλ€.
*/
simpMessagingTemplate.convertAndSend("/topic/planner-message/" + tpIdx,
Map.of("type","upload-todolist","msg",todoListService.createTodoList(dto, tpIdx)));
}
...
Java
볡μ¬
λ€μκ³Ό κ°μ΄ λ μ§λ₯Ό μμ± νμ λ κ°λ°μ λꡬλ₯Ό μ΄μ΄λ³΄λ©΄ μλμ κ°μ λ΄μ©μ νμΈν μ μμ΅λλ€.
λͺλ² νλ€λ³΄λ©΄ κΈλ°© μ΅μν΄ μ§λ΅λλ€.