소개
주문 하나가 생성되고 다른 주문이 생성된 다음 첫 주문이 결제됩니다. 현재 상태 테이블은 주문마다 최신 상태만 보여줄 수 있습니다. **이벤트(event)**는 발생한 일을 설명하므로 세 사실 모두 이력으로 유용할 수 있습니다. 새 주문에 반응하는 시스템에는 이런 사실을 애플리케이션 사이에 전달할 방법이 필요합니다.
Apache Kafka는 이벤트 기록을 저장하고 전달합니다. **생산자(producer)**는 기록을 보내고, **브로커(broker)**는 이를 받아 저장하는 서버이며, **토픽(topic)**은 기록 스트림의 이름이고, **소비자(consumer)**는 기록을 읽습니다. Kafka는 서로 다른 시간이나 속도로 작동하는 애플리케이션을 연결할 수 있습니다. 다른 처리 도구가 이벤트에서 보고서를 계산할 수 있지만 이 과정에서는 먼저 신뢰할 수 있는 전달과 읽기 진행 상태에 집중합니다.
토픽을 만들고 별도 터미널에서 생산자와 소비자를 관찰하며 첫 소비자가 종료된 뒤 같은 이벤트를 다시 읽습니다. 준비된 단일 브로커 환경은 복제본 하나를 사용하며 클러스터 배포는 별도 주제입니다. 처음 여섯 활동에는 기본 터미널 사용법만 필요합니다. 이후 Python 클라이언트 활동에는 함수, 반복문, 딕셔너리, JSON과 스크립트 실행이 필요하며 Python 경로로 준비할 수 있습니다. Java, Hadoop, Hive, Spark와 외부 계정은 선수 조건이 아닙니다. Terminal 서비스를 사용하세요.
주문 이벤트를 둘 곳 만들기
이 단계에서는 준비된 Kafka 서비스가 응답하는지 확인하고 토픽을 만듭니다. 첫 셸을 터미널 A로 유지하세요. 작업 공간에서 시작합니다.
## Terminal A
cd /home/labex/project
명령줄 클라이언트는 이미 설치되어 있습니다. --bootstrap-server는 클러스터를 발견하는 데 사용할 초기 브로커 주소를 제공합니다. 여기서 localhost:9092는 외부 계정이 아니라 준비된 로컬 서비스입니다. 실제 브로커 응답을 확인하려고 토픽을 나열합니다.
## Terminal A
kafka-topics.sh --bootstrap-server localhost:9092 --list
새 학습 환경에는 아직 애플리케이션 토픽이 없을 수 있습니다. orders-first를 만듭니다. 토픽에는 기록을 저장하는 순서 있는 로그인 **파티션(partition)**이 하나 이상 있습니다. 첫 순서를 쉽게 따라가도록 파티션 하나로 시작합니다. --replication-factor 1은 준비된 브로커 하나에 맞습니다.
## Terminal A
kafka-topics.sh --bootstrap-server localhost:9092 --create --topic orders-first --partitions 1 --replication-factor 1
새 토픽을 확인합니다.
## Terminal A
kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic orders-first
토픽 이름, PartitionCount: 1, ReplicationFactor: 1을 찾으세요. ID, 리더 식별자와 형식은 달라질 수 있습니다. 토픽 생성은 저장 대상을 마련했으며 아직 주문을 보내거나 다른 서버를 설치하지 않았습니다.
짧게 실행되는 생산자와 소비자 클라이언트가 시작하고 종료해도 브로커는 계속 실행됩니다. 다음에는 이 분리를 이용해 이벤트 도착을 관찰합니다.
다른 클라이언트가 보낸 내용을 수신하는 모습 관찰하기
이 단계에서는 터미널 하나에서 소비자를 대기시키고 다른 터미널에서 기록 세 개를 보냅니다. Terminal 서비스는 터미널 세션 관리자인 tmux로 셸을 유지합니다. 두 번째 브라우저 연결도 처음에는 같은 영속 세션을 보여줍니다. 독립적인 프롬프트를 쓰도록 터미널 B에 별도 이름의 셸 세션을 만드세요.
터미널 A에서 분리된 세션을 만듭니다. -d는 현재 터미널을 유지하고 -s는 새 세션 이름, -c는 시작 디렉터리를 선택합니다. 또 다른 Kafka 브로커가 아니라 셸을 만듭니다.
## Terminal A
tmux new-session -d -s kafka-b -c /home/labex/project
터미널 A를 열어 둔 채 같은 Terminal 서비스를 두 번째 브라우저 탭에서 엽니다. 새 탭을 터미널 B로 부르고 해당 연결을 준비된 세션으로 전환합니다.
## Terminal B
tmux switch-client -t kafka-b
전환 후 셸만 활성화된 상태에서 Ctrl-C를 한 번 눌러 아직 제출되지 않은 터미널 입력을 지웁니다. 세션 이름을 확인합니다.
## Terminal B
tmux display-message -p '#S'
kafka-b가 예상됩니다. 터미널 A는 원래 세션을 유지하며 두 셸은 같은 VM 파일에 접근합니다. 브라우저 탭을 바꿀 때 이 역할을 유지하세요. 이번 연습에서 이미 해당 세션을 만들었다면 다시 만들지 말고 재사용합니다.
터미널 B에서 아래 소비자를 시작합니다. 기록 세 개를 읽을 때까지 기다린 뒤 자동 종료합니다. --from-beginning은 이 새 소비자에 보존된 시작 지점부터 읽도록 요청하고, --max-messages 3은 작업량을, --timeout-ms 30000은 유휴 대기를 제한합니다. 파이프는 일반 출력을 tee로 보내 표시하면서 로컬 사본도 저장합니다.
## Terminal B
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic orders-first --from-beginning --max-messages 3 --timeout-ms 30000 | tee /home/labex/project/output/received-events.txt
터미널 B를 대기 상태로 두세요. 터미널 A로 전환해 30초 유휴 제한 안에 배치를 보냅니다. 아무것도 보내기 전에 시간이 끝나면 터미널 B에서 같은 소비자 명령을 다시 시작하고 돌아와 배치를 보냅니다. 이미 이벤트를 보냈다면 소비자만 다시 실행해 보존된 세 기록을 확인하세요. 생산자 배치를 다시 보내면 중복이 추가됩니다.
## Terminal A
printf '%s\n' 'order-1001 created' 'order-1002 created' 'order-1001 paid' | kafka-console-producer.sh --bootstrap-server localhost:9092 --topic orders-first
printf는 따옴표로 묶인 각 텍스트 값과 줄바꿈을 출력합니다. 파이프는 이 줄을 생산자에게 제공하며 콘솔 생산자는 한 줄을 이벤트 기록 하나로 다룹니다. printf가 끝나면 입력 스트림이 닫히므로 생산자는 대기 중인 전송을 완료하고 종료합니다. 대화형 생산자 프롬프트에 입력할 필요는 없습니다.
터미널 B로 돌아가세요. 데이터 세 줄은 다음과 같아야 합니다.
order-1001 created
order-1002 created
order-1001 paid
처리 메시지 개수나 클라이언트 진단도 터미널에 나타날 수 있습니다. 저장 파일에는 이벤트 값 세 개가 있어야 합니다. order-1001의 두 사실은 별도 기록이며 paid 이벤트가 이전 created 이벤트를 덮어쓰지 않았습니다.
소비자는 보통 메시지 세 개 뒤에 프롬프트로 돌아옵니다. 실수로 무제한 클라이언트를 실행했다면 해당 터미널에서 Ctrl-C로 그 클라이언트를 멈출 수 있습니다. 브로커를 멈추거나 토픽을 삭제하지는 않습니다. 여기서는 제한 덕분에 정상 경로가 수동 중단 없이 끝납니다.
새 소비자로 보존된 이벤트 읽기
이 단계에서는 읽기가 이벤트를 제거했는지 확인합니다. 첫 소비자는 종료되었습니다. 보존된 시작부터 읽는 새 독립 소비자에게 무엇이 보일지 예상해 보세요. 같은 세 기록입니다.
터미널 B에서 새 제한 소비자를 실행하고 두 번째 읽기를 별도로 저장합니다.
## Terminal B
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic orders-first --from-beginning --max-messages 3 --timeout-ms 30000 | tee /home/labex/project/output/replayed-events.txt
단일 파티션 안에서 같은 세 값이 같은 순서로 예상됩니다. 다른 배치를 보내지 않았습니다. 터미널 A에서 두 로컬 관찰 결과를 확인합니다.
## Terminal A
cat /home/labex/project/output/received-events.txt
## Terminal A
cat /home/labex/project/output/replayed-events.txt
둘 다 원래 이벤트 세 개를 모두 포함해야 합니다. 소비와 저장 보존은 별개입니다. 읽어도 토픽에서 기록이 제거되지 않습니다. 첫 실험은 새 콘솔 소비자를 사용합니다. 이후 이름 있는 소비자 그룹이 읽기 진행 상태를 저장하는 방법과 시작 옵션이 이미 커밋된 유효 위치를 덮어쓰지 않는 이유를 배웁니다.
짧게 실행된 두 클라이언트가 종료된 후에도 Kafka는 이벤트 이력을 유지했습니다. 다음에는 토픽 속성을 확인하고 소비 진행 상태와 독립적으로 보존 설정이 저장 정책에 미치는 영향을 살펴봅니다.
요약
Kafka의 이벤트 전달 역할을 알아보고 단일 파티션 토픽을 만들었으며 별도 생산자 및 소비자 클라이언트가 주문 이벤트 세 개를 주고받는 것을 관찰했습니다. 첫 소비자 종료 후 새 소비자가 같은 보존 이력을 읽어 읽기와 삭제가 다른 연산임을 확인했습니다. 다음에는 토픽의 파티션, 복제본과 보존 속성을 살펴봅니다.



