현재 내가 진행하고 있는 프로젝트가 실시간 채팅이 필요하기 때문에
실시간 채팅을 차근차근 구현해 볼 거다.
전 게시글에서 설명했던 양방향 통신인 웹소켓을 사용할 것이고
웹소켓을 통해 간단한 채팅방을 만들고 postman을 통해서 테스트를 해보면서 내 프로젝트에 적용해 볼 생각이다.
시작해 보자!!

자 먼저 뭘 해야 하냐
// WebSocket 관련 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-websocket'
웹소켓을 쓰기 위한 의존성부터 추가해 준다!
그리고 웹소켓을 핸들링해줄 핸들러를 만들어보자 ~~
@Slf4j
@Component
public class ChatWebSocketHandler extends TextWebSocketHandler {
// 연결된 사용자들을 저장하는 맵
// Key: 세션 ID, Value: WebSocket 세션
private final ConcurrentHashMap<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
// 사용자가 WebSocket에 연결했을 때 호출되는 메서드
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
String sessionId = session.getId();
sessions.put(sessionId, session);
log.info("===== WebSocket 연결 성공! ====");
log.info("User connected: {}", sessionId);
log.info("현재 연결된 사용자 수: {}명", sessions.size());
// 연결된 사용자에게 알림
String welcomeMessage = "채팅 연결에 성공했습니다.";
session.sendMessage(new TextMessage(welcomeMessage));
}
// 클라이언트로부터 메시지를 받았을 때 호출되는 메서드
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String sessionId = session.getId();
String receivedMessage = message.getPayload();
log.info("Message received from {}: {}", sessionId, receivedMessage);
broadcastToAll(sessionId + ": " + receivedMessage);
}
// 연결이 끊어졌을 때 호출되는 메서드
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
String sessionId = session.getId();
sessions.remove(sessionId);
log.info("WebSocket 연결 종료 - 세션 ID: {}", sessionId);
log.info("현재 연결된 사용자 수: {}명", sessions.size());
broadcastToAll(sessionId + "님이 채팅방을 나갔습니다.");
}
// 에러 발생시 호출되는 메서드
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
String sessionId = session.getId();
log.error("WebSocket 연결 중 에러 발생 - 세션 ID: {}, 에러: {}", sessionId, exception.getMessage());
// 에러 발생시 해당 세션 정리
sessions.remove(sessionId);
if (session.isOpen()) {
session.close();
}
}
// 모든 연결된 사용자에게 메시지를 보내는 메서드
private void broadcastToAll(String message) {
log.info("모든 연결된 사용자에게 전송: {}", message);
sessions.values().forEach(sessions -> {
try {
if (sessions.isOpen()) {
sessions.sendMessage(new TextMessage(message));
}
} catch (IOException e) {
log.error("메시지 전송 중 오류 발생: {}", e.getMessage());
}
});
}
}
이제 이렇게 만든 핸들러를
Config로 등록해야겠죠?
@Configuration
@EnableWebSocket // WebSocket 기능 활성화
@Slf4j
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketConfigurer {
private final ChatWebSocketHandler chatWebSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(chatWebSocketHandler, "/chat") // "/chat" 경로로 WebSocket 연결 가능
.setAllowedOrigins("*"); // 개발이기 때문에 모든 도메인에서 연결 허용
log.info("WebSocket 핸들러가 '/chat' 경로에 등록!");
}
}
이렇게 되면 localhost:8080/chat 경로로 웹소켓 연결이 가능하게 됩니다!!
테스트해볼까요?
실행했을 때
Config에서 설정했던 log가 실행되면서 핸들러가 등록된 것을 확인할 수 있습니다!
이제 postman으로 웹소켓 연결을 해서 통신을 해보려 합니다.
postman으로 두 명의 사용자가 사용하는 것처럼 테스트 해보겠습니다.
첫 번째 사용자!
위에 핸들러에서 구현한 코드 로그를 보면서 따라오시면 쉽습니다.
다른 id로 한 사람이 더 연결된 게 보이죠??
이제 채팅해볼게요!
send를 누르면
서버에 '안녕하세요?'를 보냈다고 Response에 나오고 아까 설정한 id와 메시지가 나오는 것을 볼 수 있습니다.
채팅방에 있는 다른 사람에게는
특정 id를 가진 사람이 '안녕하세요?'를 보냈다고 보이게 됩니다.
누군지 모르니까 '누구세요??'라고 보내볼게요
이런 식으로 채팅이 동작하게 됩니다!
신기하죠?
이제 제 프로젝트에 맞춰 점점 고도화를 해야겠죠?..

'Project > mo:rack (익명 커뮤니티)' 카테고리의 다른 글
채팅기능 고도화 (STOMP + JWT 토큰 인증 + 전송시 유저 정보 + sessionId 확인) (0) | 2025.07.02 |
---|---|
실시간 채팅 구현 전 개념 정리 (2) | 2025.06.30 |
로그인 사용자가 어떤 댓글에 좋아요를 눌렀는가에서 발생한 N+1 문제 해결 (0) | 2025.06.27 |
댓글 조회 리팩토링중 - feat.인덱스 (1) | 2025.06.18 |
게시글 조건 조회 - QueryDSL (동적 쿼리) feat. 페이징 (2) | 2025.06.15 |