/
MSA 설계에서 Feature 간 의존성 문제와 해결 방안

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)

문제점:

  1. 강한 결합:

    • Notification Feature가 User Feature에 강하게 결합되어, User Feature 변경 시 Notification Feature도 영향을 받습니다.

  2. MSA 독립성 원칙 위반:

    • 각 Feature는 독립적으로 배포 및 유지보수가 가능해야 하지만, 위와 같은 구조에서는 두 Feature가 독립적으로 동작하기 어렵습니다.

  3. 테스트 어려움:

    • Notification Feature를 테스트하려면 User Feature의 전체 구현이 필요할 수 있습니다.

 

모의 객체를 사용한 독립적 테스트

테스트 시 실제 User Feature를 사용하지 않고 Mock 객체를 활용하여 독립적인 테스트를 수행할 수 있습니다.

구현 예시:

  • UserClientPort 인터페이스 정의:

public interface UserClientPort { UserResponse getUser(String userId); }
  • NotificationService 테스트:

@ExtendWith(MockitoExtension.class) public class NotificationServiceTest { @Mock private UserClientPort userClientPort; @InjectMocks private NotificationService notificationService; @Test public void testNotifyUser() { // Mock 동작 정의 String userId = "123"; UserResponse mockResponse = new UserResponse(userId, "John Doe", "john.doe@example.com"); Mockito.when(userClientPort.getUser(userId)).thenReturn(mockResponse); // 테스트 실행 boolean result = notificationService.notifyUser(userId); // 검증 assertTrue(result); Mockito.verify(userClientPort).getUser(userId); } }

장점:

  • User Feature와 독립적으로 Notification Feature를 테스트할 수 있습니다.

  • Mock 객체를 사용해 다양한 시나리오를 손쉽게 검증 가능합니다.


해결 방안

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 호출

이벤트 기반 통신

항목

REST API 호출

이벤트 기반 통신

결합도

낮음

매우 낮음

성능

동기적 호출로 인해 네트워크 오버헤드 존재

비동기적 호출로 높은 성능 가능

복구 로직 필요성

있음

메시징 시스템 설정에 따라 다름

구현 복잡도

낮음

높음 (메시징 시스템 필요)


추가적으로 고려해야 할 요소

  1. 데이터 일관성 문제:

    • 이벤트 기반 통신에서는 이벤트 순서 보장중복 처리 문제가 발생할 수 있습니다.

    • CQRS(Command Query Responsibility Segregation) 패턴을 활용해 데이터 일관성을 유지할 수 있습니다.

  2. 네트워크 장애 복구 전략:

    • REST 호출에서는 서킷 브레이커(Resilience4j) 패턴을 활용합니다.

    • 이벤트 기반 통신에서는 재시도 메커니즘DLQ(Dead Letter Queue) 설정이 필요합니다.

  3. 메시징 시스템의 선택:

    • Kafka: 대용량 처리와 높은 처리율이 요구될 때 적합.

    • RabbitMQ: 낮은 지연 시간과 메시지 우선순위 처리에 유리.

  4. 장기적 확장성:

    • REST API 방식은 단순 데이터 조회/업데이트에 적합.

    • 이벤트 기반 통신은 다양한 Feature 간의 확장 가능한 아키텍처에 적합.


결론

Notification Feature와 User Feature 간 의존성 문제를 해결하기 위해 REST API 호출과 이벤트 기반 통신 두 가지 방법을 고려할 수 있습니다:

  1. REST API 호출:

    • 구현이 간단하고 동기적 처리가 필요한 경우 적합.

    • 단기적인 해결책으로 유용.

  2. 이벤트 기반 통신:

    • 성능이 중요한 비동기 환경에 적합하며, 결합도를 최소화 가능.

    • 장기적인 확장성과 유연성을 제공합니다.

프로젝트 요구사항에 맞는 방식을 선택하거나, 상황에 따라 두 방법을 조합하여 사용할 수 있습니다.

Related content

다른 Feature가 NotificationConfigImplService의 기능을 필요로 할 경우
다른 Feature가 NotificationConfigImplService의 기능을 필요로 할 경우
More like this
NotificationConfigRepository 에 대해서 NotificationConfigService는 Outbound port 이고 NotificationConfigImplService는 그에 대한 adapter라고 볼수 있나?
NotificationConfigRepository 에 대해서 NotificationConfigService는 Outbound port 이고 NotificationConfigImplService는 그에 대한 adapter라고 볼수 있나?
More like this
JPA를 통한 데이터베이스 상호작용을 위한 Port와 Adapter라면, 비즈니스 로직 외의 기능을 포함하는 것은 부적절
JPA를 통한 데이터베이스 상호작용을 위한 Port와 Adapter라면, 비즈니스 로직 외의 기능을 포함하는 것은 부적절
More like this
헥사고날 아키텍처와 MSA에서 Feature 중심 설계: Port와 Adapter를 통한 상호작용
헥사고날 아키텍처와 MSA에서 Feature 중심 설계: Port와 Adapter를 통한 상호작용
More like this
Schema
More like this