스프링부트에서 웹소켓 서버 세팅을 하여 실시간으로 메세지를 주고받을 수 있는 서버를 만들어 보겠습니다.
정말 간단합니다.
먼저 의존성을 주입해줍시다.
[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을 이용하여 테스트를 해보았습니다.
정상적으로 동작하는 것을 알수 있습니다.
잘못된 정보가 있다면, 댓글 달아주시면 성의 있게 답변드리겠습니다.
감사합니다.
끝
'Spring' 카테고리의 다른 글
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. (0) | 2023.08.01 |
---|---|
@RequestBody 와 @ResponseBody 란? (0) | 2023.06.12 |
SpringBoot Paging(페이징)에서 제공하는 변수 커스터마이징 하기. (1) | 2023.05.11 |
Springboot + chatGPT API 연동해보기. (9) | 2023.04.24 |
spring 에서 @Async 어노테이션 사용하기(비동기) (1) | 2023.04.20 |