마이크로서비스 패턴 (Microservices Patterns)

마이크로서비스 패턴 (Microservices Patterns)

난이도: ⭐⭐⭐⭐

개요

마이크로서비스 아키텍처를 성공적으로 운영하기 위해서는 다양한 패턴과 도구가 필요합니다. 이 장에서는 서비스 디스커버리, 서킷 브레이커, Bulkhead 패턴, 서비스 메시, 그리고 분산 추적에 대해 학습합니다.


목차

  1. 서비스 디스커버리
  2. 서킷 브레이커
  3. Bulkhead 패턴
  4. 서비스 메시
  5. 분산 추적
  6. 기타 중요 패턴
  7. 연습 문제

1. 서비스 디스커버리

왜 서비스 디스커버리가 필요한가?

┌─────────────────────────────────────────────────────────────────────────┐
│                     서비스 디스커버리의 필요성                          │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  전통적 방식 (하드코딩):                                                │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  Order Service                                                   │   │
│  │  config:                                                         │   │
│  │    user_service: http://10.0.1.5:8080                           │   │
│  │    product_service: http://10.0.1.10:8080                       │   │
│  │    payment_service: http://10.0.1.15:8080                       │   │
│  │                                                                  │   │
│  │  문제:                                                           │   │
│  │  - IP 변경 시 설정 수정 필요                                     │   │
│  │  - 스케일 아웃 시 수동 업데이트                                  │   │
│  │  - 장애 인스턴스 자동 제외 불가                                  │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  동적 환경에서의 문제:                                                  │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                  │   │
│  │  시간 0:  User Service @ 10.0.1.5                               │   │
│  │  시간 1:  스케일 아웃 → 10.0.1.5, 10.0.1.6, 10.0.1.7           │   │
│  │  시간 2:  10.0.1.5 장애 → 10.0.1.6, 10.0.1.7                    │   │
│  │  시간 3:  새 배포 → 10.0.1.8, 10.0.1.9                          │   │
│  │                                                                  │   │
│  │  → IP가 계속 변경! 어떻게 추적할 것인가?                        │   │
│  │                                                                  │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

클라이언트 사이드 디스커버리

┌─────────────────────────────────────────────────────────────────────────┐
│                     Client-Side Discovery                               │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│                                                                       │
│             ┌────────────────────────────────┐                       │
│                   Service Registry                                 │
│                (Eureka, Consul, etcd)                              │
│                                                                    │
│               user-service:                                        │
│                 - 10.0.1.5:8080                                   │
│                 - 10.0.1.6:8080                                   │
│                 - 10.0.1.7:8080                                   │
│                                                                    │
│             └─────────────┬──────────────────┘                       │
│                                                                      │
│      ┌─────1.Query────────┘                                          │
│          2.Return instances                                         │
│                                                                      │
│    ┌───────────────┐      3.Direct call      ┌───────────────┐       │
│     Order Service │─────────────────────────│ User Service         │
│      (Client)        (Load Balancing)       (10.0.1.5)           │
│      + LB Logic   │─────────────────────────│ (10.0.1.6)           │
│    └───────────────┘                          (10.0.1.7)           │
│                                              └───────────────┘       │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  동작 방식:                                                             │
│  1. 클라이언트가 Registry 서비스 인스턴스 조회                        │
│  2. 클라이언트가 로드밸런싱 수행 (Round Robin, Random )               │
│  3. 직접 인스턴스 호출                                                  │
│                                                                         │
│  예: Netflix Eureka + Ribbon                                           │
│                                                                         │
│  장점:                                                   단점:          │
│  - 단순한 인프라                                        - 클라이언트 복잡 │
│  - Registry 부하 분산                                   - 언어별 구현 필요│
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

서버 사이드 디스커버리

┌─────────────────────────────────────────────────────────────────────────┐
│                     Server-Side Discovery                               │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                  │   │
│  │           ┌────────────────────────────────┐                    │   │
│  │           │      Service Registry          │                    │   │
│  │           └─────────────┬──────────────────┘                    │   │
│  │                         │                                        │   │
│  │                         │ 인스턴스 정보 동기화                   │   │
│  │                         ▼                                        │   │
│  │  ┌───────────────┐  ┌───────────────────┐   ┌───────────────┐   │   │
│  │  │ Order Service │─►│   Load Balancer   │──►│ User Service  │   │   │
│  │  │  (Client)     │  │  / API Gateway    │   │ (10.0.1.5)    │   │   │
│  │  │  단순 호출    │  │                   │   │ (10.0.1.6)    │   │   │
│  │  └───────────────┘  │  - 라우팅         │   │ (10.0.1.7)    │   │   │
│  │                     │  - 로드밸런싱     │   └───────────────┘   │   │
│  │  GET /user-service  │  - 헬스체크       │                       │   │
│  │  /users/123         └───────────────────┘                       │   │
│  │                                                                  │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  동작 방식:                                                             │
│  1. 클라이언트는 LB/Gateway에 요청 (서비스 이름 사용)                   │
│  2. LB가 Registry에서 인스턴스 조회                                     │
│  3. LB가 로드밸런싱 후 인스턴스 호출                                    │
│                                                                         │
│  예: AWS ELB + Route 53, Kubernetes Service, Nginx + Consul            │
│                                                                         │
│  장점:                                        단점:                     │
│  - 클라이언트 단순화                          - LB가 SPOF              │
│  - 언어 독립적                                - 추가 홉 (지연)         │
│  - 중앙 집중 관리                             - LB 운영 비용           │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

서비스 등록

┌─────────────────────────────────────────────────────────────────────────┐
                     서비스 등록 패턴                                    
├─────────────────────────────────────────────────────────────────────────┤
                                                                         
  Self-Registration:                                                    
  ┌─────────────────────────────────────────────────────────────────┐   
    User Service                          Service Registry             
                                                                     
    시작 │─────── Register(ip, port) ─────────►│                      
                                                                     
    주기적│─────── Heartbeat ─────────────────►│                      
                                                                     
    종료 │─────── Deregister ─────────────────►│                      
                                                                     
    : Eureka Client, Consul Agent                                    
  └─────────────────────────────────────────────────────────────────┘   
                                                                         
  Third-Party Registration (Registrar):                                 
  ┌─────────────────────────────────────────────────────────────────┐   
                                                                       
    User Service        Registrar             Service Registry         
                                                                    
    시작                                                            
         │◄── 감지 ────────│                                          
                          │── Register ──────────►│                   
                                                                    
    종료 │◄── 감지 ────────│                                          
                          │── Deregister ────────►│                   
                                                                       
    : Netflix Prana, Kubernetes, Docker Swarm                       
  └─────────────────────────────────────────────────────────────────┘   
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

주요 도구 비교

도구 타입 특징
Consul CP 헬스체크, KV 스토어, DNS 인터페이스
Eureka AP Netflix OSS, Spring Cloud 통합
etcd CP Raft 합의, Kubernetes 기반
ZooKeeper CP 분산 조정, 복잡한 API
Kubernetes - Service + DNS 내장, 클라우드 네이티브

2. 서킷 브레이커

서킷 브레이커 패턴

┌─────────────────────────────────────────────────────────────────────────┐
                     서킷 브레이커 패턴                                  
├─────────────────────────────────────────────────────────────────────────┤
                                                                         
  문제: Cascading Failure (연쇄 장애)                                    
  ┌─────────────────────────────────────────────────────────────────┐   
                                                                       
    Order Service  Payment Service  Bank API                        
                                       (장애)                      
                                                                    
                  타임아웃 대기...                                    
                  스레드 고갈                                         
                                                                    
                                                                     
    타임아웃 대기...                                                   
    스레드 고갈                                                        
                                                                     
                                                                       
     하나의 장애가 전체 시스템으로 전파!                             
  └─────────────────────────────────────────────────────────────────┘   
                                                                         
  해결: 서킷 브레이커 (전기 차단기처럼 동작)                             
  ┌─────────────────────────────────────────────────────────────────┐   
                                                                       
    Order Service  [CB]  Payment Service  [CB]  Bank API          
                            ┌─────────┐         (장애)               
                             Circuit                                 
                             OPEN     ──► 즉시 실패 반환            
                            └─────────┘                                
                                                                       
     빠른 실패로 자원 보호                                           
     장애 격리                                                        
  └─────────────────────────────────────────────────────────────────┘   
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

상태 전이

┌─────────────────────────────────────────────────────────────────────────┐
│                     서킷 브레이커 상태 전이                             │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│                        실패율 임계값 초과                               │
│                    ┌────────────────────────┐                          │
│                    │                        │                          │
│                    ▼                        │                          │
│  ┌──────────────────────┐            ┌──────┴───────────────┐          │
│  │                      │            │                      │          │
│  │       CLOSED         │───────────►│        OPEN          │          │
│  │                      │            │                      │          │
│  │  - 정상 동작         │            │  - 요청 차단         │          │
│  │  - 모든 요청 허용    │            │  - 즉시 실패 반환    │          │
│  │  - 실패율 모니터링   │            │  - 폴백 실행         │          │
│  │                      │            │                      │          │
│  └──────────────────────┘            └──────────┬───────────┘          │
│           ▲                                     │                      │
│           │                                     │ 타임아웃 후          │
│           │                                     ▼                      │
│           │                          ┌──────────────────────┐          │
│           │                          │                      │          │
│           └──────────────────────────│     HALF-OPEN        │          │
│                    성공              │                      │          │
│                                      │  - 제한된 요청 허용  │          │
│                    실패              │  - 상태 확인 중      │          │
│                    ┌─────────────────│                      │          │
│                    │                 └──────────────────────┘          │
│                    │                            │                      │
│                    └────────────────────────────┘                      │
│                                                                         │
│  ─────────────────────────────────────────────────────────────────      │
│                                                                         │
│  타임라인 예시:                                                         │
│                                                                         │
│  CLOSED ────────────────────────────► OPEN ──────► HALF-OPEN           │
│  │                                    │              │                  │
│  │ ✓ ✓ ✓ ✗ ✗ ✗ ✗ ✗                   │              │ ✓               │
│  │ 실패율 50% 초과                   │              │ 성공!            │
│  │                                   │ 대기 10초    │                  │
│  │                                   │              ▼                  │
│  │                                   │          CLOSED ───────►        │
│  │                                                                      │
└─────────────────────────────────────────────────────────────────────────┘

주요 설정 파라미터

┌─────────────────────────────────────────────────────────────────────────┐
│                     서킷 브레이커 설정                                  │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  CircuitBreaker:                                                       │
│    failureRateThreshold: 50        # 실패율 임계값 (%)                 │
│    slowCallRateThreshold: 100      # 느린 호출 비율 임계값 (%)         │
│    slowCallDurationThreshold: 2s   # 느린 호출 기준 시간               │
│    minimumNumberOfCalls: 10        # 최소 호출 수 (통계 계산용)        │
│    slidingWindowSize: 100          # 슬라이딩 윈도우 크기              │
│    slidingWindowType: COUNT_BASED  # COUNT or TIME_BASED               │
│    waitDurationInOpenState: 10s    # OPEN 유지 시간                    │
│    permittedNumberOfCallsInHalfOpen: 3  # HALF-OPEN에서 허용 호출 수   │
│                                                                         │
│  ─────────────────────────────────────────────────────────────────      │
│                                                                         │
│  슬라이딩 윈도우:                                                       │
│                                                                         │
│  COUNT_BASED (최근 N개 요청 기준):                                      │
│  ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐                           │
│  │ ✓ │ ✓ │ ✗ │ ✓ │ ✗ │ ✗ │ ✓ │ ✗ │ ✗ │ ✗ │ → 실패율 60%              │
│  └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘                           │
│  ◄────────────── 최근 10개 ─────────────►                              │
│                                                                         │
│  TIME_BASED (최근 N초 기준):                                            │
│  ┌───────────────────────────────────────┐                             │
│  │  ✓ ✓ ✗   ✓ ✗ ✗   ✓ ✗ ✗ ✗             │ → 실패율 60%              │
│  └───────────────────────────────────────┘                             │
│  ◄────────────── 최근 10초 ─────────────►                              │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

폴백 전략

┌─────────────────────────────────────────────────────────────────────────┐
│                     폴백 (Fallback) 전략                                │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  1. 기본값 반환                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  def get_user_profile(user_id):                                 │   │
│  │      try:                                                       │   │
│  │          return user_service.get(user_id)                       │   │
│  │      except CircuitOpenException:                               │   │
│  │          return {"name": "Guest", "avatar": "default.png"}     │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  2. 캐시된 데이터 반환                                                  │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  def get_product_price(product_id):                             │   │
│  │      try:                                                       │   │
│  │          price = price_service.get(product_id)                  │   │
│  │          cache.set(product_id, price)                           │   │
│  │          return price                                           │   │
│  │      except CircuitOpenException:                               │   │
│  │          return cache.get(product_id)  # 마지막 캐시값          │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  3. 대체 서비스 호출                                                    │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  def send_notification(user_id, message):                       │   │
│  │      try:                                                       │   │
│  │          return push_service.send(user_id, message)             │   │
│  │      except CircuitOpenException:                               │   │
│  │          return email_service.send(user_id, message)  # 대체    │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  4. 큐에 저장 후 나중에 처리                                            │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  def process_order(order):                                      │   │
│  │      try:                                                       │   │
│  │          return order_service.process(order)                    │   │
│  │      except CircuitOpenException:                               │   │
│  │          retry_queue.enqueue(order)  # 나중에 재시도            │   │
│  │          return {"status": "pending"}                           │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

구현 도구

도구 언어 특징
Resilience4j Java 경량, 함수형, 모듈러
Hystrix Java Netflix OSS (유지보수 모드)
Polly .NET 풍부한 기능, 정책 조합
go-kit Go 미들웨어 기반
opossum Node.js Promise 지원

3. Bulkhead 패턴

Bulkhead 개념

┌─────────────────────────────────────────────────────────────────────────┐
                     Bulkhead (격벽) 패턴                                
├─────────────────────────────────────────────────────────────────────────┤
                                                                         
  선박의 격벽 (Bulkhead):                                                
  ┌─────────────────────────────────────────────────────────────────┐   
    ┌─────┬─────┬─────┬─────┬─────┐                                  
               침수              격벽으로 분리                
      A    B    C    D    E                                    
              ~~~~~              C 구역 침수해도              
    └─────┴─────┴─────┴─────┴─────┘     다른 구역은 안전!           
  └─────────────────────────────────────────────────────────────────┘   
                                                                         
  소프트웨어 적용:                                                       
  ┌─────────────────────────────────────────────────────────────────┐   
                                                                       
    격벽 없음 (공유 리소스):                                           
    ┌────────────────────────────────────────────────────────┐        
                  Thread Pool (10 threads)                          
      [Payment][Payment][Payment][Payment][Payment]...             
      모든 스레드가 느린 Payment 호출에 점유됨                       
       Order, User 서비스 호출도 불가!                             
    └────────────────────────────────────────────────────────┘        
                                                                       
    격벽 적용 (분리된 리소스):                                         
    ┌──────────────┐ ┌──────────────┐ ┌──────────────┐                
     Payment Pool    Order Pool     User Pool                   
      (5 threads)   (3 threads)    (2 threads)                  
      [P][P][P]        [O][O]          [U]                      
    └──────────────┘ └──────────────┘ └──────────────┘                
    Payment 지연되어도 Order, User는 정상 동작!                        
                                                                       
  └─────────────────────────────────────────────────────────────────┘   
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

Bulkhead 유형

┌─────────────────────────────────────────────────────────────────────────┐
│                     Bulkhead 구현 방식                                  │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  1. Thread Pool Bulkhead                                               │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                  │   │
│  │  ┌────────────────────────────────────────────────────────────┐ │   │
│  │  │  Service A Thread Pool                                     │ │   │
│  │  │  maxThreads: 10                                            │ │   │
│  │  │  queueCapacity: 100                                        │ │   │
│  │  │  ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐               │ │   │
│  │  │  │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │10 │               │ │   │
│  │  │  └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘               │ │   │
│  │  └────────────────────────────────────────────────────────────┘ │   │
│  │                                                                  │   │
│  │  장점: 완전한 격리, 타임아웃 제어 용이                           │   │
│  │  단점: 오버헤드 (컨텍스트 스위칭)                                │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  2. Semaphore Bulkhead                                                 │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                  │   │
│  │  ┌────────────────────────────────────────────────────────────┐ │   │
│  │  │  Service A Semaphore                                       │ │   │
│  │  │  permits: 10  (현재 사용: 7, 대기: 0)                      │ │   │
│  │  │                                                            │ │   │
│  │  │  Request → acquire() → Call → release()                   │ │   │
│  │  │                                                            │ │   │
│  │  │  permits 초과 시 → 즉시 거부 또는 대기                     │ │   │
│  │  └────────────────────────────────────────────────────────────┘ │   │
│  │                                                                  │   │
│  │  장점: 가벼움, 호출 스레드에서 실행                              │   │
│  │  단점: 타임아웃 제어 어려움                                      │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  ─────────────────────────────────────────────────────────────────      │
│                                                                         │
│  3. 프로세스 수준 격리 (컨테이너)                                       │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                  │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐              │   │
│  │  │  Container  │  │  Container  │  │  Container  │              │   │
│  │  │  Payment    │  │   Order     │  │    User     │              │   │
│  │  │  API calls  │  │  API calls  │  │  API calls  │              │   │
│  │  │  CPU: 2     │  │  CPU: 1     │  │  CPU: 1     │              │   │
│  │  │  Mem: 4GB   │  │  Mem: 2GB   │  │  Mem: 2GB   │              │   │
│  │  └─────────────┘  └─────────────┘  └─────────────┘              │   │
│  │                                                                  │   │
│  │  가장 강력한 격리, Kubernetes Pod 리소스 제한                    │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

4. 서비스 메시

서비스 메시 개념

┌─────────────────────────────────────────────────────────────────────────┐
│                     서비스 메시 (Service Mesh)                          │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  문제: 서비스별로 횡단 관심사 구현 필요                                 │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                  │   │
│  │  각 서비스에서 직접 구현:                                        │   │
│  │  - 서비스 디스커버리                                             │   │
│  │  - 로드밸런싱                                                    │   │
│  │  - 서킷 브레이커                                                 │   │
│  │  - 재시도/타임아웃                                               │   │
│  │  - TLS/인증                                                      │   │
│  │  - 메트릭/추적                                                   │   │
│  │                                                                  │   │
│  │  → 언어/프레임워크마다 다른 구현                                 │   │
│  │  → 일관성 유지 어려움                                            │   │
│  │  → 개발자 부담 증가                                              │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  해결: 인프라 레이어로 분리 (Service Mesh)                              │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                  │   │
│  │  네트워크 프록시가 모든 횡단 관심사 처리                         │   │
│  │                                                                  │   │
│  │  ┌───────────────────────────────────────────────────────────┐  │   │
│  │  │                     Control Plane                          │  │   │
│  │  │  (설정, 정책, 인증서 관리)                                 │  │   │
│  │  └───────────────────────────────────────────────────────────┘  │   │
│  │                           ▲ ▲ ▲                                 │   │
│  │                           │ │ │                                 │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐             │   │
│  │  │   Service   │  │   Service   │  │   Service   │             │   │
│  │  │   ┌─────┐   │  │   ┌─────┐   │  │   ┌─────┐   │             │   │
│  │  │   │Proxy│◄──┼──┼──►│Proxy│◄──┼──┼──►│Proxy│   │             │   │
│  │  │   └─────┘   │  │   └─────┘   │  │   └─────┘   │             │   │
│  │  │     ▲       │  │     ▲       │  │     ▲       │             │   │
│  │  │     │       │  │     │       │  │     │       │             │   │
│  │  │   ┌─┴─┐     │  │   ┌─┴─┐     │  │   ┌─┴─┐     │             │   │
│  │  │   │App│     │  │   │App│     │  │   │App│     │             │   │
│  │  │   └───┘     │  │   └───┘     │  │   └───┘     │             │   │
│  │  └─────────────┘  └─────────────┘  └─────────────┘             │   │
│  │                                                                  │   │
│  │  App은 비즈니스 로직에만 집중!                                   │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

사이드카 패턴

┌─────────────────────────────────────────────────────────────────────────┐
│                     사이드카 (Sidecar) 패턴                             │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  Pod (Kubernetes)                                                │   │
│  │  ┌─────────────────────────────────────────────────────────────┐ │   │
│  │  │                                                             │ │   │
│  │  │  ┌─────────────────────┐   ┌─────────────────────┐         │ │   │
│  │  │  │    Application      │   │      Sidecar        │         │ │   │
│  │  │  │    Container        │   │      Proxy          │         │ │   │
│  │  │  │                     │   │    (Envoy)          │         │ │   │
│  │  │  │  ┌───────────────┐  │   │  ┌───────────────┐  │         │ │   │
│  │  │  │  │  App Process  │◄─┼───┼─►│ Proxy Process │◄─┼─── 외부 │ │   │
│  │  │  │  │               │  │   │  │               │  │  트래픽 │ │   │
│  │  │  │  │  Port 8080    │  │   │  │  Port 15001   │  │         │ │   │
│  │  │  │  └───────────────┘  │   │  └───────────────┘  │         │ │   │
│  │  │  │                     │   │                     │         │ │   │
│  │  │  └─────────────────────┘   └─────────────────────┘         │ │   │
│  │  │                                                             │ │   │
│  │  │  공유: Network Namespace, Volume                            │ │   │
│  │  └─────────────────────────────────────────────────────────────┘ │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  사이드카가 처리하는 기능:                                              │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  Inbound Traffic:                 Outbound Traffic:             │   │
│  │  - TLS 종료                       - 서비스 디스커버리           │   │
│  │  - 인증/인가                      - 로드밸런싱                  │   │
│  │  - 레이트 리미팅                  - 서킷 브레이커               │   │
│  │  - 메트릭 수집                    - 재시도/타임아웃             │   │
│  │                                   - mTLS                        │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Istio 아키텍처

┌─────────────────────────────────────────────────────────────────────────┐
│                     Istio 아키텍처                                      │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌───────────────────────────────────────────────────────────────────┐ │
│  │                       Control Plane (istiod)                       │ │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                │ │
│  │  │   Pilot     │  │   Citadel   │  │   Galley    │                │ │
│  │  │ (설정 배포) │  │ (인증서)    │  │ (설정 검증) │                │ │
│  │  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘                │ │
│  │         └────────────────┼────────────────┘                        │ │
│  │                          │                                         │ │
│  │                          │ xDS API (설정 푸시)                     │ │
│  │                          ▼                                         │ │
│  └───────────────────────────────────────────────────────────────────┘ │
│                                                                         │
│  ┌───────────────────────────────────────────────────────────────────┐ │
│  │                        Data Plane                                  │ │
│  │                                                                    │ │
│  │  ┌─────────────────┐           ┌─────────────────┐                │ │
│  │  │  Service A      │           │  Service B      │                │ │
│  │  │  ┌───────────┐  │           │  ┌───────────┐  │                │ │
│  │  │  │  Envoy    │◄─┼───────────┼─►│  Envoy    │  │                │ │
│  │  │  │  Proxy    │  │   mTLS    │  │  Proxy    │  │                │ │
│  │  │  └─────┬─────┘  │           │  └─────┬─────┘  │                │ │
│  │  │        │        │           │        │        │                │ │
│  │  │  ┌─────┴─────┐  │           │  ┌─────┴─────┐  │                │ │
│  │  │  │    App    │  │           │  │    App    │  │                │ │
│  │  │  └───────────┘  │           │  └───────────┘  │                │ │
│  │  └─────────────────┘           └─────────────────┘                │ │
│  │                                                                    │ │
│  └───────────────────────────────────────────────────────────────────┘ │
│                                                                         │
│  주요 기능:                                                             │
│  - Traffic Management: 라우팅, 카나리 배포, A/B 테스트                  │
│  - Security: mTLS, RBAC                                                │
│  - Observability: 메트릭, 로그, 분산 추적                               │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

서비스 메시 도구 비교

도구 프록시 특징
Istio Envoy 풍부한 기능, 복잡도 높음
Linkerd linkerd2-proxy 경량, Rust 기반, 단순함
Consul Connect Envoy/내장 HashiCorp 생태계 통합
AWS App Mesh Envoy AWS 서비스 통합

5. 분산 추적

분산 추적의 필요성

┌─────────────────────────────────────────────────────────────────────────┐
│                     분산 추적 (Distributed Tracing)                     │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  문제: 마이크로서비스에서 요청 추적                                     │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                  │   │
│  │  Client → API GW → Order → Inventory → Payment → Shipping       │   │
│  │                           ↓                                      │   │
│  │                      User Service                                │   │
│  │                                                                  │   │
│  │  "주문 API가 느린데, 어디서 지연이 발생하지?"                    │   │
│  │  "에러가 발생했는데, 어느 서비스에서 시작된 거지?"               │   │
│  │                                                                  │   │
│  │  로그를 봐도:                                                    │   │
│  │  - 각 서비스 로그가 분산되어 있음                                │   │
│  │  - 어떤 로그가 같은 요청인지 알 수 없음                          │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  해결: Trace ID로 전체 요청 추적                                        │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                  │   │
│  │  Trace ID: abc123                                               │   │
│  │  ┌──────────────────────────────────────────────────────────┐   │   │
│  │  │ API GW    [──────────────────────────────────────────]    │   │   │
│  │  │ Order     │    [─────────────────────────────────]        │   │   │
│  │  │ Inventory │         [────────────────]                    │   │   │
│  │  │ Payment   │                          [──────────]         │   │   │
│  │  │ User      │    [────]                                     │   │   │
│  │  │           0ms  100ms  200ms  300ms  400ms  500ms         │   │   │
│  │  └──────────────────────────────────────────────────────────┘   │   │
│  │                                                                  │   │
│  │  → 한눈에 전체 흐름과 병목 지점 파악!                           │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Trace, Span, Context

┌─────────────────────────────────────────────────────────────────────────┐
│                     추적 구성 요소                                      │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  Trace: 전체 요청의 여정                                               │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  Trace ID: abc-123-def-456                                      │   │
│  │                                                                  │   │
│  │  Span: 하나의 작업 단위                                          │   │
│  │  ┌────────────────────────────────────────────────────────────┐ │   │
│  │  │  Span A (Root Span)                                        │ │   │
│  │  │  service: api-gateway                                      │ │   │
│  │  │  operation: handle_request                                 │ │   │
│  │  │  ┌──────────────────────────────────────────────────────┐  │ │   │
│  │  │  │  Span B (Child of A)                                  │  │ │   │
│  │  │  │  service: order-service                               │  │ │   │
│  │  │  │  operation: create_order                              │  │ │   │
│  │  │  │  ┌────────────────────────┐ ┌────────────────────┐   │  │ │   │
│  │  │  │  │ Span C (Child of B)    │ │ Span D (Child of B)│   │  │ │   │
│  │  │  │  │ service: inventory     │ │ service: user      │   │  │ │   │
│  │  │  │  │ operation: reserve     │ │ operation: get     │   │  │ │   │
│  │  │  │  └────────────────────────┘ └────────────────────┘   │  │ │   │
│  │  │  └──────────────────────────────────────────────────────┘  │ │   │
│  │  └────────────────────────────────────────────────────────────┘ │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  Span 구조:                                                             │
│  {                                                                      │
│    "traceId": "abc-123-def-456",                                       │
│    "spanId": "span-789",                                               │
│    "parentSpanId": "span-456",                                         │
│    "operationName": "create_order",                                    │
│    "serviceName": "order-service",                                     │
│    "startTime": "2024-01-15T10:30:00.000Z",                           │
│    "duration": 150,  // ms                                             │
│    "tags": { "http.status": 200, "user.id": "123" },                  │
│    "logs": [ { "event": "order_created", "orderId": "ord-999" } ]     │
│  }                                                                      │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Context Propagation

┌─────────────────────────────────────────────────────────────────────────┐
│                     Context 전파                                        │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  HTTP 헤더를 통한 전파:                                                 │
│                                                                         │
│  Order Service                           Inventory Service              │
│       │                                        │                        │
│       │  POST /inventory/reserve               │                        │
│       │  Headers:                              │                        │
│       │    X-B3-TraceId: abc123               │                        │
│       │    X-B3-SpanId: span456               │                        │
│       │    X-B3-ParentSpanId: span123         │                        │
│       │    X-B3-Sampled: 1                    │                        │
│       │───────────────────────────────────────►│                        │
│       │                                        │                        │
│       │                                        │ 새 Span 생성:          │
│       │                                        │ spanId: span789       │
│       │                                        │ parentSpanId: span456 │
│       │                                        │ traceId: abc123       │
│       │                                        │                        │
│                                                                         │
│  표준:                                                                  │
│  - B3 Propagation (Zipkin)                                             │
│  - W3C Trace Context (표준)                                            │
│  - Jaeger Propagation                                                  │
│                                                                         │
│  W3C Trace Context:                                                    │
│  traceparent: 00-abc123def456-span789-01                               │
│  tracestate: vendor=custom_value                                       │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

추적 도구

┌─────────────────────────────────────────────────────────────────────────┐
│                     분산 추적 도구                                      │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  Jaeger:                                                               │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  - CNCF 프로젝트                                                 │   │
│  │  - Uber에서 개발                                                 │   │
│  │  - Cassandra, Elasticsearch 백엔드                               │   │
│  │  - 강력한 UI                                                     │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  Zipkin:                                                               │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  - Twitter에서 개발                                              │   │
│  │  - 다양한 스토리지 지원                                          │   │
│  │  - 가벼움, 설치 쉬움                                             │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  OpenTelemetry (OTel):                                                 │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  - 표준화된 관측성 프레임워크                                    │   │
│  │  - Traces + Metrics + Logs 통합                                 │   │
│  │  - 벤더 중립적                                                   │   │
│  │  - Jaeger, Zipkin 등으로 내보내기                                │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  상용:                                                                  │
│  - Datadog APM                                                         │
│  - New Relic                                                           │
│  - AWS X-Ray                                                           │
│  - Google Cloud Trace                                                  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

6. 기타 중요 패턴

API Gateway

┌─────────────────────────────────────────────────────────────────────────┐
│                     API Gateway 패턴                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                                                                  │   │
│  │   Clients                    API Gateway                        │   │
│  │  ┌──────┐                   ┌─────────────────┐                 │   │
│  │  │ Web  │──────────────────►│                 │                 │   │
│  │  └──────┘                   │  - 라우팅        │    ┌─────────┐ │   │
│  │  ┌──────┐                   │  - 인증/인가    │───►│ User Svc│ │   │
│  │  │Mobile│──────────────────►│  - 레이트리밋   │    └─────────┘ │   │
│  │  └──────┘                   │  - 캐싱         │    ┌─────────┐ │   │
│  │  ┌──────┐                   │  - 요청 변환    │───►│Order Svc│ │   │
│  │  │ IoT  │──────────────────►│  - 로깅/메트릭  │    └─────────┘ │   │
│  │  └──────┘                   │  - SSL 종료     │    ┌─────────┐ │   │
│  │                             │                 │───►│Prod Svc │ │   │
│  │                             └─────────────────┘    └─────────┘ │   │
│  │                                                                  │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  도구: Kong, AWS API Gateway, Nginx, Envoy, Spring Cloud Gateway       │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Retry Pattern

┌─────────────────────────────────────────────────────────────────────────┐
│                     Retry 전략                                          │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  Exponential Backoff with Jitter:                                      │
│                                                                         │
│  시도 1:  ──X (실패)                                                    │
│           대기: 100ms + random(0-50ms)                                  │
│  시도 2:  ────X (실패)                                                  │
│           대기: 200ms + random(0-100ms)                                 │
│  시도 3:  ──────X (실패)                                                │
│           대기: 400ms + random(0-200ms)                                 │
│  시도 4:  ────────✓ (성공)                                              │
│                                                                         │
│  config:                                                                │
│    maxRetries: 5                                                       │
│    initialDelay: 100ms                                                 │
│    maxDelay: 10s                                                       │
│    multiplier: 2                                                       │
│    jitter: 0.5  # 50% 랜덤                                             │
│    retryableExceptions:                                                │
│      - ConnectionException                                             │
│      - TimeoutException                                                │
│      # 4xx 에러는 재시도 안함!                                          │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Health Check Pattern

┌─────────────────────────────────────────────────────────────────────────┐
│                     Health Check                                        │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  Liveness Probe (살아있는가?):                                          │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  GET /health/live                                               │   │
│  │                                                                  │   │
│  │  200 OK → 프로세스 정상                                          │   │
│  │  5xx   → 프로세스 재시작 필요                                    │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
│  Readiness Probe (요청 처리 가능한가?):                                 │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │  GET /health/ready                                              │   │
│  │                                                                  │   │
│  │  체크 항목:                                                       │   │
│  │  - DB 연결                                                       │   │
│  │  - 캐시 연결                                                     │   │
│  │  - 의존 서비스                                                   │   │
│  │  - 초기화 완료                                                   │   │
│  │                                                                  │   │
│  │  200 OK → 트래픽 라우팅                                          │   │
│  │  503    → 트래픽 제외 (재시작 안함)                              │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

7. 연습 문제

연습 1: 서킷 브레이커 설계

결제 서비스에 대한 서킷 브레이커를 설계하세요: - 적절한 임계값 설정 - 폴백 전략 정의 - 상태 전이 시나리오 작성

연습 2: 서비스 메시 선택

다음 요구사항에 적합한 서비스 메시를 선택하고 이유를 설명하세요: - 10개의 마이크로서비스 - Kubernetes 환경 - mTLS 필수 - 카나리 배포 필요 - 팀의 Kubernetes 경험은 중급

연습 3: 분산 추적 구현

주문 처리 시스템의 분산 추적을 설계하세요: - 추적해야 할 주요 스팬 정의 - 중요한 태그/메타데이터 정의 - 샘플링 전략 수립


다음 단계

15_Distributed_Systems_Concepts.md에서 분산 시스템의 기본 개념과 시간, 리더 선출 알고리즘을 배워봅시다!


참고 자료

  • "Release It!" - Michael Nygard
  • "Building Microservices" - Sam Newman
  • Istio Documentation
  • Envoy Proxy Documentation
  • OpenTelemetry Documentation
  • Netflix Tech Blog: Hystrix
  • Resilience4j Documentation
to navigate between lessons