diff --git a/Gimini-3/Week02/Chapter04.md b/Gimini-3/Week02/Chapter04.md
new file mode 100644
index 0000000..f2ea190
--- /dev/null
+++ b/Gimini-3/Week02/Chapter04.md
@@ -0,0 +1,290 @@
+# 4장 분산 메시지 큐
+
+### 메시지 큐 이점
+
+- 결합도 완화: 메시지 큐를 사용하면 컴포넌트 사이의 강한 결합이 사라지므로 각각을 독립적으로 갱신할 수 있다.
+- 규모 확장성 개선: 메시지 큐에 데이터를 생산하는 생산자(producer)와 큐에서 메시지를 소비하는 소비자(consumer) 시스템 규모를 트래픽 부하에 맞게 독립적으로 늘릴 수 있다.
+ - 예를 들어 트래픽이 몰리는 시간에는 더 많은 소비자를 추가하여 처리 용량을 늘릴 수 있다.
+- 가용성 개선: 시스템의 특정 컴포넌트에 장애가 발생해도 다른 컴포넌트는 큐와 계속 상호작용을 이어갈 수 있다.
+- 성능 개선: 메시지 큐를 사용하면 비동기 통신이 쉽게 가능하다. 생산자는 응답을 기다리지 않고도 메시지를 보낼 수 있고, 소비자는 읽을 메시지가 있을 때만 해당 메시지를 소비하면 된다.
+ - 서로를 기다릴 필요가 있다.
+
+### 메시지 큐 대 이벤트 스트리밍 플랫폼
+
+# 1단계: 문제 이해 및 설계 범위 확정
+
+생산자는 메시지를 큐에 보내고, 소비자는 큐에서 메시지를 꺼낼 수 있으면 된다.
+
+## 기능 요구사항
+
+- 생산자는 메시지 큐에 메시지를 보낼 수 있어야 한다.
+- 소비자는 메시지 큐를 통해 메시지를 수신할 수 있어야 한다.
+- 메시지는 반복적으로 수신할 수도 있어야 하고, 단 한 번만 수신하도록 설정될 수도 있어야 한다.
+- 오래된 이력 데이터는 삭제될 수 있다.
+- 메시지 크기는 킬로바이트 수준이다.
+- 메시지가 생산된 순서대로 소비자에게 전달할 수 있어야 한다.
+- 메시지 전달 방식은 최소 한 번, 최대 한 번, 정확히 한 번 가운데 설정할 수 있어야 한다.
+
+## 비기능 요구사항
+
+- 높은 대역폭과 낮은 전송 지연 가운데 하나를 설정으로 선택 가능하게 하는 기능
+- 규모 확장성. 이 시스템은 특성상 분산 시스템일 수밖에 없다. 메시지 양이 급증해도 처리 가능해야 한다.
+- 지속성 및 내구성.
+ - 데이터는 디스크에 지속적으로 보관되어야 하며 여러 노드에 복제되어야 한다.
+
+### 전통적 메시지 큐와 다른 점
+
+전통적인 큐는 메시지가 소비자에 전달되기 충분한 기간 동암난 메모리에 보관한다.
+
+- 처리 용량을 넘어선 메시지는 디스크에 보관하긴 하는데 이벤트 스트리밍 플랫폼이 감당하는 용량보다는 아주 낮은 수준이다.
+
+전통적인 메시지 큐는 메시지 전달 순서도 보존하지 않는다.
+
+- 생산된 순서와 소비되는 순서는 다를 수 있다.
+
+# 2단계: 개략적 설계안 제시 및 동의 구하기
+
+- 생산자는 메시지를 메시지 큐에 발행
+- 소비자는 큐를 구독(subscribe)하고 구독한 메시지를 소비
+- 메시지 큐는 생산자와 소비자 사이의 결합을 느슨하게 하는 서비스로, 생산자와 소비자의 독립적인 운영 및 규모 확장을 가능하게 하는 역할 담당
+- 생산자와 소비자는 모두 클라이언트/서버 모델 관점에서 보면 클라이언트고 서버 역할을 하는 것은 메시지 큐이며 이 클라이언트와 서버는 네트워크를 통해 통신
+
+## 메시지 모델
+
+### 일대일 모델
+
+일대일 모델에서 큐에 전송된 메시지는 오직 한 소비자만 가져갈 수 있다.
+
+소비자가 아무리 많아도 각 메시지는 오직 한 소비자만 가져갈 수 있다.
+
+- 어떤 소비자가 메시지를 가져갔다는 사실을 큐에 알리면 해당 메시지는 큐에서 삭제된다.
+- 이 모델은 데이터 보관을 지원하지 않는다.
+
+본 설계안은 두 주 동안은 보관할 수 있도록 하는 지속성 계층를 포함
+
+- 해당 계층을 통해 메시지가 반복적으로 소비될 수 있도록 한다.
+
+### 발행-구독 모델
+
+토픽은 메시지를 주제별로 정리하는 데 사용된다.
+
+메시지를 보내고 받을 때는 토픽에 보내고 받게 된다.
+
+이 모델에서 토픽에 전달된 메시지는 해당 토픽을 구독하는 모든 소비자에 전달된다.
+
+## 토픽, 파티션, 브로커
+
+메시지는 토픽에 보관된다. 토픽에 보관되는 데이터의 양이 커져서 서버 한 대로 감당하기 힘든 상황이 벌어지면 어떻게 될까?
+
+이 문제를 해결하는 방법은 파티션, 즉 샤딩 기법을 활용하는 것이다.
+
+토픽을 여러 파티션으로 분할한 다음에 메시지를 모든 파티션에 균등하게 나눠 보낸다.
+
+- 파티션은 토픽에 보낼 메시지의 작은 부분집합이라고 생각하면 좋다.
+- 파티션은 메시지 큐 클러스터 내의 서버에 고르게 분산 배치한다.
+
+파티션을 유지하는 서버는 보통 브로커라 부른다.
+
+- 파티션을 브로커에 분산하는 것이 높은 규모 확장성을 달성하는 비결이다.
+- 토픽의 용량을 확장하고 싶으면 파티션 개수를 늘리면 되기 때문이다.
+
+각 토픽 파티션은 FIFO 큐처럼 동작한다.
+
+같은 파티션 안에서는 메시지 순서가 유지된다.
+
+파티션 내에서의 위치는 오프셋이라고 한다.
+
+생산자가 보낸 메시지는 해당 토픽의 파티션 가운데 하나로 보내진다.
+
+메시지에는 사용자 ID 같은 키를 붙일 수 있는데, 같은 키를 가진 모든 메시지는 같은 파티션으로 보내진다.
+
+키가 없는 메시지는 무작위로 선택된 파티션으로 전송된다.
+
+토픽을 구독하는 소비자는 하나 이상의 파티션에서 데이터를 가져오게 된다.
+
+토픽을 구독하는 소비자가 여럿인 경우, 각 구독자는 해당 토픽을 구성하는 파티션의 일부를 담당하게 된다.
+
+## 소비자 그룹
+
+소비자 그룹 내 소비자는 토픽에서 메시지를 소비하기 위해 서로 협력해야 한다.
+
+하나의 소비자 그룹은 여러 토픽을 구독할 수 있고 오프셋을 별도로 관리한다.
+
+- 예를 들어 큐 용례에 따라 과금용 그룹, 회계용 그룹 등으로 나눌 수 있을 것이다.
+
+같은 그룹 내의 소비자는 메시지를 병렬로 소비할 수 있다.
+
+- 데이터를 병렬로 읽으면 대역폭 측면에서는 좋지만 같은 파티션 안에 있는 메시지를 순서대로 소비할 수는 없다.
+
+### 개략적 설계안
+
+클라이언트
+
+- 생산자: 메시지를 특정 토픽으로 보낸다.
+- 소비자 그룹: 토픽을 구독하고 메시지를 소비한다.
+
+핵심 서비스 및 저장소
+
+- 브로커: 파티션들을 유지한다. 하나의 파티션은 특정 토픽에 대한 메시지의 부분 집합을 유지한다.
+- 저장소
+ - 데이터 저장소: 메시지는 파티션 내 데이터 저장소에 보관한다.
+ - 상태 저장소: 소비자 상태는 이 저장소에 유지된다.
+ - 메타데이터 저장소: 토픽 설정, 토픽 속성 등은 이 저장소에 유지된다.
+- 조정 서비스
+ - 서비스 탐색: 어떤 브로커가 살아있는지 알려준다.
+ - 리더 선출: 브로커 가운데 하나는 컨트롤러 역할을 담당해야 하며,한 클러스터에는 반드시 활성 상태 컨트롤러가 하나 있어야 한다. 이 컨트롤러가 파티션 배치를 책임진다.
+ - 아파치 주키퍼나 etcd가 보통 컨트롤러 선출을 담당하는 컴포넌트로 널리 이용된다.
+
+# 3단계: 상세 설계
+
+- 회전 디스크의 높은 순차 탐색 성능과 현대적 운영체제가 제공하는 적극적 디스크 캐시 전략을 잘 이용하는 디스크 기반 자료 구조를 활용
+- 메시지가 생산자로부터 소비자에게 전달되는 순간까지 아무 수정 없이도 전송이 가능하도록 하는 메시지 자료 구조를 설계하고 활용할 것
+ - 전송 데이터의 양이 막대한 경우에 메시지 복사에 드는 비용을 최소화하기 위함이다.
+- 일괄 처리를 우선하는 시스템을 설계할 것
+ - 소규모의 I/O가 많으면 높은 대역폭을 지원하기 어렵다.
+ - 생산자는 메시지를 일괄 전송하고, 메시지 큐는 그 메시지들을 더 큰 단위로 묶어 보관한다.
+ - 소비자도 가능하면 메시지를 일괄 수신하도록 한다.
+
+## 데이터 저장소
+
+- 읽기와 쓰기가 빈번하게 일어난다.
+- 갱신/삭제 연산은 발생하지 않는다.
+- 순차적인 읽기/쓰기가 대부분이다.
+
+### 선택지1: 데이터베이스
+
+- 관계형 데이터베이스: 토픽별로 테이블을 만든다. 토픽에 보내는 메시지는 해당 테이블에 새로운 레코드로 추가한다.
+- NoSQL 데이터베이스: 토픽별로 컬렉션을 만든다. 토픽에 보내는 메시지는 하나의 문서가 된다.
+
+### 선택지2: 쓰기 우선 로그(Write-Ahead Log, WAL)
+
+두 번째 선택지는 쓰기 우선 로그, 즉 WAL이다.
+
+WAL은 새로운 항목이 추가되기만 하는 일반 파일이다.
+
+WAL은 다양한 시스템에서 사용되는 기술인데, MySQL의 복구 로그가 WAL로 구현되어 있고 아파치 추키퍼도 해당 기술을 활용한다.
+
+지속성을 보장해야 하는 메시지는 디스크에 WAL로 보관할 것을 추천한다.
+
+WAL에 대한 접근 패턴은 읽기/쓰기 전부 순차적이다.
+
+접근 패턴이 순차적일 때 디스크는 아주 좋은 성능을 보인다.
+
+새로운 메시지는 파티션 꼬리 부분에 추가되며, 오프셋은 그 결과를 점진적으로 증가한다.
+
+가장 쉬운 방법은 로그 파일 줄 번호를 오프셋으로 사용하는 것이다.
+
+하지만 파일의 크기도 무한정 커질수는 없으니, 세그먼트 단위로 나누는 것이 바람직하다.
+
+세그먼트를 사용하는 경우 새 메시지는 활성 상태의 세그먼트 파일에만 추가된다.
+
+해당 세그먼트의 크기가 일정 한계에 도달하면 새 활성 세그먼트 파일이 만들어져 새로운 메시지를 수용하고, 종전까지 활성 상태였던 세그먼트 파일은 다른 나머지 세그먼트 파일과 마찬가지로 비활성 상태로 바뀐다.
+
+비활성 세그먼트는 읽기 요청만 처리한다.
+
+낡은 비활성 세그먼트 파일은 보관 기한이 만료되거나 용량 한계에 도달하면 삭제해 버릴 수 있다.
+
+### 디스크 성능 관련 유의사항
+
+회전식 디스크가 느리다는 것은 널리 퍼진 편견이다.
+
+회전식 디스크가 정말로 느려지는 것은 데이터 접근 패턴이 무작위일 때다.
+
+순차적 데이터 접근 패턴을 적극 활용하는 디스크 기반 자료 구조를 사용하면, RAID로 구성된 현대적 디스크 드라이브에서 수백 MB/sec 수준의 읽기/쓰기 성능을 달성하는 것은 어렵지 않다.
+
+## 메시지 자료 구조
+
+메시지 구조는 높은 대역폭 달성의 열쇠다.
+
+메시지 자료 구조는 생산자, 메시지 큐, 그리고 소비자 사이의 계약이다.
+
+메시지가 큐를 거쳐 소비자에게 전달되는 과정에서 불필요한 복사가 일어나지 않도록 함으로써 높은 대역폭을 달성할 수 있다.
+
+## 규모 확장성
+
+### 생산자
+
+생산자의 규모 확장성은 새로운 생산자를 추가하거나 삭제함으로써 쉽게 달성할 수 있다.
+
+### 소비자
+
+소비자 그룹은 서로 독립적이므로 새 소비자 그룹은 쉽게 추가하고 삭제할 수 있다.
+
+같은 소비자 그룹 내의 소비자가 새로 추가/삭제되거나 장애로 제거되어야 하는 경우는 재조정 메커니즘이 맡아 처리한다.
+
+### 브로커
+
+브로커는 노드의 장애가 발생해 브로커가 죽었을 때 주변 브로커들이 감지를 하여 남은 브로커 노드를 위해 새로운 파티션 분산 계획을 만든다.
+
+- 파티션 분산 계획에 따라 토픽의 파티션을 브로커에 추가하거나 삭제한다.
+
+새로 추가된 사본은 단순 사본으로서, 리더에 보관된 메시지를 따라잡는 동작을 개시한다.
+
+### 브로커 결함 내성을 높이기 위해서 추가로 고려해야 할 사항
+
+- 메시지가 성공적으로 합의 되었다고 판단하려면 얼마나 많은 사본에 메시지가 반영되어야 하는가?
+- 사본은 같은 노드에 두면 안 된다
+ - 파티션의 모든 사본이 같은 브로커 노드에 있으면 해당 노드에 장애가 발생할 경우 해당 파티션은 완전 소실될 것이다.
+- 파티션의 모든 사본에 문제가 생기면 해당 파티션의 데이터는 영원히 사라진다.
+ - 사본 수와 사본 위치를 정할 때는 데이터 안전성, 자원 유지에 드는 비용, 그리고 응답 지연 등을 고려하여야 한다.
+ - 사본은 여러 데이터 센터에 분산하는 것이 안전하다..
+ - 하지만 그렇게 하면 데이터 동기화 때문에 응답 지연과 비용은 늘어난다.
+
+### 브로커 규모 확장성 더 나은 방법
+
+브로커 컨트롤러로 하여금 한시적으로 시스템에 설정된 사본 수보다 많은 사본을 허용하도록 하는 것이다.
+
+새로 추가된 브로커 노드가 기존 브로커 상태를 따라잡고 나면 더 이상 필요 없는 노드는 제거하면 된다.
+
+### 파티션 추가
+
+- 지속적으로 보관된 메시지는 여전히 기존 파티션에 존재하며 해당 데이터는 이동하지 않는다.
+- 새로운 파티션이 추가되면 그 이후 오는 메시지는 3개 파티션 전부에 지속적으로 보관되어야 한다.
+
+따라서 파티션을 늘리면 간단히 토픽의 규모를 늘릴 수 있다.
+
+### 파티션 삭제
+
+- 파티션-3을 퇴역시킨다는 결정이 내려지면 새로운 메시지는 다른 파티션에만 보관된다.
+- 퇴역된 파티션은 바로 제거하지 않고 일정 시간 동안 유지한다.
+ - 해당파티션의 데이터를 읽고 있는 소비자가 있을 수 있기 때문이다.
+ - 해당 유지 기간이 지나고 나면 데이터를 삭제하고 저장 공간을 반환한다.
+ - 따라서 파티션을 줄여도 저장 용량은 신속하게 늘어나지 않는다.
+- 파티션 퇴역 후 실제로 제거가 이루어지는 시점까지 생산자는 메시지를 남은 두 파티션으로만 보내지만 소비자는 세 파티션 모두에서 메시지를 읽는다. 실제로 파티션이 제거되는 시점이 오면 생산자 그룹은 재조정 작업을 개시해야 한다.
+
+## 메시지 전달 방식
+
+### 최대 한 번
+
+메시지를 최대 한 번 전달하는 방식
+
+- 생산자는 토픽에 비동기적으로 메시지를 보내고 수신 응답을 기다리지 않는다.(ACK=0)
+ - 메시지 전달이 실패해도 다시 시도하지 않는다
+- 소비자는 메시지를 읽고 처리하기 전에 오프셋부터 갱신한다.
+ - 오프셋이 갱신된 직후에 소비자가 장애로 죽으면 메시지는 다시 소비될 수 없다.
+
+이 전달 방식은 지표 모니터링 등, 소량의 데이터 손실은 감수할 수 있는 애플리케이션에 적합하다.
+
+### 최소 한 번
+
+같은 메시지가 한 번 이상 전달될 수는 있으나 메시지 소실은 발생하지 않는 전달 방식이다.
+
+- 생산자는 메시지를 동기적/비동기적으로 보낼 수 있으며, ACK=1 또는 ACK=all의 구성을 이용한다.
+- 즉, 메시지가 브로커에게 전달되었음을 반드시 확인한다.
+ - 메시지 전달이 실패하거나 타임아웃이 발생한 경우에는 계속 재시도할 것이다.
+- 소비자는 데이터를 성공적으로 처리한 뒤에만 오프셋을 갱신한다.
+ - 메시지 처리가 실패한 경우에는 메시지를 다시 가져오므로 데이터가 손실되는 일은 없다.
+ - 한편 메시지를 처리한 소비자가 미처 오프셋을 갱신하지 못하고 죽었다가 다시 시작하면 메시지는 중복 처리될 것이다.
+- 따라서 메시지는 브로커나 소비자에게 한 번 이상 전달될 수 있다.
+
+이 방식을 채택하면 메시지가 소실되는 일은 없지만 같은 메시지가 여러 번 전송될 수 있다.
+
+- 메시지마다 고유한 키가 있는 경우, 해당 키가 이미 데이터베이스에 있는 메시지는 처리하지 않고 버리면 될 것이다.
+
+### 정확히 한 번
+
+사용자 입장에서는 편리하지만, 시스템의 성능 및 구현 복잡도 측면에서는 큰 대가를 지불해야 한다.
+
+지불, 매매, 회계 등 금융 관련 응용에는 이 전송 방식이 적합하다.
+
+중복을 허용하지 않으며, 구현에 이용할 서비스나 제3자 제품이 같은 입력에 항상 같은 결과를 내 놓도록 구현되어 있지 않은 애플리케이션에 특히 중요하다.
diff --git a/Gimini-3/Week02/presentation.md b/Gimini-3/Week02/presentation.md
new file mode 100644
index 0000000..3bbe79c
--- /dev/null
+++ b/Gimini-3/Week02/presentation.md
@@ -0,0 +1,198 @@
+# 딜리버리서비스팀은 Kafka를 어떻게 사용하고 있을까
+
+## 누가 읽으면 좋을까
+
+딜리버리서비스팀은 **Kafka가 무엇인지 기본 개념은 알고 있는 독자**를 대상으로, “기술을 깊게 구현하는 방법”보다는 **Kafka를 중심으로 한 주요 개념(Outbox, Event Bus, Streams)을 얇고 넓게** 소개하고, 팀에서 어떻게 적용하는지 사례로 설명한다.
+
+---
+
+## Kafka, 한 섹션 요약
+
+Kafka는 **분산 스트리밍 플랫폼**으로, 대량의 데이터를 처리하고 실시간으로 전송하는 데 사용된다.
+
+Kafka는 데이터를 파일 시스템에 로그 형태로 저장하는 구조를 가지며, 여기서 로그는 **append-only(추가만 가능)**이고 **시간 순서로 정렬된 레코드 흐름**을 의미한다.
+
+
+
+Kafka에서 중요한 점은 다음과 같다.
+
+- 메시지(레코드)는 토픽에 기록되고, 토픽은 파티션으로 나뉜다.
+- **순서 보장은 토픽 전체가 아니라 같은 파티션 내부에서만** 성립한다.
+- 소비자는 오프셋(offset)으로 어디까지 읽었는지를 추적하며, **오프셋은 컨슈머 그룹 단위로 관리**된다.
+- 그래서 **같은 토픽이라도 컨슈머 그룹이 다르면 각각 독립적으로 전체 메시지를 소비**할 수 있다(=브로드캐스트에 가까운 효과).
+
+중요한 포인트
+
+- “순서 보장”을 원하면 **같은 키를 같은 파티션**으로 보내야 하고(키 기반 파티셔닝),
+- “여러 서버가 모두 같은 이벤트를 받아야” 한다면 **서버마다(혹은 서버군마다) 서로 다른 컨슈머 그룹**이 필요하다.
+
+---
+
+# 딜리버리서비스팀에서 Kafka를 활용하는 방식
+
+
+
+
+딜리버리서비스팀은 하루 100만 건 이상 생성되는 배민배달을 중계하며, 여러 주문서비스(배민배달, B마트, 배민스토어)에서 들어오는 배달 요청을 받아 **여러 배달서비스 중 하나로 분배**하고, 배달 과정을 중계·관리한다. 시스템은 이벤트 기반 분산 아키텍처로 구성되어 있고, Kafka는 팀의 핵심 기술 중 하나다.
+
+구성은 크게:
+
+- 주문/배달 서버(프로세스 관리, 이벤트 발행)
+- 분석 서버(이벤트 기반 분석/가공, 집계, 저장)
+
+ 로 나뉜다. 각 서버군은 처리량을 위해 N개의 인스턴스로 구성된다.
+
+
+---
+
+## 1) 주문-배달을 안전하게 처리하자
+
+딜리버리서비스팀이 가장 중요하게 보는 목표는 **“주문부터 배달 완료까지 안전하게 처리”**하는 것이다. 이를 위해 Kafka를 다음 2가지 관점에서 사용한다.
+
+### (1) 도메인 이벤트 순서를 보장한다
+
+
+
+
+배달은 “생성 → 배차 → 픽업 → 완료”처럼 **상태 전이가 순서를 가진 프로세스**다. 그런데 실제 운영에서는 배차 완료 직후 픽업 준비 요청처럼 **거의 동시에 발생하는 이벤트**가 있고, 네트워크/지연 때문에 컨슈머가 **뒤 이벤트를 먼저 받을 수도 있다**.
+
+딜리버리서비스팀은 이 혼란을 줄이기 위해:
+
+- **배달 식별자/주문 식별자 같은 순서가 중요한 키를 Kafka 메시지 키로 사용**
+- 같은 키는 같은 파티션으로 들어가고, 같은 파티션은 컨슈머 한 인스턴스가 담당하므로
+- **같은 배달건에 대한 이벤트는 같은 소비자에서, 파티션 내부 순서대로 처리**되도록 만든다.
+ - Kafka의 순서 보장은 **파티션 내부**에서만 성립한다.
+ - 그래서 배달 1건의 순서를 보장하려면 **deliveryId를 key로 고정**하는 방식이 일반적이다.
+
+### (2) 데이터 정합성을 확보한다 (Transactional Outbox + Debezium CDC)
+
+딜리버리서비스팀은 비즈니스 상태를 MySQL에 저장하고, 동시에 Kafka로 이벤트를 발행한다. 이때 가장 위험한 상황은 DB는 반영됐는데 Kafka 발행이 실패하는 케이스다. 예를 들어 배달 취소가 DB에 저장됐지만 이벤트가 발행되지 않으면, 다른 시스템은 취소를 모르고 배달을 계속 진행할 수 있다.
+
+이를 해결하기 위해 팀은 **Transactional Outbox Pattern**을 사용한다.
+
+- 같은 DB 트랜잭션 안에서:
+ - 비즈니스 데이터 변경 + Outbox 테이블에 이벤트 레코드 insert
+
+ 를 함께 커밋한다.
+
+- 이후 Debezium(MySQL Source Connector)이 MySQL의 **binlog(변경 로그)** 를 읽어 Outbox 테이블의 insert를 감지(CDC)하고
+- 감지된 레코드를 Kafka 토픽으로 발행한다.
+
+
+
+중요한 포인트
+
+- “WAL을 읽는다”는 표현을 쓰기도 하지만, Debezium MySQL은 보통 **InnoDB redo log(WAL) 직접 읽기**가 아니라, **MySQL binlog를 tailing**해서 변경을 읽는다.
+- Outbox가 보장하는 원자성은 비즈니스 테이블 + outbox 테이블까지다. Kafka 전송까지 DB 트랜잭션으로 묶는 것은 아니고, **eventual delivery(재시도 가능)**로 누락을 막는다.
+- CDC 기반이기 때문에 “DB 커밋된 사실”이 곧 이벤트 발행의 근거가 된다.
+
+### “MySQL source connector는 task가 1개라 순서를 보장”의 의미
+
+Debezium MySQL Source Connector는 보통 **단일 task로 동작**한다. 단일 task는 binlog를 **한 줄씩 순차로** 처리하므로, 커넥터 내부에서 이벤트 스트림이 섞이지 않는다(커넥터 관점의 순서가 깔끔해짐).
+
+하지만 단일 task의 한계도 있다.
+
+- outbox에 쌓이는 속도가 커넥터 처리 속도보다 빠르면 **지연(랙)** 이 생길 수 있다.
+
+그래서 딜리버리서비스팀은 처리량을 올리기 위해:
+
+- outbox 테이블을 토픽별/식별자 기반으로 **샤딩**한다(예: delivery-outbox1/2/3)
+- 각 테이블마다 커넥터를 붙여 병렬로 처리한다
+- 같은 키는 같은 outbox 테이블로 들어가게 해서 **키 단위 순서를 유지**한다
+
+
+
+
+---
+
+## 2) Kafka를 이벤트 버스로 활용해보자 (인메모리 설정 동기화)
+
+분산 시스템에서는 같은 역할을 하는 서버군이 여러 인스턴스로 구성된다. 이때 “한 서버에서 설정/규칙이 바뀌면, 서버군 전체가 그 변경을 알아야” 하는 문제가 자주 발생한다.
+
+딜리버리서비스팀의 예:
+
+- 배달서버가 “어떤 배달서비스로 분배할지” 규칙을 인메모리로 들고 있고,
+- 운영자가 분배 규칙을 바꾸면,
+- 서버군 전체가 동일한 규칙을 가져야 한다(안 그러면 서버마다 판단이 달라짐)
+
+이를 위해 팀은 Kafka를 **Event Bus**로 사용한다.
+
+
+
+
+- Spring Cloud의 RemoteApplicationEvent를 이용해
+- 특정 목적지(서버군)로 이벤트를 발행하고
+- 수신 측이 이벤트를 받으면 인메모리 규칙을 reload한다
+
+### 이벤트 버스 토픽을 1파티션으로 쓰는 이유
+
+딜리버리서비스팀은 이벤트 버스 토픽을 1파티션으로 운영한다.
+
+- 설정 변경 이벤트는 처리량이 높지 않다(빈도가 낮음)
+- 오히려 중요한 건 “같은 서버군이 동일한 변경을 동일한 순서로 받는 것”
+- 1파티션이면 토픽 전체가 하나의 직렬 로그가 되어 순서가 단순해진다
+
+### “모든 서버가 다른 consumer group id를 가져야” 한다는 의미
+
+Kafka에서 **같은 consumer group**은 파티션을 나눠서 처리하는 구조(경쟁 소비)라서,
+
+- 같은 group으로 묶이면 서버군 전체가 이벤트를 각각 받는 것이 아니라
+- 서버군 중 일부(또는 한 대)만 이벤트를 받을 수 있다.
+
+그래서 모든 서버(인스턴스)가 이벤트를 각자 받아 적용해야 하면,
+
+- **인스턴스마다 서로 다른 consumer group id**를 쓰면 된다.
+- 그러면 동일 이벤트가 여러 그룹에서 각각 소비되어, 한 번 발행으로도 여러 인스턴스/서버군에 브로드캐스트가 가능해진다.
+
+---
+
+## 3) 더 나은 배달을 위해 분석하자 (가공 + 실시간 집계)
+
+딜리버리서비스팀은 분석/운영을 위해 배달 현황을 **실시간 또는 준실시간**으로 보고 싶어 한다. 배치는 주기적으로만 계산하기 때문에 최신 반영이 늦을 수 있다. 이를 해결하기 위해 팀은 Kafka Streams 기반의 스트리밍 처리를 사용한다.
+
+### (1) 분석에 적합한 형태로 가공된 데이터 제공
+
+딜리버리서비스팀은 서비스 토픽과 분석용 토픽을 분리한다.
+
+- 서비스 로직에 사용하는 토픽과 분석 토픽은 요구 리소스/처리량이 다르고
+- 장애나 지연이 발생했을 때 영향 범위를 분리할 수 있다
+
+### 이벤트를 “배달 1건 요약”으로 통합하는 전처리 (Redis 임시 저장)
+
+
+
+
+배달 이벤트는 생성/배차/픽업/완료 등 여러 이벤트로 흩어져 있는데, 분석은 종종 이벤트 단위가 아니라 배달 1건 단위 요약을 원한다.
+
+예: “언제 생성됐고, 언제 배차됐고, 언제 완료됐고, 총 소요시간은?”
+
+딜리버리서비스팀은 이를 위해:
+
+- 원본 배달 토픽에서 CREATED(생성) 이벤트를 받으면 Redis에 기본 정보를 저장
+- 이후 이벤트(배차/픽업/완료)가 들어올 때마다 Redis의 해당 deliveryId 상태를 업데이트
+- COMPLETED(완료) 이벤트가 오면 요약 데이터를 완성하고
+ - Redis에서 삭제(임시 상태 정리)
+ - 배달통합이벤트(요약)를 분석 토픽에 발행
+- Redis는 여기서 deliveryId별 현재까지 누적된 상태를 들고 있는 **state store(외부 상태 저장소)** 역할을 한다.
+
+### (2) 장기 보관과 분석: S3 Sink + Athena
+
+딜리버리서비스팀은 분석 토픽에 들어간 이벤트를 S3 Sink Connector로 S3에 영구 저장하고, Athena로 조회한다.
+
+이렇게 하면:
+
+- 비즈니스 DB에 부하를 주지 않고
+- 오래된 기록까지 비용 효율적으로 분석할 수 있고
+- 월 단위 분석/정산 등에도 활용 가능하다.
+
+---
+
+# 마무리 요약
+
+딜리버리서비스팀은 Kafka를 단순 메시지 큐가 아니라,
+
+1. **안전한 주문/배달 처리(순서 + 정합성)**
+2. **분산 서버군 설정 동기화(Event Bus)**
+3. **분석/운영을 위한 스트리밍 가공·집계(Kafka Streams)**
+
+ 까지 확장해 사용하고 있다.