-
- 대부분의 클래스는 여러 리소스에 의존한다. 여기서 말하는 리소스는 의존성이다.
- 이 책에서는 SpellChecker와 Dictionary를 예로 들고 있다.
- SpellChecker 클래스는 스펠링이 맞는지 확인하는 클래스이고 Dictionary는 사전 클래스이다.
- 이때 SpellCheck가 Ditionary를 사용하고, 이를 의존하는 리소스 또는 의존성이라고 부른다.
- 이때 SpellChecker를 다음과 같이 구현하는 경우가 있다.
부적절한 구현
static 유틸 클래스
- static 유틸리티 클래스이고 인스턴스로 만들 이유가 없기에 private 한 생성자를 만들었다.
- public static 한 메서드를 사용해서 클라이언트들이 SpellChecker.isValid 식으로 유틸 클래스를 사용하도록 한다.
- 문제는 dictionary가 new로 고정이 돼있다는 점이다.
- SpellChecker를 테스트할 때 dictionary도 같이 테스트해야 한다.
싱글톤으로 구현하기
- 사전을 하나만 사용할꺼라면 위와 같은 구현도 만족스러울 수 있겠지만, 실제로는 각 언어의 맞춤법 검사기는 사용하는 사전이 각기 다르다.
- 또한 테스트 코드에서는 테스트용 사전을 사용하고 싶을 수도 있다.
- 어떤 클래스가 사용하는 리소스에 따라 행동을 달리 해야 하는 경우에는 스태틱 유틸리티 클래스와 싱글톤을 사용하는 것은 부적절하다.
- 그런 요구 사항을 만족할 수 있는 간단한 패턴으로 생성자를 사용해서 새 인스턴스를 생성할 때 사용할 리소스를 넘겨주는 방법이 있다.
적절한 구현
- Lexicon 타입의 dictionary를 쓰는데 이 dictionary에 따라 SpellChecker가 달라진다. 그럴 경우 생성자를 통한
- 의존성 주입 등을 사용해서 쉽게 바꿔낄 수 있도록 의존성 주입을 사용하는 것이 좋다.
- 위와 같은 의존성 주입은 생성자, 스태틱 팩토리 그리고 빌더에도 적용할 수 있다.
- 이 패턴의 변종으로 리소스의 팩토리를 생성자에 전달하는 방법도 있다.
- 이 방법은 자바 8에 들어온 Supplier <T> 인터페이스가 그런 팩토리로 쓰기에 완벽하다.
- Supplier <T>를 인자로 받는 메서드는 보통 bounded wildcard type으로 입력을 제한해야 한다.
- 의존성 주입이 유연함과 테스트 용이함을 크게 향상해주지만, 의존성이 많은 큰 프로젝트인 경웅에는 코드가 장황해질 수 있다.
- 그 점은 대거, 주스, 스프링 같은 프레임웍을 사용해서 해결할 수 있다.
스프링을 이용한 SpellChecker
- @Component를 통해 SpellChecker와 KoreanDictionary를 빈으로 등록시킨다.
- 해당 Config 클래스 컴포넌트 스캔을 통해 패키지 이하로 빈을 등록한다.
- ApplicationContext에 등록된 빈을 호출해서 사용한다.
- Korean이 정상적으로 찍히는 것을 확인할 수 있다.
- 다음과 같이 스프링 프레임워크를 통해 의존성 주입을 해보았다.
정리
- 요약하자면 의존하는 리소스에 따라 행동을 달리하는 클래스를 만들 때는 싱글톤이나 스태틱 유틸 클래스를 사용하지 말자.
- 그런 경우에는 리소스를 생성자나 팩토리로 전달하는 의존성 주입을 사용하여 유연함, 재사용성, 테스트 용이성을 향상하자.
참조
이펙티브 자바 3판