
카프카(Kafka)란?
Kafka는 원래 LinkedIn에서 개발되었고, 처음에는 로그 수집 및 스트리밍 플랫폼으로 사용되었습니다. 하지만 시간이 지나면서 그 기능이 마이크로서비스 간 통신에 적절하다고 생각되어 많은 곳에서 MSA 구조를 구현하는 데 사용되고 있습니다. 저는 마이크로서비스에서 사용되는 카프카에 대해 이해해 보고 간단한 실습을 진행해 보았습니다.
카프카 구성 요소
- 생산자 (Producer)
카프카에 특정 토픽을 이용한 메시지를 전송하는 클라이언트 애플리케이션을 의미합니다.
- 소비자 (Consumer)
소비자는 카프카에 특정 토픽을 구독합니다. 어떤 생산자가 해당 토픽을 발행하면 카프카로부터 해당 토픽과 메시지를 가져옵니다.
- 브로커 (Broker)
카프카의 서버. 하나의 브로커는 여러 개의 파티션을 관리합니다. 그리고 브로커 여러 개가 모여 하나의 클러스터를 구성합니다.
- 토픽 (Topic)
메시지의 카테고리라고 생각하면 됩니다. 하나의 토픽은 하나 이상의 파티션으로 구성됩니다.
- 파티션 (Partition)
토픽 내에서 메시지를 순서대로 저장하는 단위. 하나의 파티션에는 여러 메시지가 저장될 수 있고(메시지가 순서대로 추가되어 저장됨), 메시지는 오프셋을 기준으로 정렬됩니다.
- 오프셋 (Offset)
파티션 내에서 메시지의 고유한 위치를 나타내는 식별자. 소비자는 오프셋을 이용해 특정 메시지를 읽을 수 있습니다. 파티션 내에 여러 메시지가 존재하는데, 여기서 소비자는 자신이 마지막으로 읽은 메시지 이후 메시지를 모두 읽어야하기 때문에 이 위치를 오프셋이라는 개념으로 저장합니다.
- 소비자 그룹 (Consumer Group)
동일한 토픽을 구독하는 소비자를 묶어놓은 그룹.
카프카 동작 순서
- 메시지 생산 (Production)
생산자가 브로커에 특정 토픽으로 메시지를 전송합니다. - 메시지 저장 (Storage)
브로커는 받은 메시지를 해당 토픽의 파티션에 저장합니다. 이때 저장할 파티션은 기본적으로 라운드 로빈 방식(순서대로 무한 반복)을 이용해 선정합니다. 메시지는 디스크에 영구적으로 기록되며, 이로 인해 내구성을 보장합니다. - 메시지 소비 (Consumption)
소비자는 특정 토픽을 구독하고, 메시지를 읽기 위해 카프카 클러스터에 연결합니다. 구독한 토픽에서 새로운 메시지가 도착하면, 소비자는 해당 메시지를 처리합니다. - 오프셋 관리 (Offset Management)
컨슈머는 메시지를 읽은 후, 메시지를 추적하기 위해 오프셋을 기록합니다. 이는 컨슈머가 마지막으로 읽은 메시지의 위치를 저장하여, 다음에 메시지를 읽을 때 중복 처리 없이 이어서 처리할 수 있도록 합니다. - 브로커 간의 복제 (Replication)
카프카는 데이터의 내구성을 높이기 위해 각 파티션의 복제본을 다른 브로커에 저장합니다. 이로 인해 특정 브로커가 실패하더라도 데이터 손실 없이 서비스가 지속될 수 있습니다. - 소비자 그룹 내 메시지 분배 (Message Distribution within Consumer Groups)
같은 소비자 그룹에 속한 소비자가 같은 토픽을 구독하면, 카프카는 각 파티션의 메시지를 그룹 내 소비자 간에 분산시켜 처리합니다. 이로 인해 스케일 아웃이 가능하고, 더 많은 요청을 처리할 수 있게 됩니다.
카프카를 MSA에서 사용할 때
카프카를 MSA에서 사용할 때 이해해야할 것들이 조금 있습니다.
1. 소비자 그룹을 통해 스케일 아웃하기
MSA 구조를 사용하는 주된 이유는 스케일 아웃일 것입니다. 특정 서버에 트래픽이 몰리면 해당 서버를 여러 개 띄우는 것이죠. 이때 문제가 될 수 있는 부분이 생깁니다. 예를 들어 결제 로직을 담당하는 서버가 총 3개가 띄어져 있다고 가정합시다. 이때 결제를 해달라고 생산자가 카프카에 결제 관련 토픽을 전송했다고 합시다. 그러면 결제 서버 3개 모두 결제 관련 토픽을 구독하고 있을 것이기 때문에 3개 서버 모두 해당 메시지를 가져가고 결제 로직을 처리할 것입니다. 결과적으로 결제가 3번 이뤄지는 문제가 발생하죠.
이때 소비자 그룹이 이런 문제점을 해결해줍니다. 소비자 그룹은 그룹 내 소비자들이 동일한 메시지를 중복해서 소비하지 않게 관리하기 때문입니다. 즉, 소비자1은 파티션1에 저장된 메시지만 가져가고 소비자2는 파티션2에 저장된 메시지만 가져가서 중복된 작업이 이뤄지지 않게 방지합니다.
'백엔드' 카테고리의 다른 글
| [ELK] Filebeat 핵심 요약 및 설정법 (0) | 2025.02.08 |
|---|---|
| npm에서 yarn으로 갈아타기(yarn berry) (0) | 2024.11.07 |
| MSA 구조 구성의 핵심: 메시지 큐(Message Queue)란? - RabbitMQ, Kafka, Redis (0) | 2024.11.04 |
| 캐싱 전략을 이용한 백엔드 성능 향상 (0) | 2024.11.02 |
| NestJS vs Spring vs Django 무엇을 사용해야할까? (0) | 2024.10.29 |