Tan Kim

microservices

Microservices Architecture

큰 애플리케이션을 여러 개의 독립적이고 작은 서비스들로 분리하는 아키텍처입니다.

기본 개념

┌──────────────┐    ┌──────────────┐    ┌──────────────┐
│ User Service │    │ Order Service│    │ Payment      │
│  - Users DB  │    │  - Orders DB │    │ Service      │
│  - Auth      │    │  - Items     │    │  - Payments  │
└──────────────┘    └──────────────┘    │  - Wallets   │
       │                   │             └──────────────┘
       └───────────────────┴──────────────────┘
                API Gateway / Service Mesh

핵심 특징

특징 설명
독립성 각 서비스는 별도의 코드베이스, 데이터베이스, 배포 프로세스
자율성 팀이 독립적으로 개발, 배포 가능
확장성 필요한 서비스만 확장 (예: Order Service를 10개 인스턴스 실행)
느슨한 결합 HTTP/REST, gRPC, 메시지 브로커로 통신
기술 다양성 각 서비스가 다른 언어, 프레임워크 사용 가능

서비스 간 통신 방식

동기식 (Synchronous)

Service A → HTTP/REST → Service B
Service A → gRPC → Service C

장점: 간단함, 즉시 응답 단점: 강한 결합, 한 서비스 장애 시 연쇄 장애

비동기식 (Asynchronous)

Service A → Message Broker (Kafka, RabbitMQ) → Service B

장점: 느슨한 결합, 장애 격리 단점: 구현 복잡, 디버깅 어려움

예제 구조

Order Service (포트 8081)
├── src/
│   ├── controller/
│   │   └── OrderController.java
│   ├── service/
│   │   └── OrderService.java
│   ├── repository/
│   │   └── OrderRepository.java
│   └── entity/
│       └── Order.java
└── Dockerfile

User Service (포트 8082)
├── src/
│   ├── controller/
│   │   └── UserController.java
│   ├── service/
│   │   └── UserService.java
│   └── ...
└── Dockerfile

API Gateway (포트 8000)
├── routes/
│   ├── /users → User Service
│   ├── /orders → Order Service

마이크로서비스의 도전과제

기술적 문제

  • 분산 시스템의 복잡성 (네트워크 장애, 타이밍 이슈)
  • 트랜잭션 관리 어려움 (분산 트랜잭션)
  • 데이터 일관성 문제 (Eventual Consistency)
  • 로깅 및 모니터링 복잡도 증가

조직적 문제

  • 팀 규모 증가 필요
  • 운영 비용 증가
  • 서비스 간 의존성 관리

특징 정리

장점:

  • 높은 확장성 (필요한 부분만 확장)
  • 빠른 배포 (전체 재배포 불필요)
  • 기술 독립성 (다양한 스택 사용)
  • 팀 자율성 증가
  • 장애 격리 (한 서비스 장애가 전체 영향 최소)

단점:

  • 운영 복잡도 증가
  • 네트워크 지연 발생
  • 데이터 관리 복잡 (분산 데이터베이스)
  • 테스트 어려움 (통합 테스트)
  • 모니터링/로깅 복잡

언제 사용할까?

적합한 경우:

  • 대규모 애플리케이션 (Netflix, Amazon 수준)
  • 팀이 크거나 여러 팀이 함께 개발
  • 서로 다른 속도로 개발/배포되는 기능들
  • 높은 가용성과 장애 격리가 중요
  • 독립적인 확장이 필요한 서비스

부적합한 경우:

  • 스타트업 또는 소규모 팀
  • 간단한 애플리케이션
  • 운영 리소스가 부족할 때

도입 단계

  1. 모놀리식 → 패키지/계층 분리 (Modular Monolith)
  2. 로컬에서 독립 실행 가능하게 (IDE에서 여러 프로세스 실행)
  3. 별도 포트에서 실행 (localhost:8081, localhost:8082)
  4. Docker 컨테이너화
  5. 오케스트레이션 도입 (Kubernetes)
  6. 서비스 메시 도입 (Istio, Linkerd)