[Kafka] 카프카(Kafka) 이해
1. 카프카의 기본 역할: '브로커'
카프카 서버(클러스터)는 '브로커(Broker)' 즉, 중계인 역할을 합니다. 하지만 메시지의 내용을 보고 경로를 결정하는 '라우터'가 아닙니다.
카프카는 단순히 이름표가 붙은 수많은 큐(토픽)를 제공하고 관리하는 거대한 창고 🗄️ 역할만 합니다.
2. 프로듀서 (Producer)의 역할: '결정자'와 '발행자'
핵심: 메시지를 어떤 토픽으로 보낼지 결정하는 주체는 카프카 서버가 아니라 **프로듀서(채팅 서버)**입니다.
- 1. 토픽 결정: 프로듀서는 전달받은 메시지(예: {"group_id": "group-123", ...})의 내용을 봅니다.
- 2. 토픽 이름 지정: 메시지의 group_id를 보고 "이건 chat-group-123 토픽으로 보내야겠다"라고 스스로 결정합니다.
- 3. 직접 전달: 카프카 서버(브로커)에 직접 접속하여 produce('chat-group-123', ...)처럼 토픽 이름을 명시적으로 지정해 메시지를 '큐잉'합니다.
비동기 배치 전송: 프로듀서는 메시지를 1건씩 보내지 않습니다. 내부 버퍼에 메시지를 모았다가, 일정 개수나 시간이 되면 한 묶음(배치)으로 카프카 서버에 비동기 전송하여 효율을 높입니다.
3. 토픽 (Topic)의 구조: 'Queue'가 아닌 'Log' (가장 중요)
카프카 토픽은 기존의 큐(Queue)와 근본적으로 다릅니다.
- Queue (잘못된 개념): 데이터를 한 번 가져가면(pop) 사라집니다.
- Log (올바른 개념): 데이터(메시지)가 사라지지 않습니다. 마치 책의 페이지처럼 순서대로 쌓이기만 합니다. 📖
컨슈머가 메시지를 읽는 것은, 책의 페이지를 읽는 것과 같습니다. 읽는다고 해서 페이지가 찢겨나가지(pop) 않습니다.
4. 컨슈머 (Consumer)의 작동 원리
가. 컨슈머 그룹 (group.id)
카프카가 컨슈머를 식별하는 유일한 기준입니다. 이 ID가 모든 것을 결정합니다.
-
group.id가 다르면 (서로 다른 '북 클럽'):
- db-group과 push-group이 같은 토픽을 구독하면, 카프카는 이 둘을 완전히 별개의 구독자로 봅니다.
- 토픽에 메시지가 1개 오면 db-group도 받고, push-group도 받습니다. (Pub/Sub)
-
group.id가 같으면 (같은 '북 클럽'의 팀원):
- push-group이라는 이름으로 3대의 서버가 구독하면, 카프카는 이 3대를 **'하나의 팀'**으로 봅니다.
- 토픽에 메시지가 1개 오면, 3대의 서버 중 단 1대에게만 메시지가 전달됩니다. (작업 분산 / 로드 밸런싱)
나. 오프셋 (Offset)
토픽은 메시지를 'pop'하지 않기 때문에, "누가 어디까지 읽었는지"를 별도로 기록해야 합니다. 이것이 오프셋입니다.
- 오프셋 (Offset): 책의 '페이지 번호' (메시지의 고유 번호).
- 커밋된 오프셋 (Committed Offset): **'컨슈머 그룹'**별로 저장되는 '책갈피' 🔖입니다.
"**db-group은 chat-group-123 토픽의 102번 메시지까지 읽었음" (다음 읽을 차례: 103) "push-group**은 chat-group-123 토픽의 95번 메시지까지 읽었음" (다음 읽을 차례: 96)
다. 폴링 (Polling)
컨슈머는 poll() 메서드를 루프에서 계속 호출하여 카프카 서버에 "내 '책갈피' 위치 다음부터 읽을 새 메시지(페이지) 있어?"라고 주기적으로 물어봅니다(Pull).
- 이 방식은 컨슈머가 자신의 처리 속도에 맞춰 능동적으로 메시지를 가져가기 때문에, Push 방식처럼 서버가 데이터를 밀어 넣어 컨슈머가 과부하되는 것을 방지합니다.