apache-spark

7 개의 포스트

Pinterest의 Apache Spark에서 (새 탭에서 열림)

Pinterest는 대규모 Spark 환경에서 빈번하게 발생하는 OOM(Out-of-Memory) 오류를 해결하기 위해 'Auto Memory Retries' 기능을 도입했습니다. 이 시스템은 태스크 수준에서 리소스 요구량을 동적으로 판단하고, 실패 시 더 큰 메모리 프로필을 가진 실행기(Executor)에서 태스크를 재시도하도록 자동화합니다. 이를 통해 수동 튜닝의 번거로움을 줄이고 자원 효율성을 높여 전체적인 작업 실패율과 운영 비용을 획기적으로 낮추는 성과를 거두었습니다. ### 기존 Spark 리소스 관리의 한계와 문제점 * Pinterest의 Spark 클러스터는 하드웨어 대비 높은 메모리 요구량으로 인해 OOM 오류가 잦았으며, 전체 작업 실패 원인의 약 4.6%가 메모리 부족에서 기인했습니다. * 사용자가 모든 스테이지와 태스크의 메모리 요구량을 정확히 예측하여 수동으로 설정하는 것은 매우 어렵고 시간이 많이 소요되는 작업입니다. * 데이터 스큐(Skew) 현상으로 인해 같은 스테이지 내에서도 특정 태스크만 과도한 메모리를 사용하는 경우가 많아, 모든 태스크를 최대치에 맞춰 설정하면 심각한 자원 낭비가 발생합니다. * 제품 팀의 우선순위 문제로 인해 비용 절감을 위한 수동 최적화가 지속적으로 이루어지기 어려운 구조적 한계가 있었습니다. ### Auto Memory Retries의 단계별 대응 전략 * **CPU 할당량 증설을 통한 메모리 확보 (1단계):** 실행기에 1개 이상의 코어가 있는 경우, OOM 발생 시 첫 번째 재시도에서 태스크당 CPU 할당량(`spark.task.cpus`)을 두 배로 늘립니다. 이를 통해 실행기 내 동시 실행 태스크 수를 줄여 개별 태스크가 사용할 수 있는 공유 메모리 공간을 즉각적으로 확보합니다. * **물리적으로 큰 실행기 투입 (2단계):** CPU 조절만으로 해결되지 않거나 단일 태스크가 이미 실행기 전체 메모리를 사용 중인 경우, 물리적으로 더 큰 메모리를 가진 새로운 실행기를 동적으로 런칭합니다. * **하이브리드 확장 프로필 적용:** 기본 설정의 2배, 3배, 4배 크기의 리소스 프로필을 미리 등록하고 단계별로 순차 적용합니다. Apache Gluten을 사용하는 워크로드의 경우 Off-heap 메모리도 함께 증설하여 가속화된 연산을 지원합니다. ### 시스템 구현 및 Spark 엔진 확장 * **태스크 수준의 리소스 프로필:** 기존 Spark의 고정된 리소스 할당 방식에서 벗어나, `Task` 객체에 개별 리소스 프로필 ID(`taskRpId`)를 저장할 수 있도록 확장하여 동일한 TaskSet 내에서도 태스크마다 사양을 다르게 가질 수 있게 구현했습니다. * **스케줄링 로직 최적화:** `TaskSetManager`는 OOM 감지 시 즉시 상위 프로필을 할당하며, `TaskSchedulerImpl`은 증설된 CPU 속성을 가진 태스크를 기존 실행기에서 우선 실행할 수 있게 하여 리소스 재사용 속도를 높였습니다. * **동적 리소스 할당:** `ExecutorAllocationManager`가 상위 프로필을 필요로 하는 대기 태스크를 실시간으로 추적하고, 물리적으로 큰 실행기가 필요한 시점에 맞춰 Kubernetes 등에 자원을 요청합니다. * **사용자 경험 개선:** 사용자가 어떤 태스크가 더 많은 자원을 사용했는지 쉽게 파악할 수 있도록 Spark UI의 태스크 목록에 리소스 프로필 ID를 표시하는 기능을 추가했습니다. 효율적인 Spark 운영을 위해서는 모든 작업을 최대 메모리 요구량에 맞추기보다, 상위 90%(P90) 수준의 일반적인 설정으로 실행하고 예외적인 태스크만 'Auto Memory Retries'로 구제하는 탄력적 전략이 권장됩니다. 이는 데이터 스큐가 심한 대규모 파이프라인에서 운영 안정성을 확보함과 동시에 인프라 비용을 최적화할 수 있는 강력한 해법이 될 것입니다.

Pinterest의 차세대 DB 인 (새 탭에서 열림)

Pinterest는 기존의 파편화된 배치 기반 DB 적재 시스템을 개선하기 위해 Iceberg와 CDC(Change Data Capture) 기술을 결합한 통합 프레임워크를 구축했습니다. 이 시스템은 데이터 지연 시간을 24시간 이상에서 수 분 단위로 단축하고, 변경된 데이터만 처리하는 방식으로 인프라 비용을 획기적으로 절감했습니다. 이를 통해 분석, 머신러닝, 규정 준수 등 현대적인 데이터 요구사항에 기민하게 대응할 수 있는 고성능 데이터 생태계를 마련했습니다. ### 통합 CDC 프레임워크의 계층 구조 * **CDC 레이어**: Debezium 및 TiCDC를 활용해 MySQL, TiDB, KVStore의 변경 사항을 1초 미만의 지연 시간으로 포착하여 Kafka에 기록합니다. * **스트리밍 레이어**: Flink 작업이 Kafka의 이벤트를 실시간으로 처리하여 S3에 위치한 'CDC Iceberg 테이블'에 추가 전용(Append-only) 방식으로 저장합니다. * **배치 레이어**: Spark 작업이 주기적으로(15~60분) CDC 테이블의 최신 변경 사항을 읽어 `Merge Into` 구문을 통해 최종 'Base Iceberg 테이블'에 업서트(Upsert)를 수행합니다. * **부트스트랩 및 유지보수**: 초기 데이터 로드를 위한 전용 파이프라인과 소형 파일 압축(Compaction) 및 스냅샷 만료 관리를 위한 유지보수 작업을 포함합니다. ### CDC 테이블과 베이스 테이블의 이원화 관리 * **CDC 테이블**: 모든 변경 이력을 담은 시계열 원장으로, 5분 미만의 지연 시간을 유지하며 원천 데이터의 변경 로그를 보존합니다. * **베이스 테이블**: 온라인 DB의 현재 상태를 그대로 반영하는 스냅샷 테이블입니다. CDC 테이블로부터 최신 레코드를 추출하여 정합성을 맞춥니다. * **동기화 로직**: `ROW_NUMBER()` 함수를 활용해 기본 키(PK)별로 가장 최신 업데이트(최근 타임스탬프 및 GTID 기준)를 식별한 후, 삭제 유형은 제거하고 나머지는 업데이트 또는 삽입합니다. ### 성능 및 비용 최적화 전략 * **Merge-on-Read (MOR) 방식 채택**: Copy-on-Write(COW) 방식은 업데이트 시 대규모 파일을 다시 작성해야 하므로 스토리지와 계산 비용이 높습니다. Pinterest는 비용 효율성을 극대화하기 위해 MOR 방식을 표준 전략으로 선택했습니다. * **기본 키 해시 버킷팅(Bucketing)**: 베이스 테이블을 PK의 해시값(예: `bucket(100, id)`)으로 파티셔닝하여 Spark가 업서트 작업을 병렬로 효율적으로 처리할 수 있도록 설계했습니다. * **증분 처리 효율성**: 매일 전체 테이블을 덤프하던 방식에서 변경된 데이터(통상 5% 미만)만 처리하는 방식으로 전환하여 연산 리소스 낭비를 차단했습니다. 방대한 양의 데이터베이스를 데이터 레이크로 통합할 때는 Iceberg의 `Merge Into` 기능을 활용한 증분 업데이트가 필수적입니다. 특히 읽기 성능과 쓰기 비용 사이의 균형을 위해 MOR 전략을 사용하고, 쓰기 병목을 해소하기 위해 기본 키 기반의 버킷팅을 적용하는 것이 실무적으로 매우 효과적인 접근임을 보여줍니다.

PinLanding: 멀티모달 (새 탭에서 열림)

Pinterest의 'PinLanding'은 수십억 개의 제품 데이터를 멀티모달 AI를 통해 정교한 쇼핑 컬렉션으로 자동 변환하는 프로덕션 파이프라인입니다. 기존의 수동 큐레이션이나 단순 검색 기록 기반 방식에서 벗어나, 제품의 이미지와 텍스트를 직접 분석하여 사용자의 복잡하고 긴 꼬리형(Long-tail) 검색 의도에 맞는 컬렉션을 생성합니다. 이 시스템은 비전-언어 모델(VLM)을 통한 속성 추출과 CLIP 스타일의 효율적인 임베딩 모델을 결합하여 대규모 데이터셋에서도 정밀도와 확장성을 동시에 확보했습니다. **사용자 쇼핑 의도와 데이터 신호의 특성화** * 사용자의 검색 기록, 자동 완성 상호작용, 필터 사용 패턴을 분석하여 쇼핑 의도의 분포를 파악합니다. * '검은색 칵테일 드레스'와 같은 정형화된 주요 쿼리(Head)뿐만 아니라, '이탈리아 여름 휴가 때 입을 옷'과 같은 서술형 및 대화형 쿼리에 대응하는 것을 목표로 합니다. * 색상, 상황, 스타일, 핏 등 20개 카테고리에 걸친 속성 차원을 정의하여, 수요는 높지만 기존 검색 결과가 부족한 영역을 식별합니다. **VLM과 LLM-as-Judge를 활용한 쇼핑 토픽 정제** * 제품의 이미지와 메타데이터를 비전-언어 모델(VLM)에 입력하여 정규화된 키-값 쌍 형태의 속성을 생성합니다. * 초기 VLM 출력의 너무 구체적이거나 중복된 속성(예: 'boho'와 'bohemian')을 해결하기 위해 빈도 기반 필터링과 임베딩 기반 클러스터링을 수행합니다. * 최종적으로 'LLM-as-judge' 단계를 거쳐 추출된 속성들이 실제 쇼핑 의도와 일치하는지, 의미적으로 일관성이 있는지 평가하여 고품질의 쇼핑 토픽 사전을 구축합니다. **CLIP 스타일 모델을 통한 대규모 속성 할당** * 모든 제품에 VLM을 직접 적용하는 것은 비용이 과다하므로, 이미지-텍스트를 정렬하는 CLIP 스타일의 듀얼 인코더 모델을 별도로 학습시킵니다. * 제품 인코더와 속성 구절 인코더를 통해 각각의 임베딩을 생성하고, 두 벡터 간의 유사도가 임계치를 넘을 때 속성을 할당합니다. * 이 방식은 VLM 대비 연산 비용을 획기적으로 낮추면서도, 제품별 속성 밀도를 높여 더욱 일관된 제품-속성 그래프를 형성합니다. **Ray 및 Spark 기반의 효율적인 배치 추론 및 피드 구축** * 수백만 개의 핀(Pin)과 토픽을 처리하기 위해 Ray 프레임워크를 사용하여 GPU와 CPU 리소스를 독립적으로 확장하며 스트리밍 방식으로 추론을 수행합니다. * CLIP 기반 분류기는 8개의 NVIDIA A100 GPU에서 약 12시간 만에 학습 및 추론을 완료하며, 회당 비용을 약 500달러 수준으로 절감했습니다. * 최종 피드 구성은 Apache Spark를 활용하여 제품과 쇼핑 토픽 간의 속성 유사도를 계산하고, 가중치 기반 스코어링을 통해 관련성 높은 제품들을 컬렉션으로 묶어냅니다. PinLanding 시스템은 AI가 단순한 키워드 매칭을 넘어 제품의 시각적, 맥락적 의미를 깊이 있게 이해할 수 있음을 보여줍니다. 대규모 이커머스 환경에서 사용자에게 개인화되고 탐색 가능한 쇼핑 경험을 제공하려는 기업은 VLM을 통한 '지식 추출'과 CLIP 스타일 모델을 통한 '효율적 확산' 전략을 참고할 가치가 있습니다.

당근 데이터 지도를 그리다: 컬럼 레벨 리니지 구축기 (새 탭에서 열림)

당근마켓(당근) 데이터 가치화팀은 데이터의 흐름을 투명하게 파악하여 신뢰성을 높이기 위해 SQL 파싱 기반의 **컬럼 레벨 데이터 리니지(Column-level Lineage)** 시스템을 구축했습니다. 기존의 테이블 단위 추적으로는 해결하기 어려웠던 연쇄 장애 대응과 민감 정보(PII) 관리 문제를 해결하기 위해, 모든 BigQuery 쿼리 로그를 분석하여 데이터 간의 세부 의존 관계를 시각화했습니다. 이를 통해 당근의 복잡한 데이터 생태계에서 변경 영향도를 정교하게 분석하고 장애 복구 시간을 단축하는 성과를 거두었습니다. ### 데이터 흐름의 불투명성으로 인한 문제점 * **연쇄 실패 대응의 어려움**: 특정 테이블의 파이프라인이 실패했을 때 이를 참조하는 하위 테이블들을 즉각 파악할 수 없어, 수동으로 쿼리를 전수 조사하며 문제를 해결해야 했습니다. * **스키마 변경의 불확실성**: 원천 데이터(MySQL 등)의 컬럼을 삭제하거나 타입을 변경할 때, 해당 컬럼을 사용하는 수많은 파생 테이블 중 어떤 곳에 장애가 발생할지 예측하기 어려웠습니다. * **민감 정보 추적 불가**: PII(개인정보)가 여러 가공 단계를 거치며 어떤 테이블의 어떤 컬럼으로 흘러가는지 파악되지 않아 보안 관리 측면에서 한계가 있었습니다. ### 컬럼 레벨 리니지 도입의 기술적 의사결정 * **테이블 레벨의 한계**: BigQuery의 기본 기능을 통한 테이블 단위 추적은 뷰(View)의 기저 테이블을 정확히 파악하기 어렵고, 세부 컬럼의 변화를 감지하지 못하는 단점이 있었습니다. * **오픈소스(OpenLineage) 대비 효율성**: 다양한 조직이 각기 다른 환경(Airflow, 노트북 등)에서 쿼리를 실행하는 당근의 특성상, 모든 환경에 계측 코드를 심는 방식보다는 중앙화된 BigQuery 로그를 분석하는 방식이 운영 부담이 적다고 판단했습니다. * **SQL 파싱 접근법**: 실행된 모든 SQL의 이력이 남는 `INFORMATION_SCHEMA.JOBS` 뷰를 활용하여, 실행 환경과 관계없이 모든 쿼리로부터 의존성을 추출하는 방식을 채택했습니다. ### 시스템 아키텍처 및 추출 프로세스 * **기술 스택**: 대량의 쿼리 병렬 처리를 위해 **Spark**를 활용하고, SQL 파싱 및 AST(Abstract Syntax Tree) 분석을 위해 **sqlglot** 라이브러리를 사용하며, **Airflow**로 주기적인 추출 프로세스를 자동화했습니다. * **데이터 수집 및 분석**: 모든 GCP 프로젝트에서 쿼리 로그를 수집한 뒤, sqlglot으로 쿼리 구조를 분석하여 `Source Column -> Target Column` 관계를 도출합니다. * **엣지 케이스 처리**: `SELECT *`와 같은 와일드카드 쿼리는 테이블 메타데이터를 결합해 실제 컬럼명으로 확장하고, 복잡한 CTE(Common Table Expressions)나 서브쿼리 내의 의존성도 AST 탐색을 통해 정확하게 추적합니다. ### 데이터 지도를 통한 실질적 변화 * **정교한 영향도 분석**: 특정 컬럼 수정 시 다운스트림에서 이를 참조하는 모든 컬럼을 즉시 확인하여 사전에 장애를 예방할 수 있게 되었습니다. * **거버넌스 강화**: 데이터의 원천부터 최종 활용 단계까지의 흐름을 시각화함으로써 데이터 가계도(Data Genealogy)를 완성하고, 데이터 보안 및 품질 관리 수준을 한 단계 높였습니다. * **운영 효율화**: 장애 발생 시 영향 범위를 데이터 지도를 통해 한눈에 파악함으로써 원인 파악과 복구에 소요되는 리소스를 획기적으로 줄였습니다. 데이터 플랫폼의 규모가 커질수록 수동 관리는 불가능해지므로, 초기부터 SQL 로그를 활용한 자동화된 리니지 체계를 구축하는 것이 중요합니다. 특히 실행 환경이 파편화된 조직일수록 애플리케이션 계측보다는 쿼리 엔진의 로그를 파싱하는 접근법이 빠른 도입과 높은 커버리지를 확보하는 데 유리합니다.

동적 사용자 분할을 활용한 새로운 A/B 테스트 시스템을 소개합니다 (새 탭에서 열림)

동적 유저 세분화(Dynamic User Segmentation) 기술을 도입한 새로운 A/B 테스트 시스템은 사용자 ID 기반의 단순 무작위 배분을 넘어 특정 속성과 행동 패턴을 가진 정교한 사용자 그룹을 대상으로 실험을 수행할 수 있게 합니다. 이 시스템은 타겟팅 엔진과 테스트 할당 로직을 분리하여 데이터 기반의 의사결정 범위를 개인화된 영역까지 확장하며, 서비스 품질 향상과 리소스 최적화라는 두 가지 목표를 동시에 달성합니다. 결과적으로 개발자와 마케터는 복잡한 사용자 시나리오에 대해 더욱 정확하고 신뢰할 수 있는 실험 데이터를 얻을 수 있습니다. ### 기존 A/B 테스트 방식과 고도화의 필요성 * **무작위 배분의 특징**: 일반적인 시스템은 사용자 ID를 해싱하여 실험군과 대조군으로 무작위 할당하며, 구현이 쉽고 선택 편향(Selection Bias)을 줄일 수 있다는 장점이 있습니다. * **타겟팅의 한계**: 전체 사용자를 대상으로 하는 일반적인 테스트에는 적합하지만, '오사카에 거주하는 iOS 사용자'처럼 특정 조건을 충족하는 집단만을 대상으로 하는 정교한 실험에는 한계가 있습니다. * **고도화된 시스템의 목적**: 사용자 세그먼트를 동적으로 정의함으로써, 서비스의 특정 기능이 특정 사용자 층에게 미치는 영향을 정밀하게 측정하기 위해 도입되었습니다. ### 유저 세분화를 위한 타겟팅 시스템 아키텍처 * **데이터 파이프라인**: HDFS에 저장된 사용자 정보(UserInfo), 모바일 정보(MobileInfo), 앱 활동(AppActivity) 등의 빅데이터를 Spark를 이용해 분석하고 처리합니다. * **세그먼트 연산**: Spark의 RDD 기능을 활용하여 합집합(Union), 교집합(Intersect), 차집합(Subtract) 등의 연산을 수행하며, 이를 통해 복잡한 사용자 조건을 유연하게 조합할 수 있습니다. * **데이터 저장 및 조회**: 처리된 결과는 `{user_id}-{segment_id}` 형태의 키-값 쌍으로 Redis에 저장되어, 실시간 요청 시 매우 낮은 지연 시간으로 해당 사용자의 세그먼트 포함 여부를 확인합니다. ### 효율적인 실험 관리와 할당 프로세스 * **설정 관리(Central Dogma)**: 실험의 설정값은 오픈 소스 설정 저장소인 Central Dogma를 통해 관리되며, 이를 통해 코드 수정 없이 실시간으로 실험 설정을 변경하고 동기화할 수 있습니다. * **할당 로직(Test Group Assigner)**: 클라이언트의 요청이 들어오면 할당기는 Central Dogma에서 실험 정보를 가져오고, Redis를 조회하여 사용자가 타겟 세그먼트에 속하는지 확인한 후 최종 실험군을 결정합니다. * **로그 및 분석**: 할당된 그룹 정보는 로그 스토어에 기록되어 사후 분석 및 대시보드 시각화의 기초 자료로 활용됩니다. ### 주요 활용 사례 및 향후 계획 * **콘텐츠 및 위치 추천**: 특정 사용자 세그먼트에 대해 서로 다른 머신러닝(ML) 모델의 성능을 비교하여 최적의 추천 알고리즘을 선정합니다. * **마케팅 및 온보딩**: 구매 빈도가 낮은 '라이트 유저'에게만 할인 쿠폰 효과를 테스트하거나, '신규 가입자'에게만 온보딩 화면의 효과를 측정하여 불필요한 비용을 줄이고 효율을 높입니다. * **플랫폼 확장성**: 향후에는 LY Corporation 내의 다양한 서비스로 플랫폼을 확장하고, 실험 생성부터 결과 분석까지 한 곳에서 관리할 수 있는 통합 어드민 시스템을 구축할 계획입니다. 이 시스템은 실험 대상자를 정교하게 선별해야 하는 복잡한 서비스 환경에서 데이터의 신뢰도를 높이는 데 매우 효과적입니다. 특히 마케팅 비용 최적화나 신규 기능의 타겟 검증이 필요한 팀이라면, 단순 무작위 할당 방식보다는 유저 세그먼트 기반의 동적 타겟팅 시스템을 구축하거나 활용하는 것을 권장합니다.

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

네이버의 실시간 거래 리포트 시스템은 대규모 데이터를 다양한 조건으로 빠르게 조회하기 위해 Apache Iceberg와 StarRocks의 Materialized View를 핵심 기술로 활용합니다. 단순히 데이터를 적재하는 수준을 넘어, 데이터의 최신성(Freshness)과 저지연(Low-Latency) 응답 속도, 그리고 시스템 확장성을 동시에 확보하는 것이 이번 기술 여정의 핵심 결론입니다. 이를 통해 복잡한 다차원 필터링이 필요한 비즈니스 환경에서도 사용자에게 즉각적인 분석 결과를 제공하는 데이터 레이크하우스 아키텍처를 구현했습니다. **실시간 거래 리포트의 기술적 도전 과제** * 대규모로 발생하는 거래 데이터를 실시간에 가깝게 수집하면서도, 사용자가 원하는 다양한 검색 조건에 즉각 응답해야 하는 성능적 요구사항이 있었습니다. * 데이터의 양이 방대해짐에 따라 기존의 단순 조회 방식으로는 응답 속도가 저하되는 문제가 발생했으며, 데이터의 신선도와 쿼리 성능 사이의 트레이드오프를 해결해야 했습니다. * 다차원 필터링과 집계 연산이 빈번한 리포트 특성상, 인덱싱 최적화와 리소스 효율성을 동시에 고려한 설계가 필요했습니다. **Iceberg와 StarRocks를 활용한 저지연 쿼리 전략** * **Apache Iceberg 기반 데이터 관리**: 데이터 레이크의 스토리지 포맷으로 Iceberg를 채택하여 ACID 트랜잭션을 보장하고, 대규모 데이터셋에 대한 효율적인 스키마 진화와 파티션 관리를 수행합니다. * **StarRocks의 구체화 뷰(Materialized View) 도입**: Iceberg에 저장된 원본 데이터를 직접 조회하는 대신, StarRocks의 Materialized View를 활용해 자주 사용되는 쿼리 결과를 미리 연산하여 저장함으로써 조회 속도를 비약적으로 향상시켰습니다. * **증분 업데이트 및 동기화**: 실시간으로 유입되는 데이터를 Materialized View에 효율적으로 반영하기 위해 Spark와 StarRocks 간의 연동 최적화를 진행하여 데이터의 최신성을 유지합니다. **아키텍처 구성 요소 및 운영 최적화** * **Spark**: 대용량 거래 데이터의 가공 및 Iceberg 테이블로의 수집을 담당하는 컴퓨팅 엔진으로 활용됩니다. * **StarRocks**: 고성능 OLAP 엔진으로서 Iceberg 외부에 위치하며, Materialized View를 통해 복잡한 조인(Join)과 집계(Aggregation) 쿼리를 가속화합니다. * **확장성 확보**: 데이터 노드와 컴퓨팅 리소스를 분리하여 운영함으로써 트래픽 증가에 유연하게 대응할 수 있는 구조를 설계했습니다. 대용량 실시간 분석 시스템을 구축할 때 Apache Iceberg만으로는 쿼리 성능의 한계가 있을 수 있으므로, StarRocks와 같은 고성능 OLAP 엔진의 구체화 뷰를 결합하는 레이크하우스 전략이 효과적입니다. 특히 데이터의 최신성이 중요한 금융 및 거래 리포트 분야에서 이와 같은 기술 조합은 인프라 비용을 절감하면서도 사용자 경험을 극대화할 수 있는 강력한 대안이 됩니다.

스케일링 뮤즈: 넷플릭스가 조단위 데이터에서 데이터 기반 창의적 인사이트를 제공하는 방법 | 넷플릭스 기술 블로그 | 넷플릭스 기술 블로그 (새 탭에서 열림)

넷플릭스의 내부 데이터 분석 플랫폼인 'Muse'는 수조 건 규모의 데이터를 분석하여 홍보용 미디어(아트웍, 영상 클립)의 효과를 측정하고 창작 전략을 지원합니다. 급증하는 데이터 규모와 복잡한 다대다(Many-to-Many) 필터링 요구사항을 해결하기 위해, 넷플릭스는 HyperLogLog(HLL) 스케치와 인메모리 기술인 Hollow를 도입하여 데이터 서빙 레이어를 혁신했습니다. 이를 통해 데이터 정확도를 유지하면서도 수조 행의 데이터를 실시간에 가깝게 처리할 수 있는 고성능 OLAP 환경을 구축했습니다. ### 효율적인 고유 사용자 집계를 위한 HLL 스케치 도입 * **근사치 계산을 통한 성능 최적화:** 고유 사용자 수(Distinct Count)를 계산할 때 발생하는 막대한 리소스 소모를 줄이기 위해 Apache Datasketches의 HLL 기술을 도입했습니다. 약 0.8%~2%의 미세한 오차를 허용하는 대신 집계 속도를 비약적으로 높였습니다. * **단계별 스케치 생성:** Druid 데이터 수집 단계에서 '롤업(Rollup)' 기능을 사용해 데이터를 사전 요약하고, Spark ETL 과정에서는 매일 생성되는 HLL 스케치를 기존 데이터와 병합(hll_union)하여 전체 기간의 통계를 관리합니다. * **데이터 규모 축소:** 수개월에서 수년 치의 데이터를 전수 비교하는 대신, 미리 생성된 스케치만 결합하면 되므로 데이터 처리량과 저장 공간을 획기적으로 절감했습니다. ### Hollow를 활용한 인메모리 사전 집계 및 서빙 * **초저지연 조회 구현:** 모든 쿼리를 Druid에서 처리하는 대신, 자주 사용되는 '전체 기간(All-time)' 집계 데이터는 넷플릭스의 오픈소스 기술인 'Hollow'를 통해 인메모리 방식으로 서빙합니다. * **Spark와 마이크로서비스의 연계:** Spark 작업에서 미리 계산된 HLL 스케치 집계 데이터를 Hollow 데이터셋으로 발행하면, Spring Boot 기반의 마이크로서비스가 이를 메모리에 로드하여 밀리초(ms) 단위의 응답 속도를 제공합니다. * **조인(Join) 병목 해결:** 복잡한 시청자 성향(Audience Affinity) 필터링과 같은 다대다 관계 연산을 메모리 내에서 처리함으로써 기존 아키텍처의 한계를 극복했습니다. ### 데이터 검증 및 아키텍처 현대화 * **신뢰성 보장:** 아키텍처 변경 전후의 데이터 정합성을 확인하기 위해 내부 디버깅 도구를 활용하여 사전/사후 데이터를 정밀하게 비교 검증했습니다. * **기술 스택 고도화:** React 프런트엔드와 GraphQL 레이어, 그리고 gRPC 기반의 Spring Boot 마이크로서비스 구조를 통해 확장성 있는 시스템을 구축했습니다. * **분석 역량 강화:** 이를 통해 단순한 대시보드를 넘어 이상치 감지(Outlier Detection), 미디어 간 성과 비교, 고급 필터링 등 사용자들의 고도화된 분석 요구를 수용할 수 있게 되었습니다. 대규모 OLAP 시스템을 설계할 때 모든 데이터를 실시간으로 전수 계산하기보다는, HLL과 같은 확률적 자료구조와 Hollow 기반의 인메모리 캐싱을 적절히 조합하는 것이 성능 최적화의 핵심입니다. 특히 수조 건 규모의 데이터에서는 완벽한 정확도와 성능 사이의 트레이드오프를 전략적으로 선택하는 것이 시스템의 유연성을 결정짓습니다.