Foundry
실시간 채팅 시스템 설계
심화
핵심

팬아웃 전략

한 번 보낸 메시지를 N명에게 어떻게 도달시키나

메시지 하나를 보내면 채널 인원 수만큼 전달이 생깁니다. 이것을 팬아웃이라고 합니다. 채널이 최대 5만 명 이므로 한 번의 전송이 5만 개의 전달로 늘어납니다.

방식은 두 갈래이고, 쓰기와 읽기 중 어디에 비용을 낼지의 선택입니다.

보낼 때 각 수신자에게 복제하는 방식과 읽을 때 채널에서 모으는 방식의 비교 보낼 때 복제 전송 받은함 1 받은함 2 받은함 N 읽기가 빠르다 N 이 크면 쓰기가 터진다 읽을 때 모으기 전송 채널 하나 읽기 쓰기가 한 번이다 읽을 때마다 모아야 해서 조회가 느려진다

두 방식의 대가

항목보낼 때 복제읽을 때 모으기
쓰기수신자 수만큼 늘어난다한 번
읽기자기 받은함만 읽는다. 빠르다채널에서 모아야 한다. 느리다
저장같은 메시지가 N개한 개
터지는 지점큰 채널의 쓰기 증폭많은 채널을 보는 사용자의 읽기 증폭

왜 하나로 통일하지 않나

평균 채널이 12명 이라 대부분은 복제해도 부담이 없습니다. 12개의 받은함에 쓰는 것은 아무 문제가 아니고, 읽기가 빨라지는 이득만 얻습니다.

문제는 소수의 큰 채널입니다. 5만 명 짜리 채널에 메시지 하나가 오면 5만 번의 쓰기가 발생하고, 그 채널이 활발하면 쓰기가 시스템을 밀어버립니다.

그래서 인원 수를 보고 경로를 고릅니다. 작은 채널은 복제하고, 큰 채널은 채널에만 저장해 읽을 때 모읍니다. 사용자 화면에서는 두 결과를 합쳐 보여줍니다.

경계값은 재서 정한다

몇 명부터 큰 채널로 볼지는 추측하지 않습니다. 채널 크기 분포와 채널별 메시지 빈도를 재서 쓰기 증폭이 감당 한계를 넘는 지점을 찾습니다. 인원이 많아도 조용한 채널은 복제해도 되고, 인원이 적어도 초당 수십 건이 오가면 부담이 됩니다.

오프라인 사용자는 다르게 다룬다

접속하지 않은 사용자에게 실시간 전달은 의미가 없습니다. 그 사람 몫의 팬아웃은 미룰 수 있습니다. 접속할 때 못 받은 메시지를 채널에서 가져오면 되고, 알림만 따로 보냅니다.

이렇게 나누면 20만 동시 접속자 몫만 실시간 경로를 타므로 팬아웃 폭이 크게 줄어듭니다.

면접에서 이렇게 나옵니다

Q.한 메시지를 채널 인원 전체에게 어떻게 도달시키나요

팬아웃 방식을 고릅니다. 쓰기와 읽기 중 어디에 비용을 낼지의 선택입니다.

방식쓰기읽기터지는 지점
보낼 때 각자 받은함에 복제N배빠르다큰 채널의 쓰기 증폭
채널에만 저장하고 읽을 때 모으기한 번느리다많은 채널을 보는 사용자

채널이 최대 5만 명 이면 복제 방식은 메시지 하나에 5만 번의 쓰기가 됩니다. 그래서 인원 수를 보고 경로를 고릅니다. 작은 채널은 복제하고 큰 채널은 읽을 때 모읍니다.

흔한 실수: 한 방식으로 통일하겠다고 답하는 것. 평균 12명 이라 대부분은 복제가 맞고, 소수의 큰 채널만 다르게 다뤄야 합니다. 통일하면 흔한 경우가 느려지거나 드문 경우가 시스템을 밀어버립니다.

Q.큰 채널과 작은 채널을 가르는 기준은 어떻게 정하나요

재서 정합니다. 인원 수만으로는 정해지지 않습니다.

인원이 많아도 조용한 채널은 복제해도 부담이 없고, 인원이 적어도 초당 수십 건이 오가면 쓰기가 쌓입니다. 그래서 보는 것은 두 가지입니다.

재는 것
채널 크기 분포큰 채널이 몇 개나 되나
채널별 메시지 빈도그 채널이 실제로 활발한가

둘을 곱한 값이 쓰기 증폭이고, 그것이 감당 한계를 넘는 지점이 경계입니다.

여기에 접속 상태가 더 붙습니다. 오프라인 사용자 몫의 팬아웃은 미룰 수 있으므로, 실제 실시간 팬아웃 폭은 동시 접속자 비율만큼 줄어듭니다.

흔한 실수: 인원 수로만 기준을 잡는 것. 그러면 조용한 대형 채널에 불필요한 복잡도를 붙이고, 활발한 소형 채널을 놓칩니다. 기준은 인원이 아니라 초당 쓰기 횟수입니다.

Q.오프라인 사용자에게도 실시간으로 팬아웃해야 하나요

아닙니다. 접속하지 않은 사용자 몫은 미룰 수 있습니다.

실시간 전달은 화면이 열려 있을 때만 의미가 있습니다. 오프라인 사용자에게는 접속할 때 못 받은 메시지를 채널에서 가져다 주면 되고, 알림만 따로 보냅니다.

사용자 상태전달 방식
접속 중실시간 팬아웃. 지연 예산 안에 도달해야 한다
오프라인채널에 남겨 두고 접속 시 조회. 알림은 별도

이렇게 나누면 팬아웃 폭이 동시 접속자 비율만큼 줄어듭니다. 채널 인원이 5만 명 이어도 그 순간 접속 중인 사람만 실시간 경로를 탑니다.

흔한 실수: 전원에게 실시간으로 밀어주려는 것. 오프라인 사용자의 받은함에 지금 쓰는 것과 나중에 조회하게 하는 것은 사용자 경험이 같고 비용이 다릅니다. 같은 결과를 더 싸게 얻는 길이 있으면 그쪽입니다.

Q.두 방식을 섞으면 사용자 화면에서 순서가 어긋나지 않나요

어긋날 수 있습니다. 그래서 정렬 기준을 메시지 자체가 들고 있어야 합니다.

받은함에서 온 메시지와 채널에서 모아온 메시지를 합쳐 보여주므로, 두 출처의 순서를 맞출 근거가 필요합니다. 도착 시각으로 맞추면 경로에 따라 달라져 어긋납니다.

서버가 메시지를 받을 때 채널별로 증가하는 번호를 붙인다
어느 경로로 왔든 그 번호로 정렬한다

번호가 채널 단위라 전역 순서는 보장되지 않지만, 사용자는 한 채널을 보고 있으므로 그 안에서만 맞으면 됩니다. 요구사항이 채널 내 순서만 보장한다고 정한 이유가 이것입니다.

흔한 실수: 클라이언트 도착 순서로 정렬하는 것. 두 경로의 지연이 다르므로 같은 채널 메시지가 뒤바뀌어 보입니다. 정렬 기준은 서버가 붙인 값이어야 합니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

실시간 채팅 시스템 설계 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.