카프카를 왜 사용해야 할까?

반응형

카프카를 계속 공부해 왔지만, 솔직히 말하면 "왜 이걸 써야 하는지" 스스로 완전히 납득했다고 말하기는 어렵습니다.
문서와 강의에서는 늘 대규모 트래픽, 이벤트 스트리밍, 비동기 아키텍처 같은 이야기들이 나오지만, 막상 내 프로젝트와 내 문제를 떠올려 보면 카프카는 항상 거대한 산맥처럼 느껴졌습니다. 너무 크고, 너무 무겁고, 그래서 쉽게 다가가기 어려운 존재였습니다.
어쩌면 이 글에는 카프카를 사용하면서 겪은 고생담이나 운영 노하우는 없을지도 모릅니다. 대신, “그래서 우리는 도대체 카프카를 왜 쓰는가?”라는 질문에 대해, 적어도 나 스스로는 납득할 수 있는 답을 찾는 과정을 정리해 보려고 합니다. 이 글은 카프카를 잘 쓰는 방법이 아니라, 카프카를 써야 할 이유를 이해하기 위한 기록입니다.

카프카는 어떤 문제를 해결하려고 만들어졌는가?

카프카는 알다시피 LinkedIn에서 만들어졌습니다. 당시 LinkedIn은 수백 개의 서비스가 로그, 클릭 이벤트, 추천 피드 데이터, 활동 기록, 통계 데이터를 각기 다른 중앙 데이터 파이프라인으로 전송해야 하는 구조를 가지고 있었습니다.
이 구조에서는 각 서비스가 "내 데이터를 어디로 보내야 하는지"를 모두 알고 있어야 했고, 그 결과 서비스와 데이터 파이프라인 사이에는 수많은 직접 연결이 생겨났습니다. 시간이 지날수록 이 연결은 기하급수적으로 늘어났고, 구조는 점점 통제 불가능해졌습니다.

결국 데이터 유실, 순서 꼬임이 빈번하게 발생했고, 특정 파이프라인에 장애가 발생하면 그 영향을 여러 서비스가 함께 받는 상황이 되었습니다. 이 구조는 특정 파이프라인의 장애가 여러 서비스로 전파된다는 점에서, 과거 모놀리식 아키텍처가 가지던 문제와 매우 유사합니다. 하나의 문제가 시스템 전체로 번지는 구조, 그리고 변경 하나가 광범위한 수정과 배포를 요구하는 구조였습니다. 카프카는 이 문제를 "데이터 흐름"의 관점에서 분리함으로써 해결합니다. 모놀리식에서 MSA로 전환하는 방법 한 번 전송한 데이터는 재처리가 사실상 불가능했고, 새로운 소비 시스템을 추가하는 것 자체가 대규모 수정과 배포를 동반하는 작업이 되었습니다. 확장은 구조적으로 막혀 있었고, 운영 복잡도는 계속해서 누적되는 전형적인 운영 지옥의 형태였습니다.
결국 그들이 원했던 것은 "메시지를 전달하는 시스템"이 아니라, 모든 이벤트를 순서대로, 유실 없이, 그리고 언제든 다시 읽을 수 있는 중앙 이벤트 로그였습니다. 소비자가 죽어도, 시스템이 재시작되더라도, 언제든 같은 데이터를 다시 처리할 수 있는 구조. 카프카는 이 요구에서 출발했습니다. 그래서 카프카의 본질은 메시지 큐가 아니라, 이벤트 히스토리 저장소에 가깝습니다.

그래서 카프카랑 MQ랑 뭐가 다른거지?

겉보기에는 producer와 consumer를 연결하는 비동기 메시징 시스템이라는 점에서 두 시스템은 생각보다 많이 닮아 있습니다. 그래서 카프카를 재사용이 가능한 MQ 정도로 이해하고 싶어지기도 합니다. 하지만 둘의 출발점은 다릅니다. 카프카의 철학은 데이터를 쌓는 것이고, MQ의 철학은 데이터를 소비하는 것입니다. 

카프카가 데이터를 쌓는다고요? 그러면 쌓은 데이터는 언제든지 꺼내 쓸 수 있는건가?

카프카가 데이터를 쌓는 이유는 단순히 전달을 보장하기 위해서가 아니라, 언제든 다시 데이터를 재생(replay)하기 위해서입니다. 카프카에 기록된 이벤트는 소비되었다고 해서 사라지지 않고, 일정 기간 동안 로그로 남아 있습니다.
예를 들어 알림 서비스를 운영하고 있는데, 1시부터 알림 서비스가 장애로 인해 정상 동작하지 않았다고 가정해봅시다. 일반적인 MQ라면 이미 지나간 시간의 메시지를 다시 처리하는 것은 거의 불가능합니다. 하지만 카프카를 사용하고 있다면, 1시 시점의 이벤트부터 다시 읽어서 알림을 재전송하는 것이 가능합니다. 이처럼 카프카는 메시지를 전달하는 시스템이 아니라, 과거의 이벤트를 다시 재생할 수 있게 해주는 로그 저장소라는 성격을 가집니다.
그렇다고 해서, 시간을 거슬러 이벤트를 다시 재생(replay)하면 항상 문제가 없는 것은 아니다.카프카는 과거의 이벤트를 다시 흘려보낼 수 있을 뿐, 그로 인해 발생하는 중복 처리나 부작용까지 책임져 주지는 않습니다.
예를 들어 이미 전송된 알림을 다시 보내거나, 이미 처리된 결제를 다시 처리해버린다면 이는 곧바로 장애나 데이터 오염으로 이어집니다. 따라서 카프카를 사용하는 시스템에서는 다시 실행되어도 결과가 망가지지 않도록 멱등성(idempotency)을 반드시 고려한 설계가 필요하합니다. 카프카는 타임머신이 아니라, 재생 가능한 로그 저장소일 뿐입니다.

그러면 계속 말은 하고 있는데 여기서 말하는 로그는 뭘까?

계속 로그라는 표현을 쓰고 있는데, 여기서 말하는 로그는 무엇일까요? 글에서는 카프카를 로그 저장소라고 부르고 있습니다. 그렇다면 이 로그는 우리가 흔히 print()나 log.info()로 찍는 애플리케이션 로그를 의미하는 걸까요?
결론부터 말하면, 카프카에서 말하는 로그는 그런 로그가 아닙니다. 카프카의 로그는 시스템에서 실제로 일어난 사건(Event)들의 변경 이력을 의미합니다. 주문 생성, 결제 완료, 상태 변경 같은 비즈니스 이벤트들이 시간 순서대로 쌓인 기록이 바로 카프카에서 말하는 로그입니다.

그러면 카프카를 사용하면 어떤것을 포기해야 하는가?

카프카를 도입하면, 원래라면 단순한 API 호출 하나로 끝날 일을 일부러 카프카를 거쳐 한 바퀴 돌아가게 만드는 구조가 될 수 있습니다. 분명히 구조는 복잡해지고, 개발과 운영 비용도 올라갑니다. 카프카는 문제를 단순하게 만드는 기술이 아니라, 미래의 문제를 대비하기 위해 현재의 복잡함을 받아들이는 선택에 가깝습니다.

그럼에도 불구하고 카프카를 왜 사용해야 하는가?

그 이유는 언젠가 시스템의 시간이 자산이 되는 순간이 오기 때문입니다.
여기서 말하는 "시스템의 시간이 자산이 된다"는 것은, 장애로 인해 과거 이벤트를 다시 처리해야 할 때, 새로운 통계 로직을 만들고 과거 데이터부터 다시 계산해야 할 때, 혹은 새로운 서비스를 붙이고 기존 이벤트 전체를 다시 재생해야 하는 순간을 의미합니다.
그러면 이런 의문이 자연스럽게 듭니다. "그런 작업이 필요하면, 그냥 DB에서 다시 조회해서 처리하면 안 되는 걸까? DB로도 충분하지 않을까?"
물론 단순한 경우에는 DB로도 충분합니다. 하지만 DB에는 보통 최종 상태만 남아 있을 뿐, "어떤 과정을 거쳐 여기까지 왔는지"에 대한 정보는 남아 있지 않다. 반면 카프카에는 주문 생성, 결제 요청, 결제 완료 같은 이벤트의 전체 타임라인이 그대로 남아 있습니다.
DB가 결과를 저장하는 곳이라면, 카프카는 과정을 저장하는 곳입니다. 그리고 시스템의 시간이 자산이 된다는 말은, 바로 이 과정 전체를 다시 재생할 수 있는 능력이 필요해지는 순간을 의미합니다.

결론

이번 글에서는 카프카를 어떻게 쓰는가가 아니라, 왜 사용하는가 에 초점을 맞춰 정리해 보았습니다. 예전에는 카프카를 단순히 대규모 트래픽 환경에서 사용하는 MQ 정도로만 생각했습니다. 그렇게 생각해도 틀린 말은 아니지만, 지금 와서 보면 마치 소 잡는 칼로 닭을 잡는 것 같은 느낌이었습니다.
카프카를 사용하는 궁극적인 목적은, 과거의 이벤트를 다시 실행(replay)할 수 있다는 점에 있다고 생각합니다. 그리고 이것이 가능한 이유는 카프카가 단순한 메시지 브로커가 아니라, 이벤트를 시간 순서대로 저장하는 로그 저장소이기 때문입니다.
다만 카프카가 로그를 저장한다고 해서, 그 로그를 DB처럼 임의 조회하는 방식으로 사용하는 것은 카프카의 철학과 맞지 않습니다. 카프카는 로그를 순차적으로 제공하는 시스템이지, 조회를 위한 저장소가 아닙니다. 만약 조회가 목적이라면, 그때는 카프카가 아니라 차라리 DB를 사용하는 것이 더 적절하다고 생각합니다.
다음 글에서는, 이렇게 성격이 분명한 카프카를 어떤 기준으로, 어떻게 설정해야 하는지에 대해 한 번 더 고민해 보려고 합니다.

반응형

'개발 > kafka' 카테고리의 다른 글

카프카 of (프로듀서 and 컨슈머)  (0) 2025.09.05

댓글

Designed by JB FACTORY