Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

헥사고날 아키텍처와 마이크로서비스 아키텍처(MSA)를 결합하면 시스템의 복잡성을 효과적으로 관리할 수 있습니다. 이 글에서는 Feature 중심 설계와 Port와 Adapter를 활용한 Feature 간 상호작용 방법을 설명합니다.

...

  1. NotificationService:

    • NotificationService는 비즈니스 로직에서 UserClientPort를 통해 User 정보를 요청합니다.

  2. UserClientPort:

    • Notification Feature의 Outbound Port로서, UserClientAdapter의 호출 인터페이스 역할을 합니다.

  3. UserClientAdapter:

    • UserClientPort를 구현하며, UserServicePort를 호출하여 User 정보를 가져옵니다.

  4. UserServicePort:

    • User Feature의 Inbound Port로서 외부 요청을 처리합니다.

  5. UserServiceImpl:

    • UserServicePort의 구현체로, 비즈니스 로직을 처리하며 JPA Repository(UserRepository)와 상호작용합니다.

...

추가 설명: 인터페이스와 Port

  • **인터페이스(interface)**는 추상화를 제공하는 도구이지만, 무조건 Port로 간주할 수는 없습니다. 헥사고날 아키텍처에서 Port는 Core Domain의 경계를 정의하며 외부와의 상호작용을 추상화하는 데 사용됩니다.

  • UserRepository는 JPA의 인터페이스를 확장한 기술적 세부사항을 포함하며, 이는 헥사고날 아키텍처에서 Adapter의 역할에 해당합니다. Core Domain은 UserRepository를 직접 알지 못하며, 대신 추상화된 Outbound Port를 통해 접근합니다.

추가 설명: 의존성 문제와 해결 방안

Notification Feature에서 User Feature로의 의존성은 MSA 설계의 독립성 원칙을 위반할 가능성이 있습니다.

...

  • .

...

이를 해결하기 위한 방법은 다음과 같습니다:

REST API를 사용한 간접 호출:

  • User Feature가 REST API를 제공하고, Notification Feature는 이를 호출하여 User 데이터를 가져옵니다.

  • 두 Feature는 HTTP 통신을 통해 상호작용하며, 코드 의존성을 제거합니다.

Code Block
@RestController
@RequestMapping("/users")
public class UserController {
    @GetMapping("/{userId}")
    public UserResponse getUser(@PathVariable String userId) {
        return userService.getUserById(userId);
    }
}
Code Block
@Component
public class UserClientAdapter implements UserClientPort {
    private final RestTemplate restTemplate;

    public UserClientAdapter(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public UserResponse getUser(String userId) {
        return restTemplate.getForObject("http://user-service/users/" + userId, UserResponse.class);
    }
}

이벤트 기반 통신:

  • User Feature가 사용자 데이터 변경 이벤트를 발행하면 Notification Feature가 이를 구독하여 비동기로 처리합니다.

Code Block
@Component
public class UserEventPublisher {
    private final ApplicationEventPublisher eventPublisher;

    public void publishUserEvent(UserEvent event) {
        eventPublisher.publishEvent(event);
    }
}

...

...

Port와 Adapter를 사용한 설계의 장점

...