우리 팀의 핵심 분석 파이프라인은 오랫동안 매일 새벽 한 번 도는 배치였습니다. 충분히 잘 작동했지만, 비즈니스가 성장하면서 마케팅 팀은 캠페인 반응을 몇 시간 내로 보고 싶어 했고, 운영 팀은 이상 징후를 다음 날이 아니라 즉시 알고 싶어 했습니다. 결국 우리는 준실시간 스트리밍으로의 전환을 결정했습니다. 이 글은 그 6개월의 솔직한 회고입니다.
화려한 성공담이 아니라, 무엇을 잘했고 무엇에서 피를 봤는지 담았습니다. 비슷한 전환을 앞둔 팀에 참고가 되길 바랍니다.
전환을 결정한 배경
배치의 가장 큰 한계는 지연이었습니다. 데이터가 발생하고 대시보드에 반영되기까지 평균 18시간이 걸렸습니다. 의사결정 속도를 높이려면 이 간극을 분 단위로 줄여야 했습니다. 동시에 배치 윈도가 점점 길어져 새벽 처리가 업무 시작 시각까지 밀리는 일도 잦아졌습니다.
우리는 모든 것을 한 번에 바꾸지 않기로 했습니다. 가장 가치가 높은 한 도메인(주문 이벤트)부터 스트리밍으로 전환하고, 나머지는 검증 후 점진적으로 옮기는 전략을 택했습니다.
아키텍처 선택
원천 데이터베이스의 변경을 잡기 위해 CDC(Change Data Capture)를 도입했습니다. Debezium으로 DB 트랜잭션 로그를 읽어 Kafka로 흘리고, 스트림 처리로 변환한 뒤 레이크하우스에 적재하는 구조입니다. 처음엔 람다 아키텍처로 배치와 스트리밍을 병행했지만, 두 코드베이스를 유지하는 비용이 커서 결국 키파 아키텍처에 가깝게 단순화했습니다.
중요한 결정 하나는 정확히 한 번 처리(exactly-once)를 어디까지 보장하느냐였습니다. 모든 구간에 강한 보장을 걸면 복잡도와 지연이 폭증합니다. 우리는 멱등 업서트로 최종 결과의 정합성만 보장하는 실용적 절충을 택했습니다.
피를 본 지점들
가장 고생한 것은 늦게 도착하는 데이터(late-arriving data)였습니다. 네트워크 지연이나 모바일 오프라인으로 이벤트가 몇 시간 늦게 도착하면 이미 집계된 윈도를 어떻게 보정할지가 문제였습니다. 워터마크와 허용 지연(allowed lateness)을 설정해 일정 시간까지는 보정하고, 그 이후는 별도 정정 테이블로 처리했습니다.
- 상태 폭증: 무한 윈도 집계로 상태 저장소가 커짐, TTL과 윈도 한정으로 해결
- 중복 이벤트: CDC 재시작 시 재전송, 멱등 키로 방어
- 스키마 변경: 원천 DDL 변경이 스트림을 깸, 스키마 레지스트리 도입
- 디버깅 난이도: 흐르는 데이터는 재현이 어려움, 모든 단계 로깅 강화
성과와 비용
전환 후 데이터 지연은 18시간에서 평균 4분으로 줄었습니다. 마케팅 팀의 캠페인 의사결정 주기가 하루에서 시간 단위로 빨라졌고, 운영 이상 탐지도 거의 실시간이 됐습니다. 다만 인프라 비용은 약 1.4배 늘었고, 운영 복잡도는 그 이상으로 증가했습니다.
스트리밍은 공짜가 아니다. 실시간이 정말 필요한 곳에만 적용하라. 나머지는 배치가 여전히 옳다.
정리와 교훈
가장 큰 교훈은 모든 것을 실시간으로 바꿀 필요는 없다는 것입니다. 비즈니스 가치가 분명한 도메인부터 점진적으로 전환하고, exactly-once 같은 이상에 매몰되지 말고 최종 정합성이라는 실용적 목표를 잡으세요. 늦게 도착하는 데이터와 상태 관리를 초기부터 설계에 포함하면 나중의 고통이 줄어듭니다.






