[Spring] 실시간 채팅 기능 회고 - 1

일상 회고록·2024년 1월 15일
0

브릿지 프로젝트

목록 보기
1/4
post-thumbnail
post-custom-banner

안녕하세요!

브릿지 프로젝트에서 메인 기능 중 하나인 채팅 기능에 대한 회고 작성을 시작하려고 합니다.

좋은 경험이 될 것 같아서 시원하게 제가 채팅 구현을 지원했는데,,

지금까지 개발인생에서 구현한 기능 중 가장 난이도도 높고, 그만큼 여러 문제들도 마주쳤습니다.

리스펙하는 향로님의 말씀처럼 몰입의 과정을 기억하기 보단 기록해보려 합니다.

그럼 채팅 기능 회고 시작하겠습니다!

0. 개발 환경 및 요구사항

원할한 회고을 위해 간단하게 개발 환경과 채팅 요구사항에 대해 설명 드리겠습니다.

  • 개발 환경

    • 서버 : JAVA 11 + SpringBoot 2.7.14v
    • 클라이언트 : iOS + Swift
  • 요구사항

    • 1 : 1 채팅 기능 (그룹채팅은 제외)
    • 파일 전송 기능
    • 읽음 / 안읽음 상태 반영
    • 채팅 메세지 전송 시 알림

1. 기술 선택과 이유

모든 기능 개발에서 그렇듯, 다양한 기술과 알고리즘들을 비교하고, 타당한 이유로 적절한 선택을 하여 구현해야 합니다. (개인적으론 개발자란 왜?가 기본 베이스로 깔려 있어야 한다고 생각합니다.)

이러한 이야기를 하는 이유는 ‘채팅’을 막상 구현하려고 하니 정말 막막했고, 폭풍 구글링을 한 결과 명확하게 정해진 방법은 없었습니다.

즉, 제가 비교해보고, 타당한 이유를 바탕으로 적절한 기술 선택을 해야하는 상황이었죠.

이 과정부터 약간 머리가 아파오기 시작했는데요,,어쩌겠습니까 일단 해봐야죠!

일단 채팅이라는 것이 ‘실시간’으로 이루어지기 때문에, 여기서부터 관련 공부를 시작했습니다.

1-1. 실시간 통신

실시간 통신을 위한 기술은 크게 다섯가지가 있습니다.

한가지씩 알아보도록 하겠습니다.

  1. Polling

    HTTP 연결에서는 무상태성과 비연결성의 특징을 가지기 때문에 서버가 클라이언트에게 데이터를 보내고 싶어도 일방적으로 보낼 수 없습니다.

    즉, 클라이언트로부터 요청을 받아야 응답을 보낼수 있는 것이죠.

    이러한 이슈를 보완한 것이 Polling 방식입니다.


    핵심은 서버에게 요청을 주기적으로 계속 보내면서 서버가 전달할 데이터가 있다면 응답할 수 있도록 합니다.

    단점은 요청을 주기적으로 계속 보내기 때문에 HTTP 오버헤드가 크다는 점입니다.

    적합한 서비스 아래와 같습니다.

    • 실시간 메세지가 중요하지 않은 서비스
    • 잦은 요청이 부담되지 않을 서버를 가진 서비스

  1. Long Polling

    큰 틀은 Polling 방식과 유사하게 동작하고, 조건 및 설정이 추가된 방식입니다.

    • Polling 하나의 생명주기 시간을 늘린다
    • 서버로부터 이벤트가 발생할 때까지 대기한다

    즉, 핵심은 Polling 방식과 달리 이벤트가 발생할 때까지 대기 시간을 늘려 요청의 빈도를 줄이는 것입니다.

    이론만 봤을 때는 Long Polling 방식이 더 유리해보일 수 있지만, 경우에 따라 Polling 방식보다 서버에 부담을 더 줄 수 있습니다.

    적합한 서비스는 아래와 같습니다.

    • 실시간 메세지 전달이 중요하지만, 잦은 데이터 전달이 없는 서비스

  2. WebSocket

    WebSocket은 HTML5 표준 기술로, HTTP 환경에서 하나의 TCP 연결을 맺고 이를통해 실시간 전이중 통신을 가능하게 합니다.

    즉, 클라이언트와 서버간의 연결을 지속적으로 유지하고, 양방향으로 통신이 가능합니다.

    WebSocket은 요청-응답 개념보단 데이터를 주고 받는 형식입니다.

    적합한 서비스는 아래와 같습니다.

    • 실시간 양방향 통신이 필요하고, Socket 통신을 위한 전용 서버를 구축할 환경이 가능한 곳

  3. SSE (Server Sent Event)

    HTML 5 표준 기술로, 서버에서 클라이언트로 단방향 데이터를 전달할 수 있습니다.

    장점은 WebSocket과 달리 별도의 프로토콜 구축이 필요하지 않고, Polling처럼 요청을 주기적으로 보내지 않아도 됩니다.

    적합한 서비스는 아래와 같습니다.

    • 서버에서 일방적인 데이터 전달이 필요한 서비스 (ex. 실시간 검색어)
    • 스트리밍 서비스

  4. WebRTC

    위의 기술들은 모두 클라이언트-서버 구조로 동작하지만, WebRTC는 P2P 방식으로 통신이 이루어집니다.

    또한 별도의 소프트웨어 없이 음성, 영상, 텍스트, 파일 데이터를 브라우저, 단말끼리 주고 받을 수 있고, Latency가 짧은 것이 특징입니다.


    적합한 서비스는 아래와 같습니다.

    • 정말 실시간 통신이 최우선인 서비스
    • 1 : 1 혹은 소규모 대상 실시간 통신이 중점인 서비스

이렇게 여러가지의 실시간 통신 기술에 대해 간략하게 살펴봤습니다.

이제 선택을 해야합니다. 후후

1-2. WebSocket

최종적으로 브릿지 프로젝트 채팅 기능의 실시간 통신 기술로 WebSocket 기술을 선택했습니다.

선택의 근거는 생각보다 명확합니다.

  • Polling , Long Polling 방식은 양방향 통신이 아니라는 점에서 적합하지 않음
  • SSE 방식은 서버가 주된 전송 주체이고, 스트리밍에 더 적합
  • WebRTC 방식은 음성, 영상이 주요 포커스이고, 보안 이슈와 개발 난이도 측면에서 적합하지 않음
  • WebSocket 방식은 실시간 양방향 통신이 가능하고, 개발 난이도가 크지 않음

WebSocket 만으로도 충분히 요구사항을 만족하는 채팅 기능을 구현할 수 있지만,

여기에 저는 추가로 STOMP 프로토콜을 적용하기로 했습니다.

1-3. STOMP?

현재 WebSocket 기술은 텍스트 / 바이너리 두가지 유형의 메세지를 정의하고 있지만, 메세지 내용까지는 정의하지 않습니다.

STOMP는 TCP위에서 작동하는 프로토콜로, 메세지 전송을 효율적으로 하기 위해 등장한 프로토콜입니다.

STOMP는 기본적으로 Pub/Sub 구조를 따르고 있고, 메세지 브로커를 사용할 수 있는 장점이 있습니다.

그렇다면 왜 STOMP를 추가 선택했을까요?

만약 WebSocket으로만 채팅을 구현한다면,

  • 어떤 채팅방에 누가 접속 중인지?
  • 채팅방에 포함된 모두에게 메세지 전송 필요

위와 같은 이유로 채팅방마다 세션을 관리해야하는 번거로움이 존재합니다.

하지만 STOMP를 사용한다면,

  • 채팅방 별로 구독 가능
  • 누가 접속 중인지 관리 없이, 구독을 통해 채팅방으로 메세지 전송이 가능

점에서 큰 장점을 가집니다.

사실 엄밀히 말하자면 WebSocket을 사용한다기보단 틀을 가져간다고 생각하는게 좋을 것 같습니다.

WebSocket으로 HTTP → TCP 전환 후(연결 후), STOMP를 사용하는 구조입니다.

2. 정리

마지막으로 정리해보자면, 아래와 같습니다.

  • WebSocket 기술을 통해 실시간 양방향 통신
  • STOMP 기술을 통해 간편한 메세지 전송 가능

기술을 선택하는 과정에서 공부해야할 개념도 많았고, 처음보는 기술도 있기에 시간이 조금 걸렸습니다.

하지만 기본 뼈대가 튼튼해야 무너지지 않기 때문에 꼭 필요한 과정이라고 생각합니다.

그럼 채팅 회고-2 에서 뵙겠습니다.

읽어주셔서 감사합니다. :)

profile
하고 싶은 것들이 많은 개발자입니다
post-custom-banner

0개의 댓글