Kafka 토픽 키(key) 설정 전략: 10분 완독 가이드 (Java + AWS MSK 기준)

GarionNachal·2026년 1월 25일

kafka

목록 보기
18/23
post-thumbnail

Kafka에서 키(key) 는 단순한 “식별자”가 아니라, 파티션 라우팅(부하 분산)파티션 내 순서 보장을 동시에 결정하는 설계 레버입니다. 잘 잡으면 확장성이 좋아지고, 잘못 잡으면 핫 파티션/지연/리밸런스 폭탄/확장 불가로 이어집니다. Source


빠른 그림으로 시작: “키 → 파티션 → 순서”

키가 있으면(serialize된 keyBytes가 있으면) 기본 파티셔너는 murmur2 해시 → 파티션 수로 mod 해서 파티션을 정합니다. 키가 동일하면 같은 파티션으로 가므로, 그 파티션 안에서는 순서가 유지됩니다(토픽 전체 순서 보장은 아님). Source


목차

  1. 키가 실제로 하는 일(정확히)
  2. 키 전략 선택 가이드(의사결정 트리)
  3. 대표 키 전략 패턴(언제/왜/주의점)
  4. 흔한 실수/안티패턴 Top 10
  5. MSK 운영 팁: 파티션/브로커 관점
  6. Java 예제: 키 설계 구현 패턴
  7. 검증/모니터링 체크리스트
  8. 참고 자료

키가 실제로 하는 일(정확히)

1) 순서 보장은 “키”가 아니라 “파티션” 단위

Kafka가 보장하는 ordering은 파티션 단위입니다. 그래서 “같은 키로 같은 파티션에 모으는 것”이 곧 “그 키 범위의 순서를 보장하는 트릭”입니다. Source

2) 키가 있으면: murmur2(keyBytes) % partitionCount

기본 파티셔너는 키가 존재할 때 32-bit murmur2 해시 + mod 로 파티션을 선택합니다. Source

이 말은 곧:

  • 파티션 수가 바뀌면(파티션 추가) 키→파티션 매핑이 크게 바뀔 수 있음
  • “키는 잘 골라도” 파티션 증설이 순서/상태 처리에 영향을 줄 수 있음

3) 키가 없으면(null key): 균등 분산(그리고 최신 Kafka는 sticky 최적화)

키가 없을 때는 파티션을 임의 선택/분산하는 모드가 동작합니다. 특히 Kafka 2.4+에서는 “sticky” 방식으로 배치 단위 효율을 올리는 최적화가 언급됩니다. Source


키 전략 선택 가이드(의사결정 트리)

아래 트리는 “키를 무엇으로 할지”를 5분 안에 결정하기 위한 실전용입니다.

Step 0. 내 토픽의 1차 목표는?

  • A) 순서/집계/상태처리(Join/Aggregation)가 중요하다
  • B) 처리량/부하 분산이 최우선이고 순서가 덜 중요하다
    이 선택이 키 전략을 거의 결정합니다. “생산자 관점”이 아니라 “소비자가 무엇을 하느냐”가 기준입니다. Source

의사결정 트리(텍스트 버전)

1) “엔티티 단위 순서”가 필요한가?

  • 예: 주문(orderId), 계좌(accountId), 사용자(userId), 기기(deviceId) 단위로 이벤트 순서가 반드시 필요
    • YES → 엔티티 ID를 키로 (orderId, accountId …)
    • NO → 2)로

2) 소비자가 특정 기준으로 “모아서(aggregate) 처리”해야 하는가?

  • 예: queryId별 집계, tenantId별 집계, sessionId별 집계
    • YES → 그 집계 기준을 키로 (queryId, tenantId, sessionId)
    • NO → 3)로

3) “핫 파티션” 위험이 높은가?

  • 상위 1% 키가 트래픽 대부분을 만든다(대형 고객/슈퍼 유저/특정 캠페인/특정 상품 등)
    • YES → 4)로
    • NO → 엔티티/집계 기준 키로 충분 (또는 null key)

4) 핫 키를 분산할 때 “순서 보장 범위”를 줄일 수 있는가?

  • YES(부분 순서 허용) → 샤딩 키(키에 버킷 추가)
    예: orderId#bucket, tenantId:userId#bucket
  • NO(엄격 순서 필요) → 토픽/모델 재설계 고려
    • (a) 2단계 파이프라인: 1차는 랜덤/균등 분산 → 2차에서 집계 기준으로 재파티션(추가 토픽)
      New Relic 사례에서도 “핫스팟”을 겪고, 중간 단계로 완화하는 접근을 설명합니다. Source
    • (b) 핫 엔티티만 별도 토픽/별도 처리 경로(“VIP lane”)

5) 순서도 집계도 크게 중요하지 않은가?

  • YES → null key(키 없음) + 충분한 파티션으로 균등 분산

대표 키 전략 패턴(언제/왜/주의점)

1) 엔티티 ID 키 (가장 기본)

  • 키: orderId, userId, accountId
  • 장점: 해당 엔티티 단위 순서/상태 처리가 쉬움
  • 단점: 트래픽이 특정 엔티티에 몰리면 핫 파티션

Kafka가 같은 키를 같은 파티션으로 보내 순서를 보장하는 메커니즘은 이 전략의 기반입니다. Source


2) 복합 키(Composite Key): 멀티테넌트/도메인 분리

  • 키: tenantId:userId, storeId:orderId
  • 장점: 테넌트 격리 + 엔티티 순서 동시 확보
  • 단점: 키 설계가 복잡해지고, “무엇을 기준으로 join/aggregate하는가”가 흔들릴 수 있음

3) 샤딩 키(Hot key 완화용)

  • 키: orderId#0..N, userId#bucket
  • 장점: 핫 엔티티 부하 분산
  • 단점: 엄격한 “엔티티 단위 전체 순서”는 포기(혹은 애플리케이션이 재정렬/집계를 해야 함)

4) 키 없음(null key): 최대 처리량, 최소 제약

  • 장점: 균등 분산에 유리 → 소비자 스케일이 쉬움(embarrassingly parallel)
  • 단점: 관련 이벤트를 한 곳으로 모으는 보장이 약함

“랜덤 파티셔닝은 부하를 가장 고르게 퍼뜨려 스케일이 쉽다”는 설명이 대표적입니다. Source


흔한 실수/안티패턴 Top 10

1) “키를 랜덤 UUID로 준다”

겉보기엔 분산이 잘 되지만, 사실상 키 기반 의미를 다 잃고 순서/집계/상태 처리에서 아무 이점이 없습니다. 차라리 키를 비우고(null key) 의도를 명확히 하는 편이 낫습니다.

2) “region/country 같은 low-cardinality 값을 키로”

키 공간이 작으면 특정 파티션에 트래픽이 몰립니다(핫 파티션). 특히 “KR/US/JP” 같은 값은 위험합니다.

3) “고객/테넌트만 키로” (멀티테넌트에서 자주 터짐)

대형 테넌트가 전체 트래픽을 먹으면 그 테넌트 파티션이 병목이 됩니다. 필요하면 tenantId:userId 같은 복합 키 또는 샤딩이 필요합니다.

4) “파티션 수를 아무 때나 늘려도 된다”

기본 파티셔닝은 hash(key)%N 이라 N이 바뀌면 매핑이 크게 바뀝니다. Source
상태ful 처리(Kafka Streams, Flink state, 캐시 locality)가 있으면 재파티셔닝 비용이 커집니다.

5) “핫 파티션이 생기면 브로커만 늘리면 된다”

핫 파티션은 “특정 파티션의 리더가 받는 부하” 문제라, 브로커를 늘려도 키가 바뀌지 않으면 병목 파티션이 그대로 남는 경우가 많습니다.

6) “키를 비즈니스적으로 바꿨는데 소비자 영향 고려 안 함”

키 변경은 파티션 변경을 뜻하고, 곧 “순서/처리 주체(consumer instance)/상태”가 달라집니다. 롤아웃 전략이 필요합니다(새 토픽 + 이중발행, 리플레이 등).

7) “키 직렬화/정규화가 일관되지 않음”

예: 어떤 서비스는 "00123", 다른 서비스는 "123"을 같은 의미로 씀 → 서로 다른 파티션으로 갈 수 있음. “키는 계약(Contract)”입니다.

8) “메시지 키에 너무 긴 문자열/복잡한 JSON을 넣음”

키는 라우팅 목적이므로 최소한으로 유지하는 편이 좋습니다(해시/네트워크/스토리지 오버헤드).

9) “집계가 필요한데 키를 안 준다”

소비자가 어차피 다시 그룹핑해야 해서 비용이 올라가고, 순서 보장도 깨집니다.

10) “핫스팟을 발견했는데, 설계를 바꾸지 않고 모니터링만 한다”

New Relic 사례에서도 일부 key가 대부분 이벤트를 차지해 “unlucky partition” 핫스팟이 발생했다고 언급합니다. 이런 경우는 구조적 처방(샤딩/2단계 집계/토픽 분리)이 필요합니다. Source


MSK 운영 팁: 파티션/브로커 관점

키 전략은 결국 “파티션 부하 분산” 문제로 귀결되며, MSK에서는 브로커 자원/운영 제약과 직결됩니다.

1) (매우 중요) 브로커당 파티션 수 가이드를 무시하면 “업데이트가 막힐” 수 있음

MSK는 브로커 사이즈별로 권장 파티션 수(리더+팔로워 포함) 와 “업데이트를 지원하는 최대 파티션 수”를 제시합니다. 이 한도를 넘으면 클러스터 구성 업데이트 등 운영 작업이 제한될 수 있습니다. Source

2) CPU 60% 이하 권장: 키 스큐는 CPU를 한쪽으로 몰아넣는다

MSK는 브로커 CPU(User+System) 60% 이하 유지를 강하게 권장합니다. 파티션 리더가 불균형하면 특정 브로커 CPU가 먼저 차고, 지연이 연쇄적으로 늘어납니다. Source

3) “스케일 아웃 vs 스케일 업”을 키/파티션과 함께 봐야 함

AWS의 사이징 관점에서 클러스터 처리량 한계는 스토리지/네트워크/복제/컨슈머 그룹 수 등에 의해 결정될 수 있고, 스케일 전략(브로커 수 vs 브로커 크기)은 병목 지점에 따라 달라집니다. Source

키 설계가 좋으면:

  • 파티션 부하가 고르게 퍼져 스케일 아웃이 효율적
    키 설계가 나쁘면:
  • 특정 파티션/브로커가 병목이라 스케일 업을 해도 한계가 빨리 옴(근본은 키/파티션)

4) 모니터링: “균등 분산”이 전제다

AWS 사이징 글에서도 “프로듀서가 부하를 고르게 퍼뜨리고, 브로커가 파티션을 균등하게 가진다” 같은 이상 조건을 전제로 논의를 시작합니다. 현실에서 가장 많이 깨지는 전제가 바로 “키 스큐”입니다. Source

5) 이미지로 보는 “파티션 전략” 감 잡기

Kafka Partition Strategies
Source


Java 예제: 키 설계 구현 패턴

패턴 1) 엔티티 ID 키(정석)

ProducerRecord<String, String> record =
    new ProducerRecord<>("orders", orderId, payloadJson);

producer.send(record);

같은 orderId는 같은 파티션으로 가며(기본 파티셔닝: murmur2+mod), 파티션 내 순서가 유지됩니다. Source

패턴 2) 복합 키(멀티테넌시)

String key = tenantId + ":" + userId;
ProducerRecord<String, String> record =
    new ProducerRecord<>("user-events", key, payloadJson);
producer.send(record);

패턴 3) 핫 키 완화(샤딩 키)

int buckets = 16;
int bucket = Math.floorMod(orderId.hashCode(), buckets);
String key = orderId + "#" + bucket;

producer.send(new ProducerRecord<>("orders", key, payloadJson));

권장 사용 조건:

  • “orderId 전체 순서”가 아니라 “orderId#bucket 단위 순서”로도 충분할 때
  • 또는 소비자가 재정렬/머지 가능할 때

검증/모니터링 체크리스트

설계 검증(출시 전)

  • 키 후보별로 상위 1% 키가 차지하는 트래픽 비율을 산출(핫 파티션 위험)
  • 파티션 수 변경 시 영향(키→파티션 재매핑) 고려: 기본은 hash(key)%N Source
  • 소비자가 요구하는 보장:
    • 순서 단위(무엇이 “같은 그룹”인가)
    • 집계 단위(무엇을 모아서 처리하는가)

운영 모니터링(MSK)

  • 파티션/브로커 균형이 깨지면 CPU가 치우침 → MSK는 CPU 60% 이하 권장 Source
  • 브로커당 파티션 수(리더+팔로워 포함) 가이드 준수(업데이트 제한 방지) Source

참고 자료

  • Kafka message key 개념(키→파티션, 순서/그룹핑) Confluent
  • Java 기본 파티셔너 동작(murmur2+mod) The Internals of Apache Kafka
  • 파티셔닝 전략은 “소비자가 무엇을 하느냐”가 결정(랜덤/집계/핫스팟 사례 포함) New Relic
  • MSK Best Practices(브로커당 파티션 가이드, CPU, 운영 제약 등) AWS Docs
  • MSK/카프카 클러스터 사이징(네트워크/스토리지/복제/컨슈머 그룹 병목) AWS Big Data Blog
profile
AI를 꿈꾸는 BackEnd개발자

0개의 댓글