From 309e30598b892300748e02975eb820c451d7663c Mon Sep 17 00:00:00 2001
From: Chorong0824 <124541156+sjmun09@users.noreply.github.com>
Date: Wed, 1 Oct 2025 00:29:44 +0900
Subject: [PATCH 1/8] docs : DNS
---
seongjun/DNS.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 seongjun/DNS.md
diff --git a/seongjun/DNS.md b/seongjun/DNS.md
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/seongjun/DNS.md
@@ -0,0 +1 @@
+
From 63074437ed001c47d596657eba0cdf9dfe2c114b Mon Sep 17 00:00:00 2001
From: Chorong0824 <124541156+sjmun09@users.noreply.github.com>
Date: Thu, 9 Oct 2025 18:33:19 +0900
Subject: [PATCH 2/8] =?UTF-8?q?docs=20:=20=EB=8F=99=EA=B8=B0=EC=99=80=20?=
=?UTF-8?q?=EB=B9=84=EB=8F=99=EA=B8=B0=20=EC=B0=A8=EC=9D=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...0_353円271円204円353円217円231円352円270円260円.md" | 300 ++++++++++++++++++
1 file changed, 300 insertions(+)
create mode 100644 "seongjun/353円217円231円352円270円260円_353円271円204円353円217円231円352円270円260円.md"
diff --git "a/seongjun/353円217円231円352円270円260円_353円271円204円353円217円231円352円270円260円.md" "b/seongjun/353円217円231円352円270円260円_353円271円204円353円217円231円352円270円260円.md"
new file mode 100644
index 0000000..c444775
--- /dev/null
+++ "b/seongjun/353円217円231円352円270円260円_353円271円204円353円217円231円352円270円260円.md"
@@ -0,0 +1,300 @@
+
+
+### 1. 동기(Synchronous : 동시에 일어나는)
+#### Synch = 동시에, 동기화 (보통 Sync로 표현함)
+를 알아두면 좋다.
+
+- 동기는 말 그대로 동시에 일어난다는 뜻이다. 요청과 그 결과가 동시에 일어난다는 약속이다.
+
+요청을 하면 시간이 얼마나 걸리던지 요청한 바로 그 자리에서 결과가 주어져야 한다.
+순서에 맞춰 진행된다는 장점이 있지만, 여러가지 요청을 동시에 처리할 수 없다.
+
+위 그림의 (a)처럼 커피 주문을 받고 나올 때까지 기다리는 것이 동기 방식의 대표적인 예시다.
+
+
+
+### 비동기(Asynchronous: 동시에 일어나지 않는)
+#### 보통 'async' 이런 식으로 짧게 표현한다.
+- 비동기는 동시에 일어나지 않는다를 의미한다. 즉, 요청과 결과가 동시에 일어나지 않을 것이라는 약속이다.
+
+하나의 요청에 따른 응답을 즉시 처리하지 않고, 그 대기 시간동안 또 다른 요청에 대해 처리 가능한 방식이다.
+여러 개의 요청을 동시에 처리할 수 있는 장점이 있지만 동기 방식보다 속도가 떨어질 수도 있다.
+
+위 그림의 (b)처럼 점원 한 명이 커피 주문을 받고 다른 점원이 커피를 건네주는 것이 비동기 방식의 예시다.
+
+> 우리는 일상에 생각보다 많이 동기/비동기적으로 살아가고 있다.
+카페, 식당이 비동기 처리의 대표적인 예시다.
+동기 처리는 편의점 계산이라고 보면 된다.
+내가 결제할 물품을 계산대에 올려 계산하기까지 그 결과를 기다리기 때문이다.
+
+#### 동기와 비동기는 상황에 따라서 각각의 장단점이 있다.
+
+정답은 없다.
+- 동기방식은 설계가 매우 간단하고 직관적이지만 결과가 주어질 때까지 아무것도 못하고 대기해야 하는 단점이 있고,
+- 비동기방식은 동기보다 복잡하지만 결과가 주어지는데 시간이 걸리더라도 그 시간 동안 작업을 할 수 있으므로 자원을 효율적으로 사용할 수 있는 장점이 있다.
+
+
+
+
+
+1. A의 계좌는 10,000원을 뺄 생각을 하고 있다.
+2. A의 계좌가 B의 계좌에 10,000원을 송금한다.
+3. B의 계좌는 10,000원을 받았다는 걸 인지하고, A의 계좌에 10,000원을 받았다고 전송한다.
+4. A, B 계좌 각각 차감과 증가가 동시에 발생한다.
+
+- A의 계좌와 B의 계좌는 서로 요청과 응답(1~3번 과정)을 확인한 후 같은 일을 동시에 진행했다.(4번 과정)
+
+'계좌이체'같은 작업은 동기방식으로 처리해야 A에서 보냈는데 B에서 못 받는 상황이 없을 것이다.
+
+반대로 비동기 방식은 위의 예제처럼 노드 사이의 작업 처리 단위를 동시에 맞추지 않아도 된다.
+
+
+
+비동기 방식의 예(시험날의 학생과 선생)
+
+
+1. 학생은 시험문제를 푼다.
+2. 시험문제를 모두 푼 학생은 선생에게 전송한다.
+3. 선생은 학생의 시험지를 채점한다.
+4. 채점이 다 된 시험지를 학생에게 전송한다.
+5. 학생은 선생이 전송한 시험지를 받아 결과를 확인한다.
+
+- 학생과 선생은 시험지라는 연결고리가 있지만 시험지에 행하는 행위(목적)는 서로 다르다.
+
+학생은 시험지를 푸는 역할을 하고 선생은 시험지를 채점하는 역할을 한다.
+서로의 행위(목적)가 다르기 때문에 둘의 작업 처리 시간은 일치하지 않고, 일치하지 않아도 된다.
+
+
+
+동기와 비동기는 어떤 작업 혹은 그와 연관된 작업을 처리하고자 하는 시각의 차이이다.
+
+동기는 추구하는 같은 행위(목적)가 동시에 이루어지며,
+비동기는 추구하는 행위(목적)가 다를 수도 있고, 동시에 이루어지지도 않는다.
+
+
+
+비동기 방식 예제를 통해 블록과 논 블록의 차이를 간략하게 설명하면,
+학생이 시험지를 선생에게 건넨 후 가만히 앉아 채점이 끝나 시험지를 돌려받기만을 기다린다면 학생은 블록 상태이다.
+하지만 학생이 시험지를 건넨 후 선생에게 채점이 완료되었다는 전송을 받기 전까지 다른 과목을 공부한다거나 게임을 한다거나 다른 일을 하게 되면 학생의 상태는 논 블록 상태이다.
+
+
+
+## 👇 추가 정리: 동기/비동기, 블로킹/논블로킹, 선택 기준 && 패턴
+### 1) 한 줄 핵심
+- **동기 vs 비동기**: "**결과를 언제 받는가**(응답 타이밍/흐름 제어)"
+- **블로킹 vs 논블로킹**: "**기다리는 동안 쓰레드가 묶이는가**(자원 사용 방식)"
+- 둘은 독립축이다. **동기-논블로킹** / **비동기-블로킹** 조합도 가능하다.
+
+---
+
+### 2) 일상 속 빠른 예시 8가지
+- **편의점 계산**: 줄 서서 결제 끝날 때까지 **동기·블로킹**.
+- **카페 진동벨**: 주문 후 벨 울릴 때 와서 수령 **비동기·논블로킹**.
+- **패스트푸드 키오스크 + 픽업번호**: 번호 호출 전까지 다른 일 가능 **비동기**.
+- **택시 호출 앱**: 배차 대기 중 다른 앱 사용 **비동기·논블로킹**.
+- **병원 접수표(대기번호)**: 내 차례 전까지 대기 **비동기**, 대기실에만 앉아 있으면 체감은 **블로킹**.
+- **세탁소 맡기고 문자 수령**: 처리 완료 후 알림 **비동기**.
+- **엘리베이터 호출**: 버튼 누르고 앞에서 기다리면 **동기·블로킹** 체감, 다른 층 다녀오면 **비동기**처럼 활용.
+- **택배 배송 조회**: 당장 결과 필요 없고 진행상황만 보면 됨 **비동기** 사용에 적합.
+
+---
+
+### 3) 블로킹 vs 논블로킹 (자원 사용 관점)
+- **블로킹**: 결과 대기 동안 **쓰레드/프로세스가 멈춤**. I/O 대기 시 빈 시간이 길어지면 비효율.
+- **논블로킹**: 결과 대기 동안 **쓰레드가 다른 일 수행**. 콜백/이벤트 루프/리액티브로 처리.
+```
+| | 블로킹 | 논블로킹 |
+|----------------|---------------------------------------------|----------------------------------------------------|
+| 쓰레드 상태 | 대기(Idle) | 다른 작업 수행 가능 |
+| 구현 난이도 | 낮음 | 중~상(콜백/스트림/리액티브 패러다임) |
+| 적합한 상황 | 짧고 확정적 I/O, 간단한 동기식 트랜잭션 | 고동시성 I/O, 외부 호출이 잦고 지연이 가변적일 때 |
+```
+
+> **주의**: "동기=블로킹, 비동기=논블로킹"이 **항상** 성립하는 건 아니다.
+
+---
+
+### 4) 동시성(Concurrency) vs 병렬성(Parallelism)
+- **동시성**: 논리적으로 동시에 보이게 **스케줄링**(빠르게 문맥 전환). 단일 코어도 가능.
+- **병렬성**: 물리적으로 **동시에 실행**(멀티코어/멀티머신).
+- 비동기/논블로킹은 **동시성 처리량**을 높이는 데 유리하지만, **병렬성**은 하드웨어/워크로드에 달려 있다.
+
+---
+
+### 5) 언제 동기? 언제 비동기? (선택 체크리스트)
+- **즉시 결과가 사용자 경험 핵심인가?** (로그인, 결제 승인 결과 등) → **동기 우선**, 타임아웃/폴백 설계.
+- **처리 시간이 길거나 외부 의존 지연이 큰가?** (인코딩, 썸네일, 이메일) → **비동기 큐/워커**.
+- **강한 일관(ACID) 트랜잭션의 경계 안에 있어야 하나?** → 해당 범위까진 **동기**.
+- **후속 시스템으로의 확산(알림/적립/로그)은 eventual OK?** → **비동기 이벤트 발행**.
+- **호출량/팬아웃이 큰가?** → 호출부 **비동기화 + 벌크/배치 + 서킷브레이커**.
+- **SLO가 p95/99에 민감한가?** → 비동기/논블로킹으로 **꼬리지연 완화 + 백프레셔**.
+
+---
+
+### 6) 아키텍처 패턴 (시나리오/다이어그램)
+
+#### 6-1. 동기식 요청-응답 (간단/즉시결과)
+```mermaid
+sequenceDiagram
+ participant Client
+ participant API
+ participant DB
+ Client->>API: POST /transfer {from,to,amount}
+ API->>DB: in Tx: debit(from), credit(to)
+ DB-->>API: commit OK
+ API-->>Client: 200 OK (result)
+```
+
+#### 6-2. 비동기식 처리 + 콜백/웹훅 (지연 OK, 확장성)
+
+```
+sequenceDiagram
+ participant Client
+ participant API
+ participant Queue
+ participant Worker
+ participant Webhook
+ Client->>API: POST /orders
+ API->>Queue: publish(orderCreated)
+ API-->>Client: 202 Accepted (trackingId)
+ Worker->>Queue: consume(orderCreated)
+ Worker->>Webhook: POST /notify (trackingId, status=Done)
+ Note over Client: 폴링(/status) 또는 웹훅으로 상태 갱신
+```
+
+#### 6-3. 결제(예시): 동기 승인 + 비동기 정산/알림
+- **주문 생성/승인**은 사용자 UX를 위해 **동기**(타임아웃/재시도 포함).
+- **영수증 발송, 포인트 적립, 대시보드 집계**는 **비동기 이벤트**로 확산.
+
+---
+
+### 7) 실무 필수 패턴(비동기)
+- **Idempotency Key**: 동일 요청 중복 도달에도 **한 번만** 효과 반영.
+- **Outbox 패턴**: 로컬 트랜잭션 내 **DB에 이벤트 기록 → 별 프로세스가 브로커로 전송**(분산 트랜잭션 없이 ‘정확히 한 번에 가까운’ 전달 보장).
+- **전달 보장**: 대부분 **at-least-once + 멱등 처리**가 현실적. exactly-once는 비용↑/제약↑.
+- **Retry & DLQ**: 지수 백오프, 최대 재시도 후 **사망 큐**로 격리/수동 복구.
+- **Ordering**: 파티션 키(예: userId)로 **순서 보존**, 병렬성-순서성 균형 설계.
+- **Backpressure**: 소비 속도 < 생산 속도일 때 **유량 제어**(버퍼, 드롭, 슬로우 스타트). +- **관찰가능성**: 상관관계 ID, 분산 트레이싱, 메트릭(p95/p99), 알람. + +--- + +### 8) 장단점 한눈에 +| 구분 | 동기 | 비동기 | +|---|---|---| +| 사용자 피드백 | 즉시 결과, UX 명확 | 즉시 완료가 아닐 수 있음(상태 조회/알림 필요) | +| 복잡도 | 낮음 | 큐/워커/상태관리/멱등성 등 설계 복잡 | +| 확장성/자원 효율 | 쓰레드 영걸림으로 한계 | 고동시성/자원 효율 우수 | +| 일관성 | 강한 일관성 범위 한정 쉬움 | 보통 최종 일관성(eventual) | +| 실패 처리 | 호출부에서 즉시 식별 | 재시도/보상/모니터링 체계 필수 | + +--- + +### 9) Java/Spring 예시 스니펫 + +#### 9-1. 동기·블로킹 호출 (간단/즉시 결과) +```java +// Spring 6: RestClient (블로킹) +RestClient client = RestClient.create("https://pay.example.com"); +PaymentResponse res = client.post() + .uri("/approve") + .body(request) + .retrieve() + .body(PaymentResponse.class); // 완료까지 현재 쓰레드 대기 +``` + +#### 9-2. 비동기·논블로킹 (리액티브 WebClient) +```java +// 논블로킹: 결과는 Mono로 비동기 전달 +WebClient webClient = WebClient.create("https://pay.example.com"); +Mono mono = webClient.post()
+ .uri("/approve")
+ .bodyValue(request)
+ .retrieve()
+ .bodyToMono(PaymentResponse.class);
+
+// 체이닝/조합 가능 (subscribe 시점에 실행)
+mono.timeout(Duration.ofSeconds(3))
+ .doOnError(e -> log.warn("timeout/retry"))
+ .retryWhen(Retry.backoff(3, Duration.ofMillis(200)));
+
+```
+#### 9-3. 메시징(카프카) 기반 비동기
+```java
+// 생산자
+kafkaTemplate.send("order.created", orderId, payload);
+
+// 소비자(멱등 처리)
+@KafkaListener(topics = "order.created")
+public void handle(String key, OrderCreated evt) {
+ if (processedRepo.exists(evt.id())) return; // 멱등
+ // 비즈 처리...
+ processedRepo.save(evt.id());
+}
+```
+
+---
+### 10) 계좌이체 비유, 조금 더 정확히
+- "A 차감과 B 가산"은 **같은 트랜잭션 경계**에 있으면 동기·원자적으로 처리 가능.
+- 다만 **타 시스템 통합/정산/알림**은 대개 **비동기**(최종 일관성).
+ 즉, **핵심 잔액 갱신은 동기**, **주변 효과는 비동기**가 실무에서 흔한 분리다.
+
+---
+
+### 11) 실패/타임아웃/회복 전략
+- **타임아웃**: 외부 호출은 반드시 설정(서비스 SLO에 맞춤).
+- **서킷브레이커**: 연쇄 실패/폭주 방지.
+- **재시도 정책**: 지수 백오프 + 재시도 한도 + 재시도 안전성(멱등).
+- **보상 트랜잭션(Saga/TCC)**: 분산 작업 일부 실패 시 **보상 단계**로 롤백/보정.
+
+---
+
+### 12) 면접/리뷰 포인트(요약)
+- "동기/비동기와 블로킹/논블로킹의 **차이**를 설명해보라."
+- "왜 비동기가 항상 더 빠른 게 아닌가? (**지연 vs 처리량**, 컨텍스트 스위칭/큐잉 지연/오버헤드)."
+- "비동기에서 **멱등성/재시도/순서/중복**을 어떻게 보장하나?"
+- "동기 핵심 트랜잭션 + 비동기 사이드 이펙트로 **경계**를 나눈 사례는?"
+
+---
+
+### 13) TL;DR
+- **즉시 결과 필요/범위 좁은 트랜잭션** → 동기(간단, 확실).
+- **지연 허용/고동시성/외부 의존 많음** → 비동기(확장, 자원 효율) + 멱등/재시도/관찰가능성.
+
+---
+
+## (부록) 비동기 심화 정리
+
+### A. 전달 보장 & 멱등성
+- 현실적인 기본값: **at-least-once + 멱등한 소비자**.
+- 요청마다 **Idempotency-Key**(헤더/키-밸류)로 중복 방지.
+- 중복/순서 보존 필요 시 **파티션 키** 설계(예: accountId).
+
+---
+
+### B. Outbox & 트랜잭션 경계
+- 로컬 DB 트랜잭션 안에 **비즈 + outbox insert**를 함께 커밋.
+- 별 프로세스가 outbox를 읽어 브로커로 전송(전송 실패 시 재시도).
+- 분산 트랜잭션 없이 "**한 번만 처리한 것 같은**" 효과.
+
+---
+
+### C. Saga/TCC 개요
+- **Saga(오케스트레이션/코레오그래피)**: 단계별 커밋 + **보상 단계**로 롤백.
+- **TCC**: Try(예약) → Confirm(확정) / Cancel(취소).
+ **Confirm 직전 장애**는 **재시도/타임아웃/보상**으로 수렴.
+ 설계 핵심은 **멱등, 타임아웃, 상태전이 FSM**,
+ 운영 핵심은 **모니터링 + 수동 정리 경로**.
+
+---
+
+### D. 백프레셔 & 흐름 제어
+- 프로듀서 속도> 컨슈머 속도 → **큐 길이, 처리 지연, 메모리 증가**.
+- 해결: **버퍼 한도/드롭 정책/속도 조절/스케일 아웃**.
+
+---
+
+### E. 관찰가능성 & 운영
+- **코릴레이션ID**로 요청-이벤트-로그 연결.
+- **지표**: 큐 적재/소비율, 체류시간, 재시도 수, DLQ, p95/p99.
+- **경보**: 지표 임계 초과 + DLQ 발생 + 처리 정체.
From 151612c625fc8df9d3df1f110a2112a3e46dfe4d Mon Sep 17 00:00:00 2001
From: Chorong0824 <124541156+sjmun09@users.noreply.github.com>
Date: Thu, 9 Oct 2025 19:02:19 +0900
Subject: [PATCH 3/8] =?UTF-8?q?docs=20:=20=EB=B9=84=EB=8F=99=EA=B8=B0=20?=
=?UTF-8?q?=ED=86=B5=EC=8B=A0=20=ED=8C=A8=ED=84=B4=20=EC=84=A4=EB=AA=85=20?=
=?UTF-8?q?=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...0_353円271円204円353円217円231円352円270円260円.md" | 63 ++++++++++++++++++-
1 file changed, 61 insertions(+), 2 deletions(-)
diff --git "a/seongjun/353円217円231円352円270円260円_353円271円204円353円217円231円352円270円260円.md" "b/seongjun/353円217円231円352円270円260円_353円271円204円353円217円231円352円270円260円.md"
index c444775..31a2259 100644
--- "a/seongjun/353円217円231円352円270円260円_353円271円204円353円217円231円352円270円260円.md"
+++ "b/seongjun/353円217円231円352円270円260円_353円271円204円353円217円231円352円270円260円.md"
@@ -156,12 +156,71 @@ sequenceDiagram
participant Webhook
Client->>API: POST /orders
API->>Queue: publish(orderCreated)
- API-->>Client: 202 Accepted (trackingId)
+ API-->>Client: 202 Accepted (trackingId 반환)
Worker->>Queue: consume(orderCreated)
Worker->>Webhook: POST /notify (trackingId, status=Done)
- Note over Client: 폴링(/status) 또는 웹훅으로 상태 갱신
+ Note over Client: 폴링(/status) 또는 웹훅으로 상태 갱신 => 즉, Client는 polling or webhook으로 완료 상태 확인한다는 것임.
```
+#### ⚙️ 흐름 상세 해설
+
+1. **Client → API 요청**
+ - 클라이언트가 "주문 요청", "영상 인코딩", "메일 발송" 등 작업을 요청.
+ - 이때 결과가 바로 필요하지는 않음.
+
+2. **API → Queue로 메시지 발행**
+ - API 서버는 "작업 수락" 후 요청을 큐(Kafka, RabbitMQ, SQS 등)에 넣고
+ 바로 `202 Accepted` 응답을 반환.
+ - 이때 "trackingId"나 "jobId"를 같이 줘서 클라이언트가 상태를 추적 가능하게 함.
+
+3. **Worker가 Queue를 소비(Consume)**
+ - 백그라운드의 Worker가 큐에서 메시지를 꺼내 실제 작업 수행.
+ - 예: 이메일 전송, 영상 인코딩, 결제 정산 등
+
+4. **Webhook(또는 Polling)**
+ - 작업 완료 후 Worker는 클라이언트가 등록한 `callbackUrl`로 결과를 전송하거나,
+ 클라이언트가 직접 `/status/{trackingId}`를 주기적으로 조회(polling)함.
+
+5. **Client가 결과 수신 및 표시**
+ - 클라이언트는 결과를 비동기적으로 확인하고 사용자에게 보여줌.
+
+
+> "비동기 통신 구조에서 응답을 나중에 받는 패턴"을 설명한 거.
+즉, "요청은 바로 끝나지만 실제 처리는 나중에 백그라운드에서 진행되는 구조"
+
+이 구조는 요청자가 **즉시 응답("요청을 받았다")만 받고**,
+실제 작업은 **백엔드의 큐나 워커(Worker)**가 **나중에 비동기로 처리하는 방식**이다.
+
+즉,
+> 요청자(Client)는 "결과를 지금 바로 받지 않아도 된다."
+> 대신, "작업이 끝나면 나중에 알려줘" 하는 패턴이지.
+
+#### 🧠 동기식과 비교해보면
+| 구분 | 동기식 요청-응답 | 비동기식 요청-응답(콜백/웹훅) |
+|------|--------------------|------------------------------|
+| 처리 방식 | API가 모든 작업을 끝내고 응답 | 요청만 받고 작업은 나중에 |
+| 응답 시점 | 작업이 완료된 뒤 | 작업을 큐에 넣은 즉시("Received") |
+| 응답 내용 | 최종 결과 | 처리 중임(Tracking ID 등) |
+| 확장성 | 낮음 (요청 지속 유지) | 높음 (비동기 큐로 부하 완화) |
+| 예시 | 계좌이체 승인, 로그인 등 | 이메일 전송, 이미지 변환, 결제 정산 등 |
+
+
+#### 🪄 실제 비유로 보면
+- 카페에서 **진동벨 시스템**이 바로 이 구조야.
+ - 고객: "커피 주세요!"
+ - 점원: "알겠습니다 (진동벨 드림)" → 즉시 응답
+ - 커피 제조기(Worker)가 실제 작업 수행
+ - 커피 완성 시 진동벨(웹훅)이 울림
+
+이게 **비동기 + 콜백 알림(Webhook)** 구조와 완전히 동일한 형태야.
+
+
+
+
+
+
+
+
#### 6-3. 결제(예시): 동기 승인 + 비동기 정산/알림
- **주문 생성/승인**은 사용자 UX를 위해 **동기**(타임아웃/재시도 포함).
- **영수증 발송, 포인트 적립, 대시보드 집계**는 **비동기 이벤트**로 확산.
From 8a7945d87c0504ecf4740af9bb57f3e48d2751be Mon Sep 17 00:00:00 2001
From: Chorong0824 <124541156+sjmun09@users.noreply.github.com>
Date: Thu, 9 Oct 2025 19:05:37 +0900
Subject: [PATCH 4/8] =?UTF-8?q?docs:=20=EC=8B=9C=ED=80=80=EC=8A=A4=20?=
=?UTF-8?q?=EB=8B=A4=EC=9D=B4=EC=96=B4=EA=B7=B8=EB=9E=A8=20=EC=A0=81?=
=?UTF-8?q?=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...217231円352円270円260円_353円271円204円353円217円231円352円270円260円.md" | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git "a/seongjun/353円217円231円352円270円260円_353円271円204円353円217円231円352円270円260円.md" "b/seongjun/353円217円231円352円270円260円_353円271円204円353円217円231円352円270円260円.md"
index 31a2259..a7a3d42 100644
--- "a/seongjun/353円217円231円352円270円260円_353円271円204円353円217円231円352円270円260円.md"
+++ "b/seongjun/353円217円231円352円270円260円_353円271円204円353円217円231円352円270円260円.md"
@@ -147,7 +147,7 @@ sequenceDiagram
#### 6-2. 비동기식 처리 + 콜백/웹훅 (지연 OK, 확장성)
-```
+```mermaid
sequenceDiagram
participant Client
participant API
From bf967e8e1465c555a709ea6d9d482555a661c365 Mon Sep 17 00:00:00 2001
From: Chorong0824 <124541156+sjmun09@users.noreply.github.com>
Date: Thu, 9 Oct 2025 19:56:21 +0900
Subject: [PATCH 5/8] =?UTF-8?q?docs=20:=20=EC=98=B5=ED=8B=B0=EB=A7=88?=
=?UTF-8?q?=EC=9D=B4=EC=A0=80=EC=99=80=20=ED=9E=8C=ED=8A=B8(mysql,=20oracl?=
=?UTF-8?q?e=20=EB=B9=84=EA=B5=90)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
..._354円231円200円_355円236円214円355円212円270円.md" | 279 ++++++++++++++++++
1 file changed, 279 insertions(+)
create mode 100644 "seongjun/354円230円265円355円213円260円353円247円210円354円235円264円354円240円200円_354円231円200円_355円236円214円355円212円270円.md"
diff --git "a/seongjun/354円230円265円355円213円260円353円247円210円354円235円264円354円240円200円_354円231円200円_355円236円214円355円212円270円.md" "b/seongjun/354円230円265円355円213円260円353円247円210円354円235円264円354円240円200円_354円231円200円_355円236円214円355円212円270円.md"
new file mode 100644
index 0000000..14c128d
--- /dev/null
+++ "b/seongjun/354円230円265円355円213円260円353円247円210円354円235円264円354円240円200円_354円231円200円_355円236円214円355円212円270円.md"
@@ -0,0 +1,279 @@
+사실 나는 옵티마이저를 리마큐 1권을 통해 학습하여서,
+리마큐와 중복된 정리 내용이 있을 수 있음을 양해부탁드립니다!
+
+
+# 📘 옵티마이저(Optimizer)와 힌트(Hint)
+
+## 📖 목차
+1. 옵티마이저 개요
+2. 옵티마이저의 역할과 종류
+3. 옵티마이저의 실행 계획 결정 흐름 (시퀀스 다이어그램)
+4. 옵티마이저가 고려하는 요소
+5. 옵티마이저 힌트(Hint) 개념 및 사용 목적
+6. 주요 옵티마이저 힌트 예시
+7. 옵티마이저 튜닝 포인트 예시
+8. 면접/스터디용 핵심 정리
+
+---
+
+## 1️⃣ 옵티마이저 개요
+- **Optimizer**는 SQL을 **가장 효율적으로 실행할 방법(Execution Plan)** 을 결정하는 **DB 내부의 "두뇌"** 역할을 한다.
+- SQL 자체는 "무엇을 조회할지(What)"만 표현하고,
+ "어떻게 조회할지(How)"는 옵티마이저가 판단한다.
+
+> 💡 개발자는 "무엇(SELECT ~)"만 쓰고, DB가 "어떻게(인덱스/조인순서/조인방식)"를 자동으로 결정한다.
+
+---
+
+## 2️⃣ 옵티마이저의 역할과 종류
+
+| 구분 | 설명 | 대표 DB |
+|------|------|----------|
+| **규칙 기반 옵티마이저 (RBO, Rule-Based Optimizer)** | 정해진 규칙/우선순위에 따라 실행계획 결정 (예: 인덱스가 있으면 무조건 인덱스 사용) | Oracle 8 이전 |
+| **비용 기반 옵티마이저 (CBO, Cost-Based Optimizer)** | 통계 정보(카디널리티, I/O 비용 등)를 기반으로 최적의 실행계획 선택 | Oracle 9↑, MySQL, MariaDB, PostgreSQL |
+
+🔹 **MySQL / MariaDB / PostgreSQL** → 전부 **CBO 기반**
+통계정보(`ANALYZE TABLE`, `ANALYZE VERBOSE`)가 매우 중요하다.
+
+---
+
+## 3️⃣ 옵티마이저 실행계획 결정 흐름
+
+아래 시퀀스 다이어그램은 옵티마이저의 의사결정 과정을 나타낸다.
+
+```mermaid
+sequenceDiagram
+ participant User as 사용자(SQL 작성)
+ participant Parser as SQL Parser
+ participant Optimizer as 옵티마이저
+ participant Executor as 실행기(Executor)
+ participant Storage as 스토리지 엔진
+
+ User->>Parser: SQL 전달 (예: SELECT * FROM orders WHERE user_id=10)
+ Parser->>Parser: 구문 분석 / 파싱 트리 생성
+ Parser->>Optimizer: 파싱 트리 전달
+ Optimizer->>Optimizer: 통계정보 수집 (테이블/인덱스/카디널리티)
+ Optimizer->>Optimizer: 가능한 실행계획 후보 생성
+ Optimizer->>Optimizer: 각 후보별 비용 계산 (CPU, I/O, 메모리)
+ Optimizer->>Optimizer: 최소 비용의 계획 선택
+ Optimizer->>Executor: 실행계획 전달
+ Executor->>Storage: 인덱스 탐색 or 테이블 스캔 수행
+ Storage-->>Executor: 데이터 반환
+ Executor-->>User: 결과셋 반환
+```
+
+📍 **핵심 포인트**
+- 옵티마이저는 **비용 모델(cost model)** 기반으로 후보 계획을 평가한다.
+- **통계 정보가 부정확하면 비효율적인 실행계획**이 선택될 수 있다.
+ → 따라서 `ANALYZE TABLE` 주기적 수행이 중요하다.
+
+---
+
+## 4️⃣ 옵티마이저가 고려하는 요소
+
+| 항목 | 설명 |
+|------|------|
+| **통계정보** | 행 개수, 인덱스 선택도, 카디널리티 등 |
+| **조인 순서** | 어떤 테이블을 먼저 조인할지 (드라이빙 테이블) |
+| **조인 방식** | NL Join, Hash Join, Sort-Merge Join 등 |
+| **인덱스 존재 여부** | 인덱스 탐색 비용 vs 풀스캔 비용 비교 |
+| **필터 조건 선택도** | WHERE 조건으로 얼마나 줄일 수 있는가 |
+| **LIMIT / ORDER BY / GROUP BY 유무** | 정렬/집계 필요 여부 |
+
+---
+
+## 5️⃣ 옵티마이저 힌트(Hint) 개념 및 사용 목적
+
+- 옵티마이저의 **자동 선택이 비효율적일 때**, 개발자가 **직접 의사결정 방향을 강제**하기 위해 사용.
+- 즉, **"이 SQL은 이렇게 실행하라"**는 명시적 지시문이다.
+- 힌트는 SQL 문 안에 주석 형태로 작성한다.
+
+📌 **MySQL 예시**
+```sql
+SELECT /*+ INDEX(o idx_user_id) */ *
+FROM orders o
+WHERE user_id = 10;
+```
+
+📌 Oracle / MariaDB 예시
+```sql
+SELECT /*+ USE_NL(a b) LEADING(a b) INDEX(b idx_user_id) */ *
+FROM users a
+JOIN orders b ON a.id = b.user_id;
+```
+
+---
+
+## 6️⃣ 주요 옵티마이저 힌트 예시
+
+| 힌트 | 의미 | 비고 |
+|------|------|------|
+| **USE_INDEX / INDEX** | 특정 인덱스 사용 | MySQL, Oracle 공통 |
+| **IGNORE_INDEX** | 특정 인덱스 무시 | MySQL |
+| **FORCE_INDEX** | 인덱스 강제 사용 | MySQL |
+| **USE_NL / USE_HASH / USE_MERGE** | 조인 방식 지정 | Oracle / MariaDB |
+| **LEADING(a b)** | 조인 순서 강제 | Oracle / MariaDB |
+| **STRAIGHT_JOIN** | FROM 순서대로 조인 | MySQL |
+| **OPTIMIZER_FEATURES_ENABLE** | 옵티마이저 버전별 동작 모드 | Oracle |
+
+---
+
+## 7️⃣ 옵티마이저 튜닝 포인트 예시
+
+✅ **1. 실행계획(Explain) 확인**
+```sql
+EXPLAIN FORMAT=JSON
+SELECT * FROM orders WHERE user_id=10;
+```
+
+- key / key_len / rows / filtered / Extra 등을 주의 깊게 본다.
+
+✅ **2. 통계정보 최신화**
+```sql
+ANALYZE TABLE orders;
+```
+
+✅ **3. 힌트는 "임시 방편"으로만**
+
+- 힌트는 옵티마이저의 진화에 역행할 수 있다.
+- 근본 원인은 인덱스 설계/쿼리 구조일 수 있다.
+
+✅ **4. 조인 순서/조인 방식은 SQL 구조 변경으로도 개선 가능**
+```sql
+-- 비효율적인 예시
+SELECT * FROM orders o
+JOIN users u ON o.user_id = u.id
+WHERE u.status = 'ACTIVE';
+
+-- 개선된 예시 (선택도 높은 조건 먼저)
+SELECT * FROM users u
+JOIN orders o ON o.user_id = u.id
+WHERE u.status = 'ACTIVE';
+```
+
+---
+
+## 8️⃣ 면접/스터디 핵심 정리
+
+| 질문 | 핵심 요약 |
+|------|------------|
+| **Q. 옵티마이저란?** | SQL을 효율적으로 실행하기 위해 최적의 실행계획을 선택하는 DB 엔진의 두뇌 |
+| **Q. CBO가 RBO보다 나은 이유는?** | 통계 기반으로 상황별 최적화 가능 (동적, 환경 변화 대응) |
+| **Q. 힌트는 언제 사용하는가?** | 옵티마이저의 판단이 비효율적이거나 통계정보 갱신이 불가할 때 임시 조치 |
+| **Q. 옵티마이저 성능 튜닝 방법은?** | 실행계획 분석, 통계정보 갱신, 인덱스 구조 점검, 조인 순서 개선 |
+
+---
+
+## 💡 확장 주제
+
+### 1️⃣ 옵티마이저의 **비용 계산(Cost Model)** 내부 구조
+
+옵티마이저는 실행계획 후보마다 다음 세 가지 비용 요소를 합산하여 비교합니다.
+
+| 비용 요소 | 설명 | 대표 항목 |
+|------------|------|------------|
+| **I/O Cost** | 디스크 접근 횟수, 페이지 읽기/쓰기 비용 | 테이블 스캔, 인덱스 탐색 |
+| **CPU Cost** | 연산 및 비교, 정렬, 조인 계산 비용 | 필터링, 정렬, 집계 연산 |
+| **Memory Cost** | 버퍼/임시영역 사용량 | Hash Join, Temp Table |
+
+**총비용(Cost)**
+```text
+Total Cost = I/O Cost + CPU Cost + Memory Cost
+```
+> 옵티마이저는 여러 실행계획 후보를 시뮬레이션하고,
+그 중 총 비용이 가장 낮은 실행계획을 실제로 선택합니다.
+
+예시 (MySQL EXPLAIN JSON 일부)
+```json
+"cost_info": {
+ "query_cost": "45.20",
+ "read_cost": "40.00",
+ "eval_cost": "5.20"
+}
+```
+→ I/O(40.0) + CPU(5.2) = 45.2의 총 비용이 계산됨.
+
+---
+
+### 2️⃣ **카디널리티(Cardinality) 추정 오차와 해결법**
+
+- **카디널리티**: 특정 조건에 대해 예상되는 결과 행(row)의 개수
+ → 예: `WHERE gender='M'`일 때 남성 사용자의 비율
+
+| 원인 | 설명 | 해결책 |
+|------|------|--------|
+| **통계정보 오래됨** | 실제 데이터 분포와 불일치 | `ANALYZE TABLE`, `OPTIMIZE TABLE` 주기적 실행 |
+| **히스토그램 부재** | 값의 분포가 균등하지 않음 | MariaDB 10.4+, MySQL 8.0+의 히스토그램 사용 |
+| **복합 조건** | 다중 칼럼 조건 간 상관관계 무시 | 가상 컬럼, Functional Index 고려 |
+
+📌 **MySQL 히스토그램 예시**
+```sql
+ANALYZE TABLE users UPDATE HISTOGRAM ON gender, country WITH 10 BUCKETS;
+```
+
+히스토그램을 통해 "값의 분포"를 정밀하게 반영함으로써
+옵티마이저의 선택도 추정 정확도를 높인다.
+
+---
+
+### 3️⃣ **MySQL vs Oracle 옵티마이저 비교**
+
+| 구분 | MySQL | Oracle |
+|------|--------|--------|
+| **옵티마이저 유형** | CBO (Cost-Based Only) | CBO + Adaptive Optimization |
+| **통계정보 수집** | `ANALYZE TABLE` / 히스토그램 | `DBMS_STATS.GATHER_TABLE_STATS` |
+| **조인 방식** | Nested Loop / Hash Join / Block Nested Loop | NL / Hash / Sort Merge |
+| **힌트 문법** | `/*+ HINT */` 단순 구조 | 다중 힌트 조합 가능 (LEADING, PQ_DISTRIBUTE 등) |
+| **실행계획 확인 방법** | `EXPLAIN`, `EXPLAIN FORMAT=JSON` | `EXPLAIN PLAN FOR`, `AUTOTRACE`, `SQL Monitor` |
+| **비용 계산 방식** | 단순 비용 모델 (I/O 중심) | 다차원 비용 모델 (CPU, I/O, 병렬도 고려) |
+| **최적화 기능** | 옵티마이저 트레이스(`OPTIMIZER_TRACE`) | Adaptive Plan, SQL Profile, SQL Baseline |
+
+> 🔸 MySQL은 단순하고 직관적이며 빠르게 실행계획을 결정하는 반면,
+> Oracle은 **동적 적응(Adaptive Optimization)** 을 통해 실행 중에도 계획을 변경할 수 있다.
+> 실무에서는 **통계의 정확도와 SQL 구조 단순화**가 가장 큰 성능 요인이다.
+
+
+---
+
+### 4️⃣ **Explain Plan 필드별 상세 분석**
+
+MySQL의 `EXPLAIN` 결과를 해석하는 핵심 필드는 다음과 같다.
+
+| 필드 | 의미 | 설명 |
+|------|------|------|
+| **id** | 실행 순서 | 숫자가 높을수록 먼저 실행되는 서브쿼리 |
+| **select_type** | 쿼리 유형 | SIMPLE / PRIMARY / DERIVED / SUBQUERY |
+| **table** | 액세스 대상 테이블 | 실제 접근하는 테이블명 |
+| **type** | 접근 방식 | ALL, index, range, ref, eq_ref, const (왼쪽일수록 느림) |
+| **key** | 사용 인덱스 | 옵티마이저가 선택한 인덱스 |
+| **rows** | 예상 접근 행 수 | 옵티마이저의 카디널리티 예측 결과 |
+| **filtered** | 필터링 비율(%) | WHERE 조건으로 남는 비율 |
+| **Extra** | 부가 정보 | Using index, Using filesort, Using temporary 등 |
+
+📘 **예시**
+```sql
+EXPLAIN FORMAT=TRADITIONAL
+SELECT *
+FROM users u
+JOIN orders o
+ON u.id = o.user_id
+WHERE u.status = 'ACTIVE';
+```
+| id | select_type | table | type | key | rows | Extra |
+|----|--------------|--------|------|-----|------|-------|
+| 1 | SIMPLE | u | ref | idx_status | 500 | Using index |
+| 1 | SIMPLE | o | ref | idx_user_id | 1000 | Using where |
+
+→ **의미 요약**
+- `u` 테이블에서 `status` 조건으로 먼저 필터링
+- `o` 테이블을 `user_id` 기준으로 조인 (인덱스 활용)
+- 전체 조인 비용은 **(rows_u ×ばつ rows_o)** 로 추정되며, 필터링 비율이 낮을수록 효율적이다.
+
+---
+
+## 🚀 요약 정리
+
+- 옵티마이저는 **비용 기반(CBO)** 으로 실행계획을 선택한다.
+- **정확한 통계정보**가 SQL 성능의 핵심이다.
+- **힌트**는 "임시 응급조치"일 뿐, 구조적 개선이 우선이다.
+- `EXPLAIN`과 `ANALYZE`는 옵티마이저의 동작을 이해하는 최고의 도구다.
From aef7bd18ca87867d021ca9695181ce0528b4553f Mon Sep 17 00:00:00 2001
From: Chorong0824 <124541156+sjmun09@users.noreply.github.com>
Date: Thu, 9 Oct 2025 21:10:23 +0900
Subject: [PATCH 6/8] =?UTF-8?q?docs:=20Stateless=EC=99=80Stateful=20?=
=?UTF-8?q?=EC=A0=95=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
"seongjun/Stateless_354円231円200円_Stateful.md" | 620 ++++++++++++++++++
1 file changed, 620 insertions(+)
create mode 100644 "seongjun/Stateless_354円231円200円_Stateful.md"
diff --git "a/seongjun/Stateless_354円231円200円_Stateful.md" "b/seongjun/Stateless_354円231円200円_Stateful.md"
new file mode 100644
index 0000000..94f0077
--- /dev/null
+++ "b/seongjun/Stateless_354円231円200円_Stateful.md"
@@ -0,0 +1,620 @@
+# 🌐 무상태(Stateless) 설계의 핵심 정리
+
+## 1️⃣ 개요
+웹 애플리케이션에서 **Stateless(무상태)** 란,
+서버가 **이전 요청의 상태나 컨텍스트를 저장하지 않는 설계 방식**을 말한다.
+즉, **각 요청(Request)** 은 서로 완전히 **독립적**이며,
+서버는 매번 "처음 보는 요청"처럼 처리한다.
+
+> 💡 REST, HTTP, MSA 구조 모두 이 ‘무상태성’을 기반으로 한다.
+
+---
+
+## 2️⃣ 상태(State)란?
+- **State(상태)**: 클라이언트와 서버 간의 ‘대화 맥락’ 또는 ‘세션 정보’
+- 예를 들어 로그인 후 사용자 정보를 유지하는 세션, 장바구니 내역, 진행 중인 트랜잭션 등이 상태 정보에 해당한다.
+
+| 구분 | Stateful | Stateless |
+|------|-----------|------------|
+| 요청 간 맥락 | 유지됨 (세션/쿠키 등) | 없음 (독립 요청) |
+| 서버 부하 | 높음 (메모리 관리 필요) | 낮음 (단순 처리) |
+| 확장성 | 낮음 (세션 공유 필요) | 높음 (로드밸런싱 용이) |
+| 장애 복구 | 어려움 (세션 일관성 문제) | 쉬움 (무상태 서버 교체 가능) |
+
+---
+
+## 3️⃣ 무상태(Stateless) 설계 원리
+
+### (1) 요청은 항상 ‘완전해야 한다’
+> 요청 하나로 서버가 필요한 모든 정보를 알아야 한다.
+
+예
+```http
+GET /api/user/profile
+Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
+```
+- JWT를 이용해 클라이언트가 인증 정보를 직접 담아 보낸다.
+- 서버는 이전 세션을 기억하지 않고, 토큰만으로 인증을 수행한다.
+
+### (2) 서버는 ‘세션’을 저장하지 않는다
+- 로그인 상태를 서버 메모리에 저장하지 않고,
+ **토큰 기반 인증(JWT)** 으로 대체한다.
+- 장바구니, 임시 데이터 등은 **Redis 같은 외부 저장소**에 위임한다.
+
+> 💬 즉, 서버는 오직 "입력 → 처리 → 응답"만 담당하며,
+> 상태관리는 외부로 위임한다.
+
+---
+
+### (3) 클라이언트 중심 설계
+- 상태 유지는 클라이언트가 담당하거나,
+- 필요 시 서버 간 공유 가능한 **Session Store (예: Redis)** 를 사용한다.
+
+---
+
+## 4️⃣ 동작 예시 (Stateless vs Stateful 시퀀스 다이어그램)
+
+### 🧩 Stateful 구조 — 세션 기반 로그인
+
+```mermaid
+sequenceDiagram
+ participant Client as 클라이언트
+ participant LB as 로드 밸런서
+ participant ServerA as 서버 A
+ participant ServerB as 서버 B
+
+ Client->>LB: 로그인 요청 (/login)
+ LB->>ServerA: 요청 전달
+ ServerA->>ServerA: 사용자 인증 후 세션 생성 (sessionId=abc123)
+ ServerA-->>Client: 세션 쿠키 발급 (Set-Cookie: JSESSIONID=abc123)
+
+ Note over Client,ServerA: 이후 요청에서 쿠키(JSESSIONID=abc123)를 포함
+
+ Client->>LB: 프로필 요청 (/profile, 쿠키 포함)
+ LB->>ServerA: 세션이 존재하는 서버로 라우팅됨
+ ServerA->>ServerA: 세션 정보 조회
+ ServerA-->>Client: 사용자 프로필 응답
+
+ Note over LB,ServerB: 만약 LB가 ServerB로 보낸다면?
+ Client->>LB: 프로필 요청 (/profile, 쿠키 포함)
+ LB->>ServerB: 요청 전달
+ ServerB->>ServerB: ❌ 세션 정보 없음
+ ServerB-->>Client: 401 Unauthorized (로그인 만료)
+```
+
+> 요약
+서버가 세션을 메모리에 저장하므로, 요청이 항상 같은 서버로 가야 정상 처리됨.
+서버 A가 죽거나 LB가 Server B로 라우팅하면 세션 일관성 깨짐.
+확장성 낮고, Sticky Session 필요.
+
+### 🧩 Stateless 구조 — JWT 기반 로그인
+```mermaid
+sequenceDiagram
+ participant Client as 클라이언트
+ participant LB as 로드 밸런서
+ participant ServerA as 서버 A
+ participant ServerB as 서버 B
+
+ Client->>LB: 로그인 요청 (/login)
+ LB->>ServerA: 요청 전달
+ ServerA->>ServerA: 사용자 인증 후 JWT 생성 (서명 포함)
+ ServerA-->>Client: JWT 반환 (Authorization: Bearer eyJhbGciOiJIUzI1Ni...)
+
+ Note over Client: 이후 요청마다 JWT를 헤더에 포함시킴
+
+ Client->>LB: 프로필 요청 (/profile, Authorization 헤더 포함)
+ LB->>ServerB: 요청 전달 (무작위 라우팅 가능)
+ ServerB->>ServerB: JWT 서명 검증 (서버 상태 필요 없음)
+ ServerB-->>Client: 사용자 프로필 응답 (정상 처리)
+
+ Note over Client,ServerB: 모든 서버가 같은 JWT 서명 키를 공유하므로,
서버 간 상태 공유 불필요
+
+```
+>요약
+서버는 세션을 전혀 저장하지 않음.
+클라이언트가 JWT로 상태를 직접 유지하므로,
+요청이 어느 서버로 가든 인증 가능하고 수평 확장(Scale-out)에 유리하다.
+
+
+✅ 요청 간 맥락이 없어도, 토큰 기반으로 어디서나 처리 가능
+✅ 서버 간 세션 공유나 Sticky Session이 필요 없음
+
+
+#### ⚖️ 구조적 비교 요약
+
+| 항목 | Stateful (세션 기반) | Stateless (JWT 기반) |
+|------|----------------------|----------------------|
+| 상태 저장 위치 | 서버 메모리 | 클라이언트(JWT) |
+| 요청 독립성 | 낮음 | 높음 |
+| 확장성 | 세션 공유 필요 → 낮음 | 서버 간 독립 → 높음 |
+| 장애 복구 | 세션 유실 위험 | 즉시 처리 가능 |
+| REST 철학 부합 | ❌ | ✅ |
+| 적용 예시 | 전통적인 JSP/Servlet, Spring Session | REST API, MSA, Serverless, Gateway |
+
+---
+
+> 🌐 **핵심 정리**
+> Stateless 구조는 요청 간 독립성을 유지하고,
+> 서버를 ‘기억하지 않아도 되는 노드’로 만들어
+> 확장성과 복원력을 극대화한다.
+
+
+
+---
+
+## 5️⃣ 왜 중요한가? (Stateless의 가치)
+
+| 항목 | 설명 |
+|------|------|
+| 🔁 **확장성(Scalability)** | 서버 간 세션 공유 필요가 없어 수평 확장(Scale-out)에 유리 |
+| 💥 **복원력(Fault Tolerance)** | 서버 다운 시에도 다른 인스턴스가 즉시 요청 처리 가능 |
+| 🚀 **성능(Performance)** | 세션 조회나 복제 비용이 없음 |
+| 🧩 **단순성(Simplicity)** | 요청-응답 구조 단순, 유지보수 용이 |
+| 🧱 **표준성(RESTful)** | REST API의 근간이자 HTTP의 본래 철학에 부합 |
+
+---
+
+## 6️⃣ 실무 적용 포인트
+
+| 상황 | 권장 설계 |
+|------|------------|
+| 인증 유지 | JWT + Refresh Token |
+| 로그인 상태 표시 | 클라이언트에서 상태 관리 (e.g. localStorage) |
+| 장바구니, 임시 데이터 | Redis, DB 등 외부 저장소 활용 |
+| 서버 확장 | 무상태 서버로 구성, Sticky Session 피하기 |
+| MSA 간 인증 | Access Token 공유 or API Gateway 단에서 검증 |
+
+---
+
+## 7️⃣ 주의할 점 (Stateless의 오해)
+
+| 오해 | 올바른 이해 |
+|------|--------------|
+| "무상태면 로그인 못한다" | ❌ → 상태를 서버가 아닌 **클라이언트/외부 저장소**에 둔다 |
+| "모든 상태는 제거해야 한다" | ❌ → 단, **서버가 상태를 ‘기억하지 않는다’**가 핵심 |
+| "Stateful이 나쁘다" | ❌ → 일부 실시간 서비스(게임, 트레이딩)는 상태 필요 |
+
+---
+
+## 8️⃣ 확장 개념 (더 깊게 가보자)
+
+| 주제 | 설명 |
+|------|------|
+| 🧩 **Session Clustering** | 상태를 공유하기 위해 여러 서버가 세션 복제하는 구조 (비추천) |
+| 🪶 **Sticky Session** | 같은 클라이언트를 항상 같은 서버로 라우팅하는 방식 |
+| 🧱 **Token-based Auth (JWT)** | 클라이언트가 상태 정보를 포함해 요청 (무상태 핵심 구현체) |
+| 🧭 **Idempotency (멱등성)** | 무상태 API의 중요한 속성, 같은 요청은 항상 같은 결과 |
+| 🧰 **MSA 설계 원칙 중 Stateless** | 마이크로서비스 간 독립 배포·확장을 위한 핵심 원칙 |
+
+---
+
+## 9️⃣ 면접/스터디에서 자주 묻는 질문
+
+| 질문 | 핵심 답변 |
+|------|------------|
+| "왜 Stateless가 중요한가요?" | 서버 확장성과 복원력을 높이고, RESTful 원칙을 유지하기 위해 |
+| "로그인 상태를 Stateless하게 어떻게 유지하나요?" | JWT를 통해 클라이언트가 상태를 직접 전달 |
+| "Stateful과 Stateless의 중간 설계가 가능한가요?" | 가능함. 외부 세션 스토리지(Redis)를 통한 하이브리드 구조 |
+| "Sticky Session은 왜 피해야 하나요?" | 서버 간 부하 불균형 및 확장성 저하 유발 |
+
+### 💬 Q1. "왜 Stateless가 중요한가요?"
+**핵심 답변**
+Stateless는 서버 확장성과 복원력을 높이고, RESTful 원칙을 유지하기 위해 필요하다.
+
+**설명**
+- **확장성(Scalability)**: 요청에 세션 의존이 없으므로 서버를 여러 대로 쉽게 나눌 수 있다.
+ 예를 들어, 트래픽 증가 시 인스턴스를 추가해도 세션 공유가 필요 없어 바로 부하분산이 가능하다.
+- **복원력(Fault Tolerance)**: 특정 서버가 장애를 일으켜도, 다른 서버가 동일 요청을 바로 처리할 수 있다.
+- **유지보수성(Maintainability)**: 상태 관리 로직이 없으므로 서버 코드는 단순해지고, 배포 시에도 세션 데이터 손실 우려가 없다.
+- **REST 철학 부합**: REST는 HTTP 프로토콜의 기본 특성인 Stateless를 기반으로 한다.
+ "서버는 요청 간 컨텍스트를 기억하지 않는다"가 핵심 원리다.
+
+---
+
+### 💬 Q2. "로그인 상태를 Stateless하게 어떻게 유지하나요?"
+**핵심 답변**
+서버가 세션을 저장하지 않고, **JWT(Json Web Token)** 을 이용해 클라이언트가 인증 상태를 직접 유지한다.
+
+**설명**
+- 로그인 시 서버는 사용자 정보를 기반으로 JWT를 생성해 클라이언트에게 전달한다.
+- 이후 요청마다 `Authorization: Bearer ` 형태로 토큰을 함께 보낸다.
+- 서버는 토큰을 검증해 유효하면 해당 사용자를 인증한다.
+ (이때 DB 접근 없이 토큰 서명만으로 인증 가능)
+- 토큰 만료 시 **Refresh Token** 으로 재발급하는 구조를 사용하면, 보안성과 유연성을 동시에 확보할 수 있다.
+
+> 💡 이 구조 덕분에 서버는 로그인 상태를 기억할 필요가 없으며,
+> 수평 확장 시에도 인증 정보가 서버 간에 공유될 필요가 없다.
+
+---
+
+### 💬 Q3. "Stateful과 Stateless의 중간 설계가 가능한가요?"
+**핵심 답변**
+가능하다. 대표적인 방법은 **외부 세션 스토리지(Redis 등)** 를 사용하는 **하이브리드 구조**다.
+
+**설명**
+- 완전 Stateless로 설계하기 어려운 경우(예: 장바구니, 결제 과정, 트랜잭션 세션 등),
+ 세션 데이터를 서버 메모리가 아닌 **Redis** 같은 외부 인메모리 DB에 저장한다.
+- 이 방식은 클라이언트 요청이 어느 서버로 가든 동일한 세션 데이터를 조회할 수 있어,
+ **확장성과 일관성의 균형**을 맞춘다.
+- 예시
+```
+[Client] → [LoadBalancer]
+├─▶ [Server A] → Redis에서 세션 조회
+└─▶ [Server B] → 동일 세션 Redis에서 공유
+```
+
+> ⚙️ 실무에서는 "Stateless 서버 + Stateful 외부 저장소"로 혼합 설계하는 경우가 많다.
+
+---
+
+### 💬 Q4. "Sticky Session은 왜 피해야 하나요?"
+**핵심 답변**
+Sticky Session은 **확장성 저하**와 **장애 복원성 저하**를 유발하기 때문에 지양해야 한다.
+
+**설명**
+- **Sticky Session**: 클라이언트가 항상 같은 서버로 라우팅되도록 하는 방식
+(예: A 서버에서 로그인하면, 이후 요청도 항상 A 서버로 감)
+- 단점:
+1. 특정 서버에 트래픽이 몰려 **부하 불균형**이 발생한다.
+2. 해당 서버가 장애를 일으키면 세션이 사라져 사용자 로그인이 풀린다.
+3. 서버 추가 시 새로운 노드는 기존 세션을 모름 → 확장성 저하.
+- 반면 Stateless는 모든 서버가 동일하게 요청을 처리하므로,
+장애 복구 및 오토스케일링이 훨씬 간단하다.
+
+> 💬 Sticky Session은 "임시방편"으로만 쓰며,
+> 장기적으로는 세션 스토리지나 JWT로 전환하는 것이 이상적이다.
+
+---
+
+### 💬 Q5. "Stateless 설계 시 보안 문제는 없나요?"
+**핵심 답변**
+있다. 특히 토큰 탈취, 재사용 공격 등에 대비해야 한다.
+
+**설명**
+- **토큰 탈취**: 클라이언트 저장소(localStorage, sessionStorage)에 저장된 JWT가 노출될 위험
+→ 해결: HttpOnly 쿠키 사용, 토큰 암호화, 만료시간 단축
+- **토큰 위조**: 서명 검증 미흡 시 위조된 JWT로 인증 가능
+→ 해결: 공개키-비공개키(Public/Private Key) 기반 검증
+- **Refresh Token 도난**: 장기 토큰이 탈취되면 지속 인증 가능
+→ 해결: Refresh Token Rotation (재발급 시 이전 토큰 폐기)
+
+> 🔒 Stateless 구조는 보안 로직을 토큰 단에서 강화해야 한다.
+
+---
+
+### 💬 Q6. "Stateless가 항상 옳은가요?"
+**핵심 답변**
+아니다. 무상태는 대부분의 웹 서비스에 유리하지만, **실시간 연결이나 상태 기반 로직**에는 Stateful이 필요하다.
+
+**설명**
+- **Stateful이 필요한 경우**
+- 실시간 게임, 채팅, 트레이딩 시스템 등 "연결 지속성"이 중요한 서비스
+- 세션 단위로 지속적인 데이터 교환이 필요한 경우
+- **Stateless가 유리한 경우**
+- REST API, 웹 백엔드, 인증 서버, API Gateway, 배치 등
+- 실제로는 **Stateless + 일부 Stateful**을 혼합해 설계한다.
+
+---
+
+## 10️⃣ 요약
+
+> 🌐 **Stateless = 요청 간 독립성 보장 + 서버의 단순화 + 확장성 극대화**
+
+- 요청 하나로 완결되어야 한다.
+- 상태는 클라이언트나 외부 스토리지로 옮긴다.
+- 서버는 언제든 교체·확장 가능한 ‘가벼운 노드’로 설계한다.
+
+---
+
+## 💡 다음 확장 학습 주제 추천
+1. **Idempotency (멱등성)** – 무상태 API에서 왜 중요한가
+2. **JWT vs Session 비교** – 인증의 상태 관리 차이
+3. **Sticky Session과 Redis 세션 클러스터링**
+4. **API Gateway의 Stateless 인증 흐름 설계**
+5. **서버리스(Serverless) 아키텍처에서의 무상태 개념**
+
+---
+
+
+# 📌 확장 학습 주제 심화
+## 1) Idempotency(멱등성) — 무상태 API에서 재시도 안전성 보장
+
+### 한 줄 정의
+**같은 요청을 여러 번 보내도 최종 결과가 동일**하도록 만드는 속성.
+네트워크 재시도·중복 전송·타임아웃 재요청 상황에서도 **중복 부작용**(이중 결제, 이중 발송 등)을 막는다.
+
+### 왜 중요한가?
+- **무상태 서버**는 요청 간 맥락을 기억하지 않으므로, **클라이언트/중간자(게이트웨이/리트라이러)** 가 재시도할 때도 **안전해야 함**.
+- 클라우드/분산 환경의 기본 전달 보장(at-least-once, 중복 가능)과 **자연스럽게 상호 보완**.
+
+### HTTP 메서드와 멱등성
+| 메서드 | 표준상 멱등성 | 비고 |
+|---|---|---|
+| GET/HEAD | ✅ | 조회만 수행해야 함 |
+| PUT | ✅ | "리소스를 이 값으로 만들어라(Upsert)" 의미일 때 |
+| DELETE | ✅ | 여러 번 호출해도 최종 상태는 "없음" |
+| OPTIONS | ✅ | 프리플라이트 조회 |
+| POST | ❌(기본) | **Idempotency-Key**로 멱등화 가능 |
+| PATCH | ❌(기본) | 조건부 갱신(ETag/If-Match)로 멱등화 가능 |
+
+### 멱등화 핵심 패턴
+1. **리소스 키 기반(자연/비즈니스 키) Upsert**
+ - `PUT /users/42` : "항상 42번 사용자를 이 본문으로 만든다"
+ - DB 유니크 제약 + UPSERT로 중복을 구조적으로 제거
+
+2. **POST + Idempotency-Key 헤더**
+ - 클라이언트가 **요청 단위의 전역 고유키**를 생성: `Idempotency-Key: 7f2c-...`
+ - 서버/게이트웨이는 (엔드포인트, 키) 조합으로 **처리 기록 + 응답 캐시** 저장
+ - **동일 키 + 동일 페이로드** 재요청 → **이전 응답 재생산**(200/201 등)
+ - **동일 키 + 상이한 페이로드** → **409 Conflict**(정책적으로 거부)
+
+3. **조건부 갱신(Optimistic Locking)**
+ - `If-Match: `를 이용한 **버전 충돌 방지**
+ - 실패 시 412 Precondition Failed → 재시도 루프에서 안전
+
+4. **멱등 컨슈머(메시지 처리)**
+ - 메시지/이벤트마다 **Message-ID** 저장("inbox table")
+ - 이미 처리한 ID면 스킵(또는 안전한 재실행)
+ - **Transactional Outbox/Inbox** 패턴으로 **정확히 한 번처럼** 보이게
+
+### 구현 로드맵(POST 결제 예)
+1) 스키마(예시)
+```sql
+CREATE TABLE idempotency (
+ endpoint VARCHAR(120) NOT NULL,
+ idem_key VARCHAR(64) NOT NULL,
+ request_hash CHAR(64) NOT NULL,
+ response_status SMALLINT NOT NULL,
+ response_body TEXT NOT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (endpoint, idem_key)
+);
+```
+
+2) 처리 알고리즘
+- 요청 진입 → `(endpoint, idem_key)` 조회
+ - **없음** → 처리 시작 전 **행 선점(INSERT)** 후 실제 비즈니스 수행 → **응답 저장**
+ - **있음** → `request_hash` 같으면 **캐시된 응답 반환**, 다르면 **409 Conflict**
+- **TTL/보존 기간** 운영(예: 결제·주문은 24h~72h, 일반 POST는 수 시간)
+
+3) 동시성/경쟁 해결
+- **DB 유니크키** + 트랜잭션으로 "이 키는 내가 먼저 잡았다" 보장
+- 분산락(필요 시)보다 **단일 DB 제약**이 간단·견고
+
+### 멱등화 체크리스트
+- [ ] 클라이언트가 **Idempotency-Key** 생성/전달
+- [ ] 서버가 키별 **요청 해시/응답** 저장 및 **동일 응답 리턴**
+- [ ] 키 재사용 정책(동일/상이한 페이로드 처리 기준) 명시
+- [ ] 키 **보존 기간/정리 배치** 운영
+- [ ] 외부 부작용(이메일, 푸시, 결제 승인)도 **키 단위로 중복 방지**
+- [ ] 장애/타임아웃 재시도 경로에 모두 적용(게이트웨이, 워커, MQ 컨슈머)
+
+
+
+
+## 2) API Gateway 무상태 인증 흐름 설계 — "인증은 게이트웨이에서, 상태는 토큰에"
+
+### 목표
+- **게이트웨이 레벨에서 JWT 검증**으로 인증을 **완전 무상태**로 처리
+- 내부 서비스는 **신원/권한이 주입된 요청**만 신뢰하고 비즈니스에 집중
+
+### 역할 분담
+- **클라이언트**: Access Token(JWT) 보관·전달
+- **IdP/Auth 서버**: 로그인/권한 부여, **JWT 발급 + JWKS 공개**
+- **API Gateway**: 서명·클레임 검증, **정책/권한 결정(PDP/PEP)**, 컨텍스트 주입
+- **마이크로서비스**: 게이트웨이가 보장한 **주체/스코프** 신뢰, **세션 저장 없음**
+
+### 무상태 설계 키 포인트
+- **서명 검증만으로 인증**: `iss/aud/exp/nbf` 체크 + **JWKS 캐시**
+- **Key Rotation**: `kid` 기반으로 **JWKS 자동 갱신**, 실패 시 **백오프 + 로컬 캐시 유지**
+- **Clock Skew** 허용(예: ±2분), 토큰 만료 오차 최소화
+- **Claims→권한 매핑**: `scope`, `roles`, `tenant`, `sub` 등으로 RBAC/ABAC
+- **컨텍스트 주입**: 내부로 **원본 JWT** 전달 또는 **정제된 헤더**(예: `X-User-Id`, `X-Scopes`)
+- **Opaque 토큰** 사용 시**만** IdP **Introspection**(네트워크 의존) — 가능하면 **JWT 권장**
+- **게이트웨이 측 상태 저장 금지**: 세션/로그인 컨텍스트 보관 ❌ (레이트리밋 카운터는 예외적 저장소 사용 가능)
+
+### 시퀀스(로그인 후 보호 API 호출)
+```mermaid
+sequenceDiagram
+ participant Client as 클라이언트
+ participant IdP as 인증 서버(IdP)
+ participant GW as API 게이트웨이
+ participant Svc as 내부 서비스
+
+ Client->>IdP: 로그인 (OIDC/OAuth 2.1)
+ IdP-->>Client: Access Token(JWT) 발급 + (선택)Refresh Token
+
+ Client->>GW: 보호 API 호출 (Authorization: Bearer )
+ GW->>GW: JWKS 캐시에서 kid로 공개키 가져와 JWT 서명 검증
+ GW->>GW: iss/aud/exp/nbf/Scope 등 클레임 검증 + 정책 평가(RBAC/ABAC)
+ alt 검증 성공
+ GW->>Svc: 요청 전달 (원본 JWT 또는 주입 헤더 포함)
+ Svc-->>GW: 비즈니스 응답
+ GW-->>Client: 200 OK (응답)
+ else 검증 실패
+ GW-->>Client: 401/403 에러
+ end
+```
+
+#### Spring Cloud Gateway 간단 예시(YAML)
+```yml
+spring:
+ cloud:
+ gateway:
+ default-filters:
+ - RemoveRequestHeader=Cookie
+ - DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials
+ routes:
+ - id: user-api
+ uri: http://user-service
+ predicates:
+ - Path=/api/users/**
+ filters:
+ - name: JwtAuth
+ args:
+ jwk-set-uri: https://idp.example.com/.well-known/jwks.json
+ expected-issuer: https://idp.example.com
+ expected-audience: user-api
+ clock-skew: 120
+ inject-headers:
+ X-User-Id: "#{claims['sub']}"
+ X-Scopes: "#{claims['scope']}"
+
+```
+
+
+#### 운영시 체크하면 좋은 체크리스트
+- [ ] **JWKS 캐시** 및 **키 회전(kid)** 대응
+- [ ] **iss/aud/exp/nbf** 검증 + **leeway** 허용
+- [ ] **권한 정책**(경로/메서드/스코프) 중앙화
+- [ ] **멀티 테넌트**라면 `iss`/`aud` 테넌트별 매핑
+- [ ] **원본 JWT 전달/마스킹** 정책(PII 최소화)
+- [ ] **레이트리밋/서킷브레이커/CORS**는 게이트웨이에서 일괄 처리
+- [ ] **토큰 크기/헤더 크기 제한** 주의 (프록시/로드밸런서 설정 일치)
+
+
+
+### NGINX/OpenResty(Lua) 컨셉
+- `access_by_lua*`에서 **Authorization** 파싱 → **JWKS 캐시**로 서명 검증
+- 실패 시 즉시 **401 Unauthorized**, 성공 시 `X-User-*` 헤더 주입 후 **프록시 패스**
+
+
+
+
+좀더 상세히 들어간다면 ?
+
+## 🧩 NGINX / OpenResty(Lua) 기반 무상태 인증 게이트웨이 설계
+
+### 🎯 목적
+JWT 기반 인증을 **NGINX 레이어에서 직접 수행**해,
+내부 서비스에는 **검증된 요청만 전달**하고,
+서버 자체는 **완전 무상태(Stateless)** 로 유지한다.
+
+---
+
+### ⚙️ 구조 개요
+
+```mermaid
+sequenceDiagram
+ participant Client as 클라이언트
+ participant NGINX as NGINX(OpenResty + Lua)
+ participant JWKS as JWKS 서버 (Auth Provider)
+ participant Service as 내부 서비스
+
+ Client->>NGINX: Authorization: Bearer
+ NGINX->>NGINX: access_by_lua*에서 JWT 파싱
+ NGINX->>JWKS: kid 기반 JWKS 키 요청 (캐시 확인)
+ JWKS-->>NGINX: JWK 공개키 응답
+ NGINX->>NGINX: 서명 검증 + iss/aud/exp/nbf 검증
+ alt 성공
+ NGINX->>NGINX: X-User-Id, X-Scopes 등 헤더 주입
+ NGINX->>Service: 프록시 패스 (내부 API 전달)
+ Service-->>NGINX: 응답
+ NGINX-->>Client: 200 OK
+ else 실패
+ NGINX-->>Client: 401 Unauthorized
+ end
+
+```
+
+## 🧠 핵심 로직 (Lua 단계별 설명)
+
+1. Authorization 헤더 추출
+
+```lua
+local jwt_token = ngx.var.http_authorization
+if not jwt_token or not jwt_token:find("Bearer") then
+ return ngx.exit(ngx.HTTP_UNAUTHORIZED)
+end
+local token = jwt_token:gsub("Bearer ", "")
+```
+
+2. JWT 파싱 및 헤더 확인 (kid 확인)
+```lua
+local cjson = require "cjson"
+local jwt = require "resty.jwt"
+local jwt_obj = jwt:load_jwt(token)
+local kid = jwt_obj and jwt_obj.header and jwt_obj.header.kid
+if not kid then
+ ngx.log(ngx.ERR, "JWT kid not found")
+ return ngx.exit(ngx.HTTP_UNAUTHORIZED)
+end
+```
+
+3. JWKS 키 캐시 확인
+
+```lua
+local jwks_cache = ngx.shared.jwks_cache
+local jwk_key = jwks_cache:get(kid)
+if not jwk_key then
+ local http = require "resty.http"
+ local httpc = http.new()
+ local res, err = httpc:request_uri("https://idp.example.com/.well-known/jwks.json")
+ if not res or res.status ~= 200 then
+ ngx.log(ngx.ERR, "JWKS fetch failed: ", err)
+ return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
+ end
+ local jwks = cjson.decode(res.body)
+ for _, key in ipairs(jwks.keys) do
+ jwks_cache:set(key.kid, cjson.encode(key), 3600)
+ end
+ jwk_key = jwks_cache:get(kid)
+ if not jwk_key then
+ return ngx.exit(ngx.HTTP_UNAUTHORIZED)
+ end
+end
+```
+
+4. 서명 검증 및 클레임 유효성 검사
+
+```lua
+local key_obj = cjson.decode(jwk_key)
+local jwt = require "resty.jwt"
+local validators = require "resty.jwt-validators"
+
+local jwt_obj = jwt:verify_jwk_obj(key_obj, token, {
+ lifetime_grace_period = 120, -- exp 오차 허용
+ iss = "https://idp.example.com",
+ aud = "my-api"
+})
+
+if not jwt_obj.verified then
+ ngx.log(ngx.ERR, "JWT invalid: ", jwt_obj.reason)
+ return ngx.exit(ngx.HTTP_UNAUTHORIZED)
+end
+```
+
+5. 검증된 정보 헤더 주입 후 내부 서비스로 전달
+
+```lua
+ngx.req.set_header("X-User-Id", jwt_obj.payload.sub)
+ngx.req.set_header("X-Scopes", table.concat(jwt_obj.payload.scope or {}, " "))
+ngx.req.set_header("X-Tenant", jwt_obj.payload.tenant or "default")
+```
+
+### 🧩 캐싱 & 성능 전략
+| 항목 | 설명 |
+|------|------|
+| **JWKS 캐시** | `ngx.shared.DICT`에 `kid`별 JWK JSON 저장 (TTL: 1h~6h) |
+| **백오프 로직** | JWKS 서버 장애 시 기존 캐시 유지 (`ngx.timer.at` 비동기 갱신) |
+| **로컬 캐시 백업** | 초기 부팅 시 디스크 캐시 복원 (`lua-resty-lock` + 파일캐시) |
+| **서명 알고리즘 제한** | `RS256`만 허용 (HS256 금지) |
+| **exp/nbf/iat 오차 허용** | ±120초 leeway |
+
+---
+
+### 🔒 보안 포인트
+| 항목 | 설명 |
+|------|------|
+| **공개키 검증** | JWKS는 TLS 위에서만 요청, HTTP 비허용 |
+| **JWT 크기 제한** | `client_max_body_size`, `large_client_header_buffers` 설정 |
+| **PII 최소화** | 민감정보(`email`, `name`)는 X-User-* 헤더로 전달하지 않음 |
+| **CORS 정책 통합** | 게이트웨이에서 Origin/Headers/Methods 허용 제어 |
+| **Rate Limiting / Circuit Breaker** | Lua 모듈(`lua-resty-limit-traffic`, `lua-resty-circuit-breaker`)로 처리 |
+
+
+
+> 💡 **정리**
+> - OpenResty는 "NGINX + Lua" 조합으로 **무상태 인증 로직을 네트워크 계층에서 수행**할 수 있는 강력한 도구다.
+> - 서버 애플리케이션이 인증을 직접 처리하지 않아도, 게이트웨이 단에서 **JWT 검증, 클레임 주입, 접근 정책 결정**을 전부 수행할 수 있다.
+> - 이로써 전체 아키텍처가 **Stateless + Secure + Scalable** 해진다.
From f0faa2359f085db21789a94656c15c66b57cd908 Mon Sep 17 00:00:00 2001
From: Chorong0824 <124541156+sjmun09@users.noreply.github.com>
Date: 2025年10月10日 12:19:53 +0900
Subject: [PATCH 7/8] =?UTF-8?q?docs=20:=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?=
=?UTF-8?q?=ED=81=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...24354円213円234円354円247円200円355円201円220円.md" | 187 ++++++++++++++++++
1 file changed, 187 insertions(+)
create mode 100644 "seongjun/353円251円224円354円213円234円354円247円200円355円201円220円.md"
diff --git "a/seongjun/353円251円224円354円213円234円354円247円200円355円201円220円.md" "b/seongjun/353円251円224円354円213円234円354円247円200円355円201円220円.md"
new file mode 100644
index 0000000..6465680
--- /dev/null
+++ "b/seongjun/353円251円224円354円213円234円354円247円200円355円201円220円.md"
@@ -0,0 +1,187 @@
+# 🧱 RabbitMQ 이해를 위한 전제 지식 정리
+## 아키텍처
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Client as 🧍 Client (사용자 요청)
+ participant API as 💻 API 서버 (Producer)
+ participant MQ as 📬 RabbitMQ (Broker)
+ participant Worker as ⚙️ Worker 서버 (Consumer)
+ participant DB as 🗄️ DB
+
+ Note over Client,DB: **비동기 메시지 처리 흐름**
+
+ Client->>API: 주문 요청 (POST /order)
+ API->>DB: 주문 데이터 저장
+ DB-->>API: 저장 완료 (Success)
+ API->>MQ: "주문 완료" 메시지 발행 (Publish)
+ MQ-->>API: 메시지 수신 확인 (ACK)
+ API-->>Client: 주문 성공 응답 (즉시 반환)
+
+ Note over API,Worker: 이후 비동기 처리 시작
+
+ MQ->>Worker: "주문 완료" 메시지 전달 (Consume)
+ Worker->>DB: 이메일 전송 이력 저장
+ Worker->>Client: (선택적으로) 이메일 발송 완료 알림
+```
+
+
+### 🔍 다이어그램 해석
+
+| 단계 | 설명 |
+|------|------|
+| **1.** Client가 주문 요청을 API 서버에 보냄 | 사용자는 단순히 "주문하기" 버튼을 클릭 |
+| **2.** API 서버는 DB에 주문 정보를 저장 | 핵심 트랜잭션은 즉시 완료되어야 함 |
+| **3.** DB에 저장 성공 후 RabbitMQ로 이벤트 발행 | `"order.created"` 같은 메시지를 MQ로 Publish |
+| **4.** RabbitMQ는 메시지를 Queue에 안전하게 저장 | ACK으로 API에 전달 완료 알림 |
+| **5.** API는 클라이언트에 빠르게 응답 | 비동기 처리이므로 기다리지 않음 |
+| **6.** Worker(Consumer)는 MQ에서 메시지를 꺼내 후속 작업 수행 | 예: 이메일, 포인트 적립, 알림 등 |
+| **7.** Worker가 처리 완료 후 DB에 결과 기록 | 재시도나 장애 대비 가능 |
+
+---
+
+#### 💡 핵심 요약
+
+- **동기식(요청-응답)** : Client ↔ API ↔ DB
+- **비동기식(이벤트 처리)** : API ↔ RabbitMQ ↔ Worker
+- **RabbitMQ 역할**
+ - 시스템 간 결합도 최소화 (Decoupling)
+ - 장애 시 메시지 유실 방지 (Persistent Queue)
+ - 처리량 폭주 시 버퍼링 역할
+
+---
+
+#### 🧭 흐름 시각적으로 정리하면
+```
+Client
+↓ (요청)
+API 서버
+↓ (DB 저장)
+데이터베이스
+↳ 성공
+↓
+RabbitMQ (메시지 브로커)
+↓
+Worker 서버 (Consumer)
+↓
+이메일 발송 / 포인트 적립 / 알림 처리
+```
+> 💬 즉, **RabbitMQ는 요청-응답 구조에서 벗어나, "이벤트 기반 비동기 흐름"을 가능하게 해주는 중개자**이다.
+
+
+## 1️⃣ 메시징 시스템의 기본 개념
+
+| 구성요소 | 설명 |
+|-----------|------|
+| **Producer** | 메시지를 생성해 보내는 주체. (예: 주문 완료 이벤트 발행) |
+| **Consumer** | 메시지를 받아서 처리하는 주체. (예: 이메일 발송 시스템) |
+| **Broker** | 메시지를 중개·저장·분배하는 서버 (RabbitMQ, Kafka 등) |
+| **Queue** | 메시지가 소비되기 전 임시로 저장되는 버퍼 공간 |
+| **Message** | 실제로 전달되는 데이터 단위 (JSON, 문자열, 객체 등) |
+
+> 💡 기본 흐름: **Producer → Broker → Consumer**
+
+---
+
+## 2️⃣ 비동기 통신 (RabbitMQ의 필요성)
+
+| 구분 | 동기(Synchronous) | 비동기(Asynchronous) |
+|------|--------------------|----------------------|
+| 방식 | 요청 후 응답까지 기다림 | 요청 후 바로 다음 작업 수행 |
+| 예시 | REST API 호출 (결과 기다림) | MQ에 이벤트를 넣고 나중에 처리 |
+| 장점 | 단순, 직관적 | 응답 지연 감소, 확장성 높음 |
+| 단점 | 느림, 병목 발생 | 복잡한 설계 필요 (큐 관리 등) |
+
+> 🚀 RabbitMQ는 비동기 이벤트 기반 아키텍처를 위한 메시지 브로커이다.
+
+---
+
+## 3️⃣ 메시지 큐(Message Queue)의 역할
+
+### ✅ 왜 필요한가?
+- 서비스 간 **결합도 낮추기 (Decoupling)**
+- **트래픽 폭주 제어 (Buffering)**
+- **비동기 처리**를 통한 **응답 시간 단축**
+- **신뢰성 보장 (ACK, 재시도, DLQ 등)**
+
+### 🧠 예시
+> 주문 시스템(Producer)이 ‘주문 완료’ 메시지를 MQ에 넣으면,
+> 이메일 시스템(Consumer)이 MQ에서 메시지를 꺼내 이메일을 발송한다.
+
+---
+
+## 4️⃣ 메시징 패턴의 기본 구조
+
+| 패턴 | 설명 | 예시 |
+|------|------|------|
+| **단순 큐(Simple Queue)** | 1:1 메시징 | 주문 → 이메일 발송 |
+| **Fanout (Pub/Sub)** | 1:N 메시징 (모든 Consumer에게 전달) | 알림 브로드캐스트 |
+| **Direct** | 라우팅키 기반으로 특정 Consumer에게 전달 | 로그 레벨별 큐 분리 |
+| **Topic** | 와일드카드 기반 라우팅 | `topic.key.*` 형태 |
+| **Header** | 헤더값 조건으로 라우팅 | 필터링 메시징 |
+
+---
+
+## 5️⃣ 전송 보장 수준 (Delivery Guarantee)
+
+| 수준 | 설명 |
+|------|------|
+| **At most once** | 최대 한 번 전달 (유실 가능) |
+| **At least once** | 최소 한 번 전달 (중복 가능) |
+| **Exactly once** | 정확히 한 번 전달 (복잡, 트랜잭션 기반) |
+
+> ⚙️ RabbitMQ는 보통 **At least once** 전략을 사용하며
+> ACK/NACK, 재전송(requeue) 메커니즘으로 이를 보장한다.
+
+---
+
+## 6️⃣ AMQP 프로토콜 (RabbitMQ의 핵심)
+
+RabbitMQ는 **AMQP (Advanced Message Queuing Protocol)** 기반으로 동작한다.
+
+| 구성요소 | 설명 |
+|-----------|------|
+| **Exchange** | 메시지를 받아 라우팅하는 분배기 |
+| **Queue** | 메시지를 임시 저장하는 버퍼 |
+| **Binding** | Exchange → Queue로 메시지를 연결하는 규칙 |
+| **Routing Key** | 어떤 Queue로 보낼지 결정하는 식별자 |
+| **Channel** | 하나의 TCP 연결 내에서의 논리적 세션 |
+| **Connection** | Producer/Consumer ↔ Broker 간 실제 TCP 연결 |
+
+> 🔄 **Exchange → (Binding Rule) → Queue → Consumer**
+
+---
+
+## 7️⃣ RabbitMQ vs Kafka 비교
+
+| 항목 | RabbitMQ | Kafka |
+|------|-----------|--------|
+| 목적 | 메시지 브로커 (즉시 처리 중심) | 로그 스트리밍 (대용량 이벤트 중심) |
+| 프로토콜 | **AMQP 표준** | 자체 프로토콜 |
+| 모델 | Queue 기반 (Push + Pull) | Log 기반 (Pull Only) |
+| 순서 보장 | Queue 단위 | 파티션 단위 |
+| 주요 사용처 | 이메일/결제/비동기 이벤트 | 로그 수집/실시간 데이터 파이프라인 |
+
+---
+
+## ✅ 다음 단계 제안
+
+이제 RabbitMQ 자체 구조로 들어가면 된다 👇
+
+### 📘 RabbitMQ 본격 정리 목차
+1. RabbitMQ란? (역사와 개요)
+2. AMQP 아키텍처 상세 구조
+3. Exchange 타입별 동작 (Direct, Topic, Fanout, Headers)
+4. 메시지 전달 보장 메커니즘 (ACK, DLQ, TTL 등)
+5. 클러스터링 & 고가용성 (HA Queue, Quorum Queue)
+6. 운영/모니터링 (Management UI, Channel 관리)
+7. Spring AMQP & Cloud Stream 연동 구조
+8. Kafka와 RabbitMQ 비교 (Use Case 중심)
+
+---
+
+> 💬 다음은 "📘 RabbitMQ 본격 정리 — 1️⃣ RabbitMQ란?" 부터 시작
+
+---
+
+
From 81a3133e0dc98585b97b709f8c67d0e5c4616ca0 Mon Sep 17 00:00:00 2001
From: tkdtn4657
Date: 2025年10月19日 23:50:34 +0900
Subject: [PATCH 8/8] =?UTF-8?q?docs:=20RAFT=20=ED=95=A9=EC=9D=98=20?=
=?UTF-8?q?=EC=95=8C=EA=B3=A0=EB=A6=AC=EC=A6=98=20=EB=AC=B8=EC=84=9C=20?=
=?UTF-8?q?=EC=9E=91=EC=84=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sangsu/RAFT_Algorithm.md | 46 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
create mode 100644 sangsu/RAFT_Algorithm.md
diff --git a/sangsu/RAFT_Algorithm.md b/sangsu/RAFT_Algorithm.md
new file mode 100644
index 0000000..6bf49fb
--- /dev/null
+++ b/sangsu/RAFT_Algorithm.md
@@ -0,0 +1,46 @@
+# RAFT
+
+## 클러스터란?
+
+RAFT에 설명하기에 앞서 클러스터 용어의 설명이 선행되어야 합니다. 클러스터(Cluster)는 여러 대의 서버(노드)가 하나의 시스템처럼 동작하도록 구성된 집합체입니다.
+
+이를 통해 시스템은 장애 발생 시에도 서비스를 지속할 수 있는 **고가용성(HA)** 과 **데이터 일관성**을 보장할 수 있습니다.
+
+## RAFT 란?
+
+**RAFT(Raft Consensus Algorithm)** 는 분산 시스템에서 **여러 노드 간 데이터 일관성과 합의를 유지하기 위한 리더 선출 기반의 합의 알고리즘**으로 리더 선출과 로그 복제를 통해 일관성을 확보합니다.
+
+클러스터 내 노드는 리더(Leader)와 팔로워(Follower)로 구분되며, 리더는 주기적으로 하트비트(Heartbeat) 신호를 전송하여 팔로워의 상태를 모니터링하고 클러스터의 정상 동작을 유지합니다.
+
+[画像:image]
+
+## 리더 선거
+
+리더는 주기적으로 하트비트를 전송하여 팔로워의 상태를 점검합니다.
+
+팔로워 노드는 리더로부터 일정 시간(ex: 150~300ms) 하트비트 메시지를 받지 못하면 **리더 장애로 판단**하고, 스스로 **후보자**(Candidate)로 전환한 뒤 새로운 리더를 선출하는 **텀**이 시행 됩니다.
+
+텀은 리더 선출하는 임의의 기간으로, 각 후보 노드 중 과반수 표를 받으면 리더 선출이 완료됩니다.
+
+리더 선출이 성공적으로 완료되면 새 리더가 조정하는 정상적인 운영을 진행합니다.
+
+[画像:image]
+
+## 로그 복제
+
+리더는 클라이언트의 요청을 로그 형태로 기록하고, 이를 모든 팔로워에게 복제합니다. 과반수의 팔로워가 로그를 수신·저장했다는 응답을 보내면 리더는 해당 로그를 **커밋(Commit)** 하며, 커밋된 로그는 모든 노드에 동일하게 적용되어 클러스터의 **데이터 일관성**을 유지합니다.
+
+## RAFT를 왜 사용하는가?
+
+RAFT를 사용하면 다중 환경 시스템에서 클러스터 내의 고가용성을 보장하기 편리하기 때문입니다.
+
+예를 들어 MongoDB의 Replica Set 구조에서는 데이터를 저장할 때 리더에 최초 저장, 이후 팔로워가 리더의 데이터를 참고해서 복제하는 방식으로 동작합니다. 이 때 팔로워는 복제(Replication)되었기 때문에 백업 서버로 활용될 수 있으며, 고가용성(High Availability)을 위한 교체 서버로 활용할 수 있기 때문입니다.
+
+## RAFT 합의 알고리즘 실 사용 사례
+
+다양한 곳에서 RAFT 합의 알고리즘을 활용함
+
+- IBM MQ
+- MongoDB
+- RabbitMQ
+- Apache Kafka (KRaft)