Java

[Effective Java] 2-5. 객체 생성과 파괴: 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라

noahkim_ 2024. 12. 27. 03:29

조슈아 블로크 님의 "Effective Java" 책을 정리한 포스팅 입니다.


1. 정적 유틸리티 클래스와 싱글턴 패턴의 한계

강한 결합 발생

  • 구현에 의존함

 

테스트 어려움 
  • 각 테스트 케이스별로 독립적으로 실행되어야 함
  • 테스트 간 상태 공유가 일어날 수 있음
    • 공유 자원이 존재할 경우, 다른 테스트에서 영향을 받을 수 있음

 

멀티스레드 환경
  • 여러 스레드가 동시에 자원을 접근하고 수정할 수 있음
  • 상태를 공유하는 방식이 경쟁 상태가 발생할 수 있음

 

2. 의존 객체 주입

  • 협력 객체의 인스턴스 생성 시, 생성자에 필요한 자원을 넘겨주는 방식
  • 협력하는 객체를 직접 인스턴스로 생성 X

 

느슨한 결합 

  • 인터페이스 타입으로 협력 객체를 받도록 선언
  • 어떤 구현체이든 주입하여 사용할 수 있음

 

테스트 대역 확보
  • 테스트 시 mock 객체를 넘겨주어 진짜 객체를 생성하지 않고 테스트 할 수 있음

 

코드 관리

  • 의존객체 주입 프레임워크를 사용하여 코드를 깔끔하게 관리할 수 있음

 

Spring IoC Container
  • 제어의 역전으로 인해 외부에서 빈을 직접 관리
  • 손쉽게 싱글톤 Scope을 사용할 수 있음

 

변형 방식: 자원 팩토리 넘겨주기

public class SpellCheckerWithDIFactory {
    private final Dictionary dictionary;

    public SpellCheckerWithDIFactory(Dictionary dictionary) {
        this.dictionary = dictionary;
    }

    public SpellCheckerWithDIFactory(Supplier<Dictionary> dictionarySupplier) {
        this.dictionary = dictionarySupplier.get();
    }

		...
}
Supplier
  • 자원을 생성하는 함수형 인터페이스
  • 지연 초기화
    • 객체가 필요할 때, 동적으로 생성하도록 함
    • 외부 조건에 따라 생성하고자 동적으로 할 경우 유용함