REST API vs WebSocket 설계 패턴

ssongyi·2025년 5월 30일
1

Java/Spring TIL

목록 보기
15/22
REST APIWebSocket (STOMP)
HTTP 기반 (Request → Response)Persistent 연결 (연결 유지)
URL + Method 기반 라우팅 (@GetMapping, @PostMapping)destination 기반 라우팅 (@MessageMapping)
BaseResponse 등으로 표준화 쉽게 가능실시간 메시지 → 이벤트 기반 → BaseResponse가 잘 안 맞음 (실시간 응답은 주로 payload 자체로 보냄)
요청-응답 명확pub/sub 구조, 실시간 Push

팀 컨벤션이 확실하게 있는데, 웹소켓으로 기능을 구현하고자 하니 지킬 수 없게되었다.
그런데 그게 정상이라고 한다.

WebSocket용 코드에서는 팀 REST 컨벤션 (BaseResponse 래핑 등)을 "그대로 적용하려고 억지로 할 필요 없음"
→ WebSocket은 @MessageMapping + Plain Object (DTO) 로 처리하는 게 자연스러움

팀에서 많이 쓰는 방법

기능구현 방법
방 생성 (초기화 등)REST API 로 처리 → 팀 컨벤션 따름 → BaseResponse 사용
실시간 채팅 (메시지 송수신)WebSocket → @MessageMapping 사용 → Plain DTO 사용 (BaseResponse 안 씀)

1. Rest + WebSocket 혼용 패턴

장점:
✅ 방 생성, 목록 조회, 유저 목록 등은 HTTP 기반으로 안전하게 제공 가능
✅ 인증/인가 → Spring Security + OAuth2 등과 쉽게 연계 가능
✅ 클라이언트가 서버 상태를 쉽게 "초기화/조회" 가능 (ex: /api/chat/rooms 로 내 방 목록 가져오기 등)
✅ REST API는 로그 관리 / 테스트 / API 문서화 (Swagger) 등에서 매우 유리

단점:
❌ 채팅 메시지 송수신 흐름은 WebSocket으로 따로 관리해야 해서 코드가 분리됨
❌ 실시간 처리할 로직은 결국 WebSocket 쪽에서 또 중복될 수 있음

일반적으로 채팅 시스템에서 이렇게 분리:

기능구현 방식
방 생성 / 삭제 / 목록 조회REST API
실시간 메시지 송수신WebSocket (STOMP)
채팅방 입장/퇴장 알림WebSocket (STOMP) or REST 혼용 가능

2. WebSocket-only 설계 패턴

장점:
✅ 전체가 단일 통신 채널 (WebSocket) 로 통일 → 설계가 단순해짐
✅ 모바일/게임/고성능 서비스에서 선호 (연결 유지 상태에서 모든 기능 제공)
✅ 이벤트 기반 → 프론트-백 간 UX가 매끄러움
✅ WebSocket connection → session 을 활용해서 상태 관리 쉬움

단점:
❌ 방 목록 초기 조회도 WebSocket 이벤트로 해야 하므로 → 상태 동기화 코드가 늘어남
❌ 인증 처리 설계가 약간 복잡해짐 (토큰 전달 및 검증 등)
❌ 로그 기록 / API 문서화 어려움 → WebSocket은 Swagger 같은 도구로 문서화 어려움
❌ 서버 재시작 시 connection 재연결 필요 → 초기화/리커넥션 로직 고려 필요

실시간 채팅에서는 ?

조건추천 방향
아주 고성능 채팅 (게임/모바일/1:1 채팅)WebSocket-only 설계 OK
일반 서비스 채팅 (커뮤니티/그룹방/일반 Web 서비스)REST + WebSocket 혼용이 유지보수성이 더 좋음

내가 택한 방법은

  • 지금 팀 프로젝트 구조도 REST 기반이 있고
  • Spring Boot 기반 서비스
  • 그리고 그룹 채팅 설계니까 (방 생성도 있고, 멤버도 있고)

✅ 방 생성/조회/멤버 조회 → REST API
✅ 채팅 메시지 송수신/입장/퇴장 알림 → WebSocket

혼용 패턴을 사용하기로 했다!

WebSocket-only로 가면?

가능은 한데:

  • 방 목록 조회할 때도 WebSocket 이벤트 만들어야 함
  • 초기 연결 동기화 코드가 꽤 들어감
  • 테스트 & 디버깅 시 REST API에 비해 불편

WebSocket 은 STOMP 메시지 경로를 이용해 들어옴

REST API(@RestController) 처럼 요청-응답 으로 들어오는 것이 아님 !

1. 클라이언트 → 서버 (/pub 경로)

  • 클라이언트가 /pub/chat/message 같은 경로로 메시지를 보낼 때(HTTP POST 아님),
    Spring은 @MessageMapping("/chat/message") 이 붙은 메서드를 호출함

  • 이때 SimpMessagingTemplate이나 리턴값으로 다시 메시지를 브로드스트하거나 처리할 수 있다.

2. 서버 → 클라이언트 (/sub 경로)

  • 처리 결과를 messagingTemplate.convertAndSend("/sub/chat/room/{roomId}", dto) 이렇게 보내면
  • 클라이언트는 STOMP로 /sub/chat/room/{roomId}subscribe(구독) 해 두었다가, 이 메시지를 받아서 렌더링함

즉,

  • /pub/... 은 클라이언트가 “publish” 하는 엔드포인트(요청을 받는 곳),
  • @MessageMapping 은 이 퍼블리시된 메시지를 처리하는 메서드,
  • messagingTemplate.convertAndSend("/sub/...") 은 처리된 결과를 “subscribe” 중인 클라이언트에게 뿌려주는 곳입니다.

REST 컨트롤러(/api/...)와 완전히 별도의 메시징 레이어라고 생각해야 함!

0개의 댓글