apache-spark

4 개의 포스트

당근 데이터 지도를 그리다: 컬럼 레벨 리니지 구축기. SQL 파싱으로 구축한 컬럼 레벨 데이터 리니지 | by Jin-won Park | 당근 테크 블로그 | Dec, 2025 | Medium (새 탭에서 열림)

당근마켓(당근) 데이터 가치화팀은 데이터의 흐름을 투명하게 파악하여 신뢰성을 높이기 위해 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 내의 다양한 서비스로 플랫폼을 확장하고, 실험 생성부터 결과 분석까지 한 곳에서 관리할 수 있는 통합 어드민 시스템을 구축할 계획입니다. 이 시스템은 실험 대상자를 정교하게 선별해야 하는 복잡한 서비스 환경에서 데이터의 신뢰도를 높이는 데 매우 효과적입니다. 특히 마케팅 비용 최적화나 신규 기능의 타겟 검증이 필요한 팀이라면, 단순 무작위 할당 방식보다는 유저 세그먼트 기반의 동적 타겟팅 시스템을 구축하거나 활용하는 것을 권장합니다.

Iceberg Low-Latency Queries with Materialized Views (feat. 실시간 거래 리포트) (새 탭에서 열림)

네이버의 실시간 거래 리포트 시스템은 대규모 데이터를 다양한 조건으로 빠르게 조회하기 위해 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 엔진의 구체화 뷰를 결합하는 레이크하우스 전략이 효과적입니다. 특히 데이터의 최신성이 중요한 금융 및 거래 리포트 분야에서 이와 같은 기술 조합은 인프라 비용을 절감하면서도 사용자 경험을 극대화할 수 있는 강력한 대안이 됩니다.

Scaling Muse: 조 단위 로우 (새 탭에서 열림)

넷플릭스의 내부 데이터 분석 플랫폼인 '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 기반의 인메모리 캐싱을 적절히 조합하는 것이 성능 최적화의 핵심입니다. 특히 수조 건 규모의 데이터에서는 완벽한 정확도와 성능 사이의 트레이드오프를 전략적으로 선택하는 것이 시스템의 유연성을 결정짓습니다.