MSA 설계에서 Feature 간 의존성 문제와 해결 방안
Microservices Architecture(MSA)에서 Feature 간 의존성은 독립성 원칙을 위반할 위험이 있습니다. 이 문서에서는 Notification Feature가 User Feature에 의존하는 문제를 예시로 들어, 의존성 문제와 이를 해결하기 위한 방법들을 설명합니다.
의존성 문제의 정의
Notification Feature → User Feature 의존성
com.example.notification.service.NotificationService
↓
com.example.notification.port.UserClientPort (Outbound Port)
↓
com.example.notification.adapter.UserClientAdapter (Outbound Adapter) <---- 여기
↓
com.example.user.port.UserServicePort (Inbound Port)
↓
com.example.user.service.UserServiceImpl (Business Logic)
↓
com.example.user.repository.UserRepository (JPA Repository)
문제점:
강한 결합:
Notification Feature가 User Feature에 강하게 결합되어, User Feature 변경 시 Notification Feature도 영향을 받습니다.
MSA 독립성 원칙 위반:
각 Feature는 독립적으로 배포 및 유지보수가 가능해야 하지만, 위와 같은 구조에서는 두 Feature가 독립적으로 동작하기 어렵습니다.
테스트 어려움:
Notification Feature를 테스트하려면 User Feature의 전체 구현이 필요할 수 있습니다.
해결 방안
1. REST API를 사용한 간접 호출
User Feature가 REST API를 제공하고, Notification Feature는 이를 호출하여 필요한 데이터를 가져옵니다. 이 접근법은 코드 의존성을 HTTP 통신으로 대체합니다.
구현 예시:
User Feature (REST API 제공):
Notification Feature (REST Client 사용):
장점:
Feature 간 코드 의존성 제거.
각 Feature의 독립적 배포 및 유지보수 가능.
단점:
REST 호출 시 네트워크 오버헤드 발생.
호출 실패 시 복구 로직 필요.
2. 이벤트 기반 통신
User Feature가 사용자 데이터 변경 이벤트를 발행하고, Notification Feature가 이를 구독하여 처리합니다. 이는 비동기적으로 동작하며, 두 Feature 간 결합도를 낮춥니다.
구현 예시:
User Feature (이벤트 발행):
Notification Feature (이벤트 구독):
장점:
비동기적으로 동작하여 성능 개선 가능.
두 Feature 간 직접적인 의존성 제거.
단점:
이벤트 전송 지연 또는 손실 가능성.
추가적인 메시징 시스템(Kafka, RabbitMQ 등) 도입 필요.
Kafka를 활용한 이벤트 기반 통신 구현 예시:
User Feature (이벤트 발행):
Notification Feature (이벤트 구독):
RabbitMQ를 활용한 이벤트 기반 통신 구현 예시:
User Feature (이벤트 발행):
Notification Feature (이벤트 구독):
각 해결 방안의 비교
항목 | REST API 호출 | 이벤트 기반 통신 |
---|---|---|
결합도 | 낮음 | 매우 낮음 |
성능 | 동기적 호출로 인해 네트워크 오버헤드 존재 | 비동기적 호출로 높은 성능 가능 |
복구 로직 필요성 | 있음 | 메시징 시스템 설정에 따라 다름 |
구현 복잡도 | 낮음 | 높음 (메시징 시스템 필요) |
추가적으로 고려해야 할 요소
데이터 일관성 문제:
이벤트 기반 통신에서는 이벤트 순서 보장과 중복 처리 문제가 발생할 수 있습니다.
CQRS(Command Query Responsibility Segregation) 패턴을 활용해 데이터 일관성을 유지할 수 있습니다.
네트워크 장애 복구 전략:
REST 호출에서는 서킷 브레이커(Resilience4j) 패턴을 활용합니다.
이벤트 기반 통신에서는 재시도 메커니즘과 DLQ(Dead Letter Queue) 설정이 필요합니다.
메시징 시스템의 선택:
Kafka: 대용량 처리와 높은 처리율이 요구될 때 적합.
RabbitMQ: 낮은 지연 시간과 메시지 우선순위 처리에 유리.
장기적 확장성:
REST API 방식은 단순 데이터 조회/업데이트에 적합.
이벤트 기반 통신은 다양한 Feature 간의 확장 가능한 아키텍처에 적합.
결론
Notification Feature와 User Feature 간 의존성 문제를 해결하기 위해 REST API 호출과 이벤트 기반 통신 두 가지 방법을 고려할 수 있습니다:
REST API 호출:
구현이 간단하고 동기적 처리가 필요한 경우 적합.
단기적인 해결책으로 유용.
이벤트 기반 통신:
성능이 중요한 비동기 환경에 적합하며, 결합도를 최소화 가능.
장기적인 확장성과 유연성을 제공합니다.
프로젝트 요구사항에 맞는 방식을 선택하거나, 상황에 따라 두 방법을 조합하여 사용할 수 있습니다.