티스토리 뷰

이전글:  2025.05.16 - [기술노트/Apach Kafka] - Kafka 기초4 - 컨슈머 그룹

지난 글에서는 카프카에서 데이터 소비의 확장성과 안정성을 책임지는 컨슈머 그룹과 메시지 전달 의미론에 대해 자세히 알아보았다. 컨슈머가 메시지를 잘 소비하기 위해서는, 그 메시지를 어딘가에 안전하게 보관하고 있다가 요청에 맞춰 전달하는 역할이 필수적이다.

 

바로 카프카 브로커(Kafka Broker) 가 그 중요한 임무를 수행하는 주체이다.

 

이번 글에서는 카프카 시스템의 핵심 구성원이자 데이터 저장과 전송의 실무를 담당하는 브로커에 대해 좀 더 구체적으로 파고들어 보고자 한다. 브로커가 무엇이고, 데이터는 어떻게 관리하며, 클라이언트와는 어떻게 소통하는지 설명하도록 하겠다.

 

브로커(Broker)란?

 

브로커는 카프카가 설치되어 실행 중인 서버 한 대를 의미한다.
브로커들이 하나 이상 모여 하나의 군집을 이루면 카프카 클러스터라고 부른다.

 

그림1. 카프카 클러스터 구조도


클러스터 내의 여러 브로커들은 서로를 구분하기 위해 숫자로 된 ID를 가진다.
예를 들어, 브로커 ID가 101, 102, 103과 같은 형식이다. 이 ID는 브로커 설정 파일에서 지정한다.

 

프로듀서가 보낸 메세지는 토픽으로 들어가고, 이 토픽은 다시 여러 개의 파티션으로 나뉜다.
이때, 파티션 데이터가 실제로 저장되는 물리적인 공간이 브로커이다.

 

Docker 운영 환경에서는 보통 각 브로커를 하나의 Docker 컨테이너로 구동한다.
즉, 브로커 1개 = 컨테이너 1개 = 카프카 서버 1개이다.

 

브로커와 파티션의 관계

 

카프카에서 데이터는 토픽이라는 주제로 묶이고, 각 토픽은 하나 이상의 파티션으로 나뉘어 관리된다.
여기서 중요한 점은 이 파티션들이 브로커에 어떻게 배치되는가 하는 점이다.

 

그림2. 클러스터, 토픽, 파티션 구조

 

카프카의 각 토픽은 하나 이상의 파티션으로 구성된다.
이 파티션들은 카프카 클러스터를 구성하는 여러 브로커 중 하나에 저장된다.

 

예를 들어, 클러스터에 브로커1, 브로커2 2개의 브로커가 존재하고, 토픽 A에 파티션이 2개(0, 1)이 존재한다고 가정한다.

이럴 경우 아래와 같이 자동으로 파티션들을 여러 브로커에 분산시켜 저장한다.

  • 브로커1: 토픽A 파티션 0
  • 브로커2: 토픽A 파티션 1

또는 상황에 따라,

  • 브로커 1이 토픽 A의 파티션 0과 1을 모두 가질 수도 있습니다.

이는 Kafka가 부하 분산확장성을 고려하여 자동으로 파티션을 할당하기 때문이다.
모든 파티션이 항상 고르게 분산되는 것은 아니며, Kafka는 최적의 분산을 위해 내부적으로 균형을 조정한다.

 

정리하자면,

  1. 토픽의 각 파티션은 하나의 브로커에 할당된다.
  2. 모든 파티션이 모든 브로커에 고르게 배치되지는 않는다.

 

리더와 팔로워

 

브로커 1이 파티션 0, 브로커2가 파티션 1을 담당하고 있을 때,
브로커2에서 장애가 발생하다면 파티션1에 담겨있는 정보는 손실이 발생할 수 있다.

 

이를 방지하기 위해 카프카에서는 복제(Replication) 기능을 제공한다.
복제 설정을 통해 하나의 파티션은 여러 브로커에 복사본으로 존재할 수 있다.

 

이때, 복제된 파티션은 다음과 같이 역할을 부여받는다.

  • 리더(Leader): 파티션의 실제 데이터 처리 주체, 모든 읽기/쓰기 요청은 반드시 리더를 통해 처리된다.
  • 팔로워(Follower): 리더 파티션을 동기화하며 백업 역할을 수행한다.직접적인 요청을 처리하지는 않지만, 리더가 장애를 일으켰을 때 자동으로 승격 된다.

이해를 돕기 위해 예를 들어 설명하면 다음과 같다.

 

Kafka 클러스터에 3개의 브로커가 있고, 토픽 A파티션 0복제 수 3(replication factor = 3) 으로 설정되어 있다고 가정한다. 이 경우, Kafka는 아래와 같이 각 브로커에 역할을 할당한다.

브로커 역할
1번 리더 (Leader)
2번 팔로워 (Follower)
3번 팔로워 (Follower)

 

이 구조에서:

  • 모든 메시지의 생산과 소비는 브로커 1(리더) 를 통해 처리된다.
  • 브로커 2와 3(팔로워) 은 리더의 데이터를 실시간으로 복제하면서 백업 노드로 대기한다.

만약 브로커 1에 장애가 발생하면, Kafka는 브로커 2 또는 3 중 하나를 자동으로 리더로 승격시켜 서비스가 중단되지 않도록 한다.

 

데이터 분산과 스케일링

 

Kafka의 가장 강력한 특징 중 하나는 데이터 분산 처리를 기반으로 한 높은 확장성이다.
이 확장성의 핵심에는 바로 브로커(broker) 가 있다.

 

Kafka는 각 토픽을 파티션(partition) 단위로 나누고, 이 파티션들을 여러 브로커에 분산 저장한다.
즉, 특정 브로커에만 데이터가 몰리지 않고, 클러스터 내 여러 브로커가 데이터 저장과 처리 부하를 나누어 맡는 구조다.

 

예를 들어, 토픽 A의 파티션 0은 브로커 1, 파티션 1은 브로커 2에 저장되는 식으로,

Kafka는 자동으로 파티션을 브로커에 분산시켜 처리량을 분산하고 병목을 방지한다.

 

Kafka는 수평적 확장(horizontal scaling) 이 매우 용이한 구조다.
데이터가 늘어나거나 더 많은 처리량이 필요할 경우, 복잡한 설정 없이 브로커를 하나 더 추가하기만 하면 된다.

  • 새로운 브로커를 클러스터에 추가하면, Kafka는 기존 파티션을 자동으로 재분배(rebalance) 하거나,
  • 새로 생성된 파티션이 추가된 브로커에 자동으로 할당되도록 한다.

이를 통해 기존 브로커에 집중되던 부하가 자연스럽게 분산되며,
전체 시스템의 처리 성능과 저장 용량이 유연하게 확장된다.

 

리밸런싱(Rebalancing) 시 유의할 점

 

브로커를 추가하거나 제거할 때 Kafka는 파티션의 위치를 재조정하게 된다.
이를 리밸런싱이라고 부르며, 운영 중에 다음 사항들을 반드시 고려해야 한다:

  • 리밸런싱 중에는 데이터 이동이 발생하므로 네트워크 부하와 디스크 I/O가 증가한다.
  • 일시적인 성능 저하가 발생할 수 있으며, 클러스터 상태가 불안정할 수 있다.
  • 따라서 운영 중 리밸런싱을 수행할 때는 트래픽이 적은 시간대에 계획적으로 수행하는 것이 좋다.
  • 수동으로 리밸런싱을 수행하려면 Kafka에서 제공하는 kafka-reassign-partitions.sh 스크립트를 사용할 수 있다.

 

브로커 축소(Shrinking) 시 고려사항

 

브로커를 제거하거나 축소하려는 경우에도 주의가 필요하다.

  • 해당 브로커에 존재하는 파티션들을 다른 브로커로 사전에 이동시켜야 한다.
  • 복제본(replica)이 존재하더라도 리더 파티션이 해당 브로커에 있다면 장애 발생으로 이어질 수 있다.
  • 따라서 축소 전에는 반드시 파티션 리더와 복제 상태를 확인하고, kafka-reassign-partitions.sh 를 통해 안전하게 재배치한 후 제거해야 한다.

 

부트스트랩 브로커(Bootstrap Broker)란?

 

Kafka의 뛰어난 확장성과 분산 구조 덕분에 클러스터에는 수십 개 이상의 브로커가 존재할 수 있다. 그렇다면 Kafka 클라이언트(프로듀서나 컨슈머)는 이 수많은 브로커 중 어떤 브로커에 먼저 연결해야 할까?

 

Kafka에서는 이 문제를 부트스트랩 브로커(bootstrap broker) 를 통해 해결한다.

 

부트스트랩 브로커는 카프카가 클러스터에 처음 연결할 때 필요한 브로커의 주소 목록을 의미하며, 클라이언트 설정 파일(producer.properties, consumer.properties 등)에서 bootstrap.servers 항목에 "host:port" 형식의 브로커 주소들을 콤마(,)로 구분해 한두 개만 적어주면 된다.

bootstrap.servers=broker1:9092,broker2:9092

 

이 목록에 있는 하나의 브로커라도 정상적으로 연결되면, 클라이언트는 클러스터에 있는 모든 브로커 정보와 구조를 자동으로 인식하게 된다.

 

클러스터 구조 파악 과정

 

부트스트랩 브로커를 통한 클러스터 구조를 파악하는 과정은 다음과 같다:

  1. 클라이언트는 부트스트랩 브로커 중 하나에 접속하여 메타데이터(metadata) 를 요청한다.
  2. 이 메타데이터에는 다음과 같은 정보가 포함되어 있다:
    • 클러스터에 존재하는 모든 브로커의 목록
    • 토픽의 이름, 파티션 수
    • 각 파티션이 어느 브로커에 저장되어 있는지
    • 각 파티션의 리더 브로커 정보

클라이언트가 '토픽 A의 파티션 0'의 리더가 브로커 101이라는 정보를 받으면, 이후에는 해당 브로커로 직접 메시지를 보내거나 데이터를 읽게 된다.

 

Kafka의 브로커는 단순한 데이터 저장소가 아니다. 각 브로커는 클러스터 전반의 구조 정보를 공유하고 중개하는 역할도 수행한다.

 

컨트롤러 브로커(Controller)의 역할

 

카프카 클러스터의 안정적인 운영을 위해 컨트롤러 브로커라는 특별한 역할이 존재한다. 컨트롤러 브로커는 다음과 같은 중요한 기능을 담당한다:

  • Kafka 클러스터에는 컨트롤러 역할을 맡는 브로커가 존재한다.
  • 이 컨트롤러는 클러스터 전체의 메타데이터를 관리하며, 토픽/파티션 리더 할당, 브로커 장애 감지 등을 담당한다.
  • 이 정보는 다른 모든 브로커와 실시간으로 동기화된다.

덕분에 클라이언트가 부트스트랩 브로커로 접속하면, 해당 브로커는 컨트롤러로부터 전달받은 정보를 바탕으로 전체 클러스터 상황을 응답해줄 수 있다.

 

브로커 장애와 고가용성

카프카 클러스터에서 브로커 장애 발생 시에도 시스템이 계속 작동할 수 있는 이유는 이러한 부트스트랩 메커니즘 덕분이다. 클라이언트는 처음에 연결했던 브로커에 문제가 생겨도 메타데이터를 통해 다른 브로커에 자동으로 연결할 수 있다.

 

특히 복제(replication) 기능과 함께 구성되면, 리더 브로커에 장애가 발생해도 팔로워 브로커 중 하나가 새로운 리더로 선출되고, 이 정보가 메타데이터를 통해 클러스터 전체에 공유된다. 클라이언트는 메타데이터 갱신을 통해 새로운 리더를 알게 되고, 서비스 중단 없이 계속해서 데이터를 주고받을 수 있다.

 

효율적인 부트스트랩 브로커 구성 방법

 

부트스트랩 브로커 설정 시 다음과 같은 모범 사례를 따르는 것이 좋다:

  1. 여러 브로커 지정하기: 최소 2-3개의 브로커를 부트스트랩 목록에 포함시켜 가용성을 높인다.
  2. 서로 다른 장비에 위치한 브로커 선택하기: 네트워크나 하드웨어 장애에 대비해 서로 다른 물리적 위치의 브로커를 선택한다.
  3. 주기적인 메타데이터 갱신: 클라이언트는 주기적으로 메타데이터를 갱신하여 클러스터 변화에 대응할 수 있다.

이러한 부트스트랩 메커니즘은 카프카의 고가용성과 확장성의 핵심 요소로, 대규모 분산 시스템에서 안정적인 메시징을 가능하게 하는 기반이다.

 

맺음말

 

지금까지 카프카의 부트스트랩 브로커 개념과 클러스터 연결 과정에 대해 살펴보았다. 부트스트랩 브로커는 카프카 클라이언트가 분산된 브로커 클러스터에 효율적으로 연결할 수 있게 해주는 첫 관문이다. 이를 통해 클라이언트는 클러스터의 전체 구조를 파악하고, 필요한 브로커와 직접 통신할 수 있게 된다.

다음 글에서는 카프카의 핵심 기능 중 하나인 토픽 복제(Topic Replication) 에 대해 자세히 알아보겠다.

 

참고 및 출처

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함