전체 목록
설계Hard#100

마이크로서비스 아키텍처(MSA)와 모놀리식(Monolithic) 아키텍처의 장단점을 비교해주세요.

#설계#MSA#아키텍처#마이크로서비스

답변 포인트

확장성, 배포 독립성, 운영 복잡도를 기준으로 생각해보세요.

정답 및 해설

빠른 요약

모놀리식(Monolithic): 장점: 개발/배포 단순, 서비스 간 통신 오버헤드 없음, 트랜잭션 처리 용이 단점: 규모 커질수록 유지보수 어려움, 부분 장애가 전체에 영향, 기술 스택 통일 필요 MSA(Microservices Architecture): 장점: - 서비스별 독립 배포/확장 가능 - 기술 스택 자유 선택 - 장애 격리 (한 서비스 장애가 전체 영향 최소화) 단점: - 서비스 간 네트워크 통신 복잡 - 분산 트랜잭션 처리 어려움 - 운영 인프라(서비스 디스커버리, API 게이트웨이 등) 복잡도 증가 권장: 초기에는 모놀리식으로 시작 후, 서비스가 성장하면 분리 고려

모놀리식(Monolithic) 아키텍처는 애플리케이션의 모든 기능을 하나의 코드베이스와 하나의 배포 단위로 구성하는 방식이고, 마이크로서비스 아키텍처(MSA)는 각 기능을 독립적으로 배포 가능한 작은 서비스들의 집합으로 구성하는 방식입니다. 어느 것이 더 좋다고 할 수 없으며, 팀의 규모, 서비스의 복잡성, 성장 단계에 따라 적합한 아키텍처가 다릅니다.

모놀리식 아키텍처

구조

설계

                                   
                                                      
        
                                
                                  
        
                                                      
        
                                   
                                  
        
                                                      
                                 
                                      
                                 

모놀리식 코드 예시

설계
 :
my-ecommerce/
 src/
    users/
       user.controller.ts
       user.service.ts
       user.repository.ts
    orders/
       order.controller.ts
       order.service.ts
       order.repository.ts
    payments/
       payment.service.ts
    products/
        product.service.ts
 package.json           
 docker-compose.yml     
TypeScript
// 모놀리식에서 서비스 간 호출 (직접 함수 호출)
// order.service.ts
class OrderService {
  constructor(
    private userService: UserService,    // 직접 의존성 주입
    private productService: ProductService,
    private paymentService: PaymentService,
    private notificationService: NotificationService,
  ) {}

  async createOrder(userId: number, items: OrderItem[]): Promise<Order> {
    // 트랜잭션 내에서 모든 작업 처리
    return await this.db.transaction(async (trx) => {
      const user = await this.userService.findById(userId);  // 직접 호출
      const products = await this.productService.findByIds(items.map(i => i.productId));

      // 재고 확인 및 차감
      await this.productService.decreaseStock(items, trx);  // 같은 트랜잭션 공유!

      const order = await this.orderRepository.create({ userId, items }, trx);

      // 결제 처리
      await this.paymentService.process(order, trx);

      // 알림 전송 (같은 프로세스에서 실행)
      await this.notificationService.sendOrderConfirmation(user, order);

      return order;
    });
    // 하나라도 실패하면 전체 롤백 → ACID 보장 용이
  }
}

장단점

설계
  :

1. / 
   -   
   -   
   -     

2.   
   -  DB  ACID   
   -   

3.     
   -     
   -   

4. / 
   -   
   -   

5.  
   -     
   -     

  :

1.    
   -   /  
   -     

2.    
   -  ,      

3.   
   -    /  
   - :   Python, API Node.js  

4.    
   -        

5.   
   -     
   -     

마이크로서비스 아키텍처 (MSA)

구조

설계

     

   API Gateway       , //

         
    
                                  
   
 User    Order  Payment   Product  
Service Service Service   Service  
:3001   :3002   :3003     :3004    
   
                                 
      
 UserDB  OrderDB  PayDB    ProdDB 
(MySQL)  (MySQL)  (PG)     (Mongo)
      

  : REST API   (Kafka, RabbitMQ)

MSA 코드 예시

TypeScript
// 주문 서비스 (Order Service) - 독립적인 마이크로서비스
// 다른 서비스는 HTTP 요청 또는 메시지로 통신

class OrderService {
  constructor(
    private httpClient: HttpClient,
    private messageQueue: MessageQueue,
  ) {}

  async createOrder(userId: number, items: OrderItem[]): Promise<Order> {
    // 1. 사용자 서비스에 HTTP 요청 (네트워크 통신)
    const user = await this.httpClient.get(`http://user-service/users/${userId}`);

    // 2. 상품 서비스에 재고 확인 요청
    const products = await this.httpClient.post(
      'http://product-service/products/check-stock',
      { items }
    );

    // 3. 주문 생성 (자신의 DB에만 저장)
    const order = await this.orderRepository.create({ userId, items });

    // 4. 이벤트 발행 (다른 서비스가 구독하여 처리)
    await this.messageQueue.publish('order.created', {
      orderId: order.id,
      userId,
      items,
      totalAmount: order.total,
    });
    // Payment Service, Notification Service가 이 이벤트를 받아 각자 처리

    return order;
    // 분산 트랜잭션 필요 → Saga Pattern, 2PC 등 복잡한 처리 필요
  }
}
YAML
# Docker Compose로 MSA 로컬 환경 구성
version: '3.8'
services:
  api-gateway:
    image: nginx
    ports:
      - "80:80"
    depends_on:
      - user-service
      - order-service

  user-service:
    build: ./user-service
    ports:
      - "3001:3001"
    environment:
      - DB_URL=mysql://user-db:3306/users

  order-service:
    build: ./order-service
    ports:
      - "3002:3002"
    environment:
      - DB_URL=mysql://order-db:3306/orders

  payment-service:
    build: ./payment-service
    ports:
      - "3003:3003"

  kafka:
    image: confluentinc/cp-kafka
    ports:
      - "9092:9092"

장단점

설계
 MSA :

1.    
   -       
   -      

2.   
   -    /DB  
   - : Elasticsearch, : Java, : Node.js

3.  
   -      
   -       

4.   (Conway's Law )
   -     /
   -   (API)  

5.   
   -       

 MSA :

1.   
   -  , ,   
   -   (Consul, Eureka)
   -    (Saga Pattern)

2.   
   -   , ,  (Distributed Tracing)
   - Kubernetes, Service Mesh (Istio)   
   -    

3.   
   -    DB   
   -  (Event Sourcing), CQRS  

4.   
   -   (K8s,  , API )
   -     

5.  
   -     (Consumer-Driven Contract Testing)
   -     

아키텍처 선택 기준

설계
 /    
  -     
  - MSA   
  -    

/     
  -      
  -    
  -   

 /   MSA 
  -    
  -  10 
  -     

모놀리스 퍼스트 (Monolith First)

설계
Martin Fowler  :

1:  
  -  ,   
  - "모듈식 모놀리스"   

2:    
  -    
  -      
  -     

3:  MSA ()
  -     
  -     

정리

항목모놀리식MSA
배포 단위전체 애플리케이션각 서비스 독립
트랜잭션ACID 보장 용이분산 트랜잭션 복잡
확장성전체 스케일아웃서비스별 스케일아웃
장애 영향전체에 영향격리 가능
기술 스택단일서비스별 자유
개발 복잡성낮음 (초기)높음 (분산 시스템)
운영 복잡성낮음높음 (K8s, 서비스 메시 등)
적합한 규모초기, 소~중규모성장 후, 대규모

핵심: "모놀리식으로 시작해서 MSA로 진화하라 (Monolith First)". 처음부터 MSA로 시작하면 불필요한 복잡성을 초기에 감당하게 됩니다. 서비스가 성장하고 도메인이 명확해진 후 점진적으로 분리하는 것이 더 실용적입니다.

관련 질문

같은 카테고리/태그 기준