⌨️ Docs 확인과 통신 확인으로 마무리
당초에 공부해야지 하고 기획했다가 이것저것 하다가 많이 미루어져서 이제야 조금 코드를 끄적인다.
1. WebSocket
- 기존의 단방향 HTTP 프로토콜과 호환되어 양방향 통신을 제공하기 위해 개발된 프로토콜
- 일반 socket 통신과 달리 HTTP 80 포트를 이용하므로 방화벽에 제약이 없다.
- 접속까지는 HTTP 프로토콜을 이용 하고 이후에는 WebSocket 프로토콜로 통신
1.1. WebSocket 통신 방식
WebSocket 접속 과정은 TCP/IP 접속 그리고 WebSocket Established Handshake 과정으로 나눌 수 있다.
i) WebSocket 열기 Handshake
클라이언트가 먼저 핸드셰이크 요청 -> 서버가 클라이언트에 응답
HandShake Request
GET /spring-websocket-portfolio/portfolio HTTP/1.1
Host: localhost:8080
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
Sec-WebSocket-Protocol: v10.stomp, v11.stomp
Sec-WebSocket-Version: 13
Origin: http://localhost:8080
HandShake Response
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
Sec-WebSocket-Protocol: v10.stomp
1.2. WebSocket 구현
ChatHandler
소켓 통신은 서버와 클라이언트가 1:N으로 관계를 맺는다.
따라서 한 서버에 여러 클라이언트가 접속 할 수 있으며, 여러 클라이언트의 메시지를 처리해 줄 Handler 작성이 필요해진다.
TextWebSocketHandler
를 상속받아 Handler를 작성한다.
package com.example.chat.handler;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.util.ArrayList;
import java.util.List;
@Component
@Log4j2
public class ChatHandler extends TextWebSocketHandler {
private static List<WebSocketSession> list = new ArrayList<>();
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception{
String payload = message.getPayload();
log.info("payload : " + payload);
for(WebSocketSession sess: list){
sess.sendMessage(message);
}
}
/* Client 가 접속 시 호출되는 메서드 */
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
list.add(session);
log.info(session + "클라이언트 접속");
}
/* Client 가 접속 해제 시 호출되는 메서드*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
log.info(session + " 클라이언트 접속 해제");
list.remove(session);
}
}
WebSocket Config
이어서 소켓을 활성화 하기위한 Config를 작성한다.
@EnableWebSocket
를 선언하여 활성화
endpoint는 /ws/chat로 설정
CORS 해결을 위해 우선 보안에 취약하지만 테스트 단계이므로 `setAllowedOrgins("*")` 설정 추가
package com.example.chat.config;
import com.example.chat.handler.ChatHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@RequiredArgsConstructor
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
private final ChatHandler chatHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(chatHandler, "ws/chat").setAllowedOrigins("*");
}
}
Websocket 테스트
포스트맨에서 이제 웹소켓 테스트도 지원을 한다. 따라서 포스트맨으로 확인을 했다.
Spring 서버에 로그도 잘 찍히고 소켓 통신도 원활히 잘 되는 것을 확인할 수 있다.
2. 피드백
- 웹소켓 서버와 API 서버가 따로 작동해야하는 지.. 아니면 한 모듈에서 작동 가능한 지 확인하기