pile·
아키텍처·카카오 엔터테인먼트 FE카카오 엔터테인먼트 FE·

라이브채팅 플랫폼 구현기 1탄 : 개발 언어 및 기반기술 조사

카카오엔터테인먼트가 멜론뮤직어워드(MMA) 2022 생중계를 위해 실시간 채팅 플랫폼을 자체 구축하며 개발 언어·프레임워크·메시지 브로커·금칙어 처리 기술을 어떻게 골랐는지 정리한 1편이다. 동시 접속 20만 명, 메시지 왕복 1초 이내를 개발자 3명이 5개월 안에 만족해야 했고, Kotlin + Spring Boot + WebSocket + Kafka + MongoDB 조합에 아호-코라식 금칙어 필터를 얹는 것으로 결론 냈다.

핵심 포인트
  • 사전 요구사항이 동시 접속자 20만, 메시지 전송/수신 최대 1,000ms, 금칙어 실시간 반영, 도배 탐지, 메시지 영구 저장, 지표 모니터링이었다.
  • 언어는 Java·Kotlin·Go·Erlang 중 Kotlin. Go와 Erlang은 성능 우위에도 팀 경험 부재로 제외했고, Coroutine 기반 비동기 구현이 Java 대신 Kotlin을 고른 결정타였다.
  • 메시지 전달은 YouTube Live 가 쓰는 HTTP Polling 과 WebSocket 을 견줘, 라이브 영상과 대화가 수초 어긋나는 문제를 피하려 WebSocket 을 택했다.
  • 브로커는 Redis Pub/Sub 탈락 후 Cloud Pub/Sub 과 Kafka 를 실측 비교해 Kafka. Kafka Streams DSL 의 간결함과 국내 자료 양이 Dataflow/Beam 을 이겼다.
  • 금칙어 50만 개를 메시지마다 실시간 검사하려고 해시 테이블·트라이를 비교했고, 아호-코라식으로 탐색 복잡도를 O(nm) 에서 O(n+m) 로 낮췄다.
상세 정리
  • 배경: MMA 생중계에 쓰던 댓글 시스템이 참여 경험을 불편하게 만들어 실시간 채팅 플랫폼이 필요해졌다. 자체 구축·카카오톡 소스 활용·외부 플랫폼 3안 중 내부 서비스 요구사항 수용을 위해 자체 구축으로 정했다.
  • 언어 후보 검토: Java 는 익숙함 말고는 장점이 약했다(NullPointerException 처리, 행사 코드, String Template·Null Safety 지원 지연). Go 와 Erlang 은 BMT 성능은 좋았지만 인원과 기간을 감안하면 learning curve 가 리스크였다.
  • 프레임워크: Kotlin 과 궁합이 좋은 Ktor 를 검토했으나 프로덕션 적용 사례와 트러블슈팅 문서가 부족해 Spring Boot 를 유지했다. 가벼운 프로젝트라면 다시 보겠다는 단서를 남겼다.
  • HTTP Polling 의 한계: 커넥션을 유지하지 않아 서버 리소스를 아끼고 API 서버만으로 구현되지만, 폴링 주기만큼 전달이 늦고 클라이언트마다 보고 있는 메시지가 달라진다.
  • 영구 저장소: 메시지 타입(유저·아티스트·공지)마다 구조가 다르고 기능 메시지 추가가 잦을 것으로 봤으며 수정·삭제가 사실상 없어, RDBMS 대신 schemaless 한 MongoDB 를 골랐다.
  • Redis Pub/Sub 탈락 이유: 발행 시 클러스터의 모든 노드로 퍼져 노드를 늘릴수록 느려지고, 채널 구독자 수에 선형 비례해 발행이 지연된다. Sharded Pub/Sub 은 Redis 7.x 기능인데 당시 Cloud Memorystore 는 6.x 만 지원했다.
  • 지연 실측: p90 이 Cloud Pub/Sub 45~180ms 대 Kafka 30~65ms, p99 는 500~1,000ms 대 60~100ms 로 Kafka 가 앞섰다. 대신 글로벌 전파와 처리량은 Cloud Pub/Sub 이 유리했다.
  • Kafka 최종 선택: 사용자가 국내 한정이라 글로벌 대응 이점이 상쇄됐고, 처리량은 파티션을 나누는 설계로 풀었으며, 메시지 큐 등 다른 브로커 성격이 필요 없었다.
  • 스트림 프로세서 분리: 금칙어 감지, 스팸 차단, 방 인원 분할, 지표 수집, 최근 메시지 캐싱, 영구 저장을 각각 별도 프로세서로 떼어 WebSocket 서버 워크로드와 독립적으로 수직·수평 확장하게 했다.
  • Beam/Dataflow 평가: 매니지드 워크로드와 배치 겸용은 매력적이었지만, Kotlin 으로 작성하니 Java 답지 않은 인터페이스 탓에 가독성이 크게 떨어지고 저수준 행사 코드가 많았다. Scala 래퍼인 Spotify 의 Scio 를 대안으로 언급한다.
  • Kafka Streams 선택: 저수준 Processor API 위에 Fluent 인터페이스의 DSL 이 있어 Kotlin 으로 간결하게 쓸 수 있었고 국내 자료도 많았다. 매니지드 서비스가 없어 워크로드는 k8s 위에 직접 구축했다.
  • 금칙어 자료구조: 해시 테이블은 항상 해시 값을 계산해야 하지만, 트라이는 사전에 없는 단어면 즉시 종료된다. 채팅 메시지 대부분에 금칙어가 없다는 특성상 트라이가 유리하다고 판단했다.
  • 아호-코라식 실측: 위키백과 약 114만 단어 사전으로 테스트해 초기 로드 4,955ms, 첫 파싱 5ms, 이후 파싱 0~2ms 를 얻었고 메시지당 필터링에 충분하다고 보고 채택했다.
  • 2편 예고: 아키텍처 설계와 성능 테스트는 다음 글에서 다룬다.
왜 읽나대규모 실시간 채팅을 처음부터 설계하는 백엔드 개발자에게 언어·브로커·저장소 선택의 비교 근거와 실측 수치를 그대로 준다.
카카오 엔터테인먼트 FE
카카오 엔터테인먼트 FE 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 아키텍처·aws-architectureAWS Architecture·

    일관성이 새로운 지연이다: 데이터 레이어에서의 AI

    AI 에이전트가 데이터베이스 레이어에서 겪는 데이터 정합성 문제를 다룬다. 비동기 복제 지연(replication lag)으로 stale 데이터를 읽은 에이전트가 잘못된 판단을 내리는 "조용한 독"을 AWS 서비스 기반 세 가지 아키텍처 패턴으로 해결하는 방법을 제시한다. "빠르지만 틀린 답이 약간 느리지만 맞는 답보다 비싸다"는 주장 아래, 데이터베이스 아키텍처를 AI 신뢰성의 기반으로 재정의한다.

    요약 이어보기
    #ai-agent#data-consistency#aurora+2
  2. 아키텍처·flexflex·

    사람도 에이전트도, 덜 읽을수록 더 잘 고칩니다

    flex 팀이 코드베이스의 모듈 경계 설계가 AI 에이전트의 코드 탐색 효율에 미치는 영향을 실측한 글이다. 193개 에이전트 작업 로그를 분석하고, 잘 나뉜 모듈과 뭉친 모듈을 비교한 결과 — 도메인이 물리 모듈로 분리된 저장소에서 에이전트가 불필요한 파일을 덜 읽고 목표 코드에 더 집중했다. 사람도 에이전트도 컨텍스트 한도가 있어, 무관 코드를 덜 읽을수록 수리 성공률이 높다는 것이 핵심 결론이다.

    요약 이어보기
    #llm-agent#context-window#modular-architecture+1
  3. 아키텍처·aws-architectureAWS Architecture·

    데이터 거주 요건을 충족하는 재해 복구 전략

    데이터 거주(data residency) 규정을 지키면서 재해 복구(DR)를 구현해야 하는 조직을 위해 AWS가 세 가지 전략 프레임워크를 제시한다. 금융, 의료, 공공 부문처럼 지리적 데이터 보관 의무가 있는 환경에서도 복구 목표(RTO/RPO)를 달성할 수 있는 아키텍처 선택지를 비교한다.

    요약 이어보기
    #multi-cloud#compliance#disaster-recovery+2