🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

토픽과 파티션의 이해 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2026. 4. 9. · 0 Views

토픽과 파티션의 이해 완벽 가이드

Kafka의 핵심 데이터 구조인 토픽과 파티션의 개념부터 오프셋, 메시지 순서 보장, 삭제 정책까지 실무에 필요한 모든 내용을 다룹니다. 카프카를 제대로 이해하기 위해 반드시 알아야 할 기초를 탄탄하게 다집니다.


목차

  1. 토픽의_개념과_역할
  2. 파티션_분할_전략
  3. 오프셋과_메시지_순서_보장
  4. 토픽_생성_및_설정
  5. 파티션_수_결정_기준
  6. 메시지_삭제_정책_retention

1. 토픽의 개념과 역할

어느 날 김개발 씨가 팀 미팅에서 "카프카에 메시지를 보내려면 어디로 보내야 하나요?"라는 질문을 던졌습니다. 박시니어 씨가 빙그레 웃으며 답했습니다.

"토픽이라는 곳으로 보내면 됩니다. 카프카에서 모든 메시지의 여정은 토픽에서 시작되거든요."

**토픽(Topic)**은 카프카에서 메시지를 분류하는 논리적인 채널입니다. 마치 방송국의 채널처럼, 각 토픽은 특정 종류의 메시지만 담당합니다.

프로듀서는 토픽으로 메시지를 발행하고, 컨슈머는 토픽에서 메시지를 구독합니다.

다음 코드를 살펴봅시다.

// 토픽 생성 명령어 (Kafka CLI)
bin/kafka-topics.sh --create \
  --topic order-events \
  --bootstrap-server localhost:9092 \
  --partitions 3 \
  --replication-factor 1
// order-events라는 토픽이 생성됩니다
// 주문 관련 이벤트만 이 토픽에 발행합니다

// 토픽 목록 확인
bin/kafka-topics.sh --list \
  --bootstrap-server localhost:9092
// 생성된 모든 토픽을 확인할 수 있습니다

"Apache Kafka 완전 정복" 코스의 네 번째 시간입니다. 지난 시간에는 카프카를 직접 설치하고 실행해보며 브로커가 정상적으로 동작하는 것을 확인했습니다.

이번에는 카프카의 핵심 데이터 구조인 토픽과 파티션을 깊이 있게 알아보겠습니다. 김개발 씨는 입사 3개월 차 주니어 개발자입니다.

카프카 브로커까지 띄워놓고 보니, 다음 단계가 막막했습니다. "메시지를 보낼 때 도대체 어디로 보내는 거지?" 박시니어 씨가 옆에서 설명을 시작합니다.

"카프카에서 모든 메시지는 **토픽(Topic)**이라는 논리적 채널로 분류돼. 마치 도서관의 분류 체계와 같아.

역사책은 역사 코너에, 과학책은 과학 코너에 꽂히듯이, 주문 이벤트는 order-events 토픽에, 회원 가입 이벤트는 user-signup 토픽에 각각 담기는 거지." 토픽이라는 개념이 왜 중요할까요? 생각해보면 수백 가지 종류의 메시지가 한곳에 섞여 들어오면 어떻게 될까요?

결제 정보와 로그 데이터가 뒤섞이면, 결제 처리 서비스는 필요한 메시지를 찾기 위해 전체를 뒤져야 합니다. 이는 엄청난 비효율입니다.

토픽을 사용하면 이 문제가 깔끔하게 해결됩니다. 각 서비스는 자신이 관심 있는 토픽만 구독하면 됩니다.

결제 서비스는 payment-events를, 알림 서비스는 notification-events를 구독하는 식입니다. 위 코드를 보면 kafka-topics.sh 명령어로 토픽을 생성하는 방법을 알 수 있습니다.

--topic 플래그로 토픽 이름을 지정하고, --partitions로 파티션 수를, --replication-factor로 복제 팩터를 설정합니다. 이 옵션들은 뒤에서 더 자세히 다룰 예정입니다.

실무에서는 토픽 이름을 정하는 것도 중요합니다. 보통 {도메인}-{이벤트타입} 형식을 따릅니다.

예를 들어 order-created, user-registered, payment-completed처럼 명확하게 네이밍합니다. 팀원 전체가 토픽 이름만 보고도 어떤 메시지가 오가는지 알 수 있어야 합니다.

토픽의 수명은 영구적입니다. 한 번 생성된 토픽은 명시적으로 삭제하지 않는 한 계속 존재합니다.

따라서 토픽을 생성할 때는 충분히 고민한 뒤에 결정하는 것이 좋습니다. 다시 김개발 씨에게 돌아가 봅시다.

박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다. "아, 그러니까 토픽이 메시지를 분류하는 큰 카테고리인 거군요!" 맞습니다.

토픽은 카프카의 가장 기본이 되는 데이터 구조입니다. 이 개념을 탄탄히 잡아야 앞으로 파티셔닝과 컨슈머 그룹을 이해할 수 있습니다.

실전 팁

💡 - 토픽 이름은 소문자와 하이픈만 사용하는 것이 관례입니다 (예: order-events)

  • 프로덕션 환경에서는 토픽 삭제 시 복구가 어려우니 신중하게 관리하세요

2. 파티션 분할 전략

김개발 씨가 토픽의 개념을 이해한 후, 다음 궁금증이 생겼습니다. "토픽이 하나의 채널이라면, 수백만 건의 메시지가 동시에 들어오면 어떻게 처리하나요?" 박시니어 씨가 대답했습니다.

"바로 **파티션(Partition)**이 그 역할을 합니다."

**파티션(Partition)**은 토픽을 여러 개의 물리적 분할로 나눈 단위입니다. 마치 하나의 큰 파이프를 여러 개의 가느다란 파이프로 나누어 처리량을 높이는 것과 같습니다.

각 파티션은 독립적으로 메시지를 처리하므로 병렬 처리가 가능합니다.

다음 코드를 살펴봅시다.

// 파티션이 3개인 토픽의 구조
// Topic: order-events
//   Partition 0: [msg1, msg4, msg7, ...]
//   Partition 1: [msg2, msg5, msg8, ...]
//   Partition 2: [msg3, msg6, msg9, ...]

// Java 프로듀서에서 메시지 키로 파티션 지정
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer",
    "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer",
    "org.apache.kafka.common.serialization.StringSerializer");
// 메시지 키가 같으면 같은 파티션으로 배정됩니다
ProducerRecord<String, String> record =
    new ProducerRecord<>("order-events", "order-123", "주문 생성");
// "order-123" 키의 해시값에 따라 파티션이 결정됩니다

김개발 씨는 토픽이 메시지를 분류하는 채널이라는 것을 이해했습니다. 하지만 곧 실무적인 고민에 빠졌습니다.

"우리 서비스의 주문량이 하루에 수백만 건인데, 하나의 토픽이 그걸 다 감당할 수 있나요?" 박시니어 씨가 화이트보드에 그림을 그리기 시작합니다. 하나의 큰 직사각형을 세 개의 작은 직사각형으로 나누었습니다.

"이게 바로 **파티션(Partition)**이야. 토픽 하나를 여러 파티션으로 쪼개면, 각 파티션이 독립적으로 메시지를 받을 수 있어.

마치 슈퍼마켓의 계산대를 여러 개 열어두는 것과 같아." 파티션이 왜 필요할까요? 단일 파티션만 있다면 모든 메시지가 하나의 큐에 순서대로 쌓입니다.

처리 속도가 소비 속도를 따라가지 못하면 대기 시간이 길어집니다. 이는 곧 서비스 지연으로 이어집니다.

파티션으로 나누면 상황이 달라집니다. 파티션이 3개라면, 컨슈머도 최대 3개까지 동시에 병렬로 메시지를 처리할 수 있습니다.

처리량이 3배로 늘어나는 셈입니다. 파티션 수를 늘리면 늘릴수록 병렬 처리 능력도 올라갑니다.

그렇다면 메시지는 어떤 파티션으로 들어갈까요? 여기에는 세 가지 전략이 있습니다.

첫 번째, 메시지 키가 있는 경우입니다. 키의 해시값을 파티션 수로 나누어 특정 파티션에 배정합니다.

이 전략의 장점은 동일한 키를 가진 메시지가 항상 같은 파티션에 들어간다는 점입니다. 주문 ID를 키로 사용하면, 같은 주문의 모든 이벤트가 한 파티션에 모이게 됩니다.

두 번째, 메시지 키가 없는 경우입니다. 이때는 Round-Robin 방식으로 순차적으로 파티션에 분배합니다.

메시지가 골고루 퍼지기 때문에 부하 분산에 유리합니다. 세 번째, 커스텀 파티셔너를 사용하는 경우입니다.

직접 파티션 분배 로직을 구현할 수도 있습니다. 하지만 특별한 요구사항이 없다면 기본 전략을 사용하는 것이 좋습니다.

위 코드에서 ProducerRecord 생성 시 "order-123"이라는 키를 전달한 것을 볼 수 있습니다. 이 키를 기준으로 해시 연산이 수행되고, 그 결과에 따라 파티션이 결정됩니다.

하지만 파티션 수를 무한정 늘릴 수는 없습니다. 파티션이 많아질수록 카프카 브로커의 메모리와 파일 핸들을 더 많이 사용하게 됩니다.

또한 파티션 수가 컨슈머 수보다 많으면, 일부 파티션은 유휴 상태가 됩니다.

실전 팁

💡 - 파티션 수는 컨슈머 그룹의 최대 병렬 처리 수와 일치시키는 것이 이상적입니다

  • 메시지 순서가 중요한 경우 반드시 메시지 키를 지정하여 같은 파티션으로 보내세요

3. 오프셋과 메시지 순서 보장

김개발 씨가 카프카 클러스터의 모니터링 화면을 보다가 숫자 하나에 눈이 멈췄습니다. "이 숫자 42는 뭔가요?" 박시니어 씨가 설명했습니다.

"그건 **오프셋(Offset)**이야. 파티션 안에서 메시지의 위치를 가리키는 일종의 페이지 번호라고 생각하면 돼."

**오프셋(Offset)**은 파티션 내에서 각 메시지의 고유한 순번입니다. 0부터 시작하여 메시지가 추가될 때마다 1씩 증가합니다.

컨슈머는 오프셋을 통해 어디까지 메시지를 읽었는지 기억합니다.

다음 코드를 살펴봅시다.

// 컨슈머가 오프셋을 수동으로 커밋하는 예제
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "order-processor");
props.put("enable.auto.commit", "false");
// auto.commit을 false로 설정하면 수동 커밋

KafkaConsumer<String, String> consumer =
    new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("order-events"));

while (true) {
    ConsumerRecords<String, String> records =
        consumer.poll(Duration.ofMillis(100));
    for (ConsumerRecord<String, String> record : records) {
        // record.offset()으로 현재 메시지의 오프셋 확인
        System.out.println("offset=" + record.offset()
            + ", value=" + record.value());
        // 비즈니스 로직 처리 후 수동 커밋
        consumer.commitSync();
    }
}

김개발 씨는 파티션이 토픽을 나누는 단위라는 것을 이해했습니다. 하지만 새로운 궁금증이 생겼습니다.

"컨슈머가 메시지를 처리하다가 장애가 발생하면, 다시 복구했을 때 어디서부터 다시 읽어야 하나요?" 박시니어 씨가 답합니다. "그게 바로 **오프셋(Offset)**의 역할이야.

쉽게 말해 책의 페이지 번호와 같아. 42페이지까지 읽었으면, 다음에는 43페이지부터 읽으면 되잖아?" 오프셋은 파티션마다 독립적으로 관리됩니다.

파티션 0의 오프셋이 100이더라도, 파티션 1의 오프셋은 50일 수 있습니다. 이는 각 파티션이 독립적인 로그 파일처럼 동작하기 때문입니다.

오프셋의 중요한 특징 중 하나는 **불변성(Immutability)**입니다. 한 번 쓰인 오프셋은 변경되지 않습니다.

메시지가 파티션의 끝에 추가되는 방식이기 때문에, 기존 메시지의 오프셋은 절대 바뀌지 않습니다. 이를 Append-Only Log 구조라고 부릅니다.

이 특징 덕분에 카프카는 높은 처리량을 자랑합니다. 디스크의 순차 쓰기(Sequential Write)는 임의 쓰기(Random Write)보다 훨씬 빠르기 때문입니다.

마치 공책에 앞에서부터 순서대로 적어나가는 것이 중간에 끼워 넣는 것보다 빠른 것과 같습니다. 그렇다면 메시지 순서는 어떻게 보장될까요?

이 질문에 답하려면 파티션 내부의 구조를 이해해야 합니다. 같은 파티션 안에서는 메시지 순서가 보장됩니다.

오프셋 0이 오프셋 1보다 먼저 도착했고, 따라서 먼저 저장되었습니다. 컨슈머도 오프셋 순서대로 메시지를 읽습니다.

이것이 카프카가 "순서 보장"을 하는 방식입니다. 하지만 여기에 함정이 있습니다.

다른 파티션 간에는 순서가 보장되지 않습니다. 파티션 0의 오프셋 5와 파티션 1의 오프셋 3 중 어떤 것이 먼저 도착한 것인지 알 수 없습니다. 따라서 순서가 중요한 메시지는 반드시 같은 키를 사용하여 같은 파티션에 보내야 합니다.

컨슈머는 오프셋을 **커밋(Commit)**하여 자신의 읽기 위치를 기록합니다. 기본적으로 enable.auto.committrue로 설정되어 있어 주기적으로 자동 커밋됩니다.

하지만 이 방식은 메시지 처리 중 장애가 발생하면 일부 메시지가 유실될 수 있습니다. 위 코드에서는 enable.auto.commitfalse로 설정하고, 메시지 처리 완료 후 commitSync()로 수동 커밋하는 방식을 보여줍니다.

이 방식은 처리 속도는 느려지지만, 데이터 유실을 확실히 방지할 수 있어 프로덕션 환경에서 자주 사용됩니다. "아, 그러니까 오프셋이 북마크 같은 역할을 하는 거군요!" 김개발 씨의 말에 박시니어 씨가 미소를 지었습니다.

"정확해. 오프셋만 잘 이해하면 카프카의 메시지 처리 원리를 반은 이해한 거야."

실전 팁

💡 - 프로덕션 환경에서는 수동 커밋(enable.auto.commit=false)을 사용하여 데이터 유실을 방지하세요

  • 순서 보장이 필요한 메시지는 반드시 동일한 키를 사용하여 같은 파티션으로 보내야 합니다

4. 토픽 생성 및 설정

김개발 씨가 드디어 실습 환경에서 첫 토픽을 생성하려고 합니다. "그냥 토픽 이름만 주면 되는 건가요?" 박시니어 씨가 고개를 가로저었습니다.

"토픽 생성은 간단하지만, 설정 하나가 시스템의 성능과 안정성을 좌우할 수 있어. 신중하게 접근해야 해."

토픽을 생성할 때는 파티션 수, 복제 팩터, 보존 정책 등 핵심 설정을 함께 지정해야 합니다. 이 설정들은 나중에 변경 가능하지만, 일부 설정은 운영 중 변경이 까다롭습니다.

따라서 초기 설계 단계에서 충분히 고민해야 합니다.

다음 코드를 살펴봅시다.

// 프로덕션 권장 토픽 생성 명령어
bin/kafka-topics.sh --create \
  --topic order-events \
  --bootstrap-server localhost:9092 \
  --partitions 6 \
  --replication-factor 3 \
  --config retention.ms=604800000 \
  --config cleanup.policy=delete \
  --config max.message.bytes=1048576

// 토픽 상세 설정 확인
bin/kafka-topics.sh --describe \
  --topic order-events \
  --bootstrap-server localhost:9092
// 파티션 수, 복제 팩터, 리더 파티션 등을 확인

// 토픽 설정 변경 (파티션 수 증가)
bin/kafka-topics.sh --alter \
  --topic order-events \
  --bootstrap-server localhost:9092 \
  --partitions 12
// 파티션 수는 증가만 가능합니다 (감소 불가)

이제 실제로 토픽을 만들어보겠습니다. 김개발 씨는 명령어를 입력하기 전, 박시니어 씨의 조언을 주의 깊게 듣고 있었습니다.

"토픽 생성은 마집을 지을 때와 비슷해." 박시니어 씨가 비유를 들었습니다. "처음에 너무 작게 지으면 나중에 증축해야 하고, 너무 크게 지으면 유지비가 많이 들지.

적절한 크기로 시작하는 것이 핵심이야." 가장 먼저 결정해야 할 것은 파티션 수입니다. 파티션 수는 나중에 증가시킬 수 있지만, 감소시킬 수는 없습니다.

이것이 토픽 생성 시 가장 신중해야 할 부분입니다. "음, 파티션을 100개로 해볼까요?" 김개발 씨의 말에 박시니어 씨가 단호하게 말했습니다.

"파티션 수가 너무 많으면 브로커의 메모리와 CPU 부하가 커져. 처음에는 6~12개 정도로 시작하고, 모니터링하면서 필요에 따라 늘려가는 것이 좋아." 다음으로 결정할 것은 **복제 팩터(Replication Factor)**입니다.

이 값은 각 파티션의 복제본 수를 결정합니다. 복제 팩터가 3이면, 각 파티션이 3개의 브로커에 복제됩니다.

하나의 브로커가 장애가 발생해도 다른 복제본에서 메시지를 읽을 수 있어 가용성이 보장됩니다. 프로덕션 환경에서는 최소 3을 권장합니다.

--config 플래그를 사용하면 토픽별로 세부 설정을 지정할 수 있습니다. retention.ms는 메시지 보존 시간을 밀리초 단위로 설정합니다.

604800000은 7일을 의미합니다. 7일이 지난 메시지는 자동으로 삭제됩니다.

cleanup.policy는 메시지 삭제 방식을 결정합니다. delete는 시간 기준 삭제, compact는 키 기준 압축입니다.

대부분의 경우 delete를 사용합니다. max.message.bytes는 하나의 메시지 최대 크기를 지정합니다.

기본값은 1MB이며, 필요에 따라 늘릴 수 있습니다. 토픽을 생성한 후에는 --describe 명령어로 설정을 확인할 수 있습니다.

이 명령어는 각 파티션의 리더, 복제 상태, ISR(In-Sync Replicas) 목록 등 상세 정보를 보여줍니다. 운영 중 설정을 변경해야 할 때가 있습니다.

--alter 명령어로 파티션 수를 늘리거나 토픽 설정을 변경할 수 있습니다. 하지만 주의할 점이 있습니다.

파티션 수를 늘리면 기존 메시지는 새 파티션으로 재분배되지 않습니다. 새 메시지만 새 파티션에 분배됩니다.

"토픽 하나 만드는데 생각보다 고민할 게 많네요." 김개발 씨의 말에 박시니어 씨가 웃으며 대답했습니다. "지금 고민하는 시간이 나중에 장애 대응에 드는 시간보다 훨씬 짧을 거야."

실전 팁

💡 - 프로덕션 환경에서는 복제 팩터를 최소 3으로 설정하여 고가용성을 확보하세요

  • 토픽 설정 변경 시 카프카 클라이언트 재시작이 필요할 수 있으니 점검 시간에 진행하세요

5. 파티션 수 결정 기준

김개발 씨가 신규 프로젝트의 토픽 설계를 담당하게 되었습니다. 가장 고민되는 것은 파티션 수였습니다.

"3개가 좋을까요, 10개가 좋을까요?" 박시니어 씨가 공식을 하나 적어주었습니다. "파티션 수 결정에는 명확한 기준이 있어."

파티션 수를 결정할 때는 처리량(Throughput), 컨슈머 수, 브로커 리소스, 메시지 순서 요구사항을 종합적으로 고려해야 합니다. 너무 적으면 병목 현상이 발생하고, 너무 많으면 불필요한 리소스를 소모합니다.

다음 코드를 살펴봅시다.

// 파티션 수 결정 공식 (개념 코드)
// targetThroughput = 초당 처리해야 할 메시지 수
// singlePartitionThroughput = 파티션 하나의 초당 처리량
// requiredPartitions = ceil(targetThroughput / singlePartitionThroughput)

// 예시 계산
// 초당 100,000건 처리 목표
// 파티션당 초당 10,000건 처리 가능
// requiredPartitions = 100,000 / 10,000 = 10

// 실제 토픽 생성 (계산된 파티션 수 적용)
bin/kafka-topics.sh --create \
  --topic high-throughput-events \
  --bootstrap-server localhost:9092 \
  --partitions 10 \
  --replication-factor 3

// 처리량 테스트로 파티션당 성능 측정
bin/kafka-producer-perf-test.sh \
  --topic high-throughput-events \
  --num-records 1000000 \
  --record-size 1024 \
  --throughput 100000 \
  --producer-props bootstrap.servers=localhost:9092

김개발 씨는 회의실에서 팀원들과 토픽 설계를 논의하고 있었습니다. 가장 뜨거운 논쟁거리는 역시 파티션 수였습니다.

프론트엔드 팀의 이대표가 "파티션을 많이 주세요, 빠르면 빠를수록 좋잖아요"라고 말하자, 인프라 팀의 최인프라 씨가 "서버 리소스는 누가 감당하나요?"라며 반박했습니다. 박시니어 씨가 화이트보드에 간단한 공식을 적었습니다.

파티션 수 = 목표 처리량 / 파티션당 처리량. "이 공식이 출발점이야.

하지만 여기에 고려해야 할 변수가 몇 가지 더 있어." 첫 번째 변수는 컨슈머 그룹의 크기입니다. 컨슈머 그룹 내의 컨슈머 수가 파티션 수보다 많으면, 초과된 컨슈머는 아무 일도 하지 않고 유휴 상태로 대기합니다.

반대로 파티션 수가 더 많으면, 일부 컨슈머가 여러 파티션을 동시에 처리해야 합니다. 가장 이상적인 것은 컨슈머 수와 파티션 수가 일치하는 것입니다.

두 번째 변수는 브로커의 물리적 리소스입니다. 카프카 커뮤니티에서는 브로커당 파티션 수를 2,000개 이하로 유지할 것을 권장합니다.

파티션이 많아질수록 메모리 사용량이 증가하고, 리더 선출(Leader Election) 시간도 길어집니다. 클러스터에 3개의 브로커가 있다면, 전체 파티션 수는 6,000개 이하로 유지하는 것이 좋습니다.

세 번째 변수는 메시지 순서 요구사항입니다. 특정 키의 메시지 순서를 보장해야 한다면, 해당 키를 가진 메시지가 모두 같은 파티션으로 가야 합니다.

파티션이 너무 많으면 키 분포가 희박해져 각 파티션에 메시지가 고르게 분배되지 않을 수 있습니다. 네 번째 변수는 파일 시스템의 한계입니다.

각 파티션은 별도의 디렉터리와 로그 세그먼트 파일을 생성합니다. 너무 많은 파티션은 파일 디스크립터(File Descriptor) 고갈 문제를 일으킬 수 있습니다.

운영체제의 파일 디스크립터 제한(ulimit -n)도 함께 확인해야 합니다. 박시니어 씨가 마지막 조언을 덧붙였습니다.

"처음부터 완벽한 파티션 수를 찾으려고 하지 마. 보수적으로 시작해서, kafka-producer-perf-test.sh 같은 도구로 성능을 측정하면서 점진적으로 늘려가는 것이 현실적인 접근이야." 김개발 씨는 노트에 적기 시작했습니다.

"목표 처리량 측정, 파티션당 성능 벤치마크, 컨슈머 수와의 정렬, 브로커 리소스 확인. 이 네 가지를 먼저 하고 파티션 수를 결정하자."

실전 팁

💡 - 브로커당 파티션 수는 2,000개 이하로 유지하는 것이 권장됩니다

  • 파티션 수는 나중에 늘릴 수 있으므로, 초기에는 보수적으로 설정하세요

6. 메시지 삭제 정책 retention

김개발 씨가 디스크 사용량 모니터링을 보다가 화들짝 놀랐습니다. "디스크가 90%나 차 있어요!" 박시니어 씨가 차분하게 대답했습니다.

"걱정 마. 카프카에는 메시지 수명을 관리하는 **보존 정책(Retention Policy)**이 있어.

적절히 설정하면 디스크 문제는 해결돼."

**보존 정책(Retention Policy)**은 카프카가 메시지를 얼마나 오래 보관할지를 결정하는 설정입니다. 시간 기반 삭제, 크기 기반 삭제, 로그 압축 세 가지 방식이 있으며, 토픽의 특성에 따라 적절한 정책을 선택해야 합니다.

다음 코드를 살펴봅시다.

// 토픽별 보존 정책 설정 예제

// 1. 시간 기반 삭제 (7일 보관)
bin/kafka-configs.sh --alter \
  --bootstrap-server localhost:9092 \
  --entity-type topics --entity-name order-events \
  --add-config retention.ms=604800000
// 604800000ms = 7일, 이후 메시지 자동 삭제

// 2. 크기 기반 삭제 (토픽당 최대 10GB)
bin/kafka-configs.sh --alter \
  --bootstrap-server localhost:9092 \
  --entity-type topics --entity-name order-events \
  --add-config retention.bytes=10737418240
// 10GB를 초과하면 오래된 메시지부터 삭제

// 3. 로그 압축 (최신 값만 보관)
bin/kafka-configs.sh --alter \
  --bootstrap-server localhost:9092 \
  --entity-type topics --entity-name user-profile \
  --add-config cleanup.policy=compact
// 동일 키의 최신 메시지만 보관합니다

김개발 씨는 카프카를 운영하면서 디스크 사용량이 계속 늘어나는 것을 발견했습니다. "메시지를 계속 쌓기만 하면 디스크가 꽉 차겠는데, 카프카는 이걸 어떻게 관리하나요?" 박시니어 씨가 설명을 시작합니다.

"카프카에는 **보존 정책(Retention Policy)**이라는 내장 기능이 있어. 마치 냉장고의 유통기한 관리와 같아.

유통기한이 지난 음식은 자동으로 버리듯, 오래된 메시지도 자동으로 삭제돼." 가장 기본적인 정책은 시간 기반 삭제입니다. retention.ms 설정으로 보관 기간을 지정합니다.

기본값은 7일(168시간)입니다. 7일이 지난 메시지는 백그라운드 스레드에 의해 주기적으로 삭제됩니다.

이 정책은 로그 데이터나 이벤트 스트리밍 같이 시간이 지나면 가치가 떨어지는 데이터에 적합합니다. 두 번째는 크기 기반 삭제입니다.

retention.bytes로 토픽의 최대 크기를 지정합니다. 토픽 크기가 이 값을 초과하면 가장 오래된 메시지부터 삭제됩니다.

디스크 용량이 제한적인 환경에서 유용합니다. 시간 기반과 크기 기반을 함께 사용할 수도 있는데, 이 경우 두 조건 중 하나라도 충족하면 메시지가 삭제됩니다.

세 번째는 **로그 압축(Log Compaction)**입니다. 이것은 조금 다른 접근 방식입니다.

동일한 키를 가진 메시지 중 가장 최근 것만 보관하고, 이전 버전은 삭제합니다. 마치 데이터베이스의 UPDATE 연산과 비슷한 효과를 냅니다.

로그 압축은 어떤 상황에서 사용할까요? 예를 들어 user-profile 토픽에 사용자의 최신 프로필 정보를 발행한다고 가정해봅시다.

사용자가 프로필을 수정할 때마다 새 메시지가 발행되는데, 우리에게 필요한 것은 항상 최신 프로필입니다. 로그 압축을 사용하면 동일 사용자 ID를 가진 이전 메시지가 자동으로 정리되어 최신 상태만 남게 됩니다.

보존 정책 설정 시 주의할 점이 있습니다. 보존 기간을 너무 짧게 설정하면, 컨슈머가 장애로 인해 일시적으로 중단되었을 때 아직 처리하지 못한 메시지가 삭제될 수 있습니다.

반대로 너무 길게 설정하면 디스크 용량이 부족해질 수 있습니다. 컨슈머의 장애 복구 시간을 고려하여 적절한 여유를 두는 것이 좋습니다.

클러스터 수준에서 기본 보존 정책을 설정할 수도 있습니다. server.propertieslog.retention.hourslog.retention.bytes를 설정하면, 모든 토픽에 기본값으로 적용됩니다.

개별 토픽에서 별도 설정하지 않으면 이 기본값이 사용됩니다. "그러니까 용도에 따라 적절히 섞어 쓰면 되는 거군요!" 김개발 씨가 정리했습니다.

"이벤트 로그는 시간 기반, 사용자 상태는 로그 압축, 디스크가 부족한 서버는 크기 기반." 박시니어 씨가 엄지를 치켜세웠습니다. "완벽해.

이제 카프카의 데이터 관리 원리를 제대로 이해한 거야."

실전 팁

💡 - 컨슈머의 최대 장애 복구 시간보다 보존 기간을 길게 설정하세요

  • 상태 관리용 토픽에는 cleanup.policy=compact를 사용하여 최신 상태만 유지하세요
  • 이 카드뉴스는 "Apache Kafka 완전 정복" 코스의 4/15편입니다. 다음 편에서는 프로듀서 API의 핵심 기능과 메시지 전송 방식을 상세히 알아보겠습니다.

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Kafka#Topic#Partition#Offset#Retention

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.

함께 보면 좋은 카드 뉴스

Kafka 설치 및 환경 설정 완벽 가이드

Apache Kafka의 설치부터 환경 설정까지 단계별로 안내합니다. JDK 설치, ZooKeeper 구성, Kafka 브로커 설정, Docker Compose 활용, KRaft 모드까지 실무에 필요한 모든 환경 구축 방법을 다룹니다.

Premium

Apache Kafka 소개 및 특징

Apache Kafka의 탄생 배경부터 핵심 설계 철학, 다른 메시지 브로커와의 비교, 높은 처리량의 원리, 생태계 구성 요소, 실제 사용 사례까지 종합적으로 다룹니다. 이벤트 스트리밍 플랫폼으로서 카프카가 왜 업계 표준이 되었는지 알아봅니다.

Premium

메시지 큐와 이벤트 스트리밍 개념 완벽 가이드

메시지 큐의 기본 개념부터 이벤트 기반 아키텍처, 스트리밍 플랫폼의 필요성까지 술술 읽히는 이북 스타일로 설명합니다. Apache Kafka를 배우기 전 반드시 알아야 할 핵심 개념들을 다룹니다.

Premium

게임 분석과 메트릭스 완벽 가이드

Flutter와 Flame으로 개발한 게임의 성공을 측정하고 개선하는 방법을 배웁니다. Firebase Analytics 연동부터 A/B 테스팅, 리텐션 분석까지 데이터 기반 게임 운영의 모든 것을 다룹니다.

Premium

MCP 어노테이션 기반 개발 완벽 가이드

Spring AI와 MCP(Model Context Protocol)를 활용한 어노테이션 기반 도구 개발 방법을 알아봅니다. 선언적 프로그래밍으로 AI 에이전트용 도구를 쉽게 만드는 방법을 초급자도 이해할 수 있게 설명합니다.

Premium