백엔드 데이터 인프라 101편 — Kafka Multi-tenancy (Quota · Naming · ACL 분리)

2026-05-17백엔드 데이터 인프라

백엔드 데이터 인프라 101편. Kafka Multi-tenancy — 여러 팀·서비스가 같은 cluster 공유. Topic Naming Convention·Producer/Consumer Quota·ACL 분리·Resource Limit·Tenant Isolation 패턴까지 풀어쓴 학습 노트.

📚 백엔드 데이터 인프라 · 101편 — Kafka Multi-tenancy (Quota · Naming · ACL 분리)

이 글은 백엔드 데이터 인프라 시리즈 130편 중 101편이에요. 100편 까지 모니터링을 잡았다면, 이번 101편은 조직 규모 운영의 핵심인 Multi-tenancy(여러 사용자가 한 시스템을 공유) 차례예요. 여러 팀·서비스가 같은 Kafka cluster 를 함께 쓸 때 어떤 표준 패턴이 필요한지 정리할게요.

Multi-tenancy가 어렵게 느껴지는 이유

회사가 커지면 팀마다 별도 cluster 를 두는 건 비현실적이에요. 하나의 cluster 를 안전하게 공유하는 방법이 필요한데, 다음 4가지 영역이 한꺼번에 얽혀요.

첫째, Naming 으로 어떤 topic 이 어느 팀 소속인지 식별해야 해요.

둘째, Quota(자원 사용량 제한) 로 한 팀이 cluster 자원을 독점하지 못하게 막아야 해요.

셋째, ACL(Access Control List, 접근 권한 목록) 로 다른 팀 topic 에 접근하지 못하게 통제해요.

넷째, Isolation 정도 — 완전 격리할지 부분 공유할지 결정해야 해요.

이 글에서 Multi-tenancy 의 4가지 영역과 실무 패턴을 풀어볼게요.

1. Topic Naming Convention

가장 단순하면서 가장 중요한 영역이에요. 컨벤션이 없으면 카오스가 와요.

권장 패턴

{env}.{team}.{domain}.{event-type}[.v{version}]

예제:

prod.order-team.orders.created
prod.order-team.orders.completed
prod.payment-team.payments.received
prod.payment-team.payments.refunded
dev.user-team.users.signup.v2

요소:

  • {env}prod·staging·dev
  • {team} — 팀 식별자 (order-team)
  • {domain} — 도메인 영역 (orders·payments)
  • {event-type} — 이벤트 종류 (created·completed)
  • {version} — 스키마 진화 시

여기서 시험 함정이 하나 있어요 — Topic 이름은 한 번 정하면 바꾸기 매우 어렵습니다. Topic rename 명령이 따로 없어서, 새 topic 을 만들고 producer/consumer 를 이전하는 복잡한 마이그레이션이 필요해요. 그래서 처음에 컨벤션을 신중히 잡아야 해요.

다른 패턴

  • Confluent 권장: {ENV}.{COMPANY}.{TEAM}.{DOMAIN} (Pascal case)
  • 이벤트 중심: {event}_{source}_{schema-version} (OrderCreated_OrderService_v1)
  • Slack 의 예: {tier}.{source}.{event} (tier1.checkout.payment-success)

회사 규모·문화에 맞게 하나로 고정해서 가져가는 게 좋아요.

2. Producer Quota — 처리량 제한

한 팀의 producer 가 cluster 전체 처리량을 독점하지 못하게 막는 장치예요.

적용 단위

  • per user (ACL 환경)
  • per client.id
  • per (user, client.id)

설정

# 특정 사용자에 quota 적용 (15 MB/s)
$ kafka-configs.sh --bootstrap-server localhost:9092 \
    --alter --add-config 'producer_byte_rate=15728640' \
    --entity-type users --entity-name app-user

# client.id 기반
$ kafka-configs.sh --bootstrap-server localhost:9092 \
    --alter --add-config 'producer_byte_rate=15728640' \
    --entity-type clients --entity-name order-producer

# default (모든 사용자)
$ kafka-configs.sh --bootstrap-server localhost:9092 \
    --alter --add-config 'producer_byte_rate=10485760' \
    --entity-type users --entity-default

동작 — Throttling

Throttling(요청 속도를 강제로 늦추는 동작) 은 quota 를 넘은 클라이언트의 응답에 broker 가 throttle delay 를 끼워 보내는 방식으로 일어나요. Producer client 는 그만큼 기다렸다 다시 보내요.

quota: 10 MB/s
producer 가 20 MB/s 시도
→ broker 가 throttle_time_ms 50% delay 응답
→ producer 가 자동으로 속도 절반으로 조정

거부가 아니라 속도 제한이라서 메시지 손실은 없어요.

Spring Boot Producer 에 client.id

spring:
  kafka:
    producer:
      client-id: ${spring.application.name}

애플리케이션마다 별도 client.id 를 쓰면 별도 quota 를 걸 수 있어요.

3. Consumer Quota

같은 패턴으로 fetch 처리량을 제한해요.

$ kafka-configs.sh --bootstrap-server localhost:9092 \
    --alter --add-config 'consumer_byte_rate=20971520' \
    --entity-type users --entity-name analytics-user

대량 batch consumer (예를 들어 ML 학습용) 는 일반 consumer 와 분리된 quota 를 받게 두는 게 좋아요.

4. Request Quota — CPU 제한

위 두 quota 는 network bandwidth 를 다뤘다면, Request Quota 는 broker 의 CPU 사용률을 제한해요.

$ kafka-configs.sh --bootstrap-server localhost:9092 \
    --alter --add-config 'request_percentage=50' \
    --entity-type users --entity-name app-user

50 은 broker CPU 의 50% 한계를 뜻하고, 0~100 (%) 범위로 잡아요.

소수의 nasty client 가 broker CPU 를 독점하는 사고를 막아 줘요.

5. Quota 조회

$ kafka-configs.sh --bootstrap-server localhost:9092 \
    --describe --entity-type users --entity-name app-user

Configs for user-principal 'app-user' are
    producer_byte_rate=15728640
    consumer_byte_rate=20971520
    request_percentage=30

6. ACL 분리 — Team 단위

116편에서 ACL 을 깊이 다뤘는데, Multi-tenancy 의 핵심 패턴은 이거예요.

# order-team 만 prod.order-team.* 에 read/write
$ kafka-acls.sh --bootstrap-server localhost:9092 \
    --add --allow-principal User:order-team-app \
    --operation All \
    --topic 'prod.order-team.' --resource-pattern-type PREFIXED

# payment-team 은 prod.order-team 에 read-only (옵션)
$ kafka-acls.sh --bootstrap-server localhost:9092 \
    --add --allow-principal User:payment-team-app \
    --operation Read \
    --topic 'prod.order-team.orders.completed' --resource-pattern-type LITERAL

PREFIXED resource pattern(접두사가 일치하는 모든 리소스에 한꺼번에 권한) 으로 잡으면 접두사가 맞는 모든 topic 에 권한이 걸려서, 새 topic 을 추가해도 ACL 을 다시 손볼 필요가 없어요.

7. Tenant Isolation 수준

Level 1: Shared Cluster (가장 흔함)

[order-team] ─┐
[payment-team] ├─→ Single Kafka Cluster
[user-team]   ─┘

비용이 낮고 운영 부담도 낮은 대신 격리도 낮아요.

Level 2: 부분 격리 — 별도 broker pool

[order-team, payment-team] → Broker Group A (5 brokers)
[user-team, analytics-team] → Broker Group B (3 brokers)

같은 cluster 안이지만 partition 을 특정 broker 에만 배치해요. Rack-aware replica placement 를 활용하면 돼요.

Level 3: 완전 격리 — 별도 cluster

[order-team] → Kafka Cluster A
[payment-team] → Kafka Cluster B
[analytics] → Kafka Cluster C

비용·운영 부담이 올라가는 대신 장애·security·성능을 모두 떼어낼 수 있어요.

대규모 환경에서는 중요한 영역만 별도 cluster 로 빼고 나머지는 공유로 가는 Hybrid 구성을 많이 써요.

8. Resource Limit — Cluster 보호

Topic 수 제한

기본은 무제한이에요. 너무 많은 topic 을 만들면 broker 의 메모리와 파일 디스크립터가 폭증해요.

운영에서는 수동 review 와 ticketing process 를 같이 둬요. 어느 팀이 topic 을 만들면 SRE 가 승인하는 식이죠.

Partition 수 제한

비슷한 이슈예요. partition 이 1만 개를 넘어가면 controller 가 부담을 받아요.

Topic Configuration Limit

특정 설정에 최댓값을 걸어요.

# server.properties
log.retention.bytes.max=1099511627776          # 1TB max per partition

회사 단위 quota 를 운영하는 방식이에요.

9. Naming + ACL + Quota 통합 패턴

운영 표준은 다음 흐름이에요.

# 1. 새 팀 onboarding
TEAM=order-team
ENV=prod

# 2. SASL user 생성
$ kafka-configs.sh --bootstrap-server localhost:9092 \
    --alter --add-config 'SCRAM-SHA-512=[iterations=8192,password=...]' \
    --entity-type users --entity-name ${TEAM}-app

# 3. ACL 부여 (PREFIXED)
$ kafka-acls.sh --bootstrap-server localhost:9092 \
    --add --allow-principal User:${TEAM}-app \
    --operation All \
    --topic "${ENV}.${TEAM}." --resource-pattern-type PREFIXED

# 4. Consumer Group ACL
$ kafka-acls.sh --bootstrap-server localhost:9092 \
    --add --allow-principal User:${TEAM}-app \
    --operation All \
    --group "${ENV}.${TEAM}." --resource-pattern-type PREFIXED

# 5. Quota 부여
$ kafka-configs.sh --bootstrap-server localhost:9092 \
    --alter --add-config 'producer_byte_rate=20971520,consumer_byte_rate=20971520,request_percentage=30' \
    --entity-type users --entity-name ${TEAM}-app

SASL(Simple Authentication and Security Layer, 사용자 인증 프로토콜) 사용자 생성 → ACL → Quota 까지 이어지는 흐름을 스크립트로 묶으면 표준 onboarding 을 자동화할 수 있어요.

10. 모니터링 — Per-Tenant

JMX(Java Management Extensions, 자바 애플리케이션 모니터링용 표준) 메트릭이 client.id 와 user 별로 쪼개져 나와요.

kafka.server:type=Produce,user=order-team-app,client-id=order-service-1
kafka.server:type=Fetch,user=order-team-app,client-id=order-worker-1

Grafana 대시보드에서 팀별 throughput 과 error rate 를 따로 볼 수 있어요.

11. 자주 일어나는 운영 사고

1. Quota 없이 새 producer 폭주

신규 팀 onboarding 때 quota 를 빠뜨리면 한 producer 가 cluster 전체를 차지해요. 그래서 표준 onboarding 스크립트를 꼭 갖춰야 해요.

2. Naming 컨벤션 위반

임의로 topic 을 만들기 시작하면 카오스로 가요. auto.create.topics.enable=false 와 ACL 로 차단해 둬야 해요.

3. ACL 너무 풀어 줌

귀찮다고 모든 팀에 모든 권한을 주면 Multi-tenancy 의 의미가 없어져요. 최소 권한 원칙을 지키는 게 기본이에요.

4. Quota 너무 낮음

Throttle 이 폭증하면 정상 트래픽까지 영향을 받아요. 합리적인 quota 를 잡고, 바꿀 때도 점진적으로 가야 해요.

5. Topic 수 폭증

환경·팀·이벤트마다 topic 을 만들다 보면 수만 개까지 늘어날 수 있어요. 주기적으로 cleanup 을 돌려야 해요.

12. Confluent / SaaS 의 Multi-tenancy

Confluent Cloud, AWS MSK, Azure Event Hubs 같은 SaaS 는 multi-tenant 가 기본 운영 모델이에요. 전용 cluster 로 쓸지 공유 cluster 로 쓸지 옵션을 골라요.

  • Dedicated cluster = 비용 ↑, 완전 격리
  • Standard (shared underlay) = 비용 ↓, 약간 격리

시험 직전 한 번 더 — Kafka Multi-tenancy 함정 압축 노트

  • 4가지 영역 = Naming · Quota · ACL · Isolation 수준
  • Naming Convention = {env}.{team}.{domain}.{event-type}[.v{N}]
  • Topic rename 불가 → 처음 컨벤션 신중
  • Producer Quota = producer_byte_rate (per user·client.id)
  • Consumer Quota = consumer_byte_rate
  • Request Quota = request_percentage (CPU 제한)
  • Quota 초과 = throttling (delay, 거부 X)
  • 적용 단위 = user·client.id·(user, client.id)·default
  • 조회 = kafka-configs.sh --describe --entity-type users
  • ACL 분리 = --resource-pattern-type PREFIXED 로 접두사 권한
  • 새 topic 추가 시 ACL 추가 불필요 (PREFIXED 매칭)
  • Tenant Isolation 3 Level — Shared (가장 흔함) · 부분 격리 (broker pool) · 완전 격리 (별도 cluster)
  • 대규모 = Hybrid (중요 영역만 별도 + 나머지 공유)
  • Resource Limit = topic 수·partition 수 (수동 review + ticketing)
  • 표준 onboarding 패턴 = SASL user 생성 + ACL (PREFIXED) + Quota 설정 스크립트화
  • 모니터링 = JMX 가 user·client.id 별 분해 → Grafana 대시보드 팀별
  • 함정 — Quota 없는 onboarding 으로 cluster 차지
  • 함정 — Naming 컨벤션 위반 카오스
  • 함정 — ACL 너무 풀어 줌
  • 함정 — Quota 너무 낮음
  • 함정 — Topic 수 폭증
  • SaaS (Confluent Cloud·MSK·Event Hubs) = multi-tenant 가 기본

공식 문서: Kafka Multi-tenancy 에서 자세한 패턴을 확인할 수 있어요.

시리즈 다른 편 (앞뒤 글 모음)

이전 글:

다음 글:

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!