- 아래는 채팅 앱에 대한 설계 문제입니다.
- 일대일 채팅 앱과 그룹 채팅 앱은 다르므로 요구사항을 확실히 알아야 합니다.
1단계 문제 이해 및 설계 범위 확정#
- 아래는 요구 사항입니다.
- 응답지연이 낮은 일대일 채팅 기능
- 최대 100명까지 참여할 수 있는 그룹 채팅 기능
- 사용자의 접속상태 표시 기능
- 다양한 단말 지원, 하나의 계정으로 여러 단말에 동시 접속 지원
- 푸시 알림
- 5천만 DAU를 처리할 수 있으면 좋습니다.
2단계 개략적 설계안 제시 및 동의 구하기#
- 채팅 서비스는 아래 기능을 제공해야 합니다.
- 클라이언트들로부터 메시지 수신
- 메시지 수신자(recipient) 결정 및 전달
- 수신자가 접속(online) 상태가 아닌 경우에는 접속할 때까지 해당 메시지 보관
- 서버가 연결을 만드는 방법으로 많은 기법이 존재합니다.
- 폴링은 클라이언트가 주기적으로 서버에게 새 메시지가 있는지 물어보는 방법입니다.
- 폴링 비용은 폴링을 자주하면 할수록 올라갑니다.
롱 폴링#
- 폴링은 여러 가지로 비효율적일 수 있어서 나온 기법이 롱 폴링입니다.
- 롱 폴링의 경우 클라이언트는 새 메시지가 반환되거나 타임아웃 될 때까지 연결을 유지합니다.
- 아래의 약점이 있습니다.
- 메시지를 보내는 클라이언트와 수신하는 클라이언트가 같은 채팅 서버에 접속하게 되지 않을 수도 있습니다.
- 서버 입장에서는 클라이언트가 연결을 해제했는지 아닌지 알 좋은 방법이 없습니다.
- 여전히 비효율적입니다.
웹소켓#
- 서버가 클라이언트에게 비동기 메시지를 보낼 때 가장 널리 사용하는 기술입니다.
- 웹소켓 연결은 클라이언트가 시작합니다. 한번 맺어진 연결은 항구적이며 향방향입니다.
- 웹소켓을 이용하면 메시지를 보낼 때나 받을 때 동일한 프로토콜을 사용할 수 있으므로 설계뿐만 아니라 구현도 단순합니다.
개략적 설계안#
- 개략적 설계는 다음으로 나눌 수 있습니다.
- 무상태 서비스
- 상태유지(stateful) 서비스
- 3자 서비스 연동
무상태 서비스#
- 무상태 서비스는 로그인, 회원가입, 사용자 프로파일 표시 등을 처리하는 전통적인 요청/응답 서비스입니다.
상태 유지 서비스#
- 채팅 서비스는 상태 유지가 필요합니다.
- 클라이언트가 채팅 서버와 독립적인 네트워크 설정을 유지해야 합니다.
제 3자 서비스 연동#
- 제3자 서비스는 푸시 알림입니다. 새 메시지를 받았다면 설사 앱이 실행 중이지 않더라도 알림을 받아야 합니다.
규모 확장성#
- 트래픽 규모가 낮으면 얼마 되지 않을 때는 방금 설명한 모든 기능을 서버 한 대로 구현할 수 있습니다.
- 아래는 그 시작 포인트입니다.
- 채팅 서비는 클라이언트 사이에 메시지를 중계하는 역할을 담당합니다.
- 접속상태 서버는 사용자의 접속 여부를 관리합니다.
- API 서버는 로그인, 회원가입, 프로파일 변경 등 그 외 나머지 전부를 처리합니다.
- 알림 서버는 푸시 알림을 보냅니다.
- 키-값 저장소에는 채팅 이력을 보관합니다.
저장소#
- 채팅 시스템이 다루는 데이터는 보통 두 가지입니다.
- 첫 번째는 사용자 프로파일, 설정, 친구 목록처럼 일반적인 데이터입니다.
- 두 번째는 유형의 데이터는 채팅 시스템에 고유한 데이터로 바로 채팅 이력입니다.
- 페이스북이나 왓츠앱은 매일 600억 개의 메시지를 처리합니다.
- 키-값 저장소는 아래의 추천점이 있습니다.
- 수평적 규모확장이 쉽습니다.
- 키-값 저장소는 데이터 접근 지연시간(latency)가 낮습니다.
- 관계형 데이터베이스는 데이터 가운데 롱 테일에 해당하는 부분을 잘 처리하지 못합니다.
- 많은 안정적인 채팅 시스템은 키-값 저장소를 채택할 수 있습니다.
데이터 모델#
- 1:1 채팅을 위한 메시지 테이블과 그룹 채팅을 위한 메시지 테이블이 있습니다.
메시지 ID#
- message_id의 값은 고유해야 합니다.
- ID 값은 정렬 가능해야 하며 시간 순서와 일치해야합니다.
3단계 상세 설계#
서비스 탐색#
- 서비스 탐색 기능의 주된 역할은 클라이언트에게 가장 적합한 채팅 서버를 추천하는 것입니다.
- 대표적인 오픈 소스 솔루션으로 아파치 주키퍼가 있습니다.
메시지 흐름#
1:1 채팅 메시지 처리 흐름#
여러 단말 사이의 메시지 동기화#
- 단말기마다 cur_max_message_id 를 들고 있으며 최신화 정보를 유지합니다.
소규모 그룹 채팅에서의 메시지 흐름#
접속 상태 표시#
사용자 로그인#
- 사용자가 로그인 하면, last_active_at 타임 스탬프 값을 키-값 저장소에 보관합니다.
로그아웃#
- 키-값 저장소에 보관된 사용자 상태가 online-offline 으로 바꿉니다.
접속 장애#
- 주기적 박동 검사를 통해 접속 장애 검사를 합니다.
상태 정보의 전송#
- 그룹 크기가 적을 때는 발행-구독 모델을 사용하는 것이 좋은 방법일 수 있습니다.
- 그러나 커지는 경우에는 수동으로 하도록 유도해야합니다.
4단계 마무리#
- 아래의 내용에 대해 더 이야기해볼 수 있습니다.
- 채팅 앱을 확장하여 사진이나 비디오 등의 미디어를 지원하도록 하는 방법
- 종단 간 암호화: 왓츠앱은 메시지 전송에 있어 좋단 간 암호화를 지원합니다.
- 캐시: 클라이언트에 이미 읽은 메시지를 캐시해 두면 서버와 주고받는 데이터 양을 줄일 수 있습니다.
- 로딩 속도 개선: 슬랙은 사용자의 데이터, 채널 등을 지역적으로 분산하는 네트워크를 구축하여 앱 로딍 속도를 개선했습니다.
- 오류 처리
- 채팅 서버 오류: 서버가 죽을 경우, 서비스 탐색 기능이 동작하여 클라이언트에게 새로운 서버를 배정하고 다시 접속할 수 있도록 해야합니다.
- 메시지 재전송: 재시도나 큐는 메시지의 안정적 전송을 보장하기 위해 흔히 사용됩니다.