airflow

2 개의 포스트

Apache Flink + RocksDB 튜닝으로 광고 Frequency Capping 실시간 집계를 일주일까지 확장하기 (새 탭에서 열림)

토스 데이터 서비스 플랫폼 팀은 광고 노출 집계의 정확성을 높이고 서빙 효율을 개선하기 위해, 기존 Airflow 배치와 Flink 스트리밍이 혼재된 시스템을 전면 Flink 기반의 실시간 슬라이딩 집계 시스템으로 전환했습니다. 1분부터 7일까지의 광범위한 집계 구간을 단일 Redis 조회로 제공하기 위해 집계 특성별로 Flink 앱을 분리하고, RocksDB 및 런타임 설정을 최적화하여 비즈니스 오차를 최소화했습니다. 이 과정에서 대규모 상태(State) 관리와 초기 데이터 적재의 정합성 문제를 해결하며 운영 신뢰성을 확보했습니다. ### 광고 노출 제어(Frequency Capping)의 중요성 * 광고주 예산 낭비를 막고 노출 기회 손실을 방지하기 위해 사용자별 광고 노출 횟수를 정확하게 카운트하고 제어하는 메커니즘입니다. * 광고 상품에 따라 '하루 3회', '7일간 1회' 등 집계 구간이 다양하므로, 1분부터 7일까지의 모든 구간에 대해 이벤트 단위의 정밀한 슬라이딩 윈도우 집계가 필요합니다. ### 기존 시스템의 한계와 개선 동기 * 기존에는 Airflow를 이용해 당일(Head), 과거(Mid), 경계 보정(Tail)의 3단계로 나누어 처리하는 배치 구조를 사용했으나, 유지보수해야 할 DAG가 너무 많고 구조가 복잡했습니다. * 서빙 시점에 구간별로 Redis를 최대 4회 조회해야 하는 구조적 번거로움이 있었으며, 실시간으로 변하는 슬라이딩 윈도우를 정밀하게 구현하는 데 한계가 있었습니다. ### 병목 패턴에 따른 앱 분리 및 아키텍처 * 집계 구간별 병목 현상이 다르다는 점에 착안하여 시스템을 **Minutes**(1~30분), **Hours**(최대 12시간), **Days**(최대 7일)의 3개 앱으로 분리했습니다. * **Minutes**: 빈번한 만료 처리로 인한 Write Stall이 주요 병목이며, RocksDB Write 경로 튜닝이 핵심입니다. * **Hours**: 대량의 광고 ID 누적으로 인한 Filter Block Cache Miss와 CPU 포화가 발생하여 Managed Memory 증설이 필요합니다. * **Days**: Savepoint가 230GB에 달하는 대규모 상태가 병목이며, Checkpoint I/O 문제를 해결하기 위해 Changelog State Backend를 활용합니다. * Flink State를 '단일 진실 공급원(SSOT)'으로 삼아, 장애 발생 시에도 Redis를 State로부터 언제든 다시 구성할 수 있도록 설계했습니다. ### 초기 적재와 전환 정합성 확보 * 7일치의 과거 데이터를 채우는 과정에서 '백필(카운트만 수행)'과 '캐치업(카운트와 만료 타이머 함께 등록)' 파이프라인을 분리하는 2단계 구조를 설계했습니다. * 백필 도중 만료 타이머가 미리 발화하여 집계가 틀어지는 문제를 방지하기 위해, 백필 완료 후 특정 시점부터만 Redis에 쓰기가 수행되도록 제어했습니다. * `withIdleness` 설정을 통해 특정 파티션의 지연이 전체 Watermark 진행을 막지 않도록 하고, `timerState`의 TTL을 윈도우보다 길게 설정해 지연 상황에서도 감소 로직이 누락되지 않도록 보장했습니다. ### RocksDB와 런타임 최적화 * **Minutes 앱**: Write Buffer Manager(WBM) 압박을 완화하여 RocksDB가 쓰기를 멈추는 Write Stall 현상을 방지했습니다. * **Hours 앱**: Bloom Filter 및 메모리 설정을 통해 캐시 미스를 줄여 CPU 효율을 높였습니다. * **Days 앱**: 거대한 SST 파일로 인한 체크포인트 부하를 줄이기 위해 레벨 최적화와 Changelog 메커니즘을 적용했습니다. 대규모 데이터를 다루는 실시간 집계 시스템에서는 모든 구간을 하나의 설정으로 처리하기보다, 데이터의 규모와 병목 지점에 따라 앱을 분리하고 각기 다른 RocksDB 튜닝 전략을 적용하는 것이 운영 안정성 측면에서 효과적입니다. 또한, 상태(State)를 시스템의 최상위 데이터 원천으로 관리하는 원칙을 지킬 때 장애 복구와 데이터 정합성 유지가 훨씬 용이해집니다.

사업자 데이터 리터러시 높이기: BC Monthly Report 발행기 (새 탭에서 열림)

토스는 각 사업부별로 흩어져 있던 사업자(Business Customer, BC) 데이터를 통합하여 '단일 진실의 근원(SSOT)'인 데이터 마트를 구축하고, 이를 기반으로 전사적인 월간 리포트를 발행하여 비즈니스 의사결정 구조를 혁신했습니다. 이 과정에서 파편화된 지표 정의를 하나로 모으고 현업의 니즈를 반영한 결과, 전사 구성원들이 동일한 기준으로 사업 현황을 파악하고 데이터에 기반해 실질적인 액션 아이템을 도출할 수 있는 환경이 마련되었습니다. 이러한 여정은 단순한 데이터 정리를 넘어 토스 전반의 데이터 리터러시를 높이고 비즈니스 성장을 가속화하는 기폭제가 되었습니다. **단일 진실의 근원(SSOT)을 위한 데이터 마트 구축** * 쇼핑, 광고, 페이 등 각 사업부별로 분산되어 관리되던 사업자 데이터를 통합하여 전사적으로 공통된 언어를 사용하는 'BC 데이터 마트'를 설계했습니다. * 사업부별로 상이했던 매출과 비용 발생 기준을 표준화하기 위해 도메인 담당자들과의 소통을 거쳐 '토스에서 활동하는 사업자'에 대한 명확한 정의를 수립했습니다. * 이를 통해 "이번 달 매출을 발생시킨 사업자가 몇 명인가?"라는 기초적인 질문에 대해 전사가 동일한 숫자로 답변할 수 있는 기술적 기반을 마련했습니다. **통찰을 제공하는 Monthly BC Report 설계 및 자동화** * 데이터의 전파력을 높이기 위해 신규(New), 이탈(Churn), 유지(Retained) 트렌드와 매출 규모별 티어(Tier) 분석을 포함한 월간 리포트를 기획했습니다. * 단순 지표 나열이 아닌, 코호트 리텐션(Cohort Retention) 분석을 통해 플랫폼 만족도를 확인하고, 이탈 가맹점 리스트 등 실무자가 즉시 활용 가능한 로우 데이터(Raw Data)를 함께 제공했습니다. * 데이터 파이프라인은 Airflow를 통해 마트를 구축하고 Jenkins로 배치 작업을 수행하며, 최종적으로 태블로(Tableau)와 SQL을 연동해 매달 자동으로 업데이트되는 환경을 구현했습니다. **현업 피드백을 통한 리포트의 고도화와 데이터 리터러시 확산** * PO, 세일즈 팀장 등 실제 사용자의 니즈를 파악하기 위해 심층 인터뷰를 진행하고, 이를 바탕으로 '회원 가입' 단계 분석이나 도메인 간 활성화 순서 등 구체적인 지표를 리포트에 추가했습니다. * 리포트 발행 이후 사업자 데이터에 대한 전사적 관심이 급증하며, 이탈 가맹점 상세 분석이나 데일리 트래킹 등 후속 심화 분석 프로젝트로 이어지는 성과를 거두었습니다. * 고정된 포맷에 안주하지 않고 매달 현업의 피드백을 반영하여 지표를 개선함으로써, 조직 전체의 데이터 이해도와 활용 능력을 점진적으로 상향 평준화했습니다. 데이터 마트 구축과 리포트 발행은 끝이 아닌 시작이며, 현업과의 지속적인 피드백 루프를 통해 리포트를 ' 살아있는 문서'로 관리하는 것이 중요합니다. 조직 내 데이터 리터러시를 높이고 싶다면 표준화된 지표 정의부터 시작해 구성원들이 실제 업무에 바로 적용할 수 있는 액션 중심의 데이터를 제공하는 단계적 접근이 필요합니다.