1단계 문제 이해 및 설계 범위 확정
•
채팅은 단순하면서도 복잡하다. 1대1 채팅에 집중하는 앱이 있는가 하면 그룹 채팅에 집중하는 업무용이나 게임용 채팅 애플리케이션도 있다.
•
따라서 초반에 던지는 질문들은 면접관이 원하는 앱이 정확히 무엇인지 알아내기 위한 의도로 해야한다.
•
아래는 면접관에게 해볼 수 있는 질문들이다.
◦
1대1, 그룹 어떤 유형의 채팅을 지원해야 하는지
▪
그룹 채팅의 경우, 인원 제한이 있는지
◦
앱인지 웹인지
◦
처리해야 하는 트래픽 규모는 어느 정도인지?
◦
주요 기능으로는 어떤 것이 있는지?
◦
메시지 길이에 제한이 있는지?
◦
종단 간 암호화를 지원해야 하는지?
◦
채팅 기록은 얼마나 오래 저장해야 하는지?
•
이번 예제는 다음과 같은 기능을 갖는다고 가정하자.
◦
응답지연이 낮은 일대일 채팅 기능
◦
최대 100명까지 참여할 수 있는 그룹 채팅 기능
◦
사용자의 접속상태 표시 기능
◦
다양한 단말 지원, 하나의 계정으로 여러 단말에 동시 접속 지원
◦
푸시 알림
◦
5천만 DAU
2단계 개략적 설계안 제시 및 동의 구하기
•
채팅 서비스는 다음과 같은 기능을 제공해야 한다.
◦
클라이언트들로부터 메시지 수진
◦
메시지 수신자 결정 및 전달
◦
수신자가 접속 상태가 아닌 경우에는 접속할 때까지 해당 메시지 보관
•
채팅 서비스의 경우, 네트워크 통신 프로토콜을 결정하는 것도 중요한 설계사항 중에 하나다. 따라서 상의 하에 적절한 선택을 하자.
◦
HTTP의 경우, 메시지 전송 용도로는 괜찮은 선택이다.
◦
메시지 수신의 경우, 폴링, 롱 폴링, 웹 소켓 등이 있다.
폴링
•
클라이언트가 주기적으로 서버에게 새 메시지가 있는지 물어보는 방법이다.
•
이 경우, 답해줄 메시지가 없으면 서버 자원이 불필요하게 낭비된다는 문제가 생긴다.
롱 폴링
•
롱 폴링의 경우, 폴링의 문제를 보완하기 위해 추가된 개념으로 클라이언트는 새 메시지가 반환되거나 타임아웃 될 때까지 연결을 유지한다.
•
클라이언트가 새 메시지를 받으면 기존 연결을 종료하고 서버에 새로운 요청을 보내어 모든 절차를 다시 시작한다.
웹소켓
•
서버가 클라이언트에게 비동기 메시지를 보낼 때 가장 널리 사용하는 기술이다.
•
웹소켓 연결은 클라이언트가 시작한다. 한번 맺어진 연결은 항구적이며 양방향이다. 처음에는 HTTP 연결로 시작하지만 특정 핸드셰이크 절차 후, 웹소켓 연결로 업그레이드 된다.
•
이 연결이 만들어지고 나면 서버는 클라이언트에게 비동기적으로 메시지를 전송할 수 있게 된다.
•
웹소켓을 사용하면 전송, 수신에 같은 프로토콜을 사용할 수 있으므로 구현도 단순하고 직관적이다.
•
유의할 것은 항구적으로 유지되어야 하기 때문에 서버 측에서 연결 관리를 효율적으로 구현해주어야 한다.
개략적 설계안
•
무상태 서비스
◦
해당 설계에서 무상태 서비스는 로그인, 회원가입 등 전통적인 요청/응답 형태를 띄는 서비스다.
◦
무상태 서비스는 로드밸런서 뒤에 위치하며 이중 살펴볼만한 서비스는 클라이언트가 접속해야할 채팅 서버의 DNS 호스트명을 클라이언트에게 알려주는 기능 정도가 있다.
•
상태유지 서비스
◦
채팅 서비스가 유일하게 상태유지 서비스다.
•
제3자 서비스 연동
◦
푸시 알림을 제공하기로 했으므로 필요한 제3자 서비스는 푸시 알림이다.
데이터 모델
•
저장 이력 관리를 위해 데이터 계층 기술을 적절히 사용해야 한다.
•
메시지 ID의 경우, 스노플레이크 방법을 사용하거나, 특정 값에 한해(1대1의 경우, 사용자, 그룹의 경우, 채널) 유니크하므로 지역적 순서 번호 생성기를 사용해볼 수도 있다.
3단계 상세 설계
•
채팅 시스템의 경우, 서비스 탐색, 메시지 전달 흐름, 사용자 접속 상태 표시 방법 정도가 더 자세히 살펴볼만 하다.
서비스 탐색
•
가장 적절한 채팅 서버를 추천하는 것으로, 클라이언트의 접속 위치, 서버의 용량 정도를 참고하여 서버를 결정할 수 있다.
•
이 기능을 구현하는 가장 널리 알려진 서비스는 아파치 주키퍼로 동작은 다음과 같다.
◦
채팅 서버를 해당 서비스에 등록해두고, 클라이언트가 접속을 시도하면 사전에 정하 기준에 따라 최적의 채팅 서버를 골라주는 것이다.
메시지 흐름
•
다음은 1대1 채팅에서 메시지 처리 흐름이다.
1.
사용자 A가 채팅 서버 1로 메시지 전송
2.
채팅 서버 1은 ID 생성기를 사용해 해당 메시지의 ID 결정
3.
채팅 서버 1은 해당 메시지를 메시지 동기화 큐로 전송
4.
메시지가 키-값 저장소에 보관됨
a.
사용자 B가 접속중인 경우, 메시지는 사용자 B가 접속 중인 채팅 서버로 전송됨
b.
사용자 B가 접속중이 아닌 경우, 푸시 알림 메시지를 푸시 알림 서버로 보냄
5.
채팅 서버 2는 메시지를 사용자 B에게 전송, 사용자 B와 채팅 서버 2 사이에는 웹소켓 연결이 존재하므로 이를 사용
•
여러 단말 사이의 메시지 동기화
◦
각 단말 별로 가장 최신의 message_id를 기준으로 새 메시지들을 조회한다.
•
소규모 그룹 채팅에서의 메시지 흐름
◦
사용자 A가 A, B, C가 있는 그룹 채팅에 메시지를 전송한 경우, B, C의 메시지 동기화 큐에 복사될 것이다.
접속상태 표시
•
사용자의 상태가 바뀌는 상황들에 따라 접속상태 표시를 적절히해주어야 한다.
4단계 마무리
•
상세 설계 후, 시간이 남는다면 다음 사항들에 대해서 면접관과 얘기를 나눠보는 것이 좋다.
◦
채팅 앱을 확장하여 사진이나 비디오 등의 미디어를 지원하도록 하는 방법
◦
종단 간 암호화
◦
캐시
◦
로딩 속도 개선
◦
오류 처리
▪
채팅 서버 오류
•
특정 서버 하나가 죽는 경우, 클라이언트에게 새로운 서버를 배정하고 다시 접속할 수 있도록 해주어야 한다.
▪
메시지 재전송