다니던 전 회사에서 NestJS와 Redis Pub/Sub 기능을 사용하여 분산환경에서의 채팅 서버를 구축한 적이 있었다.
하지만 개념들을 짚지않은채로 일단 되면 된다는 식으로 막무가내로 개발을 진행한 결과 나에게 남은 것도 없었고, 안정적인 서버를 구축할 수 없었다.
8개월이 지나고 프로그래머스 대브매칭에서 부트캠프를 진행하던 와중 이전 팀 멘토님께서 기술 블로그를 공유해 주셔서 읽어보았는데 나에게 너무 감명 깊었고 나에 대한 회고와 함께 리뷰를 해보기로 했다.
"배민쇼핑라이브를 만드는 기술: 채팅 편"
배민쇼핑라이브 채팅을 자체 구현하기 위해 비동기 처리를 위한 Spring WebFlux와 채팅 서버들이 Redis Pub Sub을 통해 메시지를 주고받았도록 구성하였다. 또한 클라이언트와 통신을 위해 WebSocket을 활용하였다.
배운점
1. WebSocket의 최소화
WebSocket으로 처리할 기능들이 많으면 코드상에서 분기가 많아지고 복잡성이 늘어난다는 점에서 많은 공감이 되었다.
실제로 채팅 서버를 개발하면서 이러한 부분은 REST API로 제공하고 있는데 Socket 통신으로도 제공해야하는가? 라는 의문도 들었지만 혹시 모를 불안감에 socket통신은 socket으로 처리해야지 라는 느낌이 강하게 들었었다.
하지만 배민쇼핑라이브 채팅은 주요한 소켓 통신을 제외한 나머지 기능(조회, 유저 제한)들은 REST API로 충분히 처리할 수 있으면 되도록 그런식으로 처리하여 복잡성을 줄이도록 하였다.
( 메세지를 보내고 받는 본질만 남겨두어 SRP를 지킨 것인가..?)
2. RDB 직접 접근을 배제
채팅 기능을 개발하면서 꼭 필요한 부분이 사용자 인증이었다. 왜냐하면 채팅은 사용자들끼리의 대화이기 때문에 유저정보가 필요했고, 이러한 정보는 매번 채팅에서 RDB에서 가져와 사용하였다.
하지만 배민쇼핑라이브 채팅에서는 RDB 접근을 최소화하여 websocket의 non-blocking 기능을 최대화 하였고, 대부분 필요한 데이터를 모두 Redis에 저장하고 사용했다고 한다.
( 그러면 채팅 기록들이나, 사용자 정보는 어디서 가져오는가?? )
위의 의문들 중 꼭 필요한 데이터라고 판단하면 DB에 영구히 저장하는 쪽으로 처리하고 휘발되어도 될 정보는 Redis에 저장하였다고 한다. (선택적 DB 선택 저장)
그리고 사용자 정보는 다음 단락에서 설명하겠다.
3. 채팅에서 사용자 정보 가져오는 방법
이 부분이 가장 특이하였고 또 배운점이 많았다.
- 웹 소켓 앤드포인트 url을 클라이언트에 두는게 아닌, 서버에 rest api 에서 정보를 제공해준다는 점. 이로써 서버 endpoint를 좀더 유연하게 대처할 수 있다는 점이고,
- 웹소켓 endpoint url과 함께 전용 토큰을 발급해주는데, 회원의 다양한 role들에 대해 채팅 접속 이후에 일관된 방식으로 인증을 처리하기 위함이라고 한다. 와우. 이렇게 처리한다면, 외부 인증 서버에 의존하지 않아 연쇄적인 장애 발생 위험을 줄일 수 있다고도 한다.
4. 궁금한 점
1 ) Session 부분에서 WebSession과 그냥 Session은 다른 저장소인가?
2) 토큰 파싱된 데이터들을 로직에서 사용해야하는데 이러한 부분을 Session에 저장하는 것인가?
너무 뼈를 많이 맞은 것 같다. 그래도 이 글을 읽고 백엔드 개발자로써 Messaing Platfrom 쪽 분야로 성장하고 나아가고 싶은 꿈이 생겼다.
참고 사이트
배민쇼핑라이브를 만드는 기술: 채팅 편 | 우아한형제들 기술블로그
2021년 10월 14일 | 라이브선물스쿼드의 오지산입니다. 이 글에서는 저희 배민쇼핑라이브에서 "채팅을 자체 구현하게 된 배경"과, "기술적인 부분"을 설명드리려고 합니다. 배민쇼핑라이브에서 채
techblog.woowahan.com
- 도와주신분: @Marco 멘토