우아한테크코스 테코톡
루키의 Spring WebSocket과 STOMP를 활용한 실시간 통신 구조
https://youtu.be/ckxmMbwmn98?si=HhbJK3EH4S4_sfkQ
루키의 Spring WebSocket과 STOMP를 활용한 실시간 통신 구조
- 루키의 Spring WebSocket과 STOMP를 활용한 실시간 통신 구조
- Spring WebSocket + STOMP: 실시간 통신을 제대로 설계하는 방법
- HTTP는 왜 실시간 통신에 부적합할까
- WebSocket: 연결을 유지하는 통신 방식
- WebSocket 연결 과정 (핵심 포인트)
- WebSocket의 한계: “형식이 없다”
- STOMP: 메시지에 구조를 입히다
- STOMP 메시지 구조
- STOMP의 핵심: Pub/Sub 모델
- 채팅 예시로 이해하기
- STOMP 메시지 예시
- Spring 내부 처리 흐름
- 1. 메시지 수신 (Inbound Channel)
- 2. 메시지 라우팅 (Message Handler)
- 3. 메시지 브로커 (Broker Channel)
- 4. 클라이언트 응답 (Outbound Channel)
- 전체 흐름 정리
- 이 구조가 중요한 이유
- 핵심 정리
- 한 줄 핵심
- 실무 관점에서 중요한 포인트
- 마무리
Spring WebSocket + STOMP: 실시간 통신을 제대로 설계하는 방법
실시간 채팅, 알림, 협업 툴 같은 기능을 만들 때 가장 먼저 마주치는 문제는 이것이다.
“HTTP로 실시간을 만들 수 있을까?”
결론부터 말하면 가능은 하지만 비효율적이다. 이 문제를 해결하기 위해 등장한 것이 WebSocket, 그리고 그 위에서 구조를 만들어주는 STOMP다.
이 글에서는 HTTP의 한계 → WebSocket → STOMP → Spring 내부 흐름 순서로 실무 관점에서 정리한다.
HTTP는 왜 실시간 통신에 부적합할까
HTTP는 기본적으로 요청 → 응답 구조다.
즉, 클라이언트가 요청해야만 서버가 응답할 수 있다.
채팅을 예로 보면 흐름은 이렇게 된다.
- 사용자가 메시지 전송
- 일정 시간 후 서버에 “새 메시지 있나요?” 요청
- 없으면 “없음” 응답
- 다시 요청 반복
이 구조의 핵심 문제는 이것이다.
- 계속 요청해야 한다 (Polling)
- 불필요한 트래픽 발생
- 응답 지연 발생
발표에서도 이 방식을 “주기적으로 서버에 물어봐야 하는 매우 비효율적인 방식”이라고 설명한다.
WebSocket: 연결을 유지하는 통신 방식
WebSocket은 이 문제를 근본적으로 해결한다.
핵심 개념은 하나다.
“연결을 끊지 않는다”
HTTP는 요청마다 연결을 열고 닫지만, WebSocket은 한 번 연결하면 계속 유지된다.
비유하면 이렇다.
- HTTP → 문자 보내기
- WebSocket → 전화 연결
즉, 서버가 언제든지 클라이언트에게 메시지를 보낼 수 있다.
WebSocket의 핵심 장점
- 양방향 통신 가능
- 실시간 데이터 전달
- 불필요한 요청 제거
WebSocket 연결 과정 (핵심 포인트)
WebSocket은 처음부터 WebSocket이 아니다.
HTTP로 시작해서 WebSocket으로 업그레이드된다.
1. 클라이언트 요청
Connection: Upgrade
Upgrade: websocket
이 헤더는 “연결 방식을 WebSocket으로 바꿔달라”는 의미다.
2. 서버 응답
- WebSocket으로 전환 승인
- 연결 유지 시작
이 순간부터 HTTP가 아닌 지속적인 연결이 만들어진다.
WebSocket의 한계: “형식이 없다”
여기서 중요한 문제가 하나 발생한다.
WebSocket은 데이터만 보낼 뿐, 형식을 정의하지 않는다.
즉, 이런 상황이 된다.
"hello"
이 메시지를 서버는 어떻게 해석해야 할까?
- 채팅 메시지?
- 알림?
- 명령어?
구분할 수 없다.
발표에서도 이 문제를 명확히 지적한다.
“WebSocket은 메시지 형식을 제공하지 않는다”
STOMP: 메시지에 구조를 입히다
이 문제를 해결하는 것이 STOMP(Simple Text Oriented Messaging Protocol)다.
STOMP는 쉽게 말하면
“WebSocket 위에서 동작하는 메시지 규칙”
이다.
STOMP 메시지 구조
STOMP 메시지는 3가지로 구성된다.
1. Command (무엇을 할 것인가)
- CONNECT
- SEND
- SUBSCRIBE
- DISCONNECT
2. Header (추가 정보)
- destination (어디로 보낼지)
- content-type
3. Body (실제 데이터)
- 메시지 내용
발표에서도 STOMP 메시지는 “명령어, 헤더, 바디 3가지로 구성된다”고 설명한다.
STOMP의 핵심: Pub/Sub 모델
STOMP의 진짜 핵심은 메시지 구조가 아니라 Pub/Sub (발행/구독 모델)이다.
구성 요소
- Publisher → 메시지 보내는 사람
- Subscriber → 메시지 받는 사람
- Topic → 메시지 경로
채팅 예시로 이해하기
1번 채팅방이 있다고 가정해보자.
/topic/room/1
메시지 흐름
- 사용자가 메시지 전송 (Publisher)
- Topic으로 메시지 전달
- 해당 Topic 구독자 모두 수신 (Subscriber)
즉, 한 번 보내면 여러 명이 동시에 받는다.
발표에서도 이 구조를 “하나의 메시지를 여러 사용자에게 동시에 전달”한다고 설명한다.
STOMP 메시지 예시
destination: /topic/1
body: 안녕 친구들
이 의미는 단순하다.
“1번 채팅방에 메시지를 보낸다”
Spring 내부 처리 흐름
Spring은 WebSocket + STOMP를 조합해서 꽤 정교한 메시지 처리 구조를 제공한다.
흐름을 단계별로 보면 다음과 같다.
1. 메시지 수신 (Inbound Channel)
클라이언트 → WebSocket → 서버
- 텍스트 메시지 수신
- Inbound Channel로 전달
- STOMP 형식으로 파싱
2. 메시지 라우팅 (Message Handler)
- destination 확인
- 해당 핸들러로 전달
이 핸들러는 사실상
“WebSocket용 Controller”
라고 보면 된다.
여기서 우리가 작성한 비즈니스 로직이 실행된다.
3. 메시지 브로커 (Broker Channel)
핸들러가 결과 메시지를 반환하면:
- Broker Channel로 전달
- 구독자 확인
- 해당 Topic 구독자에게 전파
4. 클라이언트 응답 (Outbound Channel)
- Outbound Channel에서 메시지 전달
- 구독된 클라이언트에게 전송
전체 흐름 정리
Client
→ WebSocket
→ Inbound Channel
→ Message Handler (비즈니스 로직)
→ Broker Channel
→ Outbound Channel
→ Client
이 구조가 중요한 이유
이 구조는 단순 채팅 구현을 넘어서 확장 가능한 실시간 시스템 구조다.
예를 들어:
- 실시간 알림 시스템
- 주식/코인 시세
- 협업 문서
- 게임 상태 동기화
모두 동일한 구조로 확장 가능하다.
핵심 정리
Spring WebSocket + STOMP 구조의 본질은 이렇다.
1. WebSocket
- 지속 연결
- 양방향 통신
- HTTP 비효율 제거
2. STOMP
- 메시지 구조 제공
- Pub/Sub 모델 지원
3. Spring
- 메시지 라우팅 자동화
- 브로커 기반 전파
- 컨트롤러처럼 개발 가능
한 줄 핵심
“WebSocket은 연결을 만들고, STOMP는 의미를 만든다.”
실무 관점에서 중요한 포인트
1. HTTP → WebSocket 업그레이드 이해
→ LB / Proxy 설정 시 필수
2. Topic 설계
→ /topic/chat/room/{id} 구조
3. 브로커 선택
- SimpleBroker (기본)
- RabbitMQ / Kafka (확장)
4. 인증 처리
→ WebSocket은 HTTP처럼 stateless 아님 → 별도 인증 처리 필요
마무리
Spring WebSocket + STOMP는 단순 기술이 아니라 실시간 시스템 설계의 기본 패턴이다.
정리하면:
- HTTP는 요청 기반이라 비효율적
- WebSocket은 연결 기반으로 해결
- STOMP는 메시지 구조를 제공
- Spring은 이를 자동으로 연결
그리고 결국 핵심은 하나다.
“실시간 시스템은 연결 + 메시지 구조 + 라우팅으로 완성된다.”