-
[클린 아키텍처 09] 애플리케이션 조립하기프로그래밍/기타 2024. 9. 29. 13:00반응형
왜 조립까지 신경 써야 할까?
유스케이스가 영속성 어댑터를 호출해야 하고 스스로 인스턴스화한다면 코드 의존성이 잘못된 방향으로 만들어 진 것
유스케이스는 인터페이스만 알아야 하고, 런타임에 이 인터페이스의 구현을 제공받아야 한다.
그럼 객체 인스턴스를 생성할 책임은 누구에게 있을까?
의존성 규칙을 어기지 않으면서 그렇게 할 수 있을까?
아키텍처에 대해 중립적이고 인스턴스 생성을 위해 모든 클래스에 대한 의존성을 가지는 설정 컴포넌트가 있어야 함!
설정 컴포넌트는 각 클래스의 인스턴스 생성 역할을 한다.
평범한 코드로 조립하기
class Application { public static void main(String[] args) { AccountRepository accountRepository = new AccountRepository(); ActivityRepository activityRepository = new ActivityRepository); AccountPersistenceAdapter accountPersistenceAdapter = new AccountPersistenceAdapter (accountRepository, activityRepository); ,,, startProcessingWebRequests(sendMoneyController); }
자바에서는 애플리케이션이 main 메서드로부터 시작됨.
main 메서드 안에서 웹 컨트롤러부터 영속성 어댑터까지, 필요한 모든 클래스의 인스턴스로를 생성한 후 함께 연결한다.
startprocessing webRequests()는 웹 어댑터를 HTTP로 노출시키는데 필요한 애플리케이션 부투스트랩핑 로직이 들어갈 곳이다.
이 코드 방식은 애플리케이션을 조립하는 가장 기본적인 방법이다.
단점
- 위의 예시는 컨트롤러, 유스케이스, 영속성 어댑터가 단 하나씩만 있을 때 -> 완전한 애플리케이션을 실행시키려면? ㄷㄷ
- 각 클래스가 속한 패키지 외부에서 인스턴스를 생성하기 때문에 이 클래스는 전부 public이어야 함 -> 유스케이스가 영속성 어댑터에 직접 접근하는 것을 막지 못한다.
스프링의 클래스패스 스캐닝으로 조립하기
스프링 프레임워크를 이용해서 애플리케이션을 조립한 결과물을 애플리케이션 컨텍스트라고 한다.
애플리케이션 컨텍스트는 애플리케이션을 구성하는 모든 객체를 포함한다.
애플리케이션 컨텍스트를 조립하기 위한 방법
1) 클래스패스 스캐닝
스프링은 클래스패스 스캐닝으로 클래스패스에서 접근 간으한 모든 클래스를 확인해서 @Component 애너테이션이 붙은 클래슬르 찾음
그러고 나서 이 어노테이션이 붙은 각 클래스의 객체를 생성함
해당 클래스는 필요한 모든 필드를 인자로 받는 생성자를 가지고 있어야함!
스프링은 해당 생성자를 찾아 -> 생성자의 인자로 사용된 @Component가 붙은 클래스를 찾고, 이 클래스들의 인스턴스를 만들어 애플리케이션 컨텍스트에 추가한다.
스프링이 인식할 수 있는 어노테이션을 직접 만들 수도 있다.
@Target ({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface PersistenceAdapter { @AliasFor(annotation = Component.class) String value() default ""; }
클래스패스 스캐닝 방식 단점
- 클래스에 프레임워크에 특화된 어노테이션을 붙여야 함
- 스프링 전문가가 아니라면 원인을 찾는데 수일이 걸릴 수 있는 부수효과 발생 가능성
스프링의 자바 컨피그로 조립하기
애플리케이션 컨텍스트에 추가할 빈은 생성하는 설정 클래스
@Configuration @EnableJpaRepositories class PersistenceAdapterConfiguration { @Bean AccountPersistenceAdapter accountPersistenceAdapter( AccountRepository accountRepository, ActivityRepository activityRepository, AccountMapper accountMapper){ return new AccountPersistenceAdapter( accountRepository, activityRepository, accountMapper); @Bean AccountMapper accountMapper (){ return new AccountMapper(); } }
- @Configuration을 통해 이 클래스가 스프링의 클래스패스 스캐닝에서 발견해야 할 설정 클래스임을 표시.
- @Bean 어노테이션이 붙은 팩토리 메서드를 통해 빈이 생성 -> 2개의 레포지토리와 한개의 매퍼를 생성자 입력으로 받음 -> 이 객체들을 자동으로 팩터리 메서드에 대한 입력으로 제공
- @EnabledJpaRepositories를 통해서 레포지토리 객체들을 스프링이 직접 생성해서 제공해서 제공한다.
PersistenceAdapterconfiguration를 사용해서 영속성 계층에서 필요로 하는 모든 객체를 인스턴스화 하는 매우 한정적인 범위의 영속성 모듈을 만듦 -> 스프링의 클래스 패스 스캐닝을 통해 자동 선택
장점
- 특정 모듈만 포함, 다른 모듈의 빈 모킹해서 애플리케이션 컨텍스트 생성 가능 -> 테스트의 유 연성
- @Component 어노테이션을 코드 여기저기에 붙이도록 강제 X -> 애플리케이션 계층 깔끔하게 유지
단점
- 설정 클래스가 생성하는 빈이 설정 클래스와 같은 패키지에 존재하지 않는다면 이 빈들을 public으로 만들어야 함
유지보수 가능한 소프트웨어를 만드는 데 어떻게 도움이 될까?
전용 설정 컴포넌트
- 서로 다른 모듈로부터 독립되어 응집도가 매우 높은 모듈을 만들 수 있다
반응형'프로그래밍 > 기타' 카테고리의 다른 글
[클린 아키텍처 11] 의식적으로 지름길 사용하기 (0) 2024.10.11 [클린 아키텍처 10] 아키텍처 경계 강화하기 (1) 2024.10.01 [클린 아키텍처 07] 아키텍처 요소 테스트하기 (0) 2024.09.09 [클린 아키텍처 06] 영속성 어댑터 구현하기 (0) 2024.09.01 [클린 아키텍처 05] 웹 어댑터 구현하기 (0) 2024.09.01