본문 바로가기

Spring

SpringBoot + WebSocket server 간단하게 구현해보기

728x90
반응형
SMALL

스프링부트에서 웹소켓 서버 세팅을 하여 실시간으로 메세지를 주고받을 수 있는 서버를 만들어 보겠습니다.

 

정말 간단합니다.

 

먼저 의존성을 주입해줍시다.

 

 

[Gradle]

implementation 'org.springframework.boot:spring-boot-starter-websocket'

[Maven]

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

 

그다음에는

 

websocket에 대한 전반적인 설정을 해줘야 합니다.

어떤 요청에 대한 어떤 응답을 할것인지에 대한 정의를 결정합니다.

@Configuration
@EnableWebSocket
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketConfigurer {

    private final WebSocketHandler webSocketHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(webSocketHandler, "/아무거나해요").setAllowedOrigins("*");
    }
}

'/아무거나해요' 이부분은 나중에 서버 세팅을 끝난 후 실제로 테스트해볼때 정해지는 url 입니다.

ex) ws://127.0.0.1:포트/아무거나해요

 

그리고 setAllowedOrigins("*") 는 웹소켓 cors 정책으로 인해, 허용 도메인을 지정해줘야합니다.

현재 저희는 테스트이기때문에 * 와일드카드로 모든 도메인을 열어줍시다.(실제로 개발하실때에는 보안상의 위험으로 와일드카드는 쓰시면안됍니다.)

 

WebSocketHandler 가 에러가 날텐데. 이제 만들어줄겁니다.

 

 

@Component
public class WebSocketHandler extends TextWebSocketHandler {

    private static final ConcurrentHashMap<String, WebSocketSession> CLIENTS = new ConcurrentHashMap<String, WebSocketSession>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        CLIENTS.put(session.getId(), session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        CLIENTS.remove(session.getId());
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String id = session.getId();  //메시지를 보낸 아이디
        CLIENTS.entrySet().forEach( arg->{
            if(!arg.getKey().equals(id)) {  //같은 아이디가 아니면 메시지를 전달합니다.
                try {
                    arg.getValue().sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

TextWebSocketHandler를 상속받게 되면, 3개의 메소드를 오버라이딩 해야합니다.

 

먼저 상단에 이 코드는

private static final ConcurrentHashMap<String, WebSocketSession> CLIENTS = new ConcurrentHashMap<String, WebSocketSession>();

private static final ConcurrentHashMap<String, WebSocketSession> CLIENTS = new ConcurrentHashMap<String, WebSocketSession>();

CLIENTS 라는 변수에 세션을 담아두기위한 맵형식의 공간입니다.

 

 @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        CLIENTS.put(session.getId(), session);
    }

이 코드는 사용자가 웹소켓 서버에 접속하게 되면 동작하는 메소드 입니다.

이때 WebSocketSession 값이 생성 되는데 그 값을 위에서 미리 만들어준, CLIENTS 변수에 put으로 담아줍니다.(키값은 세션의 고유값 입니다.)

 

@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
     CLIENTS.remove(session.getId());
   }

이 코드는 웹소켓 서버접속이 끝났을때 동작하는 메소드 입니다.

이때 CLIENTS 변수에 있는 해당 세션을 제거 합니다.

 

@Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String id = session.getId();  //메시지를 보낸 아이디
        CLIENTS.entrySet().forEach( arg->{
            if(!arg.getKey().equals(id)) {  //같은 아이디가 아니면 메시지를 전달합니다.
                try {
                    arg.getValue().sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

이 코드는 사용자의 메세지를 받게되면 동작하는 메소드입니다.

CLIENT 변수에 담긴 세션값들을 가져와서 반복문으로 돌려서, 위 처럼 메세지를 발송해주면, 본인 이외의 사용자에게 메세지를 보낼 수 있는 코드가 됩니다.

 

확장 프로그램인 Chrome의 Web Socket Testing을 이용하여 테스트를 해보았습니다.

정상적으로 동작하는 것을 알수 있습니다.

 

잘못된 정보가 있다면, 댓글 달아주시면 성의 있게 답변드리겠습니다.

 

감사합니다.

 

728x90
반응형
LIST