🎯 20주차 학습 커리큘럼 — HTTP/네트워크 + DevOps + Observability

Psj·2026년 5월 6일

F-lab

목록 보기
21/239

🎯 20주차 학습 커리큘럼 — HTTP/네트워크 + DevOps + Observability

19주차(테스트 심화) 이후 Claude가 임의로 구성한 학습 여정의 최종 주차.
1~19주차의 모든 코드가 사용자에게 전달되고 운영되는 영역 을 정복한다.

  • HTTP/네트워크 깊이 — 백엔드의 토대
  • 컨테이너와 Kubernetes — 현대 배포의 표준
  • CI/CD — 코드를 사용자에게 전달하는 다리
  • Observability — 운영 중 일어나는 일을 보는 눈

4년차 풀스택 개발자가 시니어/리드 로 가는 마지막 관문.


🤔 왜 20주차에 이 주제들인가

1~19주차의 위치:

  • 코드를 잘 만드는 법 은 충분히 학습
  • 그러나 그 코드가 어떻게 사용자에게 도달하고, 어떻게 운영되는지 는 미학습

왜 이 시점에 결정적인가:

  1. 시니어 면접 차별화 — "장애 대응 경험은?" "K8s 써보셨나요?" "TLS handshake 설명?"
  2. 실무 80%가 코드 작성 외 영역 — 4년차에서 시니어로 가는 핵심 차이
  3. ILIC 운영의 토대 — 102 테이블, 431 API가 안정적으로 돌아가려면 필수
  4. 면접 출제 빈도 높음 — "RESTful API"부터 "K8s 컨셉"까지

ILIC 관점:

  • 현재 Docker 사용 추정 (CLAUDE.md 컨텍스트에서 언급)
  • 그러나 K8s, 모니터링, 분산 추적 도입 여부는 미지수
  • 도입한다면 큰 가치, 안 했다면 면접 답변 보강 필요

📊 학습 경로 한눈에 보기

[Part A — 네트워크 기초 (Day 1-2)]
  [Phase 1] HTTP 깊이 (HTTP/1.1, HTTP/2, HTTP/3)
     ↓
  [Phase 2] TCP/IP와 TLS ◄ 정점 1

[Part B — DevOps와 컨테이너 (Day 3-4)]
  [Phase 3] Docker 깊이
     ↓
  [Phase 4] Kubernetes 핵심 ◄ 정점 2

[Part C — CI/CD와 운영 (Day 5-6)]
  [Phase 5] CI/CD 파이프라인
     ↓
  [Phase 6] 12-Factor App과 운영 원칙

[Part D — Observability (Day 7)]
  [Phase 7] 3 Pillars (Logs, Metrics, Traces) ◄ 정점 3
     ↓
  [Phase 8] 장애 대응과 사고 분석

총 8 Phase × 28 Unit — 정점 3개를 가진 압축 단일 주차.

🔗 1~20주차 흐름 정리 — 학습 여정의 완성

영역주차의미
Java 언어1-3기초
동시성4단일 JVM
Spring 생태계5-10프레임워크
JPA11-12영속성
DB13-14데이터
Spring MVC15웹 계층
분산 시스템16-17시스템 확장
Spring Security18보안
테스트19검증
HTTP/DevOps/Observability20운영

시니어 백엔드 개발자가 알아야 할 거의 모든 영역


🗓️ 권장 학습 일정 (압축 7일)

DayPhase학습 목표
1일차Phase 1HTTP 깊이
2일차Phase 2TCP/IP + TLS (★)
3일차Phase 3Docker 깊이
4일차Phase 4Kubernetes (★)
5일차Phase 5 + 6CI/CD + 12-Factor
6일차Phase 7Observability 3 Pillars (★)
7일차Phase 8 + 종합장애 대응 + 자기 점검

여유 일정 (14일): 각 Part에 +1-2일. 특히 Phase 4, 7은 직접 실습 권장.


🌐 Part A — 네트워크 기초 (Day 1-2)

📚 Phase 1 — HTTP 깊이

목표: 매일 쓰지만 깊이 모르는 HTTP를 정확히 이해한다.

Unit 1.1 — HTTP의 본질과 메시지 구조

선수 지식: 6주차 Phase 7 (웹 인프라), 15주차 (Spring MVC)

HTTP (HyperText Transfer Protocol):

"TCP 위의 텍스트 기반 요청-응답 프로토콜"

핵심 특성 ⭐ :
1. Stateless — 매 요청 독립
2. Request-Response — 클라이언트 시작
3. Text-based — 사람이 읽을 수 있음 (HTTP/2 전까지)
4. Connection-less — 응답 후 연결 종료 (기본)


HTTP 메시지 구조:

Request:

GET /api/fares/1 HTTP/1.1                    ← Start Line
Host: api.ilic.com                           ← Headers
Accept: application/json
Authorization: Bearer eyJ...
                                              ← 빈 줄
                                              ← Body (POST/PUT 시)

Response:

HTTP/1.1 200 OK                              ← Status Line
Content-Type: application/json               ← Headers
Content-Length: 256
Cache-Control: max-age=60
                                              ← 빈 줄
{"id": 1, "amount": 50000}                   ← Body

HTTP 메서드 의미 (15주차 복습 + 심화):

메서드의미멱등성안전성Body
GET조회권장 X
POST생성
PUT전체 수정
PATCH부분 수정❌*
DELETE삭제옵션
HEAD메타데이터만X
OPTIONS메서드 확인X

안전성(Safe): 서버 상태 변경 X
멱등성(Idempotent): 여러 번 호출해도 결과 동일


자주 헷갈리는 헤더 ⭐ :

헤더의미
Content-Type요청/응답 body의 타입
Accept클라이언트가 받을 수 있는 타입
Authorization인증 정보
Cache-Control캐싱 정책
ETag리소스 버전 식별
Content-Lengthbody 크기
Connection연결 유지 (keep-alive)
Host가상 호스팅용
User-Agent클라이언트 정보
Referer이전 페이지
Set-Cookie / Cookie쿠키 설정/전송

자기 점검

  • HTTP가 왜 Stateless인가? (힌트: 서버 부담 ↓, 확장성 ↑)
  • ILIC API가 멱등성을 어떻게 보장하는가? (힌트: PUT/DELETE 본질, POST는 Idempotency Key)

Unit 1.2 — HTTP 상태 코드 5계열 + 흔한 오해

선수 지식: Unit 1.1, 15주차 Phase 4

5계열 ⭐ :

계열의미
1xx정보 (드물게 사용)
2xx성공
3xx리다이렉션
4xx클라이언트 오류
5xx서버 오류

자주 쓰는 코드 + 흔한 오해 ⭐⭐ :

2xx — 성공

  • 200 OK — 일반 성공
  • 201 Created — POST 후 (Location 헤더 권장)
  • 204 No Content — 성공, body 없음 (DELETE 후)
  • 206 Partial Content — Range 요청

3xx — 리다이렉션

  • 301 Moved Permanently — 영구 이동 (캐시됨)
  • 302 Found — 임시 이동 (캐시 X)
  • 304 Not Modified — 캐시 유효 (ETag 매칭) ⭐
  • 307 Temporary Redirect — 메서드 보존
  • 308 Permanent Redirect — 메서드 보존

흔한 오해 ⚠️ :

  • 301 vs 302: 검색엔진 SEO에 영향 (301은 PageRank 전달)
  • 302 vs 307: 307은 메서드 보존 (POST → POST)

4xx — 클라이언트 오류

  • 400 Bad Request — 형식 오류
  • 401 Unauthorized인증 필요 (18주차)
  • 403 Forbidden인가 거부 (18주차)
  • 404 Not Found — 리소스 없음
  • 405 Method Not Allowed — 메서드 미지원
  • 409 Conflict — 충돌 (중복 등록)
  • 422 Unprocessable Entity — Validation 실패
  • 429 Too Many Requests — Rate Limit ⭐

흔한 오해:

  • 401 vs 403: 18주차에서 다룸 — 거의 매 면접 출제
  • 400 vs 422: 둘 다 클라이언트 오류, 422가 더 구체적 (시맨틱 오류)
  • 404를 보안용으로? — 권한 없는 리소스에 404 반환 (정보 노출 방지)

5xx — 서버 오류

  • 500 Internal Server Error — 일반 서버 오류
  • 502 Bad Gateway — 게이트웨이가 받은 응답이 잘못됨 ⭐
  • 503 Service Unavailable — 일시 다운 (재시도 권장)
  • 504 Gateway Timeout — 게이트웨이 타임아웃

흔한 오해 ⚠️ :

  • 502: 보통 upstream 서비스 다운 (예: Nginx → Spring Boot 다운)
  • 503: 명시적 점검/과부하 (Retry-After 헤더 가능)
  • 504: Nginx → Spring Boot 응답이 너무 느림 (timeout)

ILIC 시나리오 ⭐ :

사용자: 운임 견적 등록
  ↓
404 → 잘못된 ID
401 → 토큰 만료 → 재로그인
403 → 권한 부족
409 → 이미 등록된 견적
422 → 필수 필드 누락
429 → API 호출 한도 초과
500 → 서버 내부 버그
502 → 결제 서비스 다운
504 → DB 쿼리 타임아웃

자기 점검

  • 502와 504의 차이는? (힌트: 응답 받음 vs 응답 못 받음)
  • ILIC에서 5xx 에러를 어떻게 모니터링하는가?

Unit 1.3 — HTTP/1.1 → HTTP/2 → HTTP/3 ⭐

선수 지식: Unit 1.2

진화 과정:

HTTP/1.0 (1996)

  • 매 요청마다 새 TCP 연결
  • 매우 비효율적

HTTP/1.1 (1997, 사실상 표준)

  • Keep-Alive — 한 연결로 여러 요청
  • Pipelining (그러나 거의 사용 X)
  • Host 헤더 — 가상 호스팅
  • 텍스트 기반

한계:

  • Head-of-Line Blocking (HOL) ⚠️
    • 한 연결에 요청 A, B 보냄
    • A 응답 늦으면 B도 대기
  • 헤더 중복 전송 (매 요청마다 같은 헤더)

HTTP/2 (2015) ⭐

핵심 개선:

1. 바이너리 프레이밍

  • 텍스트 → 바이너리
  • 파싱 빠름

2. Multiplexing (멀티플렉싱) ⭐⭐

"한 연결에 여러 요청/응답을 동시에"

HTTP/1.1:

Connection 1: [Req A] → [Res A]
Connection 2: [Req B] → [Res B]  (별도 연결 필요)

HTTP/2:

Connection 1: [Req A, Req B, Req C 동시]
              [Res A, Res B, Res C 순서 무관]

HOL Blocking 해결 (Application 계층)

3. Header Compression (HPACK)

  • 헤더를 인덱스로 압축
  • 매 요청 같은 헤더 → 인덱스만 전송

4. Server Push

  • 클라이언트 요청 전에 서버가 미리 보냄
  • 예: HTML 응답 + CSS/JS 미리 전송
  • 그러나 잘 안 쓰임 (캐시와 충돌)

HTTP/3 (2022) ⭐

핵심 변화:

  • TCP → QUIC (UDP 기반)
  • TCP 자체의 HOL Blocking 해결

HTTP/2의 한계 (TCP 때문):

  • TCP는 순서 보장
  • 패킷 1 손실 → 패킷 2, 3 도착했어도 대기
  • TCP Layer의 HOL Blocking ⚠️

HTTP/3 (QUIC):

  • 각 스트림이 독립적
  • 한 스트림 패킷 손실 → 다른 스트림 영향 X
  • 연결 핸드셰이크 빠름 (0-RTT)

채택 현황:

  • Google, Cloudflare, YouTube 등 사용
  • 점차 확대 중

비교 매트릭스 ⭐ :

HTTP/1.1HTTP/2HTTP/3
전송 방식텍스트바이너리바이너리
멀티플렉싱X (HOL)
헤더 압축XHPACKQPACK
전송 계층TCPTCPQUIC (UDP)
TCP HOL있음있음해결
핸드셰이크1-2 RTT1-2 RTT0-1 RTT

ILIC 적용:

  • Spring Boot — HTTP/2 지원 (Tomcat 기본)
  • 활성화:
server:
  http2:
    enabled: true
  • HTTP/3 — 아직 일반적 X (CDN/리버스 프록시 활용)

자기 점검

  • HTTP/2에서도 TCP HOL이 남는 이유는? (힌트: 전송 계층 자체)
  • ILIC가 HTTP/2를 켜면 어떤 효과? (힌트: 모바일 클라이언트 응답 시간 ↓)

📚 Phase 2 — TCP/IP와 TLS (★ 정점 1)

목표: 면접 단골 — 네트워크 토대를 깊이 이해한다.

Unit 2.1 — OSI 7계층과 TCP/IP 4계층 ⭐

선수 지식: 컴퓨터 기초

OSI 7계층 (이론):

계층이름
7ApplicationHTTP, FTP, SMTP
6PresentationTLS, SSL, JPEG
5SessionNetBIOS
4TransportTCP, UDP
3NetworkIP, ICMP
2Data LinkEthernet, Wi-Fi
1Physical케이블, 광섬유

TCP/IP 4계층 (실제):

계층OSI 매핑
Application7-5
Transport4
Internet3
Network Access2-1

핵심 캡슐화 ⭐ :

[HTTP Request 데이터]
  ↓ Application Layer
[HTTP + 데이터]
  ↓ Transport Layer (TCP)
[TCP 헤더 + HTTP + 데이터] = TCP 세그먼트
  ↓ Internet Layer (IP)
[IP 헤더 + TCP 세그먼트] = IP 패킷
  ↓ Network Access
[Ethernet 헤더 + IP 패킷] = Frame
  ↓
[전송]

자기 점검

  • HTTP는 OSI 몇 계층? (힌트: 7)
  • TLS는 어디에 위치? (힌트: 5-6 사이 — 또는 Transport 위)

Unit 2.2 — TCP 3-way Handshake ⭐⭐⭐ (면접 100% 출제)

선수 지식: Unit 2.1

TCP:

"연결 지향적, 신뢰성 있는 전송 프로토콜"

3-way Handshake — 연결 수립 ⭐ :

Client                    Server
  |                          |
  |─── SYN (seq=x) ─────────→|  1. "연결할게"
  |                          |
  |←── SYN-ACK (seq=y, ─────|  2. "OK, 너도 OK?"
  |    ack=x+1)              |
  |                          |
  |─── ACK (ack=y+1) ───────→|  3. "OK"
  |                          |
  |═══ 연결 수립 ═══════════|
  |                          |
  |─── HTTP Request ────────→|
  |←── HTTP Response ────────|

왜 3번? ⭐ :

  • 양쪽 모두 "송신/수신 능력 확인"
  • 2번이면 한 쪽만 확인됨
  • 4번이면 중복

4-way Handshake — 연결 종료 ⭐ :

Client                    Server
  |                          |
  |─── FIN ─────────────────→|  1. "끝낼게"
  |                          |
  |←── ACK ──────────────────|  2. "OK"
  |                          |
  |   (서버 작업 마무리)      |
  |                          |
  |←── FIN ──────────────────|  3. "나도 끝"
  |                          |
  |─── ACK ─────────────────→|  4. "OK"
  |                          |
  |═══ TIME_WAIT (Client) ══|

TIME_WAIT ⭐ :

  • Client가 마지막 ACK 후 일정 시간 대기 (보통 2MSL = 1-4분)
  • 마지막 ACK 손실 시 재전송 가능
  • → Client 측에 TIME_WAIT 소켓 누적
  • 부하 큰 클라이언트 (예: 프록시)에서 문제

TIME_WAIT 해결:

  • SO_REUSEADDR 옵션
  • Connection Pool로 재사용

TCP의 신뢰성 보장 메커니즘 ⭐ :

1. Sequence Number

  • 각 바이트에 번호
  • 순서 보장

2. ACK

  • 받은 데이터 확인
  • 미수신 시 재전송

3. Checksum

  • 데이터 무결성 검증

4. Flow Control (흐름 제어)

  • Sliding Window
  • 수신자 처리 속도 맞춤

5. Congestion Control (혼잡 제어)

  • Slow Start, Congestion Avoidance
  • 네트워크 혼잡 시 속도 ↓

TCP vs UDP ⭐ :

TCPUDP
연결연결 지향비연결
신뢰성X
순서보장보장 X
속도느림빠름
Header20+ bytes8 bytes
용도HTTP, DBDNS, 게임, VoIP

면접 모의 답변 ⭐ :

"TCP는 연결 지향적이고 신뢰성 있는 전송 프로토콜입니다. 연결 수립 시 3-way handshake를 거치는데, SYN, SYN-ACK, ACK 세 번의 메시지로 양쪽 모두의 송수신 능력을 확인합니다.

종료 시에는 4-way handshake로, 양쪽이 각각 FIN과 ACK를 주고받습니다. 이때 마지막 ACK 손실에 대비해 TIME_WAIT 상태로 일정 시간 대기하는데, 이게 누적되면 소켓 고갈 문제가 발생할 수 있어 SO_REUSEADDR 옵션이나 Connection Pool로 해결합니다.

TCP는 신뢰성을 위해 Sequence Number, ACK, Checksum, Flow Control, Congestion Control을 사용합니다. 이런 메커니즘 때문에 UDP보다 느리지만, 정확성이 중요한 HTTP, DB 통신 등에 사용됩니다."

자기 점검

  • 왜 3-way이고 4-way인가의 차이는? (힌트: 종료는 양쪽이 독립적으로 끝남)
  • TIME_WAIT가 부하가 되는 시나리오는? (힌트: 프록시, 로드밸런서)

Unit 2.3 — HTTPS와 TLS Handshake ⭐⭐

선수 지식: Unit 2.2, 18주차 (Security)

HTTPS:

"HTTP + TLS — 암호화된 HTTP"

왜 필요한가:

  • HTTP는 평문 → 누구나 도청 가능
  • 비밀번호, 카드 정보 노출 위험
  • 현대 웹은 사실상 HTTPS 필수

TLS (Transport Layer Security):

  • SSL의 후속 (SSL 3.0 → TLS 1.0/1.1/1.2/1.3)
  • 현재 표준: TLS 1.2, 1.3 (1.0/1.1은 deprecated)

TLS 1.2 Handshake (전통):

Client                            Server
  |                                  |
  |─── ClientHello ─────────────────→|  지원 암호 알고리즘
  |                                  |
  |←── ServerHello ──────────────────|  선택한 알고리즘
  |←── Certificate (인증서) ─────────|  서버 인증서
  |←── ServerHelloDone ──────────────|
  |                                  |
  |   [인증서 검증]                  |
  |                                  |
  |─── ClientKeyExchange ───────────→|  Pre-Master Secret 전송
  |─── ChangeCipherSpec ────────────→|
  |─── Finished ────────────────────→|
  |                                  |
  |←── ChangeCipherSpec ─────────────|
  |←── Finished ─────────────────────|
  |                                  |
  |═══ 암호화된 통신 ════════════════|

RTT: 2 RTT (왕복 2번)


TLS 1.3 Handshake (2018) ⭐ :

Client                            Server
  |                                  |
  |─── ClientHello + Key Share ─────→|
  |                                  |
  |←── ServerHello + Cert + Key + ──|
  |    Finished                      |
  |                                  |
  |─── Finished ────────────────────→|
  |                                  |
  |═══ 암호화된 통신 ════════════════|

RTT: 1 RTT
0-RTT 모드: 이전 세션 재개 시 즉시

개선점:

  • 안전하지 않은 알고리즘 제거 (RC4, MD5, SHA-1 등)
  • Forward Secrecy 강제
  • 더 빠름

핵심 원리 ⭐ :

1. 비대칭 암호화 (Asymmetric)

  • 공개키 + 개인키
  • 인증서 검증 + 세션키 교환 에 사용
  • RSA, ECDSA

2. 대칭 암호화 (Symmetric)

  • 단일 키
  • 실제 데이터 암호화 에 사용
  • AES, ChaCha20

왜 둘 다?:

  • 비대칭은 안전하지만 느림
  • 대칭은 빠르지만 키 교환 어려움
  • → 비대칭으로 키 교환, 대칭으로 데이터 암호화

3. 인증서 (Certificate)

  • 서버의 신원 보증
  • CA (Certificate Authority) 가 서명
  • 브라우저가 CA의 공개키로 검증

인증서 체인:

Root CA (브라우저에 내장)
  ↓ 서명
Intermediate CA
  ↓ 서명
Leaf Certificate (실제 사이트)

Let's Encrypt:

  • 무료 인증서 발급
  • 90일 유효 + 자동 갱신

HTTPS 비용 ⚠️ :

  • 핸드셰이크 추가 RTT (TLS 1.3로 완화)
  • CPU 사용량 (대칭 암호화는 매우 빠름)
  • 인증서 비용 (Let's Encrypt로 해결)

현대 결론:

  • 모든 HTTP는 HTTPS여야 함
  • HSTS 헤더로 강제

ILIC 적용:

  • 운영: Nginx/ALB에서 TLS 종료 (SSL Termination)
  • 내부 통신: 보통 HTTP (별도 보안 영역)
  • TLS 1.2+ 강제

자기 점검

  • 왜 비대칭과 대칭을 섞는가? (힌트: 속도 + 보안)
  • "Let's Encrypt가 무료인데 안전한가?" (힌트: 안전 — CA 검증 거침)

Unit 2.4 — DNS와 Load Balancing

선수 지식: Unit 2.3

DNS (Domain Name System):

"도메인 이름 ↔ IP 주소 변환"

api.ilic.com → 203.0.113.42

DNS 조회 흐름:

1. Browser Cache 확인
2. OS Cache 확인
3. Router Cache 확인
4. ISP DNS 서버 조회
5. Root → TLD → Authoritative DNS

DNS 레코드 타입 ⭐ :

타입의미
A도메인 → IPv4
AAAA도메인 → IPv6
CNAME도메인 → 다른 도메인 (별칭)
MX메일 서버
TXT텍스트 (SPF, DKIM, 인증)
NS네임서버
SRV서비스 (포트 포함)

Load Balancing ⭐ :

역할:

  • 여러 서버에 트래픽 분산
  • 장애 자동 우회 (Health Check)
  • SSL Termination

알고리즘:

알고리즘특징
Round Robin순차 분배
Least Connections연결 수 적은 곳
IP Hash같은 IP는 같은 서버 (Sticky)
Weighted가중치 기반

Layer 4 vs Layer 7 LB ⭐ :

L4 (Transport)L7 (Application)
기준IP, PortURL, Header, Cookie
속도빠름느림
기능단순풍부 (Path 라우팅 등)
AWS NLBAWS ALB, Nginx

ILIC 시나리오:

  • AWS ALB로 SSL 종료 + Path 기반 라우팅
  • /api/* → Spring Boot
  • /static/* → CDN

Sticky Session ⚠️ :

  • 같은 사용자를 같은 서버로
  • Session 기반 인증 시 필요
  • → JWT (Stateless)면 불필요 (18주차)

자기 점검

  • DNS Cache TTL을 짧게 하면 어떤 효과? (힌트: 빠른 변경, 그러나 부하)
  • L4와 L7 중 ILIC에 적합한 것은? (힌트: API 경로 라우팅 → L7)

🐳 Part B — DevOps와 컨테이너 (Day 3-4)

📚 Phase 3 — Docker 깊이

목표: ILIC가 이미 사용 중일 가능성 높지만 깊이 정리한다.

Unit 3.1 — 컨테이너 vs VM과 Docker의 본질

선수 지식: 운영체제 기초

전통 배포의 문제:

  • "내 컴퓨터에서는 돌아간다" 😅
  • OS, 라이브러리 버전 차이
  • 환경 격리 어려움

가상화의 진화:

VM (Virtual Machine)

[App A] [App B] [App C]
[Guest OS] [Guest OS] [Guest OS]    ← 무거움
[Hypervisor]
[Host OS]
[Hardware]

컨테이너 (Container)

[App A] [App B] [App C]
[Bin/Lib] [Bin/Lib] [Bin/Lib]
[Container Runtime (Docker)]
[Host OS]                            ← 공유
[Hardware]

핵심 차이:

  • VM: OS 자체 가상화 — GB
  • Container: 프로세스 격리 — MB

Docker의 핵심 메커니즘 ⭐ :

1. Namespace (격리)

  • PID, Network, Mount, User 등 분리
  • 컨테이너끼리 안 보임

2. cgroups (제한)

  • CPU, 메모리, I/O 한계

3. Union File System

  • 레이어 기반
  • 변경분만 추가
  • → 빠르고 효율적

3가지 핵심 개념 ⭐ :

Image (이미지)

  • 정적 — 변경 불가
  • 레이어들의 조합
  • Dockerfile로 생성

Container (컨테이너)

  • 이미지의 실행 인스턴스
  • 동적 — 상태 가짐
  • 종료 시 변경 사라짐 (volume 외)

Registry (저장소)

  • 이미지 저장
  • Docker Hub, ECR, GCR

자기 점검

  • VM과 Container의 결정적 차이는? (힌트: OS 공유)
  • 왜 컨테이너가 빨리 시작하는가? (힌트: 프로세스 시작)

Unit 3.2 — Dockerfile과 이미지 최적화 ⭐

선수 지식: Unit 3.1

기본 Dockerfile (Spring Boot):

FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/ilic.jar app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]

문제:

  • 매번 jar 빌드 결과를 통째로 복사 → 코드 1줄 수정해도 전체 레이어 재생성
  • 이미지 크기 ↑

Multi-stage Build ⭐ — 빌드와 실행 분리:

# 빌드 스테이지
FROM gradle:8-jdk17 AS builder
WORKDIR /build
COPY . .
RUN gradle build -x test

# 실행 스테이지
FROM openjdk:17-jre-slim
WORKDIR /app
COPY --from=builder /build/libs/ilic.jar app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]

효과:

  • 최종 이미지는 jdk가 아닌 jre
  • gradle, 소스코드 등 제외
  • 1GB → 200MB 가능

레이어 캐싱 활용 ⭐ :

나쁜 예:

COPY . .
RUN gradle build  # 코드 1줄 변경해도 처음부터

좋은 예 (Spring Boot 권장):

# 의존성만 먼저
COPY build.gradle settings.gradle ./
RUN gradle dependencies

# 그 다음 소스
COPY src ./src
RUN gradle build

→ 의존성 변경 없으면 캐시 활용


Spring Boot Layered JAR ⭐ :
Spring Boot 2.3+가 제공하는 최적화:

FROM openjdk:17-jre-slim
WORKDIR /app
ARG JAR_FILE=target/ilic.jar
COPY ${JAR_FILE} app.jar
RUN java -Djarmode=layertools -jar app.jar extract

FROM openjdk:17-jre-slim
WORKDIR /app
COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/spring-boot-loader/ ./
COPY --from=builder /app/snapshot-dependencies/ ./
COPY --from=builder /app/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

효과:

  • 의존성과 애플리케이션 코드 분리
  • 코드만 변경 시 매우 빠른 재빌드

보안 모범 사례 ⭐ :

1. non-root 사용자

RUN useradd -ms /bin/bash appuser
USER appuser

2. 최소 베이스 이미지

  • alpine 또는 slim 변형
  • distroless (Google) — 더 작음

3. .dockerignore

.git
.gradle
target
*.md

4. 명시적 버전

FROM openjdk:17.0.9-jre-slim   # ❌ latest 금지

ILIC 시나리오:

  • Multi-stage + Layered JAR
  • non-root 사용자
  • 이미지 크기 200MB 이하 목표

자기 점검

  • 이미지 크기를 1/5로 줄이는 방법 3가지는?
  • ILIC가 latest 태그를 쓰면 어떤 위험? (힌트: 재현 불가능, 의도치 않은 업데이트)

Unit 3.3 — Docker Compose

선수 지식: Unit 3.2

문제:

  • ILIC는 Spring Boot + MySQL + Redis + Kafka...
  • 각각 docker run 명령어 6개?

Docker Compose:

"여러 컨테이너를 YAML로 정의 + 한 번에 실행"

version: '3.8'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/ilic
      - SPRING_DATASOURCE_PASSWORD=${DB_PASSWORD}
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - ilic-network
  
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
      MYSQL_DATABASE: ilic
    volumes:
      - mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - ilic-network
  
  redis:
    image: redis:7-alpine
    networks:
      - ilic-network
  
  kafka:
    image: confluentinc/cp-kafka:latest
    networks:
      - ilic-network

volumes:
  mysql-data:

networks:
  ilic-network:

실행:

docker-compose up -d
docker-compose down
docker-compose logs -f app

Compose vs Kubernetes:

  • 개발/테스트: Compose
  • 운영: Kubernetes (Phase 4)

ILIC 활용:

  • 로컬 개발 환경 구성
  • 통합 테스트 환경 (19주차 Testcontainers의 보완)

자기 점검

  • depends_on의 healthcheck가 왜 중요? (힌트: MySQL 시작과 ready의 차이)
  • volumes를 안 쓰면? (힌트: 컨테이너 재시작 시 데이터 손실)

📚 Phase 4 — Kubernetes 핵심 (★ 정점 2)

목표: 현대 운영의 표준 — K8s의 핵심 컨셉을 면접 답변 가능 수준으로.

Unit 4.1 — 왜 Kubernetes인가

선수 지식: Phase 3

Docker만으로의 한계:

  • 서버 1대에 컨테이너 100개? 관리 어려움
  • 컨테이너 자동 재시작?
  • 트래픽 폭증 시 자동 확장?
  • 무중단 배포?

Kubernetes (K8s):

"컨테이너 오케스트레이션 표준"


핵심 기능 ⭐ :

1. Self-healing

  • 컨테이너 다운 시 자동 재시작
  • 노드 다운 시 다른 노드로 이전

2. Auto-scaling

  • 부하에 따라 자동 확장/축소
  • HPA (Horizontal Pod Autoscaler)

3. Service Discovery

  • 서비스 이름으로 통신
  • 17주차의 Service Discovery가 K8s에서는 자동

4. Load Balancing

  • Service가 자동 LB

5. Rolling Update

  • 무중단 배포
  • 점진적 교체

6. Configuration Management

  • ConfigMap, Secret으로 설정 분리

Cluster 구조 ⭐ :

[Control Plane (Master)]
├── API Server  ← 모든 명령의 입구
├── etcd        ← 상태 저장 (17주차 합의 알고리즘)
├── Scheduler   ← Pod 배치 결정
└── Controller Manager  ← 상태 유지

[Worker Nodes]
├── Node 1
│   ├── kubelet      ← 노드 에이전트
│   ├── kube-proxy   ← 네트워크
│   └── Pods (containers)
├── Node 2
└── Node 3

자기 점검

  • K8s가 등장한 핵심 동기는?
  • ILIC 같은 단일 앱이 K8s를 쓸 가치가 있는가? (힌트: 작으면 Compose도 충분)

Unit 4.2 — Pod, Deployment, Service ⭐⭐ (면접 단골)

선수 지식: Unit 4.1

3가지 핵심 리소스 ⭐ :

1. Pod — 가장 작은 배포 단위

apiVersion: v1
kind: Pod
metadata:
  name: ilic-pod
spec:
  containers:
  - name: ilic-app
    image: ilic:1.0.0
    ports:
    - containerPort: 8080

특징:

  • 컨테이너 1개 또는 그 이상
  • 같은 Pod 컨테이너는 IP/Volume 공유
  • 수명이 일시적 (다시 만들면 IP 변경)

왜 Pod인가 (그냥 컨테이너 아니고):

  • 사이드카 패턴 (로깅 컨테이너, 프록시 등)
  • 의존성 강한 컨테이너 묶기

2. Deployment — Pod의 관리자

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ilic-deployment
spec:
  replicas: 3                     ← 3개 Pod
  selector:
    matchLabels:
      app: ilic
  template:
    metadata:
      labels:
        app: ilic
    spec:
      containers:
      - name: ilic-app
        image: ilic:1.0.0
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1000m"

역할 ⭐ :

  • Replicas 관리 — N개 Pod 보장
  • Rolling Update — 무중단 배포
  • Rollback — 이전 버전으로 복구
  • Self-healing — Pod 다운 시 재생성

Rolling Update 흐름:

v1: [Pod1] [Pod2] [Pod3]
       ↓
v2 시작: [Pod1] [Pod2] [Pod3] [Pod4(v2)]
       ↓
[Pod2] [Pod3] [Pod4(v2)] [Pod5(v2)]  ← Pod1 종료
       ↓
[Pod4(v2)] [Pod5(v2)] [Pod6(v2)]

3. Service — Pod 노출

문제: Pod IP는 변함 → 어떻게 접근?

Service:

"Pod 그룹의 안정적인 접근점"

apiVersion: v1
kind: Service
metadata:
  name: ilic-service
spec:
  selector:
    app: ilic                ← 이 라벨의 Pod 묶음
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP

Service Type ⭐ :

Type의미
ClusterIP클러스터 내부만 (기본)
NodePort노드의 특정 포트로 노출
LoadBalancer외부 LB 자동 생성 (AWS ELB 등)
ExternalNameDNS CNAME

Service Discovery (17주차 자동 해결):

  • http://ilic-service 으로 접근 → K8s가 자동 라우팅
  • Eureka 등 별도 도구 불필요

ILIC 시나리오:

# Backend
Deployment: ilic-app (replicas: 3)
Service: ilic-service (ClusterIP)

# Frontend
Deployment: ilic-vue (replicas: 2)
Service: ilic-vue-service

# Ingress (외부 접근)
Ingress:
  - api.ilic.com → ilic-service
  - ilic.com → ilic-vue-service

자기 점검

  • Pod와 Deployment 중 무엇을 직접 만들까? (힌트: Deployment — Pod는 자동)
  • LoadBalancer Type의 비용은? (힌트: 클라우드 LB 비용)

Unit 4.3 — Ingress, ConfigMap, Secret

선수 지식: Unit 4.2

Ingress — HTTP 라우팅

문제: LoadBalancer Service를 도메인마다 만들면 비용 ↑

Ingress:

"HTTP/HTTPS L7 라우팅"

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ilic-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt
spec:
  tls:
  - hosts:
    - api.ilic.com
    secretName: ilic-tls
  rules:
  - host: api.ilic.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: ilic-service
            port:
              number: 80
      - path: /admin
        pathType: Prefix
        backend:
          service:
            name: ilic-admin-service
            port:
              number: 80

역할:

  • 도메인/Path 기반 라우팅
  • TLS 종료
  • 인증서 자동 발급 (cert-manager)

ConfigMap — 환경 설정

apiVersion: v1
kind: ConfigMap
metadata:
  name: ilic-config
data:
  application.yml: |
    spring:
      profiles:
        active: prod
    server:
      port: 8080

사용:

spec:
  containers:
  - name: ilic-app
    volumeMounts:
    - name: config
      mountPath: /config
  volumes:
  - name: config
    configMap:
      name: ilic-config

Secret — 민감 정보

apiVersion: v1
kind: Secret
metadata:
  name: ilic-secret
type: Opaque
data:
  db-password: cGFzc3dvcmQ=    # Base64

사용:

env:
- name: DB_PASSWORD
  valueFrom:
    secretKeyRef:
      name: ilic-secret
      key: db-password

⚠️ 주의:

  • Secret은 Base64 인코딩만 (암호화 X)
  • Vault, Sealed Secrets 등 추가 도구 권장
  • 18주차 보안과 연결

ILIC 적용:

  • ConfigMap: 환경별 설정
  • Secret: DB 비밀번호, JWT 키
  • Ingress: api.ilic.com 라우팅 + Let's Encrypt 자동 갱신

자기 점검

  • Secret이 Base64만이면 보안인가? (힌트: NO — 외부 도구 필요)
  • Ingress vs Service LoadBalancer? (힌트: Ingress 1개로 여러 서비스)

Unit 4.4 — Health Check와 Auto-scaling

선수 지식: Unit 4.2

Health Check (Probe) ⭐

3가지 Probe:

spec:
  containers:
  - name: ilic-app
    livenessProbe:                      ← "살아있나?"
      httpGet:
        path: /actuator/health
        port: 8080
      initialDelaySeconds: 30
      periodSeconds: 10
      failureThreshold: 3
    
    readinessProbe:                     ← "트래픽 받을 준비?"
      httpGet:
        path: /actuator/health/readiness
        port: 8080
      periodSeconds: 5
    
    startupProbe:                       ← "시작 중?"
      httpGet:
        path: /actuator/health
        port: 8080
      failureThreshold: 30
      periodSeconds: 10

차이점 ⭐ :

LivenessReadinessStartup
실패 시재시작트래픽 차단다른 Probe 시작
용도Deadlock 감지일시적 부하느린 시작

Spring Boot Actuator 활용:

management:
  endpoints:
    web:
      exposure:
        include: health
  endpoint:
    health:
      probes:
        enabled: true

/actuator/health/liveness, /actuator/health/readiness 자동 제공


HPA (Horizontal Pod Autoscaler) ⭐

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: ilic-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: ilic-deployment
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

효과:

  • CPU 70% 초과 → Pod 추가
  • CPU 낮으면 Pod 제거
  • min ~ max 범위 내

ILIC 시나리오:

  • 평소: 3 Pod
  • 트래픽 폭증: 자동으로 10 Pod까지
  • 새벽: 다시 3 Pod로 축소 → 비용 절감

VPA (Vertical) vs HPA (Horizontal) ⭐ :

  • VPA: Pod 자체 리소스 늘림 (Scale-Up 유사)
  • HPA: Pod 개수 늘림 (Scale-Out 유사)
  • HPA가 일반적

자기 점검

  • Liveness와 Readiness가 같으면 안 되는 이유는? (힌트: Readiness는 일시적 OK, Liveness는 재시작)
  • HPA가 즉시 반응하지 않는 이유는? (힌트: 메트릭 수집 주기, 안정성)

🚀 Part C — CI/CD와 운영 (Day 5-6)

📚 Phase 5 — CI/CD 파이프라인

목표: 코드를 사용자에게 자동으로 전달하는 다리를 이해한다.

Unit 5.1 — CI/CD의 본질과 단계

선수 지식: Phase 4, 19주차 (테스트)

CI (Continuous Integration):

"자주 통합 — 빌드 + 테스트 자동화"

CD (Continuous Delivery / Deployment):

  • Delivery: 자동으로 배포 가능한 상태까지
  • Deployment: 자동으로 운영 환경까지 배포

전형적 파이프라인 ⭐ :

[Code Push]
    ↓
[Build]              ← Gradle build
    ↓
[Static Analysis]    ← SonarQube, Checkstyle
    ↓
[Unit Test]          ← JUnit (19주차)
    ↓
[Integration Test]   ← Testcontainers (19주차)
    ↓
[Build Image]        ← Docker
    ↓
[Push to Registry]   ← ECR, GCR
    ↓
[Deploy to Dev]      ← 자동
    ↓
[E2E Test]           ← 자동
    ↓
[Deploy to Staging]  ← 자동
    ↓
[Manual Approval]    ← 운영 배포 전
    ↓
[Deploy to Prod]
    ↓
[Smoke Test]

각 단계의 의미 ⭐ :

단계목적
Build코드 → 실행 가능 형태
Static Analysis컴파일 전에 잡기 (코드 스멜, 보안)
Unit Test빠른 회귀 검증
Integration Test통합 검증
Build Image배포 단위
Deploy to Dev개발자 검증
E2E Test전체 시나리오
Deploy to Staging운영과 동일 환경
Manual Approval위험 통제
Deploy to Prod사용자 노출

자기 점검

  • "왜 매번 Manual Approval?" 자동화의 한계는? (힌트: 비즈니스 결정, 큰 변경)
  • ILIC가 어디까지 자동화되어 있는가?

Unit 5.2 — GitHub Actions 실전

선수 지식: Unit 5.1

GitHub Actions (가장 보편):

.github/workflows/ci-cd.yml:

name: CI/CD
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      mysql:
        image: mysql:8.0
        env:
          MYSQL_ROOT_PASSWORD: test
          MYSQL_DATABASE: test
        ports:
          - 3306:3306
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'temurin'
    
    - name: Cache Gradle
      uses: actions/cache@v3
      with:
        path: |
          ~/.gradle/caches
          ~/.gradle/wrapper
        key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
    
    - name: Run Tests
      run: ./gradlew test
    
    - name: Generate Coverage Report
      run: ./gradlew jacocoTestReport
    
    - name: Upload Coverage to Codecov
      uses: codecov/codecov-action@v3

  build-and-push:
    needs: test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Build with Gradle
      run: ./gradlew build -x test
    
    - name: Build Docker Image
      run: docker build -t ilic:${{ github.sha }} .
    
    - name: Login to ECR
      uses: aws-actions/amazon-ecr-login@v2
    
    - name: Push Image
      run: docker push ${{ env.ECR_REGISTRY }}/ilic:${{ github.sha }}

  deploy:
    needs: build-and-push
    runs-on: ubuntu-latest
    steps:
    - name: Deploy to K8s
      run: kubectl set image deployment/ilic ilic=ilic:${{ github.sha }}

핵심 개념:

Workflow

  • 자동화 흐름

Job

  • 병렬/순차 실행 단위
  • needs로 의존성

Step

  • Job 안의 명령

Action

  • 재사용 가능한 빌딩 블록
  • 마켓플레이스에서 가져옴

캐싱 ⭐ — 속도 향상:

  • Gradle 의존성 캐시
  • Docker 레이어 캐시
  • 빌드 시간 50% 절감 가능

자기 점검

  • main 브랜치에만 배포하는 이유는? (힌트: 안정성)
  • Secret을 GitHub Actions에 어떻게 안전하게? (힌트: Repository Secrets)

Unit 5.3 — 배포 전략 (Blue-Green, Canary, Rolling) ⭐

선수 지식: Phase 4, Unit 5.2

3가지 배포 전략 ⭐ :

1. Rolling Update (K8s 기본)

v1: [Pod] [Pod] [Pod]
       ↓ 1개씩 교체
v2: [Pod(v2)] [Pod(v1)] [Pod(v1)]
       ↓
v2: [Pod(v2)] [Pod(v2)] [Pod(v1)]
       ↓
v2: [Pod(v2)] [Pod(v2)] [Pod(v2)]

장점: 단순, 자원 효율
단점: 롤백 느림, 두 버전 공존


2. Blue-Green

Blue (운영): [Pod(v1)] [Pod(v1)] [Pod(v1)]  ← 트래픽
Green (대기): [Pod(v2)] [Pod(v2)] [Pod(v2)]
       ↓ 트래픽 전환
Blue (대기):  [Pod(v1)] [Pod(v1)] [Pod(v1)]
Green (운영): [Pod(v2)] [Pod(v2)] [Pod(v2)]  ← 트래픽

장점: 즉시 롤백 가능, 두 버전 공존 X
단점: 자원 2배


3. Canary

v1: [Pod] [Pod] [Pod] [Pod] [Pod]    ← 95% 트래픽
v2:                          [Pod]    ← 5% 트래픽
       ↓ 점진적 확대
v1: [Pod] [Pod] [Pod]
v2:               [Pod] [Pod]         ← 50% 트래픽
       ↓
v1:
v2: [Pod] [Pod] [Pod] [Pod] [Pod]    ← 100% 트래픽

장점: 점진적 검증, 실패 시 적은 영향
단점: 복잡

Argo Rollouts, Flagger 등 도구 활용.


선택 가이드 ⭐ :

상황추천
일반 배포Rolling
빠른 롤백 필요Blue-Green
위험한 변경, 점진 검증Canary
자원 여유 적음Rolling
완전 격리 필요Blue-Green

ILIC 시나리오:

  • 일반 기능 추가 → Rolling
  • 결제 시스템 변경 → Canary (5% → 50% → 100%)
  • 메이저 버전 업그레이드 → Blue-Green

자기 점검

  • "롤백이 5분 이내여야 한다" 시 어떤 전략? (힌트: Blue-Green)
  • ILIC의 운영 배포 빈도는? Canary 도입 가치 있는가?

📚 Phase 6 — 12-Factor App과 운영 원칙

목표: 클라우드 네이티브의 표준 원칙을 정리한다.

Unit 6.1 — 12-Factor App ⭐ (간단 정리)

선수 지식: Phase 5

12-Factor:

"클라우드 네이티브 앱의 12가지 원칙" (Heroku 발표)


12가지 원칙 요약 ⭐ :

#원칙의미
1Codebase한 앱 = 한 저장소
2Dependencies명시적 선언 (build.gradle)
3Config환경변수로 분리
4Backing ServicesDB/Redis 등 = 외부 자원
5Build/Release/Run단계 분리
6ProcessesStateless
7Port Binding자체 포트 노출
8Concurrency프로세스 단위 확장
9Disposability빠른 시작/종료 (Graceful Shutdown)
10Dev/Prod Parity환경 동일성
11Logsstdout으로 출력 (Phase 7)
12Admin Processes일회성 작업 분리

핵심 강조 ⭐ :

Config (3) — 가장 자주 위반

  • 비밀번호 하드코딩 X
  • ConfigMap/Secret 활용 (Phase 4)
  • 환경별 다른 yml

Stateless (6) — MSA의 핵심

  • Pod 재시작해도 OK
  • Session은 외부 (Redis)
  • 18주차 JWT와 연결

Logs (11) — 운영의 시작

  • 파일 X, stdout 으로
  • K8s/Docker가 수집
  • Phase 7에서 자세히

Disposability (9) — Graceful Shutdown

// Spring Boot
server:
  shutdown: graceful
spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s

→ SIGTERM 받으면 새 요청 안 받고, 진행 중인 요청 완료 후 종료.


ILIC 점검:

  • 비밀번호가 코드에 있는가?
  • Session을 메모리에 저장하는가?
  • 로그를 파일에 쓰는가?
  • Graceful Shutdown이 되는가?

자기 점검

  • 12-Factor 중 ILIC가 가장 약한 부분은?
  • "Stateless가 왜 어려운가?" (힌트: 캐시, Session, 파일 업로드)

👁️ Part D — Observability (Day 7) — ★ 정점 3

📚 Phase 7 — 3 Pillars of Observability

목표: 운영 중 일어나는 일을 보는 세 가지 눈을 정복한다.

Unit 7.1 — Observability vs Monitoring

선수 지식: Phase 5-6

Monitoring (전통):

  • 미리 정의한 지표 추적
  • "CPU 80% 넘으면 알림"
  • 알려진 문제 탐지

Observability (현대):

  • 시스템 내부를 관찰 가능 한 상태로
  • "왜 이렇게 느린가?" 를 추적 가능
  • 알려지지 않은 문제 탐지

관계:

"Monitoring은 Observability의 부분 집합"


3 Pillars ⭐⭐⭐ :

Pillar답하는 질문도구
Logs무슨 일이 일어났는가?ELK, Loki
Metrics얼마나 일어났는가?Prometheus, Grafana
Traces어떻게 흘렀는가?Zipkin, Jaeger

→ 17주차 Distributed Tracing이 Traces.

자기 점검

  • Monitoring과 Observability의 결정적 차이는?
  • ILIC가 현재 어느 Pillar가 약한가?

Unit 7.2 — Logs (구조화된 로깅)

선수 지식: Unit 7.1

나쁜 로그:

2024-05-04 10:00:00 - 운임 처리 시작
2024-05-04 10:00:05 - 알 수 없는 오류 발생

문제:

  • 검색 어려움
  • 컨텍스트 없음
  • 알림 자동화 X

구조화 로깅 (JSON) ⭐ :

{
  "timestamp": "2024-05-04T10:00:00Z",
  "level": "ERROR",
  "service": "ilic-fare-service",
  "trace_id": "abc123",
  "user_id": "42",
  "fare_id": "100",
  "error": "PaymentTimeout",
  "duration_ms": 5000,
  "message": "결제 처리 시간 초과"
}

효과:

  • 필드 단위 검색 (Elasticsearch)
  • 자동 알림 (특정 error 발생 시)
  • 통계 분석

Spring Boot 구조화 로깅:

# logback-spring.xml
<configuration>
  <appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
      <providers>
        <timestamp/>
        <logLevel/>
        <loggerName/>
        <mdc/>
        <message/>
      </providers>
    </encoder>
  </appender>
  
  <root level="INFO">
    <appender-ref ref="JSON"/>
  </root>
</configuration>

MDC (Mapped Diagnostic Context) ⭐ — 컨텍스트 전파:

@Component
public class TraceIdFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(...) {
        String traceId = request.getHeader("X-Trace-Id");
        if (traceId == null) traceId = UUID.randomUUID().toString();
        
        MDC.put("trace_id", traceId);
        try {
            filterChain.doFilter(request, response);
        } finally {
            MDC.clear();
        }
    }
}

→ 모든 로그에 trace_id 자동 포함


ELK Stack (전통):

  • Elasticsearch — 저장 + 검색
  • Logstash — 수집 + 변환
  • Kibana — 시각화

Grafana Loki (현대):

  • 가벼움 (메트릭과 통합)
  • 비용 효율적

ILIC 적용:

  • JSON 로그 → stdout
  • K8s가 자동 수집
  • ELK 또는 Loki로 집계

자기 점검

  • 평문 vs JSON 로그의 결정적 차이는?
  • ILIC가 100개 서버라면 로그 검색을 어떻게?

Unit 7.3 — Metrics (Prometheus + Grafana) ⭐

선수 지식: Unit 7.2

Metrics:

"시계열 숫자 데이터 — 얼마나 일어났는가"

:

  • 초당 요청 수 (RPS)
  • 응답 시간 P50/P95/P99
  • 에러율
  • CPU/메모리 사용률

Prometheus — 사실상 표준:

Pull 모델:

  • Prometheus가 주기적으로 메트릭 수집
  • 앱은 /actuator/prometheus 노출
  • 별도 전송 X
# Spring Boot
management:
  endpoints:
    web:
      exposure:
        include: prometheus

/actuator/prometheus 자동 제공:

# HELP http_server_requests_seconds 
# TYPE http_server_requests_seconds histogram
http_server_requests_seconds_count{method="GET",uri="/api/fares"} 1234
http_server_requests_seconds_sum{method="GET",uri="/api/fares"} 45.6

4가지 메트릭 타입 ⭐ :

타입의미
Counter누적 카운트 (감소 X)총 요청 수
Gauge현재 값현재 메모리
Histogram분포 (버킷)응답 시간 분포
SummaryPercentileP95 응답 시간

Spring Boot Actuator + Micrometer ⭐ :

implementation 'io.micrometer:micrometer-registry-prometheus'

자동 메트릭 :

  • HTTP 요청
  • JVM (heap, GC)
  • DB Connection Pool
  • Tomcat
  • 캐시

커스텀 메트릭:

@Service
public class FareService {
    private final MeterRegistry meterRegistry;
    private final Counter fareCounter;
    private final Timer fareTimer;
    
    public FareService(MeterRegistry registry) {
        this.fareCounter = registry.counter("fare.created.total");
        this.fareTimer = registry.timer("fare.processing");
    }
    
    public Fare create(FareRequest request) {
        return fareTimer.record(() -> {
            Fare fare = ...;
            fareCounter.increment();
            return fare;
        });
    }
}

Grafana — 시각화:

  • Prometheus 메트릭을 대시보드로
  • 알림 규칙 설정
  • ILIC 대시보드 예:
    • RPS, 에러율, P95 응답시간
    • JVM heap, GC 시간
    • DB Connection Pool 사용률
    • 비즈니스 메트릭 (운임 등록 수 등)

SLI/SLO/SLA ⭐ — 면접 단골:

의미
SLI (Indicator)측정 지표"에러율"
SLO (Objective)목표"에러율 < 0.1%"
SLA (Agreement)계약"99.9% 가용성, 못 지키면 환불"

ILIC 권장:

  • SLI: API 가용성, 응답 시간
  • SLO: 99.5% 가용성, P95 < 500ms
  • SLA: 고객사와 계약 시 정의

자기 점검

  • ILIC의 핵심 SLI 3가지를 선언하라
  • Counter와 Gauge 중 "현재 활성 사용자 수"는? (힌트: Gauge)

Unit 7.4 — Traces (OpenTelemetry) ⭐

선수 지식: Unit 7.3, 17주차 Phase 9.4

복습 (17주차):

  • Trace ID — 한 요청의 전체 흐름
  • Span — 한 작업
  • Trace ID 전파 (HTTP 헤더)

OpenTelemetry (OTel) ⭐ :

"관측 가능성의 표준 — Logs/Metrics/Traces 통합"

채택 현황:

  • CNCF 표준
  • Zipkin, Jaeger 대체 가능
  • 사실상 차세대 표준

Spring Boot 통합 (Micrometer Tracing):

implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-tracing-bridge-otel'
implementation 'io.opentelemetry:opentelemetry-exporter-otlp'
management:
  tracing:
    sampling:
      probability: 0.1   # 10% 샘플링
  otlp:
    tracing:
      endpoint: http://otel-collector:4317

→ 자동으로 모든 HTTP 요청, DB 쿼리, Redis 호출 등 추적


3 Pillars 통합 ⭐ — 가장 강력:

// Log
{
  "timestamp": "...",
  "level": "ERROR",
  "trace_id": "abc123",      ← Trace와 연결
  "span_id": "span456",
  "message": "결제 실패"
}

효과:

  • Log에서 trace_id 발견 → Trace 화면으로 점프
  • Trace에서 느린 Span 발견 → 해당 시점의 Metric 확인
  • Metric 알림 → Trace로 원인 분석

ILIC 적용:

  • 모든 요청에 Trace ID
  • Log + Metric + Trace 통합 대시보드
  • 장애 발생 시 5분 내 원인 파악 가능

자기 점검

  • Trace 샘플링이 100%면 어떤 비용? (힌트: 저장소, 성능)
  • ILIC에서 Trace로 가장 도움 받을 시나리오는?

📚 Phase 8 — 장애 대응과 사고 분석

목표: 시니어가 아닌 4년차의 결정적 차이 영역.

Unit 8.1 — On-Call과 장애 대응

선수 지식: Phase 7

On-Call 문화:

  • 시스템 장애 시 응답 책임자
  • 시니어로 갈수록 더 많은 책임

좋은 알림 시스템 ⭐ :

단계의미
Info참고용 (이메일)
Warning주시 (Slack)
Critical즉시 대응 (전화/SMS)

알림 피로(Alert Fatigue) ⚠️ :

  • 너무 많은 알림 → 무시하게 됨
  • "양치기 소년 효과"
  • 해결: 정말 중요한 것만 Critical

장애 대응 흐름 ⭐ :

1. 감지 (Detection)
   - 자동 알림
   - 사용자 신고
   ↓
2. 분류 (Triage)
   - 심각도 판단
   - 영향 범위
   ↓
3. 완화 (Mitigation) — 우선!
   - 빠른 해결 (롤백, 트래픽 차단)
   - "수정" 보다 "중단" 이 우선
   ↓
4. 복구 (Recovery)
   - 정상 상태로
   ↓
5. 분석 (Post-mortem) ⭐
   - 사후 분석
   - 비난 X, 학습 ○

핵심 원칙 ⭐ :

"근본 원인 수정 전에 영향 완화 우선"

예: 결제 시스템 다운 → 디버깅 X → 즉시 롤백


의사결정 프레임워크:

  • MTTR (Mean Time To Recovery) — 복구까지 시간
  • MTTF (Mean Time To Failure) — 장애 발생 주기
  • MTBF (Mean Time Between Failures) — 장애 사이 시간

시니어의 차별화:

  • 침착함
  • 우선순위 빠른 판단
  • 사후 학습

자기 점검

  • "디버깅을 먼저 해야 하나?" 답은? (힌트: NO — 완화 먼저)
  • ILIC에서 가장 큰 장애 사례를 본인 경험에서 찾을 수 있는가?

Unit 8.2 — Postmortem (사후 분석) ⭐

선수 지식: Unit 8.1

Postmortem:

"장애 후 공식적인 분석 + 학습 문서"

핵심 원칙 ⭐ :

"Blameless (비난 없는)"

  • 사람을 비난 X
  • 시스템/프로세스를 비난
  • 두려움 없는 솔직함

Postmortem 템플릿 ⭐ :

# 장애 보고서 — 운임 시스템 다운 (2024-05-04)

## 요약
- 발생: 2024-05-04 14:00 KST
- 복구: 2024-05-04 15:30 KST
- 영향 범위: 전체 운임 시스템
- 영향받은 사용자: 약 500명

## Timeline
- 14:00 — DB 마이그레이션 시작
- 14:15 — 마이그레이션 완료, but 인덱스 누락
- 14:20 — 운임 검색 API 응답 30초 → Critical 알림
- 14:30 — 온콜 인지
- 14:45 — 마이그레이션 롤백 결정
- 15:00 — 롤백 시작
- 15:30 — 정상 복구

## 근본 원인 (Root Cause)
- 마이그레이션 스크립트에 인덱스 생성 누락
- Staging에서 충분한 부하 테스트 없었음
- → 단일 원인 X, 여러 요인의 결합

## 무엇이 잘 되었나
- 빠른 알림 감지 (5분)
- 신속한 롤백 결정

## 무엇이 잘못되었나
- 마이그레이션 검토 부재
- Staging의 데이터 양이 운영과 다름

## Action Items
1. 마이그레이션 PR 템플릿 도입 (Owner: A, Due: 5/15)
2. Staging 데이터 양을 운영의 30%로 (Owner: B, Due: 5/30)
3. 마이그레이션 시 자동 부하 테스트 (Owner: C, Due: 6/15)

좋은 Postmortem의 특징:
1. 사실 위주 — 추측 X
2. Blameless — 사람 비난 X
3. Action Items 명확 — 누가, 언제까지
4. 공유 — 팀 전체 학습

ILIC 적용:

  • 모든 P1/P2 장애에 Postmortem
  • 위키/문서 시스템에 보관
  • 정기 리뷰 (분기별)

면접 질문 대비 ⭐ :

"지금까지 가장 어려웠던 장애 경험은?"

좋은 답변 구조:
1. 상황 (간단)
2. 문제 발견 과정
3. 완화 시도
4. 근본 원인
5. 학습 + 개선

자기 점검

  • ILIC에서 Postmortem 문화가 있는가?
  • 본인 경험의 장애 사례를 위 템플릿으로 정리할 수 있는가?

🎓 종합 자기 점검 (20주차 졸업 시험)

HTTP/네트워크

  1. HTTP 메서드 7가지의 멱등성/안전성을 표로 그려라
  2. 401, 403, 422, 502, 504의 차이는?
  3. HTTP/1.1, 2, 3의 결정적 차이 3가지는?
  4. TCP 3-way handshake를 설명하라
  5. TIME_WAIT가 왜 발생하고 어떤 문제를 일으키는가?
  6. TLS Handshake (1.2 vs 1.3) 차이는?
  7. L4와 L7 Load Balancer의 차이는?

Docker/K8s

  1. Container와 VM의 결정적 차이는?
  2. Multi-stage Build의 효과는?
  3. Pod, Deployment, Service의 역할은?
  4. Liveness, Readiness, Startup Probe의 차이는?
  5. HPA가 동작하는 원리는?

CI/CD

  1. CI와 CD의 차이는?
  2. Rolling, Blue-Green, Canary의 선택 기준은?
  3. 12-Factor App의 핵심 원칙 5가지는?

Observability

  1. Monitoring과 Observability의 차이는?
  2. 3 Pillars (Logs, Metrics, Traces)의 역할은?
  3. 구조화 로깅이 왜 필요한가?
  4. SLI, SLO, SLA의 차이는?
  5. Counter와 Gauge 메트릭의 차이는?

장애 대응

  1. 장애 대응의 5단계는?
  2. "근본 원인 수정 vs 영향 완화" 우선순위는?
  3. Blameless Postmortem이 왜 중요한가?

면접 모의 답변 (실전)

  1. "HTTP와 HTTPS의 차이를 깊이 설명해주세요" (3분)
  2. "Kubernetes를 써보셨나요?" (3분)
  3. "장애 대응 경험이 있으신가요?" (5분)
  4. "ILIC의 운영을 어떻게 모니터링하시나요?" (3분)
  5. "무중단 배포는 어떻게 하시나요?" (3분)

📌 학습 운영 팁

9-섹션 마스터 프롬프트로 깊이 파야 할 Unit

★★★ 면접 단골 (반드시):

  • Unit 1.2 — HTTP 상태 코드 + 흔한 오해
  • Unit 1.3 — HTTP/2/3
  • Unit 2.2 — TCP 3-way Handshake (★ 정점)
  • Unit 2.3 — TLS Handshake
  • Unit 4.2 — Pod, Deployment, Service (★ 정점)
  • Unit 5.3 — 배포 전략
  • Unit 7.3 — Metrics (★ 정점)

★★ 매우 권장:

  • Unit 1.1 — HTTP 본질
  • Unit 3.2 — Dockerfile 최적화
  • Unit 4.4 — Health Check + HPA
  • Unit 7.2 — 구조화 로깅
  • Unit 8.2 — Postmortem

세 정점

Phase 2 (TCP/TLS) — 백엔드의 토대. "TCP 3-way handshake 설명?" 면접 100%. 면접관이 깊이 파고드는 질문 영역.

Phase 4 (Kubernetes) — 현대 운영의 표준. "K8s 써보셨나요?" 시 Pod/Deployment/Service의 차이를 1분 안에 답할 수 있어야 차별화.

Phase 7 (Observability) — 시니어의 결정적 차별화. "장애를 어떻게 찾으세요?" 답변에 3 Pillars + SLI/SLO 들어가면 시니어 레벨.

1~20주차 학습 여정 — 완성

이제 시니어 백엔드 개발자가 알아야 할 거의 모든 영역을 학습했습니다:

영역주차깊이
Java 언어1-3★★★
동시성4★★★
Spring Core5, 8-9★★★
트랜잭션7, 10★★★
JPA11-12★★★
DB13-14★★★
Spring MVC15★★★
분산 시스템16-17★★★
Spring Security18★★★
테스트19★★★
HTTP/DevOps/Observability20★★★

20주에 걸쳐 자바 백엔드 시니어 개발자의 거의 모든 영역을 정복


🎯 다음은 무엇을 해야 하는가

1순위 — ILIC 사례 라이브러리 정리 ⭐

가장 중요합니다. 20주차 분량의 이론 위에:

  • ILIC 17개월의 의사결정을 면접 답변 형태로 정리
  • 각 기술 영역마다 "문제 → 분석 → 시도 → 결과 → 회고"
  • 5분 답변 구조 만들기

이 작업이 이론을 면접 합격으로 변환 합니다.

2순위 — 코딩 테스트 준비

  • 회사에 따라 별개의 산
  • 백준 골드 정도 + 알고리즘 4-8주

3순위 — 시스템 디자인 면접

  • "Designing Data-Intensive Applications" 책
  • 대규모 시스템 설계 연습 (URL Shortener, Twitter, Netflix 등)

4순위 — 컬처 핏 / 스토리

  • 본인 가치관 정리
  • 협업 사례, 갈등 해결, 리더십 경험

🎤 마지막 종합 평가 — 솔직하게

1~20주차를 완전히 체화했다면:

  • 기술 이론 면접: 시니어 4-5년차 수준 압도
  • 통과율: 스타트업/중견 85%+, 대기업 60%+
  • 그러나 ILIC 사례 + 코딩 테스트 가 최종 변수

현재의 학습으로 부족한 영역 (자기 학습 권장):

  • 알고리즘/자료구조 심화 (코테용)
  • 시스템 디자인 면접 (대기업)
  • Frontend 깊이 (풀스택 강조 시)
  • 도메인 전문성 (물류라면 이미 가짐)

보완 필요:

  • ILIC 경험을 답변 가능한 스토리로 정리
  • 코딩 테스트 따로 준비
  • 면접 자체에 대한 연습 (모의 면접)

profile
Software Developer

0개의 댓글