실시간 사기 분석 파이프라인 구축하기
아키텍처 살펴보기: 초당 5만 건의 이벤트를 수집하고 스마트 시그널로 보강한 뒤, 스트리밍 엔진으로 10ms 이내에 위험도를 산출하는 방법.
초당 50,000건의 핑거프린트 이벤트를 처리하고, 각 이벤트를 스마트 시그널로 보강하며, 10밀리초 이내에 위험 점수를 반환하려면 세심하게 설계된 스트리밍 아키텍처가 필요합니다. 이 글에서는 수집부터 판정까지 우리의 파이프라인을 단계별로 살펴봅니다.
수집 계층
이벤트는 방문자의 브라우저에서 실행되는 우리의 JavaScript 에이전트로부터 HTTPS POST 요청으로 도착합니다. 각 이벤트에는 암호화된 시그널 페이로드가 담겨 있으며, 일반적으로 130개 이상의 브라우저 시그널을 포함한 8~12KB의 압축 데이터입니다. 우리의 엣지 서버는 TLS를 종료하고, 요청 서명을 검증한 뒤, 페이로드를 처리 파이프라인으로 전달합니다.
우리는 엣지 서버를 고객의 CDN 노드와 코로케이션하는 멀티 리전 배포를 사용합니다. 이를 통해 전 세계 요청의 95%에서 네트워크 왕복 시간을 20ms 이하로 유지합니다. 엣지 서버는 로드 밸런서 뒤에서 실행되는 무상태(stateless) Go 서비스로, 요청량에 따라 수평으로 확장됩니다.
시그널 추출
첫 번째 처리 단계에서는 시그널 페이로드를 복호화하고 파싱합니다. 각 시그널은 추출되고, 검증되며, 타입이 지정됩니다. Canvas 해시는 알려진 불가능한 값(캔버스 차단 또는 스푸핑을 의미)과 대조하여 검증됩니다. WebGL 파라미터는 일관성을 위해 교차 검증됩니다. Navigator 속성은 알려진 유효한 조합과 대조하여 확인됩니다.
이 단계에서는 시그널 정규화도 수행합니다. User agent 문자열은 구조화된 구성 요소(브라우저, 버전, OS, 기기)로 파싱됩니다. 화면 크기는 DPI 스케일링을 고려하여 정규화됩니다. 타임존 오프셋은 IP 지오로케이션 데이터와 대조하여 검증됩니다.
스마트 시그널 보강
추출된 시그널은 이어서 스마트 시그널 분석 — 우리의 서버 측 인텔리전스 계층 — 으로 보강됩니다. 여기에는 시크릿 모드 탐지(시그널 패턴을 알려진 프라이빗 브라우징 시그니처와 비교), VPN 탐지(IP 데이터를 타임존 및 로케일 시그널과 상호 참조), 브라우저 변조 탐지(시그널 스푸핑을 나타내는 불일치 식별), 가상 머신 탐지(VMware, VirtualBox, 클라우드 VM과 연관된 하드웨어 프로필 인식)가 포함됩니다.
각 스마트 시그널은 독립적으로 계산되며, 불리언 결과와 신뢰도 점수를 함께 생성합니다. 보강 단계는 각 이벤트에 24개의 추가 시그널을 더하여, 클라이언트 측 수집만으로는 달성할 수 없는 포괄적인 위협 평가를 제공합니다.
위험 스코어링 엔진
보강된 이벤트는 우리의 위험 스코어링 엔진으로 전달됩니다. 이는 레이블이 지정된 수백만 건의 이벤트로 학습된 그래디언트 부스팅 의사결정 트리 모델입니다. 이 모델은 130개 이상의 원시 시그널, 24개의 스마트 시그널, 그리고 몇 가지 파생 특징 — 속도 지표(지난 5분, 1시간, 24시간 동안 이 기기에서 발생한 이벤트 수), 과거 행동 패턴, 네트워크 평판 점수 — 를 모두 고려합니다.
모델은 0에서 100 사이의 위험 점수와 함께 주요 기여 요인을 출력합니다. 예를 들어 85점에는 "VPN 탐지됨", "시크릿 모드", "높은 속도 — 5분 동안 47건의 이벤트"와 같은 요인이 함께 제시될 수 있습니다. 이러한 설명 가능성은 특정 이벤트가 왜 플래그되었는지 이해해야 하는 사기 분석가에게 매우 중요합니다.
저장 및 쿼리 계층
모든 이벤트는 ClickHouse — 대규모 데이터셋에 대한 분석 쿼리에 최적화된 컬럼형 데이터베이스 — 에 저장됩니다. ClickHouse는 우리의 쓰기 처리량(초당 5만 건의 이벤트)을 손쉽게 감당하며, 컬럼형 저장 방식 덕분에 수십억 행에 대한 분석 쿼리를 1초 이내에 처리할 수 있습니다.
우리는 다계층 보존 전략을 사용합니다. 핫 데이터(최근 7일)는 100ms 이하의 쿼리 응답을 위해 NVMe SSD에 저장됩니다. 웜 데이터(7~90일)는 일반 SSD에 저장됩니다. 콜드 데이터(90일 이상)는 압축되어 오브젝트 스토리지로 이동되며, 쿼리는 가능하지만 지연 시간이 더 높습니다.
중추로서의 Kafka
Apache Kafka가 파이프라인을 하나로 묶습니다. 모든 단계는 Kafka 토픽에서 읽고 씁니다. 수집 계층은 원시 이벤트를 씁니다. 시그널 추출 단계는 원시 이벤트를 읽고 추출된 이벤트를 씁니다. 스마트 시그널 보강 단계는 추출된 이벤트를 읽고 보강된 이벤트를 씁니다. 위험 스코어링 엔진은 보강된 이벤트를 읽고 점수가 매겨진 이벤트를 씁니다.
이 아키텍처는 여러 가지 이점을 제공합니다. 각 단계를 독립적으로 확장할 수 있고, 한 단계의 장애가 다른 단계에 영향을 주지 않으며, 디버깅이나 재처리를 위해 어느 단계로든 이벤트를 재생(replay)할 수 있습니다. Kafka의 컨슈머 그룹은 각 단계 내에서 병렬 처리를 가능하게 하고, 정확히 한 번(exactly-once) 시맨틱은 어떤 이벤트도 두 번 처리되거나 유실되지 않도록 보장합니다.
지연 예산
우리의 엔드투엔드 지연 목표는 보강된 시그널 페이로드가 처리 파이프라인에 도착한 순간부터 위험 점수가 반환되는 순간까지 10ms입니다. 예산은 다음과 같이 분배됩니다. 시그널 추출에 12ms, 스마트 시그널 보강에 34ms, 위험 스코어링에 23ms, 직렬화 및 응답에 12ms가 소요됩니다. 단계 사이의 Kafka 홉은 코로케이션 배포 환경에서 1ms 미만을 추가합니다.
초당 5만 건의 이벤트에서 이 예산을 일관되게 지키려면 모든 단계에서 세심한 최적화가 필요합니다. 우리는 사전 할당된 메모리 풀, 제로 카피(zero-copy) 직렬화, 배치 처리된 ClickHouse 쓰기를 사용합니다. 위험 스코어링 모델은 ONNX Runtime을 사용해 네이티브 코드로 컴파일되어 Python 인터프리터 오버헤드를 제거합니다.
Mark는 파이프라인을 2주 동안 프로파일링한 끝에 분산 조회 계층에서 병목을 찾아냈습니다. 단일 뮤텍스가 모든 고루틴에 걸친 조회를 직렬화하고 있었던 것입니다. 샤딩된 락 설계로 전환한 뒤 p99가 48ms에서 9ms로 떨어졌습니다. 때로는 원인을 찾고 나면 해결책이 민망할 만큼 간단합니다.