분산 시스템

34 개의 포스트

woowahan원문

기획부터 개발까지 전부 직접 했습니다 – 우테코 7기 크루 서비스 론칭! | 우아한형제들 기술블로그 (새 탭에서 열림)

우아한테크코스 7기 크루들이 기획부터 디자인, 개발 및 운영까지 전 과정을 직접 수행하며 실제 사용자를 위한 서비스를 성공적으로 론칭했습니다. 이번 프로젝트는 단순한 기술 습득을 넘어 개발자가 왜 기획과 디자인에 참여해야 하는지, 그리고 사용자 피드백이 아키텍처와 도메인 설계에 어떤 영향을 미치는지 몸소 체험하는 과정이었습니다. 결과적으로 크루들은 2주 단위의 스프린트와 실시간 모니터링, 배포 환경 구축 등 실무에 근접한 경험을 통해 현장 중심의 문제 해결 역량을 갖춘 개발자로 성장했습니다. **개발자 중심의 기획과 협업 문화의 정착** - 우아한테크코스는 레벨 3, 4 과정을 통해 개발자가 직접 기획과 디자인을 포함한 서비스의 전주기를 책임지는 팀 프로젝트를 진행합니다. - 기술적인 구현뿐만 아니라 말하기, 글쓰기 교육을 병행하여 팀원 간의 의견 조율 및 설득 등 소프트 스킬의 중요성을 강조합니다. - 아키텍처 설계와 같은 기술적 결정이 팀의 목표와 사용자의 가치에 어떻게 부합해야 하는지 고민하며 개발자의 역할을 확장했습니다. **픽잇(Pickeat): 취향과 제약을 반영한 협업형 식사 선택 서비스** - "아무거나"라는 답변 뒤에 숨겨진 기피 음식과 다이어트 등의 제약 사항을 실시간 투표로 해결하여 최적의 식당을 추천합니다. - 위치 정보 기반의 식당 자동 조회 및 템플릿 기능을 도입하여 반복되는 회식이나 미팅 시 의사결정 속도를 높였습니다. - 데모데이와 홍보를 통해 받은 피드백을 바탕으로 UI와 백엔드 도메인 구조를 유연하게 재설계하며 사용자 중심의 반복적인 개선 과정을 거쳤습니다. **보따리(Bottari): 실시간 동기화 기반의 상황별 체크리스트** - 출근, 여행, 이사 등 다양한 상황에 맞춘 템플릿 기반 리스트 생성과 팀 단위의 실시간 협업 체크 기능을 제공합니다. - 단순한 기능 구현을 넘어 사용자가 물건을 잊지 않게 돕는 알림 타이밍과 체크 상태 동기화 등 사용자 경험(UX)의 세부 요소를 정밀하게 다듬었습니다. - '기술은 문제를 해결하는 도구'라는 철학 아래 사용자가 안심하고 기억을 맡길 수 있는 흐름을 구현하는 데 집중했습니다. **커피빵(Coffee Bread): 웹소켓 기반의 실시간 내기 미니게임** - 가위바위보보다 더 큰 재미와 긴장감을 주기 위해 실시간 미니게임과 가중치 적용 룰렛 시스템을 도입한 서비스입니다. - 웹소켓(WebSocket) 기술과 분산 환경이라는 기술적 난제를 극복하며 실시간 상호작용이 끊김 없이 이루어지도록 개발했습니다. - 게임의 공정성과 재미를 위해 룰렛 알고리즘을 수차례 수정하고, 실제 사용자들의 피드백을 반영해 밸런스를 최적화했습니다. 이 서비스들은 단순한 교육용 프로젝트를 넘어 실제 배포와 운영을 거치며 기술적 완성도를 높였습니다. 개발자가 기획 단계부터 깊이 관여할 때 사용자에게 더욱 가치 있는 프로덕트가 탄생한다는 점을 시사하며, 실무적인 문제 해결 역량을 키우고 싶은 주니어 개발자들에게 좋은 협업의 귀감이 됩니다.

dropbox원문

미래를 구축하다: Dropbox (새 탭에서 열림)

드롭박스는 2025년 여름 인턴십 프로그램을 통해 43명의 인턴과 함께 AI 기반 통합 검색 도구인 '드롭박스 대시(Dropbox Dash)'를 비롯한 핵심 서비스의 성능과 인프라를 혁신했습니다. 엔지니어링 중심의 이번 기수들은 12주간 멘토링과 실무 프로젝트에 참여하며, 특히 AI 모델의 신뢰성 강화와 다국어 검색 지원 등 드롭박스의 차세대 기술 역량을 끌어올리는 데 기여했습니다. 결과적으로 이번 프로그램은 인턴들에게는 실질적인 기술적 성장을, 기업에는 레거시 시스템 현대화와 운영 효율화라는 실용적 성과를 동시에 안겨주었습니다. ### 드롭박스 대시와 AI 기술 고도화 * **다국어 검색 지원 확대**: 통합 검색 플랫폼(USP)에 언어 감지 파이프라인을 통합하여 리플레이(Replay) 등 드롭박스 제품 전반에 걸쳐 20개 이상의 언어를 지원하는 네이티브 검색 환경을 구축했습니다. * **ML 모델 모니터링 시스템(AI Sentinel)**: 머신러닝 엔지니어가 수동으로 확인하던 모델 배포 상태를 실시간으로 가시화하는 시스템을 개발하여 배포의 신뢰성을 높이고 반복 주기를 단축했습니다. * **커넥터 플랫폼 최적화**: 대시의 데이터 저장소에서 최신 정보에 직접 접근할 수 있는 도구를 빌드하여, 외부 시스템의 데이터를 매번 다시 다운로드하지 않고도 최신 메타데이터 기반으로 모델을 학습시킬 수 있게 했습니다. * **문서 미리보기 및 웹 자동화**: 대시 내에서 문서를 즉시 미리 볼 수 있는 UI와 대화형 AI 기능을 통합하고, 폼 채우기나 교정 등의 반복 업무를 자동화하는 모듈형 AI 에이전트를 개발했습니다. ### 인프라 성능 및 데이터 효율화 * **스토리지 코어(Magic Pocket) 지연 시간 단축**: 디스크 재시작 시 발생하는 쓰기 지연 문제를 해결하기 위해 스토리지 상태를 추적하는 캐시와 성능이 저하된 볼륨을 제외하는 필터링 옵션을 추가하여 검색 결과의 정확도를 높였습니다. * **파일 시스템 메타데이터 리팩토링**: 레거시 파일 이력 추적 시스템을 현대화하여 메타데이터 인프라를 단순화하고 운영 비용을 대폭 절감했습니다. * **대규모 데이터 분석 최적화**: Databricks 쿼리와 ETL 파이프라인의 고비용 패턴을 식별하는 추천 시스템을 구축하고, 500TB 규모의 모바일 이벤트 로그를 최신 데이터 레이아웃 기술인 '리퀴드 클러스터링(Liquid Clustering)'으로 마이그레이션했습니다. ### 개발자 경험 및 운영 도구 개선 * **AI 기반 코드 마이그레이션**: 특정 폴더나 유형에 대해 코드 마이그레이션을 자동화하고 결과가 성공적일 경우 자동으로 Pull Request를 생성하는 도구를 제작하여 대규모 마이그레이션 작업을 효율화했습니다. * **지능형 지표 감지 시스템(Vortex2)**: 고정된 임계값 대신 데이터의 계절성과 변화 패턴을 학습하는 적응형 이상 탐지 기법을 도입하여 알림 피로도를 줄이고 장애 대응 속도를 개선했습니다. 이러한 인턴들의 성과는 드롭박스가 단순한 파일 저장소를 넘어 AI 중심의 워크플로우 플랫폼으로 진화하고 있음을 보여줍니다. 특히 대규모 마이그레이션 자동화나 인프라 수준의 지연 시간 최적화와 같은 실무적인 기술 해결책은 엔지니어링 팀의 생산성을 직접적으로 높이는 실용적인 결론을 도출했습니다.

naver원문

네이버 TV (새 탭에서 열림)

Apache Kafka의 차세대 소비자 그룹 프로토콜(Consumer Group Protocol v2)은 기존 v1 프로토콜이 가진 리밸런싱 성능의 한계와 복잡성을 근본적으로 해결하기 위해 도입되었습니다. 새로운 프로토콜은 리밸런싱 로직의 주체를 클라이언트에서 서버(Broker)로 옮겨 전체적인 시스템 안정성을 높였으며, 대규모 클러스터 운영 시 발생하던 중단 시간을 획기적으로 단축했습니다. 이 글은 네이버의 실무 경험을 바탕으로 v2의 주요 특징과 성능 개선 사항, 그리고 안정적인 마이그레이션 전략을 제시합니다. **기존 Consumer Group Protocol v1의 문제점** * **Stop-the-world 리밸런싱:** 리밸런싱이 발생하면 모든 컨슈머가 데이터 처리를 멈추고 파티션을 재할당받아야 하므로 일시적인 처리 지연이 불가피했습니다. * **클라이언트 측의 과도한 부담:** 리밸런싱 로직이 컨슈머 클라이언트에 포함되어 있어, 클라이언트 수가 늘어날수록 통신량과 계산 복잡도가 급증하는 구조적 한계가 있었습니다. * **디버깅의 어려움:** 리밸런싱 과정이 복잡하고 클라이언트별로 상태가 달라 문제 발생 시 원인 파악과 모니터링이 까다로웠습니다. **Consumer Group Protocol v2의 핵심 특징과 장점** * **서버 중심 리밸런싱:** 그룹 코디네이터(Broker)가 파티션 할당 로직을 직접 수행하여 클라이언트의 계산 부하를 줄이고 전체 프로세스를 단순화했습니다. * **점진적 협력 리밸런싱:** 모든 컨슈머를 멈추지 않고, 변경이 필요한 파티션만 점진적으로 재할당하여 서비스 가용성을 극대화했습니다. * **하트비트 메커니즘 개선:** 하트비트 응답 내에 리밸런싱 명령을 포함시켜 별도의 JoinGroup/SyncGroup 절차 없이도 빠른 상태 동기화가 가능해졌습니다. **성능 향상 및 운영 효율화** * **확장성 강화:** 수천 개의 파티션과 수백 명의 컨슈머가 참여하는 대규모 그룹에서도 리밸런싱 시간을 일관되게 유지합니다. * **불필요한 리밸런싱 감소:** 컨슈머의 일시적인 네트워크 순단이나 짧은 지연에 대해 보다 유연하게 대응하여 불필요한 그룹 재편성을 방지합니다. * **전용 툴 지원:** 새로운 프로토콜에 최적화된 모니터링 툴과 API를 통해 소비자 그룹의 상태를 더 정밀하게 확인하고 관리할 수 있습니다. **성공적인 마이그레이션 및 설정 가이드** * **호환성 확인:** Kafka 브로커와 클라이언트 버전을 확인하여 v2 프로토콜(KIP-848) 지원 여부를 먼저 점검해야 합니다. * **단계적 도입:** `group.protocol` 설정을 통해 기존 v1과 새로운 v2를 선택적으로 적용할 수 있으며, 개발 환경에서 충분한 검증 후 운영 환경에 반영하는 것이 권장됩니다. * **클라이언트 업데이트:** v2의 이점을 온전히 누리기 위해서는 브로커뿐만 아니라 컨슈머 클라이언트 라이브러리 역시 최신 버전으로 업그레이드해야 합니다. 대규모 트래픽을 처리하며 리밸런싱으로 인한 지연 시간에 민감한 서비스라면 Kafka 3.x 후반대 버전부터 도입된 Consumer Group Protocol v2로의 전환을 적극적으로 검토해야 합니다. 특히 컨슈머 그룹의 규모가 크거나 빈번한 배포가 일어나는 환경일수록 v2 도입을 통한 운영 안정성 향상 효과가 더욱 뚜렷하게 나타날 것입니다.

netflix원문

넷플릭스가 실시간 분산 그래프를 구축한 방법과 이유: 1부 — 인터넷 규모의 데이터 스트림 수집 및 처리 (새 탭에서 열림)

넷플릭스는 비디오 스트리밍을 넘어 광고, 라이브 이벤트, 모바일 게임으로 비즈니스를 확장하면서 발생하는 데이터 파편화 문제를 해결하기 위해 '실시간 분산 그래프(RDG)'를 구축했습니다. 기존 마이크로서비스 아키텍처에서 발생하는 데이터 고립을 극복하고, 다양한 서비스 접점에서 발생하는 사용자 활동을 실시간으로 연결하여 개인화된 경험을 제공하는 것이 핵심 목표입니다. 이를 통해 복잡한 데이터 조인 없이도 수억 개의 노드와 엣지 사이의 관계를 즉각적으로 파악할 수 있는 기술적 기반을 마련했습니다. **데이터 파편화와 비즈니스 환경의 변화** * 스트리밍, 게임, 라이브 스포츠 등 서비스 영역이 넓어지면서 사용자가 여러 기기와 도메인에서 수행하는 활동을 하나의 맥락으로 통합해야 할 필요성이 커짐. * 넷플릭스의 강점인 마이크로서비스 아키텍처(MSA)는 서비스 독립성에는 유리하지만, 데이터가 각 서비스에 고립(Silo)되어 있어 통합적인 데이터 과학 및 엔지니어링 작업에 큰 비용이 발생함. * 기존 데이터 웨어하우스 방식은 데이터가 서로 다른 테이블에 저장되고 처리 주기가 제각각이라, 실시간으로 연관 관계를 분석하는 데 한계가 있음. **그래프 모델 도입의 기술적 이점** * **관계 중심 쿼리:** 테이블 기반 모델에서 필요한 비용 중심적인 조인(Join)이나 수동적인 비정규화 없이도 노드와 엣지 사이를 빠르게 탐색(Hop)할 수 있음. * **유연한 확장성:** 새로운 엔티티나 관계 유형이 추가될 때 대대적인 스키마 변경이나 아키텍처 재설계 없이도 신속하게 데이터 모델을 확장할 수 있음. * **패턴 및 이상 탐지:** 숨겨진 관계, 순환(Cycle) 구조, 그룹화 등을 식별하는 작업을 기존의 포인트 조회 방식보다 훨씬 효율적으로 수행함. **실시간 데이터 수집 및 처리 파이프라인 (RDG 레이어 1)** * 전체 시스템은 수집 및 처리, 저장, 서빙의 3개 레이어로 구성되며, 첫 번째 단계인 수집 레이어는 이기종 업스트림 소스로부터 이벤트를 받아 그래프 데이터를 생성함. * DB의 변경 사항을 추적하는 CDC(Change Data Capture)와 애플리케이션의 실시간 로그 이벤트를 주요 소스로 활용하여 데이터 소외 현상을 방지함. * 수집된 원시 데이터는 스트리밍 처리 엔진을 통해 그래프 스키마에 맞는 노드와 엣지 형태로 변환되며, 대규모 트래픽 환경에서도 실시간성을 유지하도록 설계됨. 복잡하게 얽힌 현대의 서비스 환경에서 데이터 간의 관계를 실시간으로 규명하는 것은 사용자 경험 고도화의 핵심입니다. 넷플릭스의 RDG 사례처럼 파편화된 마이크로서비스의 데이터를 그래프 형태로 통합하는 접근 방식은, 실시간 통찰력이 필요한 대규모 분산 시스템 설계 시 강력한 해결책이 될 수 있습니다.

netflix원문

스트림 뒤편: 라이브 이벤트를 위한 실시간 추천 3부 | 넷플릭스 기술 블로그 | 넷플릭스 테크블로그 (새 탭에서 열림)

넷플릭스는 수천만 명의 시청자가 동시에 접속하는 라이브 이벤트 상황에서 시스템 과부하를 방지하면서도 실시간 개인화 추천을 제공하기 위해 '프리페칭(Prefetching)'과 '실시간 브로드캐스팅'이라는 2단계 전략을 도입했습니다. 이 시스템은 이벤트 시작 전 미리 데이터를 기기에 저장해 두었다가, 실제 시작 시점에는 최소한의 신호만 보내 로컬에서 추천 정보를 활성화함으로써 '천둥 번개 효과(Thundering Herd)' 문제를 효과적으로 해결합니다. 이를 통해 넷플릭스는 클라우드 자원을 무리하게 확장하지 않고도 전 세계 수억 대의 기기에 지연 없는 실시간 스트리밍 경험을 제공할 수 있게 되었습니다. **라이브 이벤트와 시동 시간의 제약** * VOD와 달리 라이브 이벤트는 모든 시청자가 특정 시점에 동시에 접속하므로, 짧은 시간 내에 수억 개의 기기에 업데이트를 전달해야 하는 기술적 난관이 존재합니다. * 단순히 서버를 증설하는 선형적 확장은 비효율적이며, 다른 핵심 서비스의 자원을 고갈시킬 위험이 있습니다. * 성공적인 실시간 추천을 위해서는 업데이트 소요 시간(Time), 서비스 처리 용량(Request Throughput), 요청의 다양성(Compute Cardinality)이라는 세 가지 제약 조건을 동시에 최적화해야 합니다. **프리페칭을 통한 트래픽 분산** * 이벤트 시작 전 사용자가 평소처럼 앱을 탐색하는 동안, 라이브 이벤트와 관련된 메타데이터, 아트워크, 개인화된 추천 리스트를 미리 기기 캐시에 저장합니다. * 이를 통해 서버 요청을 시간에 따라 자연스럽게 분산시켜, 이벤트 직전 발생하는 트래픽 스파이크를 제거하고 시스템 안정성을 확보합니다. * 서버 측에서 미리 계산된 '구체화된 추천(Materialized Recommendations)'을 제공함으로써 기기별 요청의 복잡도를 낮춥니다. **저카디널리티 실시간 브로드캐스팅** * 이벤트가 실제로 시작되거나 일정이 변경될 때, 넷플릭스의 푸시 서비스(Zuul Push)를 통해 연결된 모든 기기에 '저카디널리티(Low-cardinality)' 메시지를 전송합니다. * 이 메시지는 복잡한 데이터를 담지 않고 단순히 미리 캐싱된 데이터를 화면에 표시하라는 트리거 역할만 수행하여 네트워크 부하를 최소화합니다. * '최소 한 번(At-least-once)' 전달 방식을 채택하여 네트워크 상태가 불안정한 기기도 다시 온라인 상태가 되면 누락된 업데이트를 즉시 따라잡을 수 있도록 설계되었습니다. **데이터 기반의 동적 적응** * 라이브 이벤트의 특성상 경기 시간이 지연되거나 일정이 변동될 수 있는데, 브로드캐스팅 시스템은 이러한 실시간 제작 상황에 맞춰 전송 타이밍을 동적으로 조절합니다. * 수천만 대의 기기가 동시에 서버에 데이터를 재요청하는 대신 로컬 데이터를 활용하게 함으로써, 전 세계 모든 사용자가 동일한 순간에 일관된 추천 UI를 볼 수 있게 합니다. 라이브 이벤트와 같은 초고부하 상황에서는 무조건적인 서버 증설보다는 클라이언트의 로컬 자원을 활용하고 서버 부하를 시간적으로 분산하는 아키텍처가 필수적입니다. 실시간성이 중요한 서비스라면 모든 데이터를 실시간으로 전송하기보다, 정적인 데이터는 미리 배치하고 상태 변화를 알리는 최소한의 신호만 실시간으로 처리하는 하이브리드 접근 방식을 권장합니다.

airbnb원문

에어비앤비의 키-값 저장소에서 정적 속도 제한에서 적응형 트래픽 관리로 (새 탭에서 열림)

에어비앤비는 분산 키-밸류 저장소인 'Mussel'의 트래픽 관리 방식을 단순 요청 횟수 제한(QPS)에서 자원 기반의 적응형 제어 시스템으로 진화시켰습니다. 이 시스템은 요청의 실제 비용을 계산하는 자원 인식형 속도 제한(RARC)과 우선순위 기반의 부하 차단(Load Shedding) 계층을 도입하여 시스템의 유용 작업량(Goodput)을 극대화합니다. 결과적으로 Mussel은 예기치 못한 트래픽 급증이나 DDoS 공격 상황에서도 핵심 서비스의 성능을 안정적으로 유지할 수 있게 되었습니다. ### 정적 QPS 제한의 한계와 자원 인식형 제어(RARC)의 도입 기존의 단순 QPS 제한 방식은 요청의 복잡도와 상관없이 동일한 할당량을 차감했기에 효율적인 자원 관리가 불가능했습니다. * **비용 가변성 해결**: 단일 행 조회와 수만 행의 스캔 작업을 동일하게 취급하던 문제를 해결하기 위해, 행 수, 바이트 크기, 대기 시간(latency)을 결합한 '요청 단위(RU, Request Unit)' 개념을 도입했습니다. * **RU 계산 모델**: 읽기 비용은 $1 + w_r \times \text{읽은 바이트} + w_l \times \text{대기 시간}$과 같은 선형 모델을 통해 산출되며, 이는 하드웨어 리소스(CPU, I/O)에 가해지는 실제 부하를 더 정확하게 반영합니다. * **토큰 버킷 알고리즘**: 각 디스패처(Dispatcher)는 짧은 에포크(Epoch)마다 할당된 RU를 로컬 토큰 버킷에 채우고, 요청마다 실시간으로 계산된 비용을 차감하여 할당량 초과 시 즉각적으로 요청을 거부합니다. ### 지연 시간 비율 기반의 적응형 부하 차단 트래픽이 급격히 변하거나 특정 샤드에 병목이 발생할 때, 시스템 전체의 붕괴를 막기 위해 실시간 신호를 기반으로 한 부하 차단 메커니즘을 운용합니다. * **지연 시간 비율(Latency Ratio) 활용**: '장기 p95 지연 시간'을 '단기 p95 지연 시간'으로 나눈 비율을 시스템 스트레스 지표로 사용합니다. 이 비율이 설정값(예: 0.3) 이하로 떨어지면 시스템 부하가 급증한 것으로 판단합니다. * **임계치 기반의 단계적 대응**: 시스템 스트레스가 감지되면 낮은 우선순위의 클라이언트 그룹부터 RU 비용을 가중해 부과함으로써 자연스럽게 트래픽 백프레셔(Backpressure)를 유도합니다. * **P² 알고리즘 적용**: 고정된 메모리 내에서 대기 시간의 백분위수(Percentile)를 추정하는 P² 알고리즘을 사용하여, 별도의 샘플 저장소나 노드 간 통신 없이도 개별 디스패처가 신속하게 의사결정을 내릴 수 있습니다. ### 데이터 접근 패턴 최적화 및 안정성 확보 단순히 요청을 차단하는 것을 넘어, 데이터 접근의 불균형으로 인한 병목 현상을 해결하는 메커니즘을 포함합니다. * **핫키(Hot-key) 탐지 및 완화**: 특정 키에 대한 요청이 집중되는 패턴을 실시간으로 감지하여, 백엔드 저장소에 도달하기 전 캐싱하거나 중복 요청을 하나로 합치는(Coalescing) 방식으로 저장소 계층을 보호합니다. * **트래픽 분리 및 고립**: 특정 클라이언트의 데이터 패턴으로 인해 발생한 병목이 전체 클러스터로 전이되지 않도록 격리 수준을 높여 다중 사용자(Multi-tenant) 환경의 안정성을 강화했습니다. 멀티 테넌트 환경의 대규모 시스템을 운영한다면 단순한 횟수 기반의 제한보다는 자원 소비량을 기반으로 한 RU 모델과 시스템 상태에 반응하는 적응형 부하 차단 전략을 도입하는 것이 서비스 가용성 확보에 훨씬 유리합니다.

netflix원문

100배 빠르게: 넷플릭스 마에스트로의 워크플로 엔진을 어떻게 강화했는가 (새 탭에서 열림)

넷플릭스는 대규모 데이터 및 머신러닝 워크플로우를 관리하는 오케스트레이터인 'Maestro'의 엔진을 전면 개편하여 성능을 100배 이상 향상시켰습니다. 기존 수 초 단위에 달하던 실행 오버헤드를 밀리초(milliseconds) 단위로 단축함으로써, 광고나 라이브 스트리밍과 같이 저지연 및 고빈도 스케줄링이 필요한 신규 비즈니스 요구사항을 충족하게 되었습니다. 이번 업데이트를 통해 Maestro는 확장성뿐만 아니라 극도로 빠른 실행 속도까지 갖추게 되어 개발자들의 작업 효율을 획기적으로 개선했습니다. **기존 아키텍처의 한계와 병목 현상** * **3계층 구조의 복잡성:** Maestro는 API/런타임, 엔진, 내부 플로우 엔진의 3단계로 구성되었으나, 각 계층 간의 데이터 전달과 상태 동기화 과정에서 상당한 시간이 소요되었습니다. * **폴링(Polling) 방식의 지연:** 기존의 내부 플로우 엔진은 일정 간격으로 태스크를 확인하는 폴링 방식으로 동작하여, 단계별 상태 전이 시마다 초 단위의 불필요한 대기 시간이 발생했습니다. * **분산 큐 및 데이터베이스 부하:** 분산 작업 큐(Dyno-queues)와 데이터베이스 액세스 패턴에서 발생하는 오버헤드로 인해 워크플로우가 복잡해질수록 전체 실행 속도가 저하되는 문제가 있었습니다. * **경합 조건 발생:** 강력한 일관성 보장이 부족하여 특정 단계가 두 개의 워커에서 동시에 실행되는 등의 레이스 컨디션(Race condition) 문제가 간혹 발생했습니다. **100배 빠른 엔진을 위한 설계 최적화** * **이벤트 기반 리액티브 모델:** 폴링 방식을 폐기하고 이벤트 기반 아키텍처를 도입하여, 태스크 완료 즉시 다음 단계가 실행되도록 지연 시간을 최소화했습니다. * **상태 머신 직접 관리:** 워크플로우 그래프를 내부 플로우 태스크로 변환하던 중간 레이어를 제거하고, 엔진이 직접 워크플로우와 단계별 상태 머신을 제어하도록 단순화했습니다. * **데이터 액세스 최적화:** 데이터베이스 쓰기 횟수를 줄이고 효율적인 캐싱 및 분산 잠금(Distributed Locking) 메커니즘을 적용하여 성능과 안정성을 동시에 확보했습니다. * **추상화 계층 정합성:** Maestro 엔진이 상태 전이와 생명주기를 전담하게 함으로써, 하부 플로우 엔진에 대한 의존성을 없애고 엔진의 실행 효율을 극대화했습니다. **성능 향상 결과 및 활용 사례** * **실행 속도 극대화:** 워크플로우 엔진의 내부 오버헤드가 수 초에서 밀리초 단위로 줄어들며 전체적인 응답 속도가 100배 이상 개선되었습니다. * **신규 비즈니스 지원:** 1시간 미만의 짧은 주기로 실행되는 스케줄링이나 광고(Ads), 게임 등 저지연 워크플로우가 필수적인 도메인에 적용 가능해졌습니다. * **개발 생산성 제고:** 반복적인 개발 및 테스트 사이클에서 발생하는 대기 시간이 사라져 엔지니어들의 반복 작업 효율이 크게 향상되었습니다. 대규모 확장성과 초고성능을 동시에 요구하는 환경이라면, 넷플릭스에서 검증되고 오픈 소스로 공개된 최신 버전의 Maestro 도입을 적극적으로 검토해 볼 가치가 있습니다. 특히 기존 워크플로우 엔진의 지연 시간으로 인해 실시간 처리에 어려움을 겪고 있는 조직에 강력한 해결책이 될 수 있습니다.

netflix원문

넷플릭스에서 Write-Ahead (새 탭에서 열림)

넷플릭스는 대규모 데이터 환경에서 발생하는 데이터 손실, 시스템 엔트로피, 복제 및 재시도 메커니즘의 한계를 극복하기 위해 분산 **Write-Ahead Log(WAL)** 추상화 레이어를 구축했습니다. 이 시스템은 데이터 변경 사항을 캡처하고 강력한 내구성을 보장하며 하위 소비자에게 데이터를 안정적으로 전달하는 단일 인터페이스를 제공합니다. 결과적으로 개발자는 복잡한 데이터 정합성 문제를 직접 해결할 필요 없이 비즈니스 로직에 집중할 수 있게 되었으며, 플랫폼 전반의 탄력성과 운영 효율성이 크게 향상되었습니다. **WAL의 핵심 구조와 유연한 API** * **WriteToLog API:** 단순한 인터페이스를 통해 내부 구현을 추상화하며, 데이터 내구성을 '성공/실패/알 수 없음'의 세 가지 상태(Trilean)로 반환하여 신뢰성을 높였습니다. * **네임스페이스(Namespace):** 데이터의 저장 위치와 방식을 정의하는 논리적 격리 단위로, 설정에 따라 Kafka, SQS 등 다양한 기반 스토리지를 선택할 수 있습니다. * **페르소나 기반 아키텍처:** 네임스페이스 설정에 따라 지연 큐, 복제 도구, 인덱싱 도구 등 목적에 맞는 다양한 '페르소나'로 동작합니다. **지연 큐와 신뢰할 수 있는 재시도 메커니즘** * 네트워크 오류나 다운스트림 서비스 장애 발생 시 데이터 처리 처리량을 희생하지 않고도 실패한 메시지를 안전하게 재시도합니다. * SQS를 기본 스토리지로 활용하여 메시지 전달 시점을 조절하는 지연 기능을 구현함으로써 실시간 데이터 파이프라인의 안정성을 확보했습니다. **범용 교차 리전 복제 및 데이터 동기화** * Kafka를 활용하여 서로 다른 리전 간에 데이터를 복제하며, 기본적으로 복제를 지원하지 않는 스토리지 엔진에서도 리전 간 데이터 정합성을 유지할 수 있게 합니다. * Key-Value 저장소와 Elasticsearch 같은 서로 다른 데이터 저장소 간의 상태를 동기화하여 구체화된 뷰(Materialized Views)나 보조 인덱스를 안정적으로 구축합니다. **안정적인 데이터 삭제 및 부하 관리** * 데이터베이스에서 대량의 데이터를 삭제할 때 발생하는 메모리 부족(OOM) 문제를 해결하기 위해 WAL을 활용합니다. * 삭제 요청을 WAL에 기록한 후 처리 속도를 제어(Rate-limiting)하거나 예약된 시간에 실행함으로써 데이터베이스 노드에 가해지는 충격을 완화합니다. **시스템 설계 원칙과 격리 전략** * **수집 및 소비의 분리:** 고가용성 수집 레이어와 신뢰 중심의 소비 레이어를 분리하여 트래픽 급증이나 다운스트림 장애가 전체 시스템으로 전이되는 것을 방지합니다. * **멀티테넌시와 격리:** 공유 리소스를 사용하되 네임스페이스별로 격리된 리소스 풀을 할당하여 특정 작업이 다른 서비스의 성능에 영향을 주지 않도록 설계되었습니다. 데이터 플랫폼 차원의 통합 WAL 솔루션 도입은 각 서비스 팀이 개별적으로 구축하던 복제 및 재시도 로직의 중복을 제거하고 기술 부채를 크게 줄여줍니다. 대규모 분산 시스템을 운영하는 조직이라면 데이터의 최종 정합성과 시스템 탄력성을 확보하기 위해 이러한 추상화된 로그 계층을 검토하는 것이 권장됩니다.

airbnb원문

Viaduct, 5년 후: (새 탭에서 열림)

에어비앤비는 자사의 데이터 중심 서비스 메시인 'Viaduct'의 5년간의 운영 성과를 공유하며, 이를 오픈소스로 공개하고 차세대 아키텍처인 'Viaduct Modern'으로의 전환을 발표했습니다. Viaduct는 중앙 집중식 스키마와 서버리스 비즈니스 로직 호스팅, 재진입(Re-entrancy) 구조를 통해 트래픽이 8배 성장하는 과정에서도 운영 효율성과 비용 선형성을 유지해 왔습니다. 이번 개편은 파편화되었던 API를 단순화하고 실행 엔진과 비즈니스 로직 사이의 추상화 경계를 강화하여, 거대해진 코드베이스의 유지보수성과 개발 생산성을 높이는 데 중점을 두었습니다. ### Viaduct의 핵심 설계 원칙 * **중앙 스키마(Central Schema):** 전사의 모든 도메인을 하나의 통합된 그래프로 연결합니다. 개발은 팀별로 분산되어 진행되지만, 사용자는 단일한 접점을 통해 모든 데이터와 기능에 접근할 수 있어 내부 요청의 75%가 Viaduct 내에서 처리됩니다. * **호스팅된 비즈니스 로직(Hosted Business Logic):** GraphQL 서버를 단순한 게이트웨이로 사용하는 대신, 비즈니스 로직을 직접 실행하는 서버리스 플랫폼으로 운영합니다. 이를 통해 개별 마이크로서비스 운영 부담을 줄이고 개발자가 로직에만 집중할 수 있는 환경을 제공합니다. * **재진입성(Re-entrancy):** Viaduct에 호스팅된 로직이 다른 로직을 호출할 때 GraphQL 프래그먼트와 쿼리를 사용하도록 설계되었습니다. 이는 대규모 코드베이스에서 직접적인 코드 의존성을 방지하고 모듈성을 유지하는 핵심 장치입니다. ### Viaduct Modern의 API 단순화 * **Tenant API의 통합:** 과거에는 기능 구현 방식이 복잡하고 파편화되어 있었으나, 이를 '노드 리졸버(Node Resolver)'와 '필드 리졸버(Field Resolver)' 두 가지 메커니즘으로 대폭 통합하여 개발자 경험을 개선했습니다. * **결정 트리 제거:** 구현 방식을 고민해야 했던 복잡한 결정 과정을 없애고, 스키마 자체의 정의에 따라 리졸버 유형이 자연스럽게 결정되도록 설계하여 학습 곡선을 낮췄습니다. ### 테넌트 모듈성과 협업 구조 * **테넌트 모듈(Tenant Module):** 스키마와 구현 코드를 팀별 소유권 단위로 묶어 관리합니다. 팀 간의 직접적인 코드 참조는 지양하고 GraphQL 인터페이스를 통해서만 소통합니다. * **선언적 데이터 의존성:** 예를 들어 '메시징 팀'이 '사용자 팀'의 타입에 새로운 필드를 추가할 때, `@Resolver` 어노테이션에 필요한 데이터 필드(예: 성, 이름)를 선언하기만 하면 됩니다. * **코드 의존성 해소:** 데이터 수요를 선언적으로 명시함으로써, 다른 팀의 내부 로직이나 데이터 소스가 무엇인지 알 필요 없이 독립적으로 기능을 확장할 수 있습니다. ### 프레임워크 계층화 및 유지보수성 * **강력한 추상화 경계:** GraphQL 실행 엔진, 테넌트 API, 애플리케이션 코드 사이의 인터페이스를 명확히 분리했습니다. 과거의 느슨했던 경계를 강화하여 서비스 로직의 중단 없이 엔진 성능을 개선하거나 라이브러리를 업데이트할 수 있는 구조를 갖췄습니다. * **운영 안정성:** 이러한 구조적 개선을 통해 개발자 수와 코드 라인 수가 급격히 증가함에도 불구하고 장애 시간을 절반으로 줄이는 성과를 거두었습니다. Viaduct는 대규모 조직에서 데이터 접근 방식을 통합하고 비즈니스 로직을 효율적으로 관리하려는 팀에게 강력한 모델을 제시합니다. 특히 마이크로서비스의 복잡도를 낮추고 싶은 조직이라면, Viaduct의 재진입 구조와 서버리스 호스팅 개념을 도입하여 개발 민첩성과 시스템 안정성을 동시에 확보하는 방향을 고려해 볼 만합니다.

discord4분 읽기큐레이션 요약

디스코드가 수조 개의

Discord는 메시지 검색을 Elasticsearch 기반으로 운영했지만, 메시지와 트래픽이 조 단위로 증가하면서 Redis 큐 유실, 장애에 취약한 벌크 색인, 대규모 클러스터의 운영 부담, 단일 인덱스의 문서 수 제한 문제가 발생했다. 이를 해결하기 위해 Kubernetes와 Elastic Kubernetes Operator(ECK)를 도입하고, 거대한 클러스터 대신 여러 개의 작은 클러스터를 운영하는 셀(cell) 아키텍처로 전환하려 했다. 목표는 장애 격리, 무중단 업그레이드, 확장성, 비용 효율성을 동시에 확보하는 것이었다. ## 기존 메시지 검색 구조 - 2017년 Discord는 Elasticsearch에 메시지를 색인했다. - 메시지는 Discord 서버(guild) 또는 DM 단위로 Elasticsearch 인덱스에 분산했다. - 같은 guild의 메시지를 한곳에 모아 검색 속도를 높였다. - 클러스터를 여러 개로 나누어 관리 가능한 규모를 유지했다. - 사용자가 검색을 이용하지 않는 경우를 고려해 메시지는 지연 색인(lazy indexing)했다. - Redis 기반 메시지 큐와 작업자가 메시지를 묶음으로 가져와 Elasticsearch 벌크 색인을 수행했다. ## Redis 메시지 큐의 메시지 유실 - Elasticsearch 장애로 색인 작업이 밀리면 Redis 큐에 메시지가 빠르게 쌓였다. - 큐가 과도하게 커지면서 Redis CPU 사용량이 한계에 도달했고, 결국 메시지가 유실됐다. - 즉, 색인 대상 메시지를 안정적으로 보관해야 할 큐 자체가 장애 지점이 되었다. ## 장애에 취약한 벌크 색인 - 한 번의 벌크 요청에 서로 다른 인덱스와 Elasticsearch 노드에 속한 메시지가 함께 포함됐다. - 예를 들어 50개 메시지를 색인하는 요청이 최대 50개 노드로 분산될 수 있었다. - 그중 단 하나의 노드라도 실패하면 벌크 요청 전체가 실패하고, 모든 메시지를 다시 큐에 넣어 재시도해야 했다. - 100개 노드 클러스터에서 50개 메시지를 무작위로 색인할 때, 특정 노드 하나가 장애 나면 요청 중 약 40%가 실패할 수 있었다. - 실제 장애 하나가 색인 실패와 재시도를 대량으로 유발해 Redis 큐 적체를 악화시켰다. ## 대규모 Elasticsearch 클러스터의 운영 부담 - 메시지와 guild 수가 증가할 때 노드와 인덱스를 추가하는 방식으로 수평 확장했다. - 하지만 클러스터가 커질수록 하나의 벌크 작업이 더 많은 인덱스와 노드로 분산됐다. - 이로 인해 노드 간 조정과 네트워크 팬아웃 비용이 커져 색인 성능이 저하됐다. - 노드 수가 많아질수록 어느 한 노드에서 장애가 발생할 가능성도 증가했다. ## 롤링 재시작과 보안 업데이트의 어려움 - 단일 노드 장애에도 색인 시스템이 크게 영향을 받았기 때문에 안전한 롤링 재시작이 어려웠다. - 200개가 넘는 노드와 수 테라바이트의 데이터를 가진 클러스터를 노드별로 비우고 재시작하는 데 지나치게 오랜 시간이 걸렸다. - 그 결과 오래된 운영체제와 Elasticsearch 버전을 계속 사용해야 했고, 보안 패치와 성능 개선을 적용하지 못했다. - Log4Shell 대응 당시에는 `log4j2.formatMsgNoLookups=true` 설정을 적용하기 위해 전체 검색 시스템을 중단하고 모든 노드를 재시작해야 했다. ## 대형 guild의 인덱스 크기 제한 - 일부 인덱스에는 매우 큰 guild의 메시지가 집중됐다. - Elasticsearch 인덱스는 내부적으로 하나의 Lucene 인덱스이며, 약 20억 개 문서라는 `MAX_DOC` 제한이 있다. - 이 한도에 도달하면 해당 인덱스의 모든 색인 작업이 실패한다. - 당시에는 Safety 팀과 협력해 스팸 목적의 guild를 찾아 삭제하는 방식으로 복구했다. - 그러나 정상적인 대규모 커뮤니티가 20억 개 이상의 메시지를 축적하는 상황도 지원해야 했다. ## Kubernetes와 Elastic Operator 도입 - Discord는 무상태 서비스 운영에서 이미 Kubernetes의 편의성과 비용 최적화 효과를 경험하고 있었다. - 이후 Elasticsearch 같은 상태 저장 서비스에도 Elastic Kubernetes Operator(ECK)를 적용하는 방안을 선택했다. - ECK를 사용하면 다음을 선언적으로 관리할 수 있다. - Elasticsearch 클러스터 토폴로지 - 노드 구성과 설정 - Kubernetes 노드풀 위의 클러스터 배포 - 운영체제 업그레이드를 자동화하고, 안전한 롤링 재시작과 Elasticsearch 업그레이드 도구를 활용할 수 있게 됐다. ## 여러 소형 클러스터를 사용하는 셀 아키텍처 - 기존처럼 200개가 넘는 노드를 가진 거대한 클러스터 하나를 운영하는 대신, 더 많은 수의 작은 Elasticsearch 클러스터를 운영하는 구조를 구상했다. - 작은 클러스터는 다음과 같은 이점을 제공한다. - 장애 범위 축소 - 클러스터 자체의 조정 오버헤드 감소 - 노드 장애가 전체 검색 시스템에 미치는 영향 완화 - 업그레이드와 유지보수의 단순화 - Kubernetes와 ECK를 기반으로 이러한 클러스터들을 표준화하고 운영하려 했다. 대규모 검색 시스템에서는 단순히 노드를 추가하는 것보다 장애 격리와 운영 가능성을 함께 설계하는 것이 중요하다. 특히 벌크 작업을 부분 실패에 강하게 만들고, 클러스터를 작은 단위로 나누며, 롤링 업그레이드가 가능한 플랫폼을 채택하는 것이 장기적인 안정성에 유리하다.

원문 읽기(새 탭에서 열림)
datadog원문

신뢰할 수 있는 분산 시스템을 설계하기 위해 형식 모델링, 경량 시뮬레이션, 카오스 테스트를 활용하는 방법 (새 탭에서 열림)

분산 시스템의 복잡성으로 인해 발생하는 시스템 수준의 설계 오류를 해결하기 위해, 데이터독(Datadog)은 차세대 메시지 큐 서비스인 'Courier'의 설계 과정에서 포멀 모델링(Formal Modeling)과 경량 시뮬레이션을 도입했습니다. 이 방식은 전통적인 단위 테스트나 카오스 테스트가 발견하기 어려운 고차원적인 설계 결함을 설계 단계에서 미리 검증하고, 시스템의 성능 특성을 통계적으로 예측할 수 있게 해줍니다. 결과적으로 이러한 접근법은 가용성과 신뢰성이 필수적인 핵심 인프라 서비스가 복잡한 실패 모드에서도 안정적으로 동작함을 확인하는 강력한 도구가 되었습니다. **포멀 모델링과 경량 시뮬레이션의 도입** - **포멀 모델링(Formal Modeling):** 고수준의 명세 언어를 사용해 시스템의 속성을 기술하고, 모델 체커를 통해 발생 가능한 모든 상태를 전수 조사함으로써 설계상의 논리적 결함이 없는지 검증합니다. - **경량 시뮬레이션(Lightweight Simulation):** 포멀 모델링이 확인하기 어려운 지연 시간(Latency), 비용, 확장성 등의 통계적 성능 지표를 실제 부하 환경과 유사한 조건에서 실행하여 분석합니다. - **도입 배경 및 트레이드오프:** 구현 자체를 검증하지는 못하고 모델 유지 보수의 오버헤드가 발생하지만, 대규모 장애(2023년 3월 사례)를 방지하고 설계의 정확성을 보장하기 위해 도입되었습니다. **차세대 메시지 큐 서비스: Courier** - **배경:** 기존 Redis 기반 시스템의 처리량 및 확장성 한계를 극복하기 위해 설계된 멀티테넌트 메시지 큐 서비스입니다. - **최소 1회 전달(At-least-once delivery):** 메시지 손실 없이 전송을 보장하며, 실패 시 데드 레터 큐(DLQ)로 이동하여 알림 누락을 방지합니다. - **점진적 성능 저하(Graceful Degradation):** 가용 컴퓨팅 자원이 줄어들더라도 처리량이 급격히 추락하지 않고 선형적으로 감소하도록 설계하여 전체 서비스 마비를 방지합니다. - **수평적 확장성:** 컴퓨팅 자원 추가에 따라 처리량이 선형적으로 증가하는 구조를 목표로 합니다. **멀티테넌시 및 고가용성을 위한 아키텍처** - **FoundationDB 기반 샤딩:** 여러 개의 FoundationDB 클러스터를 구축하고, 각 테넌트를 특정 클러스터 조합(예: 8개 중 4개 선택)에 샤딩하여 테넌트 간 간섭을 최소화합니다. - **폭발 반경(Blast Radius) 제어:** 특정 테넌트가 4개의 클러스터에 부하를 주더라도, 다른 테넌트는 최소 25% 이상의 가용 용량을 확보할 수 있도록 격리 수준을 높였습니다. - **브로커 레이어(Broker Layer):** gRPC API를 통해 샤딩 로직을 처리하고, 백엔드 클러스터의 상태 점검(Health Check)을 수행하며 3개의 가용 영역(AZ)에 분산 배치되어 고가용성을 유지합니다. 이러한 포멀 모델링과 시뮬레이션 기법은 복잡한 분산 시스템을 구축할 때 직관에 의존하는 대신 수학적·통계적 근거를 바탕으로 의사결정을 내릴 수 있게 합니다. 특히 Courier와 같이 신뢰성이 최우선인 기반 시스템을 설계할 때, 초기 단계에서의 철저한 검증은 추후 발생할 수 있는 막대한 수정 비용과 대규모 장애 위험을 줄이는 데 매우 효과적인 투자입니다.

datadog원문

엔지니어링 부문 VP 스포트라이트: 이보 디미트로프 (새 탭에서 열림)

데이터독(Datadog)의 엔지니어링 VP 이보 디미트로프(Ivo Dimitrov)는 30년 이상의 경력을 가진 베테랑으로서, 고성능 저수준 시스템 개발자에서 대규모 분산 시스템을 총괄하는 리더로 성장해 온 인물입니다. 그는 마이크로소프트와 링크드인에서 쌓은 대규모 스토리지 인프라 구축 경험을 바탕으로, 현재 데이터독에서 메트릭과 이벤트 플랫폼의 기술적 혁신을 이끌고 있습니다. 기술적 깊이와 조직적 비전 사이의 균형을 강조하는 그의 여정은 복잡한 데이터 시스템을 다루는 엔지니어와 관리자들에게 중요한 통찰을 제공합니다. ### 저수준 시스템 개발에서 엔지니어링 리더십으로의 전환 * 전기 공학 전공 중 실시간 운영체제(RTOS) 커널 기여를 통해 소프트웨어 개발에 입문했으며, 이후 10년간 C/C++ 기반의 고성능 시스템 프로그래밍에 집중했습니다. * 마이크로소프트의 Azure Blob Storage 초기 팀에서 근무하던 중 조직 개편을 계기로 관리직을 맡게 되었으며, 현장에서의 실무 교육과 멘토링을 통해 리더십 역량을 쌓았습니다. * 자신의 업무에만 집중하는 단계를 넘어 타인의 성장을 촉진하고 조직 간의 경계를 조율하는 '오너십(Ownership)'의 가치를 발견하며 매니지먼트의 매력을 느꼈습니다. ### 대규모 분산 스토리지 플랫폼 구축 경험 * 링크드인 재직 당시, 현재까지 전체 데이터셋의 95% 이상을 처리하는 독점 키-값(Key-Value) 저장소인 'Espresso'를 초기 단계에서 성숙한 플랫폼으로 성장시켰습니다. * 파생 데이터 서빙을 위한 'Venice', 오픈소스 블록 스토리지인 'Ambry', 클러스터 관리자인 'Helix' 등 인터넷 규모의 스토리지 인프라 프로젝트들을 주도했습니다. * 이러한 경험을 통해 대규모 레거시 환경의 제약에서 벗어나, 기술적 위험을 감수하고 빠르게 혁신할 수 있는 문화적 유연성의 중요성을 깨달았습니다. ### 데이터독의 분산 데이터 시스템과 기술적 지향점 * 현재 데이터독에서 메트릭(Metrics), 이벤트(Events), 로그 및 트레이스 등 반정형 데이터를 처리하는 분산 데이터 시스템 조직을 총괄하고 있습니다. * 온라인 분석 워크로드에 최적화된 특수 메인 메모리 데이터베이스인 'Driveline'을 통해 시계열 데이터 처리의 효율성을 극대화하고 있습니다. * 서로 다른 도메인별 API를 통합하는 '교차 플랫폼 쿼리(Cross-Platform Queries)' 팀을 운영하여, 고객과 엔지니어 모두가 통일된 인터페이스로 데이터에 접근할 수 있도록 추상화 계층을 구축 중입니다. * 전체 쿼리의 80% 이상을 차지하는 알람(Alerts) 플랫폼을 메트릭 및 이벤트 플랫폼과 통합하여 시스템의 일관성을 높이고 있습니다. **실용적인 제언** 개인 기여자(IC)에서 관리자로 전환할 때는 기술적 전문성을 포기하는 것이 아니라, 그 전문성을 바탕으로 조직의 비전을 설계하고 팀원들이 역량을 발휘할 수 있는 환경을 조성하는 데 집중해야 합니다. 특히 데이터독의 사례처럼 쿠버네티스(Kubernetes) 기반의 현대적 인프라와 실험을 장려하는 문화를 결합할 때, 기술적 부채를 최소화하면서도 폭발적인 성장을 뒷받침하는 시스템을 구축할 수 있습니다.

figma3분 읽기큐레이션 요약

대규모 실시간 데이터를

Figma의 실시간 데이터 서비스 LiveGraph는 사용자와 쿼리 증가, 데이터베이스 샤딩으로 기존 구조의 한계에 도달했다. Figma는 초기 로컬 캐시와 단일 PostgreSQL의 전역 변경 스트림에 의존하던 아키텍처를 100배 규모까지 확장할 수 있도록 근본적으로 재설계하려 했다. 새 설계의 목표는 성능과 안정성을 유지하면서 데이터베이스 샤드와 읽기·업데이트 부하를 독립적으로 확장하고, 사용자 영향 없이 점진적으로 마이그레이션하는 것이다. ## LiveGraph의 역할 - LiveGraph는 GraphQL과 유사한 쿼리를 구독하는 웹 API를 제공한다. - 쿼리 결과를 JSON 트리로 반환하며, 객체와 관계를 정의한 스키마와 특정 그래프 일부를 조회하는 뷰를 사용한다. - Figma의 커스텀 React Hook을 통해 데이터가 변경되면 프런트엔드가 자동으로 다시 렌더링된다. - 캔버스 공동 편집, 댓글, FigJam 투표 등 여러 협업 기능에서 최신 데이터를 유지하는 기반 역할을 한다. ## 규모 증가로 드러난 문제 - 2021년 이후 LiveGraph 세션 수가 3배 증가했다. - 최근 1년 동안 뷰 요청 수는 5배 늘어났고, 세션 하나의 처리 비용도 점점 커졌다. - 데이터베이스 역시 단일 PostgreSQL 인스턴스에서 여러 수직·수평 샤드 구조로 변화하고 있었다. - 따라서 문제는 단순히 각 LiveGraph 서버가 데이터베이스 변경 사항을 모두 수집하는 데 그치지 않고, 클라이언트 세션·읽기 요청·데이터베이스 업데이트가 동시에 증가하는 복합적인 확장성 문제였다. ## LiveGraph 100x의 설계 목표 Figma는 현재의 읽기 및 데이터베이스 업데이트 부하를 장기적으로 100배까지 처리하기 위한 “LiveGraph 100x” 계획을 시작했다. - **서비스 속도 유지** - 초기 로드 시간과 실시간 업데이트에 대한 SLO를 유지하거나 개선해야 했다. - **데이터베이스 확장 지원** - 수직 확장뿐 아니라 수평 샤딩도 기본적으로 지원해야 했다. - 샤드가 늘어나도 신뢰성과 성능이 저하되지 않아야 했다. - **독립적인 확장 수단 확보** - 클라이언트 읽기량이 증가할 때와 쿼리 업데이트량이 증가할 때 서로 다른 구성 요소를 확장할 수 있어야 했다. - **안전한 점진적 마이그레이션** - 기존 LiveGraph 사용자를 중단시키지 않고 단계적으로 구조를 개선해야 했다. ## 초기 아키텍처와 변경 스트림 초기 LiveGraph는 단일 PostgreSQL과 하나의 서버를 중심으로 구성됐다. - PostgreSQL의 논리적 복제 스트림은 WAL에 기록된 행 단위 변경 사항을 전달한다. - 각 변경에는 행의 변경 전·후 이미지와 단조 증가하는 시퀀스 번호가 포함된다. - LiveGraph는 이 스트림을 추적해 데이터 변경을 실시간 업데이트로 재사용했다. - 모든 LiveGraph 쿼리는 기본 데이터베이스인 primary를 조회했다. - 서버 내부에는 인메모리 쿼리 캐시가 있었고, PostgreSQL의 각 행 변경이 발생할 때마다 관련 쿼리 결과를 직접 수정했다. - 즉, 캐시는 전체 결과를 다시 계산하기보다 개별 mutation을 결과에 반영하는 방식이었다. ## 단일 데이터베이스 구조의 한계 초기 구조에서는 데이터베이스가 하나였기 때문에 변경 스트림의 전역 순서를 가정할 수 있었다. - 모든 변경 사항이 하나의 PostgreSQL 인스턴스에서 생성됐다. - 따라서 LiveGraph는 하나의 전역적으로 정렬된 업데이트 스트림을 처리하면 됐다. - 하지만 단일 PostgreSQL 인스턴스가 용량 한계에 도달하면서 데이터베이스를 여러 수직 샤드로 나누게 됐다. - 여러 샤드가 동시에 변경 사항을 생성하면서 업데이트의 전역 순서가 더 이상 보장되지 않았다. - 기존의 “하나의 전역 순서 스트림”이라는 가정은 샤딩된 데이터베이스 환경에서 유지될 수 없었다. ## 재설계가 필요해진 이유 - LiveGraph는 데이터베이스 확장에 맞춰 변경 사항 수집과 캐시 갱신 방식을 바꿔야 했다. - 수직·수평 샤딩 환경에서는 여러 변경 스트림을 안정적으로 처리해야 한다. - 읽기 요청과 실시간 업데이트가 서로 다른 속도로 증가하므로, 전체 시스템을 한 방식으로만 확장해서는 효율적이지 않다. - Figma는 데이터베이스 용량 문제에 신속히 대응하면서도 기존 서비스의 성능과 안정성을 유지할 수 있는 전략적 변경이 필요했다. 실무적으로는 단일 데이터베이스의 전역 순서와 중앙 캐시에 의존하는 실시간 시스템이 초기에는 단순하고 효율적이지만, 샤딩 단계에서는 변경 순서·캐시 일관성·부하 분리 문제를 별도로 설계해야 한다는 점을 보여준다.

원문 읽기(새 탭에서 열림)
figma4분 읽기큐레이션 요약

Figma 데이터베이스 팀이 대

Figma는 데이터베이스 규모가 2020년 이후 약 100배 성장하면서 단일 Postgres와 수직 분할만으로는 한계에 도달했다. 먼저 캐시, 읽기 복제본, 수직 파티셔닝으로 확장 여유를 확보했지만, 수 테라바이트 규모의 테이블과 급격히 증가하는 쓰기량 때문에 수평 샤딩이 필요해졌다. Figma는 새로운 데이터베이스로 전면 이전하기보다 기존 RDS Postgres 전문성과 데이터 일관성을 유지하는 점진적 수평 샤딩을 선택해 약 9개월 만에 확장 기반을 마련했다. ## 급격한 성장과 수직 파티셔닝의 한계 - Figma는 2020년 AWS의 가장 큰 물리 인스턴스에서 단일 Postgres를 운영했다. - 2022년 말에는 다음과 같은 분산 구조로 발전했다. - 캐시 - 읽기 복제본 - 약 12개의 수직 분할 데이터베이스 - “Figma 파일”, “조직”처럼 연관된 테이블 그룹을 별도 데이터베이스로 분리해 점진적으로 확장했다. - 수직 파티셔닝은 CPU 사용량을 낮추고 빠르게 확장 여유를 확보하는 데 효과적이었다. - 그러나 수직 분할의 최소 단위는 테이블 하나이므로, 하나의 테이블 자체가 지나치게 커지는 문제는 해결하지 못했다. ## 데이터베이스 병목을 정량적으로 측정 - Figma는 CPU뿐 아니라 다음 지표를 함께 모니터링했다. - 디스크 I/O - 테이블 크기 - 기록되는 행 수 - 데이터베이스별 처리 한계 - 과거 운영 데이터와 부하 테스트를 조합해 각 데이터베이스와 샤드의 “남은 확장 여유”를 예측했다. - 수 테라바이트와 수십억 개의 행을 가진 테이블에서는 Postgres의 `VACUUM` 작업이 안정성에 영향을 주기 시작했다. - `VACUUM`은 트랜잭션 ID 고갈을 방지하는 필수 백그라운드 작업이지만, 대형 테이블에서는 처리 부담이 커진다. - 쓰기량이 가장 많은 테이블은 AWS RDS가 제공하는 최대 IOPS에 곧 도달할 상황이었다. - 이 문제는 테이블을 다른 데이터베이스로 옮기는 수직 분할만으로는 해결할 수 없어 수평 샤딩이 요구됐다. ## 확장 설계의 목표 Figma는 단순히 데이터를 여러 데이터베이스에 나누는 것보다, 운영과 애플리케이션 변경 위험을 최소화하는 것을 중요하게 봤다. - **개발자 영향 최소화** - 기존의 복잡한 관계형 데이터 모델을 최대한 유지한다. - 애플리케이션 개발자가 대규모 데이터 접근 코드를 전면 수정하지 않도록 한다. - **투명한 확장** - 최초에 샤딩 호환성을 확보한 뒤에는, 향후 샤드를 추가할 때 애플리케이션 변경을 최소화한다. - **대규모 백필 회피** - 수개월이 걸릴 수 있는 전체 테이블 백필이나 전체 데이터 마이그레이션을 피한다. - **점진적 적용** - 빠르게 증가하는 테이블부터 단계적으로 적용한다. - 각 단계에서 위험을 검증해 대규모 장애 가능성을 낮춘다. - **롤백 가능성 확보** - 물리적 샤딩 이후에도 문제가 생기면 이전 상태로 되돌릴 수 있어야 한다. - **강한 일관성 유지** - 다운타임과 일관성 위험을 유발할 수 있는 이중 쓰기 방식을 피한다. - 거의 무중단에 가까운 확장을 목표로 한다. - **기존 역량 활용** - 이미 축적한 RDS Postgres 운영 경험과 도구를 활용해 새로운 저장소의 불확실성을 줄인다. ## 대체 데이터베이스 검토 - Figma는 수평 확장을 지원하는 여러 기술을 검토했다. - CockroachDB - TiDB - Spanner - Vitess - 그러나 새 데이터베이스로 전환하려면 기존 Postgres와 새 저장소 사이의 복잡한 데이터 마이그레이션이 필요했다. - 데이터 일관성과 안정성을 확보하면서 핵심 기능을 모두 이전하려면 상당한 시간이 필요했다. - Figma는 이미 RDS Postgres를 안정적이고 성능 좋게 운영하는 전문성을 갖고 있었으므로, 새로운 데이터베이스로 바꾸면 이 역량을 다시 구축해야 했다. - 성장 속도가 매우 빨라 남은 확장 여유가 수개월뿐이었기 때문에, 새로운 저장소를 도입하는 것은 기술적으로 가능하더라도 일정과 위험 측면에서 적합하지 않았다. ## NoSQL을 선택하지 않은 이유 - NoSQL은 기본적으로 수평 확장을 제공하지만, Figma의 데이터 모델과는 잘 맞지 않았다. - Figma는 복잡한 관계형 데이터와 여러 테이블 간 관계를 Postgres 위에서 활용하고 있었다. - NoSQL API만으로는 이러한 관계형 질의와 데이터 모델의 유연성을 동일하게 제공하기 어려웠다. - 따라서 애플리케이션 구조를 대규모로 재설계하는 대신, 기존 관계형 모델을 유지하면서 Postgres를 수평 확장하는 방향을 택했다. ## 실용적인 결론 데이터베이스 확장은 처음부터 수평 샤딩으로 시작하기보다, 캐시·읽기 복제본·수직 파티셔닝으로 단기 여유를 확보한 뒤 실제 병목을 측정하며 단계적으로 진행하는 것이 현실적이다. 특히 기존 데이터베이스에 대한 운영 역량과 강한 일관성이 중요하다면, 새로운 저장소로 전면 이전하기보다 현재 시스템을 유지한 채 점진적으로 샤딩하는 전략이 위험과 개발 비용을 줄일 수 있다.

원문 읽기(새 탭에서 열림)
datadog원문

Husky: 대규모 환경에서의 정확히 한 번 데이터 수집과 멀티테넌시 (새 탭에서 열림)

Datadog의 3세대 이벤트 저장소인 Husky는 대규모 멀티테넌트 환경에서 데이터 중복 없는 '정확히 한 번(Exactly-once)'의 인입을 보장하기 위해 데이터 지역성(Locality) 기반의 라우팅 아키텍처를 도입했습니다. 스캔과 집계에 최적화된 Husky의 특성상 고성능 포인트 조회가 어렵다는 점을 극복하기 위해, 결정론적 샤딩을 통해 중복 제거의 범위를 샤드 단위로 한정하여 시스템 복잡도를 낮췄습니다. 이를 통해 테넌트별 데이터 격리 비용을 최소화하고, 가변적인 트래픽 상황에서도 효율적으로 스토리지와 컴퓨팅 자원을 확장할 수 있는 기반을 마련했습니다. ## 샤드 라우터를 통한 데이터 지역성 확보 * **결정론적 매핑**: 업스트림 서비스인 'Shard Router'를 사용하여 이벤트의 ID와 타임스탬프를 기반으로 특정 샤드(파티션 그룹)에 이벤트를 할당합니다. * **샤드 할당 전략**: 각 테넌트에게 고정된 리스트의 샤드를 할당하고, 해당 리스트 내에서 이벤트 ID를 해싱하여 샤드를 선택함으로써 무작위 라우팅을 방지합니다. * **테넌트 격리**: 개별 워커 노드가 노출되는 테넌트와 인덱스의 수를 최소화하여, 시스템 전체의 복잡도를 관리 가능한 수준으로 유지합니다. ## 데이터 지역성 도입의 기술적 이점 * **중복 제거(Deduplication) 효율화**: 동일한 ID를 가진 이벤트는 항상 같은 샤드로 라우팅되므로, 전체 시스템이 아닌 샤드 내부에서만 중복 여부를 확인하면 됩니다. 이벤트 ID 세트가 메모리에 수용 가능한 크기로 유지되어 처리 속도가 비약적으로 향상됩니다. * **스토리지 비용 절감**: Husky는 테넌트별로 데이터를 전용 테이블에 격리하며 파일 단위로 저장합니다. 지역성을 통해 워커당 처리하는 테넌트 수를 제한하면 생성되는 파일 수가 줄어들어, 클라우드 스토리지 비용과 후속 컴팩션(Compaction) 작업의 부하를 동시에 낮출 수 있습니다. * **성능 최적화**: 워커 노드가 처리해야 할 논리적 네임스페이스의 카디널리티(Cardinality)가 낮아짐에 따라 쓰기 성능이 개선되고 리소스 효율성이 높아집니다. ## 동적 환경에서의 라우팅 도전 과제 * **할당 변경 관리**: 특정 테넌트의 트래픽이 갑자기 수십 배 증가하거나 전체 샤드 수가 변경될 때, 기존의 결정론적 규칙을 유지하면서도 유연하게 샤드 배정을 변경해야 합니다. * **분산 노드 간 합의**: 모든 샤드 라우터 노드가 동일한 라우팅 규칙을 공유해야 중복 데이터 유입을 방지할 수 있으며, 이를 위해 노드 간의 일관성 있는 결정 메커니즘이 필수적입니다. * **부하 분산(Load Balancing)**: 모든 샤드에 인입 트래픽이 균등하게 배분되도록 설계하여 특정 워커 노드에 부하가 집중되는 '핫스팟' 현상을 방지해야 합니다. 대규모 분산 시스템에서 데이터 일관성을 유지하며 비용을 최적화하려면, 무상태(Stateless) 라우팅보다는 데이터의 특성에 맞춘 지역성 설계를 우선 고려해야 합니다. 특히 테넌트 수가 많은 SaaS 환경에서는 워커가 처리하는 테넌트의 카디널리티를 물리적으로 제한하는 것이 스토리지 관리 비용을 결정짓는 핵심 요소가 됩니다.