TIL - 20251226

juni·2025년 12월 25일

TIL

목록 보기
219/316

1226 마이크로서비스 아키텍처(MSA) 심화: 분산 트랜잭션과 메시징


✅ 1. MSA의 데이터 관리: 데이터베이스 분리

  • 원칙: 마이크로서비스 아키텍처의 핵심 원칙 중 하나는 "서비스당 하나의 데이터베이스(Database per Service)"입니다.

    • 각 마이크로서비스는 자신만의 독립적인 데이터베이스를 소유하고 관리합니다.
    • 다른 서비스는 해당 서비스의 데이터베이스에 직접 접근할 수 없으며, 오직 API를 통해서만 데이터에 접근해야 합니다.
  • 이유:

    1. 느슨한 결합 (Loose Coupling): 한 서비스의 데이터베이스 스키마 변경이 다른 서비스에 직접적인 영향을 주지 않습니다.
    2. 기술 스택의 유연성: 각 서비스의 특성에 맞는 최적의 데이터베이스 기술을 자유롭게 선택할 수 있습니다. (e.g., 주문 서비스는 관계형 DB, 상품 검색 서비스는 검색 엔진, 사용자 세션은 인메모리 DB)
    3. 독립적인 확장: 특정 서비스의 데이터베이스에 부하가 몰릴 경우, 해당 데이터베이스만 독립적으로 확장할 수 있습니다.

✅ 2. 분산 트랜잭션의 문제

  • 문제점: 데이터베이스가 서비스별로 분리되면서, 여러 서비스에 걸쳐 데이터의 원자성(Atomicity)을 보장해야 하는 분산 트랜잭션 문제가 발생합니다.

    • 예시: "주문" 서비스와 "결제" 서비스가 있다고 가정해봅시다. 사용자가 주문을 하면, 주문 DB에는 "주문 생성"이 기록되고, 결제 DB에는 "결제 완료"가 기록되어야 합니다. 만약 주문 생성은 성공했는데, 결제 처리에서 오류가 발생하면 어떻게 될까요? 주문 데이터만 남고 결제는 이루어지지 않은, 데이터 불일치(Inconsistency) 상태에 빠지게 됩니다.
  • 전통적인 2PC(Two-Phase Commit) 방식은 모든 서비스가 서로를 강하게 결합시켜 MSA의 장점을 해치므로, MSA 환경에서는 다른 접근 방식이 필요합니다.


✅ 3. 해결 방안: 사가 패턴 (Saga Pattern)

  • 사가(Saga)는 분산 환경에서 데이터의 최종 일관성(Eventual Consistency)을 보장하기 위한 트랜잭션 관리 패턴입니다.

  • 핵심 아이디어: 하나의 거대한 트랜잭션을 여러 개의 로컬 트랜잭션과, 각 로컬 트랜잭션 실패 시 실행될 보상 트랜잭션(Compensating Transaction)으로 나누어 관리합니다.

  • 동작 방식 (주문-결제 예시):

    1. [주문 서비스] 주문 생성 로컬 트랜잭션을 실행하고, 성공하면 "주문이 생성됨(OrderCreated)" 이벤트를 발행합니다.
    2. [결제 서비스] "주문이 생성됨" 이벤트를 구독하고 있다가, 이벤트가 발생하면 결제 처리 로컬 트랜잭션을 실행합니다.
    3. [성공 시] 결제가 성공하면, "결제 완료됨(PaymentCompleted)" 이벤트를 발행하고 프로세스가 종료됩니다.
    4. [실패 시] 만약 결제 처리가 실패하면, 결제 서비스는 "결제 실패함(PaymentFailed)" 이벤트를 발행합니다.
    5. [주문 서비스] "결제 실패함" 이벤트를 구독하고 있다가, 이벤트가 발생하면 보상 트랜잭션주문 취소 로컬 트랜잭션을 실행하여 데이터의 일관성을 맞춥니다.
  • 최종 일관성: 사가 패턴은 모든 작업이 즉시 원자적으로 처리되는 것을 보장하지는 않지만, 중간에 실패가 발생하더라도 보상 트랜잭션을 통해 결국에는(Eventually) 데이터가 일관된 상태에 도달하는 것을 보장합니다.


✅ 4. 비동기 통신과 메시지 큐 (Message Queue)

  • 위에서 설명한 사가 패턴과 같은 이벤트 기반 아키텍처를 구현하기 위한 핵심 기술이 바로 메시지 큐입니다.

  • 메시지 큐 (MQ)는 서비스 간의 통신을 비동기적(Asynchronous)으로 처리하고, 시스템을 느슨하게 결합시키는 미들웨어입니다. (e.g., RabbitMQ, Apache Kafka)

➕ MSA에서 메시지 큐의 역할

  1. 서비스 간의 비동기 통신:

    • 주문 서비스는 "주문 생성됨" 이벤트를 메시지 큐에 던져놓기만 하면, 자신의 일은 끝납니다. 결제 서비스나 알림 서비스가 이 메시지를 언제 어떻게 처리하는지 기다릴 필요가 없습니다. 이를 통해 서비스 간의 의존성이 제거되고, 전체 시스템의 응답성이 향상됩니다.
  2. 이벤트 전달 보장:

    • 메시지는 큐에 안전하게 저장되므로, 결제 서비스가 일시적으로 장애 상태이더라도 메시지가 유실되지 않습니다. 결제 서비스가 복구되면 큐에 쌓여있던 메시지를 가져와 순차적으로 처리할 수 있습니다.
  3. 유연한 확장:

    • 결제 처리량이 많아지면, 메시지를 처리하는 결제 서비스의 인스턴스(컨슈머) 수만 늘려서 전체 처리량을 쉽게 확장할 수 있습니다.
  • 동기(Synchronous) vs 비동기(Asynchronous) 통신:
    • 동기 통신 (e.g., REST API 호출): 요청을 보낸 서비스가 응답을 받을 때까지 기다려야 합니다. 구현이 간단하지만, 호출하는 서비스에 장애가 발생하면 요청한 서비스까지 영향을 받는 강한 결합을 가집니다.
    • 비동기 통신 (e.g., 메시지 큐): 요청을 보낸 후 응답을 기다리지 않습니다. 구현이 더 복잡하지만, 서비스 간의 결합도를 낮추어 시스템의 탄력성과 확장성을 높입니다.

📌 요약

  • MSA에서는 "서비스당 하나의 데이터베이스" 원칙에 따라 데이터를 분리하며, 이로 인해 분산 트랜잭션 문제가 발생합니다.
  • 사가 패턴은 이 문제를 해결하기 위한 핵심 패턴으로, 로컬 트랜잭션과 실패 시를 대비한 보상 트랜잭션의 연속으로 데이터의 최종 일관성을 보장합니다.
  • 사가 패턴과 같은 이벤트 기반 아키텍처를 구현하기 위한 핵심 기술은 메시지 큐(RabbitMQ, Kafka)입니다.
  • 메시지 큐는 서비스 간의 통신을 비동기적으로 처리하여 느슨한 결합을 가능하게 하고, 시스템 전체의 안정성과 확장성을 크게 향상시킵니다.

0개의 댓글