pile·
아키텍처·당근당근 테크블로그·

천만 MAU를 지탱하는 커뮤니티 시스템 아키텍처

당근 커뮤니티실이 2021년 약 100 RPS에서 현재 약 20,000 RPS를 처리하는 규모로 성장한 과정과, 이를 가능하게 한 "여러 웹앱 + 하나의 서버앱" 모듈형 모놀리스 아키텍처를 다룬다. 동네생활, 모임, 카페, 아파트 서비스를 소규모 팀이 장기 운영 가능한 구조로 설계한 원칙과, 장애 경험에서 도출한 resilience 패턴까지 단계별로 정리했다.

핵심 포인트
  • 100 RPS → 4,000 RPS → 20,000 RPS 성장에도 모듈형 모놀리스를 유지한 이유는 한 코드베이스에서 도메인 변경 추적, 트랜잭션 조율, 소규모 팀의 지속 운영이 가능하기 때문이다.
  • 서버앱을 API(응답 시간), Worker(처리량·적체), Batch(스케줄 1회 실행), Console(운영자 도구) 4가지 실행 단위로 분리해 각 트래픽 특성에 맞게 운영한다.
  • OpenAPI 계약을 중앙 저장소에서 관리하고 Kotlin 서버 스텁과 TypeScript 클라이언트를 자동 생성해, CI에서 하위 호환성을 자동 검사한다.
  • 게시글 작성 시 본문·투표·해시태그는 동기 트랜잭션으로 처리하고, 검색 색인·임베딩·알림은 비동기 이벤트로 격리해 한 작업 실패가 다른 작업을 막지 않는다.
  • 장애 대응이 초기 DB CPU 100% → 커넥션 풀 소진/JVM 메모리 누수 → 시스템 간 상호작용 장애 순으로 복잡해졌고, 단계마다 회로 차단기·요청 취소·폴백·선제 스케일링을 추가했다.
상세 정리
  • 규모 변화: 2021년 가을 약 100 RPS로 시작, 당근모임 전국 오픈 시 약 4,000 RPS, 현재 약 20,000 RPS를 처리한다.
  • 아키텍처 선택 기준: 마이크로서비스를 지양한 게 아니라 "누가 이것을 관리하고 운용할 수 있는가"를 기준으로 모듈형 모놀리스를 선택했다.
  • 웹 계층 진화: CSR → SSR → Streaming SSR로 점진적으로 개선했다. Streaming SSR은 API 없이 뼈대를 먼저 송신하고 이후 콘텐츠를 스트리밍하며, 타임아웃 시 CSR로 자동 폴백한다.
  • 서버앱 4분류: API(사용자 요청, 응답 시간 중심), Worker(이벤트 기반 후속 작업, 처리량·적체 모니터링), Batch(스케줄 작업, 프로세스당 1회 실행 후 종료), Console(운영자 도구, 트래픽 분리) 로 실행 단위를 구분한다.
  • 데이터 계층: Amazon RDS(PostgreSQL)을 원본으로, Valkey(Redis 대체)·로컬 캐시 조합, RabbitMQ(내부 메시징), Kafka(전사 연계), OpenSearch(파생 조회 모델)를 사용한다.
  • 모듈화 원칙: "같은 이유로 바뀌는 코드를 묶고, 다른 이유로 바뀌는 코드를 나눈다." 도메인 규칙·데이터 접근·인프라를 별도 모듈로 분리하고 모듈 간 의존은 인터페이스만 허용한다.
  • OpenAPI 계약: 중앙 저장소에서 API 계약을 관리하고 Kotlin 서버 스텁과 TypeScript 클라이언트를 코드 생성한다. CI에서 하위 호환성을 자동 검사해 "명세와 구현이 어긋날 가능성을 줄인다".
  • 이벤트 격리: 게시글 작성 시 본문·투표·해시태그·장소·구독 상태는 동기 트랜잭션, 검색 색인·임베딩 생성·콘텐츠 검수·배지 발급·알림은 비동기 이벤트로 분리해 실패 격리를 달성한다.
  • 피드 조립 흐름: 후보 목록 구성 → 추천 엔진 정렬 → 노출 정책 적용 → 카드 조립 순으로 진행하며, 추천 실패 시 기본 순서, SSR 실패 시 CSR로 폴백한다.
  • 아키텍처 테스트: 모듈 간 의존 방향을 자동으로 검사하고 "기준선 기법(기존 위반 동결, 새 위반만 차단)"으로 레거시와 신규 코드를 구분해 관리한다.
  • 장애 단계별 진화: 초기에는 문제 쿼리로 DB CPU 100%, 확장 단계에서는 커넥션 풀 소진과 JVM 버전업 후 메모리 누수, 고도화 단계에서는 검색 부하·웹앱 재시도 증폭·미완료 요청 누적 같은 시스템 간 복합 장애로 진화했다.
  • Resilience 도입: 요청 취소(cancellation), 폴백, 회로 차단기(circuit breaker), 기능 제어, 선제 스케일링을 차례로 도입해 고도화 장애에 대응했다.
  • 컴포넌트 공통화 원칙: 위치 정보·투표·임베딩 등 공통 기능은 "두 번째 사용처가 생겼다는 이유만으로 곧바로 공통화하지 않는다"는 원칙 하에 신중하게 추출한다.
  • 향후 방향: 화면 단위 API에서 리소스 중심 API로 전환해 웹앱이 조립 책임을 가져가는 구조, AI 기반 콘텐츠 플랫폼 구축, 더 작은 단위 검증·빠른 배포·빠른 롤백 체계 3가지를 과제로 제시했다.
왜 읽나20,000 RPS 규모까지 모듈형 모놀리스를 소규모 팀으로 5년간 운영한 당근의 아키텍처 결정·장애 대응 경험을 단계별로 볼 수 있어, 서비스 성장에 따른 시스템 설계를 고민하는 백엔드·아키텍처 엔지니어에게 유용하다.
당근
당근 테크블로그 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 아키텍처·cloudflare-blogCloudflare Blog·

    Meerkat 소개: 글로벌 합의를 위한 실험

    Cloudflare Research가 전 세계 330개 이상의 데이터센터에서 컨트롤 플레인 상태를 관리하기 위한 분산 합의 서비스 Meerkat을 개발 중이다. 기존 Raft의 리더 의존성과 타임아웃 기반 리더 선출이 광역 네트워크(WAN)에서 야기하는 가용성 저하를 해결하기 위해 2023년 EPFL에서 발표한 QuePaxa 합의 알고리즘을 채택했다.

    #fault-tolerance#distributed-systems#raft+2
  2. 아키텍처·cloudflare-blogCloudflare Blog·

    Monetization Gateway 공개: x402로 Cloudflare 뒤 모든 리소스에 과금하기

    Cloudflare가 HTTP 402 상태 코드를 재활용한 오픈 결제 프로토콜 x402와 스테이블코인 정산을 결합한 Monetization Gateway를 발표했다. 웹페이지·데이터셋·API·MCP 도구 어디든 Cloudflare 뒤에 놓으면 사용량 기반 마이크로페이먼트를 붙일 수 있다. AI 에이전트가 광고를 안 보고 구독도 유지하지 않는 시대에, 개발자와 퍼블리셔가 콘텐츠·도구를 직접 과금할 수 있는 인프라를 엣지에서 제공하는 것이 핵심이다.

    #http-protocol#x402#micropayment+2
  3. 아키텍처·cloudflare-blogCloudflare Blog·

    Cloudflare Workflows에 사가 롤백을 구현한 방법

    Cloudflare Workflows 엔진에 사가(Saga) 패턴 롤백 기능을 추가한 과정을 다룬다. 다단계 워크플로우에서 중간 단계가 실패했을 때 이전 단계의 부작용을 되돌리는 보상 로직(compensating action)을 각 step에 선언적으로 정의할 수 있게 됐다. Workers RPC의 callable reference를 활용해 엔진 재시작 후에도 핸들러를 복구할 수 있는 내구적 설계를 택했다.

    #workflow-engine#cloudflare-workers#saga-pattern+2