소개
하나의 주문에 생성, 결제, 배송 등 여러 이벤트가 발생할 수 있습니다. 관련 레코드가 일관되게 라우팅되면 컨슈머는 하나의 파티션 안에서 해당 주문의 흐름을 따라갈 수 있습니다. 레코드 키는 일정한 라우팅 입력값을 제공합니다. 개별 이벤트 발생을 식별하는 event_id와는 다릅니다.
이 실습에서는 세 주문의 이벤트가 섞인 데이터를 파티션이 세 개인 토픽에 발행하고, 실제 키와 위치를 출력한 뒤 기존 주문에 이벤트를 하나 더 추가합니다. 오프셋은 한 파티션 내에서 레코드가 차지하는 위치입니다. 토픽 전체의 행 번호가 아니며, 서로 다른 파티션의 레코드 사이에는 하나의 전역 순서가 보장되지 않습니다.
브로커와 입력 데이터는 이 실습용으로 독립적으로 준비됩니다. 기본적인 터미널 사용법만 알면 됩니다. 이벤트 값은 읽기 쉬운 JSON 텍스트이며 Python, JSON 프로그래밍, 클러스터 설정이나 이전 토픽 상태는 필요하지 않습니다. 실험 내내 파티션 수와 클라이언트 라우팅 전략을 그대로 유지하세요. 터미널을 사용합니다.
주문 키를 사용해 섞여 있는 이벤트 발행하기
이 단계에서는 전체 이벤트를 값으로 유지하면서 변하지 않는 주문 식별자를 키로 전송합니다. 제공된 레코드 다섯 개를 확인하세요.
cd /home/labex/project
cat /home/labex/project/data/keyed-orders.txt
각 줄의 형식은 key|value입니다. 키는 주문 식별자입니다. JSON 값은 중괄호 안에 이름이 있는 필드를 사용합니다. event_id는 고유하며, order_id는 키와 일치합니다. sequence는 해당 주문의 업무상 순서이고, event_type은 발생한 일을 나타냅니다. JSON 텍스트는 값의 형식일 뿐이며 Kafka가 이를 자동으로 테이블 스키마로 해석하지는 않습니다.
파티션이 세 개이고 복제 계수가 1인 토픽을 만드세요.
kafka-topics.sh --bootstrap-server localhost:9092 --create --topic orders-keyed --partitions 3 --replication-factor 1
프로듀서의 --reader-property 옵션은 입력 줄을 해석하는 방식을 설정합니다. parse.key=true와 key.separator=|는 구분자를 기준으로 각 줄을 나눕니다. 구분자 자체는 키나 값에 포함되지 않습니다. 셸의 <는 파일을 표준 입력으로 전달하며, 프로듀서는 주어진 입력을 모두 전송한 뒤 종료됩니다.
kafka-console-producer.sh --bootstrap-server localhost:9092 --topic orders-keyed --reader-property parse.key=true --reader-property 'key.separator=|' < /home/labex/project/data/keyed-orders.txt
파일에는 여러 주문이 섞여 있으므로 order-2001의 이벤트들이 입력에서 연속으로 나타나지 않습니다. 키 라우팅 전략과 파티션 수가 같으면 동일한 키는 같은 파티션으로 라우팅됩니다. 서로 다른 키가 하나의 파티션을 공유할 수도 있습니다. 주문이 세 개라고 해서 반드시 서로 다른 세 파티션에 배치되는 것은 아닙니다.
제공된 레코드 다섯 개는 한 번만 발행하세요. 컨슈머 읽기를 반복하면 데이터를 다시 확인하지만, 이 프로듀서 명령을 반복하면 레코드 다섯 개가 추가됩니다. 이미 발행한 뒤 실습을 재개했다면 파일을 다시 보내지 말고 컨슈머 확인 단계로 진행하세요.
파티션 번호를 직접 선택하는 대신 라우팅 입력값을 제공했습니다. 다음으로 실제 라우팅 결과를 읽어 확인합니다.
키, 파티션, 오프셋 함께 확인하기
이 단계에서는 각 값과 함께 레코드 메타데이터를 표시합니다. 콘솔 컨슈머의 --formatter-property 옵션은 표시 방식을 제어하며 기본 출력에 키, 파티션, 오프셋을 추가합니다. 저장된 이벤트 내용은 바뀌지 않습니다. 새 컨슈머가 처음부터 읽는 옵션, 메시지 다섯 개 제한, 유휴 시간 제한을 사용하므로 정해진 범위의 확인을 반복할 수 있습니다. 출력을 로컬에 저장하세요.
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic orders-keyed --from-beginning --max-messages 5 --timeout-ms 30000 --formatter-property print.key=true --formatter-property print.partition=true --formatter-property print.offset=true > /home/labex/project/output/keyed-first.txt
cat /home/labex/project/output/keyed-first.txt
각 데이터 줄에는 실제 숫자와 전체 JSON 값이 포함되어 다음과 같은 형태로 표시됩니다.
Partition:... Offset:... order-... {"event_id":"...",...}
구분자는 탭입니다. k1과 k3을 찾아보세요. 둘 다 키가 order-2001이므로 같은 파티션에 있어야 하고, k3의 오프셋이 더 커야 합니다. k2와 k4도 마찬가지로 order-2002의 파티션을 공유해야 합니다. 두 주문이 서로 다른 파티션을 사용해야 하는 것은 아닙니다.
오프셋은 키가 아니라 파티션에 속합니다. 다른 키가 같은 파티션을 공유하면 한 주문의 연속된 이벤트 사이에 오프셋 간격이 생길 수 있습니다. 페이로드의 sequence 필드는 애플리케이션이 정한 값이며, Kafka가 오프셋으로 생성한 값이 아닙니다.
컨슈머는 여러 파티션의 레코드를 섞어서 표시할 수 있으므로 전체 출력 순서가 프로듀서 파일과 일치하지 않을 수 있습니다. 출력을 하나의 전역 순서 목록으로 취급하지 말고, 키와 파티션, 증가하는 오프셋을 통해 관련 이벤트를 확인하세요.
기존 주문에 이벤트 하나 더 추가하기
이 단계에서는 프로듀서를 다시 실행하여 같은 라우팅 규칙을 시험합니다. order-2001의 shipped 이벤트가 어디로 갈지 예상해 보세요. 해당 주문의 기존 파티션에 배치되고 앞선 레코드 뒤에 이어져야 합니다. 정확한 오프셋은 같은 파티션에 있는 다른 레코드에 따라 달라집니다.
첫 Kafka 실습에서 사용한 printf 방식으로 키가 포함된 완전한 한 줄을 동일한 설정의 콘솔 프로듀서에 전달합니다.
printf '%s\n' 'order-2001|{"event_id":"k6","order_id":"order-2001","sequence":3,"event_type":"shipped"}' | kafka-console-producer.sh --bootstrap-server localhost:9092 --topic orders-keyed --reader-property parse.key=true --reader-property 'key.separator=|'
보관된 레코드 여섯 개를 모두 읽어 새 관찰 파일에 저장하세요.
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic orders-keyed --from-beginning --max-messages 6 --timeout-ms 30000 --formatter-property print.key=true --formatter-property print.partition=true --formatter-property print.offset=true > /home/labex/project/output/keyed-with-shipped.txt
cat /home/labex/project/output/keyed-with-shipped.txt
order-2001과 sequence 3이 있는 k6을 찾으세요. 파티션과 오프셋을 k1, k3의 값과 비교하세요. 파티션 내 오프셋 순서로 보면 주문의 흐름은 created, paid, shipped를 유지해야 합니다. 특정 파티션 번호일 필요는 없습니다.
처음 관찰한 레코드 다섯 개는 keyed-first.txt에 남아 있습니다. 새 프로듀서는 이전 이벤트를 대체하지 않고 이벤트를 추가했습니다. 토픽 파티션 수와 라우팅 전략은 라우팅 결과에 영향을 줄 수 있으므로 이 실험에서는 둘 다 바꾸지 않습니다. 이후 다른 클라이언트 구현에서도 같은 매핑이 필요하다면 호환되는 라우팅 전략을 선택해야 합니다.
이제 전체 이벤트의 전역 순서나 주문당 하나의 전용 파티션을 가정하지 않고도, 키별로 일정한 라우팅과 파티션 내부 순서를 확인했습니다. 다음 도전 과제에서는 토픽, 보관 설정, 키가 있는 발행 기술을 새 데이터에 적용합니다.
요약
이 실습에서는 주문 키를 제공하고 실제 파티션과 오프셋을 확인했으며, 같은 라우팅 규칙에서 추가 이벤트가 해당 주문의 앞선 레코드 뒤에 배치되는지 검증했습니다. 전역 순서를 가정하지 않으면서 이벤트 ID, 주문 키, 페이로드 순서, 파티션 오프셋을 구분했습니다. 다음 도전 과제에서는 이 기술과 토픽 보관 설정을 새 데이터에 함께 적용합니다.



