7. 토픽 설계
코드는 언제든 고치지만, 파티션 수와 키는 데이터가 쌓인 뒤엔 못 무른다
이 장에서 처음 나오는 말4개
보존Retention- 데이터를 언제까지 남길지의 정책. 기간(
retention.ms)과 용량(retention.bytes)으로 정하고, 지나면 세그먼트째 지운다. 컴팩션Compaction- 기간이 아니라 키별 최신값만 남기는 보존 방식. "이력"이 아니라 "현재 상태"가 필요한 토픽에 쓴다.
툼스톤Tombstone- value가 null인 레코드. 컴팩션 토픽에서 "이 키를 지워라"는 표시다.
스키마Schema- 토픽에 흐르는 메시지의 형식 계약. 생산자와 소비자가 독립 배포되는 순간부터 필요해진다.
토픽을 어떻게 나눌까
섹션 제목: “토픽을 어떻게 나눌까”토픽은 이벤트 종류 하나 = 토픽 하나가 기본형이다. 판단 기준은 스키마다 — 한 토픽에는 한 가지 형식의 메시지가 흐르는 것이 소비자를 단순하게 만든다.
- 이름은 규칙을 세워 일관되게 —
<도메인>.<대상>.<사건>꼴이 흔하다 (order.payment.completed,user.account.created). 나중에 ACL·정리의 단위가 된다 - 너무 잘게 (사건마다 새 토픽 수백 개) — 관리·모니터링이 흩어진다.
너무 굵게 (만능
events토픽 하나) — 소비자가 필요 없는 메시지까지 다 받아 거른다. 도메인 단위로 묶고, 소비 패턴이 다르면 나눈다 — “같이 읽히는 것끼리 한 토픽” - 한 대상의 사건들 사이에 순서가 필요하면 한 토픽이어야 한다 — 토픽이 다르면 같은 키라도 순서가 없다 (6장)
파티션 수 — 가장 무르기 어려운 결정
섹션 제목: “파티션 수 — 가장 무르기 어려운 결정”2장·5장의 결론이 여기로 모인다 — 파티션 수 = 소비 병렬성의 상한이고, 늘리면 키 배정이 바뀌며, 줄일 수는 없다.
- 병목은 대부분 브로커가 아니라 컨슈머의 처리 속도다(DB 쓰기, API 호출…) — 그래서 분모는 추정이 아니라 실측이어야 한다
- 감이 없으면 6~12개로 시작하는 것이 무난하다 — 웬만한 서비스 이벤트 토픽에 충분하고, 컨슈머를 늘릴 여유도 있다
- 많다고 좋은 것이 아니다 — 파티션마다 파일 핸들 · 복제 트래픽 · 리더 선출 부담이 붙는다. “일단 100개”는 클러스터 전체(수천 파티션 규모)에 비용으로 돌아온다
보존 — 지우는 정책이 곧 계약이다
섹션 제목: “보존 — 지우는 정책이 곧 계약이다”cleanup.policy=delete. 기본 7일(retention.ms) — 대부분의 이벤트 토픽은 이대로 쓴다.
cleanup.policy=compact. 오래된 것이 아니라 같은 키의 옛 값을 지운다 —
전 키의 최신값이 항상 남아, 토픽이 “이력”이 아니라 “현재 상태의 스냅숏”이 된다.
- 어울리는 곳: CDC로 흘린 테이블 상태, 설정/피처 플래그 배포, 사용자 프로필 캐시 원본 — “처음부터 읽으면 최신 상태가 복원되는” 토픽
- 삭제는 툼스톤(value=null)으로 — 컴팩션이 언젠가 키째 걷어 간다
- 컴팩션은 백그라운드에서 느슨하게 돈다 — “키당 정확히 1건”이 실시간 보장되는 것은 아니고, 소비자는 여전히 같은 키를 여러 번 볼 수 있다는 전제로 읽는다
스키마 — 형식 계약을 어떻게 지킬 것인가
섹션 제목: “스키마 — 형식 계약을 어떻게 지킬 것인가”브로커는 value를 검사하지 않는다(2장) — 형식이 깨진 메시지도 그대로 들어간다. 생산자와 소비자가 따로 배포되는 순간, “필드 하나 바꿨더니 소비자가 죽었다”는 사고는 시간 문제다.
- 시작은 JSON으로 충분하다 — 대신 버전 필드를 넣고, 소비자는 모르는 필드를 무시하게(관용적 읽기) 짠다
- 토픽·연동이 늘면 스키마 레지스트리(8장)로 계약을 강제한다 — 호환성 규칙(뒤 호환: 필드 추가는 되고 삭제·타입 변경은 막는 식)을 등록 시점에 검사해, 깨지는 변경이 배포 전에 걸린다
- 어느 쪽이든 원칙은 같다 — 스키마 변경은 추가만, 삭제·의미 변경은 새 토픽
7장 요약
섹션 제목: “7장 요약”- 토픽은 이벤트 종류 단위 · 한 토픽 한 스키마 · 순서가 필요한 사건들은 한 토픽에
- 파티션 수는 목표 처리량 ÷ 컨슈머 실측 처리량 + 여유 — 감이 없으면 6~12로 시작, 늘리기엔 대가(키 재배정)
- 보존은 계약이다 — delete는 재처리 여유 시간, compact는 키별 최신 상태. 디스크 = 유입 × 보존 × RF
- 형식 계약은 처음엔 관용적 JSON, 규모가 붙으면 스키마 레지스트리로 강제(8장)
8. 생태계Connect · 스키마 레지스트리 · 스트림 처리 — 언제 무엇을 더 얹는가.