확장 가능한 토픽
확장 가능한 토픽 (Scalable Topics)
파티션 토픽은 생성할 때 파티션 개수를 정해두고 시작하는데, 이 방식은 트래픽 변화에 따라 확장·축소하기 어렵고 크기 변경 시 키 순서가 깨지는 구조적 한계가 있어요. 확장 가능한 토픽(Scalable Topic)은 실행 중에 자신의 용량을 스스로 조절하는 토픽으로, 로드가 늘면 키 범위 세그먼트를 분할하고 줄면 병합해요. 이 글에서는 왜 필요한지, 어떻게 동작하는지, 기존 파티션 토픽과 무엇이 다른지 정리해 드릴게요.
출처: 문서
본문
확장 가능한 토픽은 실행 중에 자신의 용량을 스스로 조절하는 토픽이에요. 고정된 수의 파티션으로 생성되는 대신, 내부적으로 키 범위(key-range) 세그먼트로 나뉘어 있으며 브로커가 로드가 늘면 분할하고 줄면 병합해요. 다운타임도 없고 클라이언트 변경도 없으며 키별 순서 손실도 없어요. 확장 가능한 토픽은 topic:// 스킴으로 주소를 지정해요:
topic://tenant/namespace/name
참고 확장 가능한 토픽은 신규 애플리케이션에 권장되는 선택이에요. 기존 파티션 및 비파티션 토픽은 완전히 지원되며, 기존 애플리케이션과 아직 V5 API를 지원하지 않는 클라이언트에 적합해요. 아래 언제 무엇을 사용할까를 보세요.
확장 가능한 토픽이 필요한 이유
기존 파티션 토픽은 토픽을 만들 때 파티션 수를 고정해 확장해요. 이 모델에는 세 가지 구조적 한계가 있어요:
- 크기를 미리 맞춰야 해요. 파티션 수는 실제 트래픽을 알기 전에 정해지며, 토픽 수명 동안 최대 소비자 병렬성을 제한해요.
- 축소할 수 없어요. 파티션 토픽의 파티션 수는 늘릴 수 있지만 절대 줄일 수 없어서, 트래픽 급증을 위해 프로비저닝한 토픽은 영원히 과대한 크기를 유지해요.
- 크기 변경이 키 순서를 깨뜨려요. 메시지가 hash(key) % partitionCount로 라우팅되므로 파티션 수를 변경하면 키가 다른 파티션에 다시 매핑되어 키별 순서 보장이 깨져요.
확장 가능한 토픽은 이 세 가지 한계를 모두 제거해요. 용량이 로드를 따라 양방향으로 자동 조절되고, 모든 크기 변경에서 키별 순서가 보존돼요.
동작 방식
내부적으로 확장 가능한 토픽은 해시 키 공간을 일련의 세그먼트에 퍼뜨려요. 각 세그먼트는 키 공간의 연속적인 범위를 소유하며 자신의 내부 토픽으로 뒷받침돼요. 세그먼트들이 함께 방향성 비순환 그래프(DAG)를 형성해 범위가 시간에 따라 어떻게 분할·병합되었는지 기록해요.
- 분할(Split): 세그먼트가 뜨거워지면 컨트롤러가 키 범위를 둘로 나누고 각 절반을 새 자식 세그먼트에 넘겨줘요. 이렇게 하면 로드가 걸린 키 공간의 정확히 그 부분에 대한 병렬성이 높아져요.
- 병합(Merge): 인접한 세그먼트가 차가워지면 컨트롤러가 그 범위를 하나로 병합해 용량을 되찾아요.
- 범위 기반 키 라우팅: 메시지 키는 현재 자신의 해시 범위를 소유하는 세그먼트에 매핑돼요. hash(key) % N이 아니라 범위로 라우팅되므로, 분할이나 병합은 키를 여전히 그 키를 포함하는 부모 범위에서 자식 범위로만 옮겨요. 따라서 어떤 개별 키의 순서도 절대 깨지지 않아요.
이 분할/병합 활동은 브로커의 토픽별 컨트롤러가 주도하며 기본적으로 자동이에요. 분할과 병합을 수동으로 트리거할 수도 있어요. 세그먼트 토폴로지는 전적으로 서버에서 관리되고 변경 시 클라이언트로 푸시되므로, 애플리케이션은 세그먼트를 보거나 크기 변경에 반응할 필요가 없어요. 애플리케이션에게 확장 가능한 토픽은 그저 단일 스트림일 뿐이에요.
확장 가능한 토픽 vs 파티션 토픽
| 파티션 토픽 (기존) | 확장 가능한 토픽 | |
|---|---|---|
| 병렬성 단위 | 생성 시 설정한 고정 파티션 수 | 세그먼트; 실행 중에 수가 변함 |
| 확장 | 파티션 수 증가 (수동) | 뜨거운 세그먼트의 자동 분할 |
| 축소 | 불가능 | 차가운 세그먼트의 자동 병합 |
| 키 라우팅 | hash(key) % partitionCount |
범위 기반 해시 할당 |
| 크기 변경 시 키 순서 | 깨짐 (키가 파티션 간 재매핑) | 분할·병합에서도 보존됨 |
| 앱에 보이는 토폴로지 | 파티션 수와 인덱스가 노출됨 | 불투명; 브로커가 관리 |
| 클라이언트 | 모든 Pulsar 클라이언트 | V5 API를 지원하는 클라이언트 |
소비자 모델
확장 가능한 토픽은 4가지 기존 구독 유형(Exclusive, Failover, Shared, Key_Shared)을 세 가지 목적에 맞는 소비자로 대체하는 V5 클라이언트 API를 사용해요:
- 스트림 소비자(Stream consumer) — 누적 확인과 함께 순서 있는 소비를 제공해요. 순서가 중요한 로그 스타일 처리를 위한 것이며 Exclusive와 Failover를 대체해요.
- 큐 소비자(Queue consumer) — 개별 확인, 부정 확인, 데드레터 처리와 함께 병렬 소비를 제공해요. 작업 큐 스타일 팬아웃을 위한 것이며 Shared와 Key_Shared를 대체해요.
- 체크포인트 소비자(Checkpoint consumer) — 구독도 확인도 없고, 애플리케이션이 직렬화 가능한 체크포인트로 자신의 위치를 추적해요. Flink나 Spark처럼 자신의 오프셋을 관리하는 스트림 처리 엔진을 위해 설계됐어요.
각 소비자 유형은 V5 클라이언트 문서에서 자세히 다룹니다.
언제 무엇을 사용할까
- 신규 애플리케이션 — 확장 가능한 토픽을 추천해요. 자동으로 적정 크기가 맞춰지고 파티션 수를 고를 필요가 없어요.
- 기존 애플리케이션 — 기존 파티션 및 비파티션 토픽을 계속 사용하세요. 완전히 지원되며 마이그레이션 요구 사항이 없어요. 준비가 되면 기존 토픽을 데이터 복사 없이 제자리에서 확장 가능한 토픽으로 마이그레이션할 수 있어요.
- V5를 지원하지 않는 클라이언트 — 기존 토픽을 사용하세요. 확장 가능한 토픽은 V5 API를 지원하는 클라이언트 SDK가 필요해요 (아래 참조).
요구 사항
- V5 지원 클라이언트 SDK. 확장 가능한 토픽은 V5 클라이언트 API를 통해 제공되며, class API를 사용하는 클라이언트는 topic:// 주소로 접근하면 거부돼요. Java V5 클라이언트는 현재 확장 가능한 토픽을 지원하며, 다른 언어 SDK도 뒤를 이어 지원되고 있어요.
- 스트리밍 watch를 지원하는 메타데이터 저장소. Oxia가 권장돼요. 컨트롤러가 Oxia가 기본 지원하는 스트리밍 watch를 통해 토폴로지 변경을 클라이언트에 푸시하기 때문이에요. 아직 ZooKeeper를 사용 중이라면 메타데이터 저장소 마이그레이션을 보세요.
다음 단계
- 메타데이터 구성: 메타데이터 저장소 구성 및 ZooKeeper에서 Oxia로 메타데이터 저장소 마이그레이션.
- 비교를 위해 기존 토픽 모델 익히기: 메시징 개념 - 토픽.
더 알아보기 (Learn more)
- 메시징 개념 — 기존 파티션·비파티션 토픽 모델과 비교해 보세요.
- 확장 가능한 토픽 관리 API — 확장 가능한 토픽을 실제로 다루는 방법을 익혀요.
- 아키텍처 개요 — 브로커와 메타데이터 저장소 구조를 이해해요.