Project/mo:rack (익명 커뮤니티)

간단한 실시간 채팅 구현 feat. postman 테스트

창브로 2025. 6. 30. 19:39

현재 내가 진행하고 있는 프로젝트가 실시간 채팅이 필요하기 때문에

실시간 채팅을 차근차근 구현해 볼 거다.

 

전 게시글에서 설명했던 양방향 통신인 웹소켓을 사용할 것이고

웹소켓을 통해 간단한 채팅방을 만들고 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를 가진 사람이 '안녕하세요?'를 보냈다고 보이게 됩니다.

 

누군지 모르니까 '누구세요??'라고 보내볼게요

 

 

 

 

이런 식으로 채팅이 동작하게 됩니다!

 

신기하죠?

 

이제 제 프로젝트에 맞춰 점점 고도화를 해야겠죠?..