본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Spring framework/Spring boot

간단하게 구성하는 SpringBoot Websokcet server(스프링부트 웹소켓 서버)

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2021. 12. 27.

 

스프링부트에서 웹소켓 서버 환경을 구성하는 아주 간단하고 빠른 방법 입니다.

프로젝트 자체가 당연히 웹 서버 기반으로 기초 환경구성이 되어야 하겠습니다.

필요한 의존성 라이브러리는 딱 1개 입니다.

 

* gradle 기준

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

* mavne 기준

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

 

첫번째 단계로는 어떠한 요청에 대해서 서버가 응답할지를 결정하는 설정파일을 작성하는 것 입니다.

WebSocketConfigurer 인터페이스를 상속받는 설정 클래스를 만들어 줍니다.


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
@EnableWebSocket
public class 웹소캣설정 implements WebSocketConfigurer{

    private final 웹소켓핸들러 webSocketHandler;

    public 웹소캣설정(웹소켓핸들러 webSocketHandler) {
        this.webSocketHandler = webSocketHandler;
    }

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(webSocketHandler, "/원하는이름").setAllowedOrigins("*");
    }
}

 

"원하는이름" 이라는 항목은 호출할 이름을 의미합니다.

아래 텍스트를 보면 어떠한 의미인지 쉽게 알 수 있습니다.

본인의 개발환경 및 스타일에 맞게 변경해 주도록 합니다.

ws://127.0.0.1:포트/원하는이름

 

위 코드를 작성하여 보면, "웹소켓핸들러" 라는 클래스가 없기 때문에 오류가 발생하게 됩니다.

이제 "웹소켓핸들러" 라는 클래스를 작성하여 줍니다.

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

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;

@Component
public class 웹소켓핸들러 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();
                }
            }
        });
    }

}

 

여기서의 핵심 부분은 오버라이드한 2개의 메소드 입니다.

afterConnectionEstablished 메소드는 사용자가(브라우저) 웹소켓 서버에 붙게되면 동작하는 메소드 입니다.

이때 WebSocketSession 값이 생성이 되는데 해당 값을 static 변수인 CLIENTS 객체에 put 메소드를 활용하여 고유 아이디값을 키로 하고 세션을 값으로 하여 넣어주었습니다.

 

다음 handleTextMessage 메소드는 사용자의 메시지를 받게되면 동작하는 메소드입니다.

구글링을 하면 해당 메소드에서 session객체에 바로 sendMessage를 보내는 코드가 많습니다.

이러한 경우에는 자기 자신한테만 응답하는 에코(echo) 기능만 동작하게 됩니다.

 

하지만 afterConnectionEstablished 메소드에서 접속한 사용자를 CLIENTS 객체에 담아주었으므로 해당 변수에는 접속한 세션의 값들이 전부 보관되고 있습니다.

handleTextMessage 메소드에서 CLIENTS 객체에 담긴 세션값들을 가져와서 반복문을 통해 위 처럼 메시지를 발송 해 주면, 자기자신 이외의 사용자에게 메시지를 보낼 수 있는 코드가 완성이 되게 됩니다.

 

afterConnectionClosed메소드에서는 접속이 끊어진 사용자가 발생하면 호출되는 메소드 입니다.

해당 메소드를 활용하여 CLIENTS 객체에서 접속이 끊어진 아이디 값을 제거하도록 하면 코드는 완성 입니다.

간단한 확장 프로그램을 크롬, 파이어폭스를 통하여 테스트를 해 봅니다.

잘되네요!

 

코드도 매우 간결하고 심플한 모습의 웹소켓 서버 기능이 완성되었습니다.

스프링 부트로 이렇게 간결하게 구현을 할 수 있네요!

 

이상으로 간단하게 살펴본 스프링부트 웹소켓 서버 구성 방법 이였습니다.

궁금한점 또는 틀린부분은 언제든 연락주세요! 👻

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글