아키텍처

[클린 아키텍처] 애플리케이션 조립하기 & 아키텍처 경계 강제하기

icecupregular 2025. 3. 28. 04:06

왜 조립까지 신경 써야 할까?

  • 모든 의존성은 안쪽, 도메인 방향으로 향해야 한다
  • 도메인 코드가 바깥으로부터 안전해진다.

한 클래스가 필요로 하는 모든 객체를 생성자로 전달할 수 있다면 실제 객체 대신 목으로 전달할 수 있고, 이렇게 되면 격리된 단위 테스트를 생성하기 쉬워진다.

설정 컴포넌트는 우리가 제공한 조각들로 애플리케이션을 조립하는 것을 책임진다. 이 컴포넌트는 다음과 같은 역할을 수행해야 한다.

  • 웹 어댑터 인스턴스 생성
  • HTTP 요청이 실제로 웹 어댑터로 전달되도록 보장
  • 유스케이스 인스턴스 생성
  • 웹 어댑터에 유스케이스 인스턴스 생성
  • 유스케이스에 영속성 어댑터 인스턴스 제공
  • 영속성 어댑터가 실제로 데이터베이스에 접근할 수 있도록 보장

스프링의 클래스패스 스캐닝으로 조립하기

@Component 애노테이션이 붙은 클래스를 찾는다. 그리고 각 클래스의 객체를 생성한다.

스프링의 자바 컨피그로 조립하기

@Configuration 사용

→ 애플리케이션 계층을 스프링 프레임워크 의존성 없이 깔끔하게 유지할 수 있다.

경계와 의존성

가장 안쪽에는 도메인 엔티티가 있다. 애플리케이션 계층은 애플리케이션 서비스 안에 유스케이스를 구현하기 위해 도메인 엔티티에 접근한다. 어댑터는 인커밍 포트를 통해 서비스에 접근하고, 반대로 서비스는 아웃고잉 포트를 통해 어댑터에 접근한다. 마지막으로 설정 계층은 어댑터와 서비스 객체를 생성할 팩터리를 포함하고 있고, 의존성 주입 매커니즘을 제공한다.

접근 제한자

package-private 제한자는 왜 그렇게 중요할까? 자바 패키지를 통해 클래스들을 응집적인 ‘모듈’로 만들어 주기 때문이다. 이러한 모듈 내에 있는 클래스들은 서로 접근 가능하지만, 패키지 바깥에서는 접근할 수 없다. 그럼 모듈의 진입점으로 활용될 클래스들만 골라서 public으로 만들면 된다. 이렇게 하면 의존성이 잘못된 방향을 가리켜서 의존성 규칙을 위반할 위험이 줄어든다.

  • 접근 제한자가 추가된 패키지 구조
  • buckpal
    • account
      • adapter
        • in
          • web
            • AccountController
        • out
          • persistence
            • AccountPersistenceAdapter
            • SpringDataAccountRepository
      • domain
        • Account
        • Activity
      • application
        • SendMoneyService
        • port
          • in
            • SendMoneyUseCase
          • out
            • LoadAccountPort
            • UpdateAccountStatePort

유지보수 가능한 소프트웨어를 만드는 데 어떻게 도움이 될까?

  • 하나의 빌드 모듈 안에서 아키텍처 경계를 강제화
  • 아키텍처 요소를 독립적인 빌드 모듈로 추출
  • 유지보수하기 좋은 코드를 위해