1 분 소요

Item 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라

   자원을 직접 명시한다는 것은 해당 클래스에서 사용할 객체를 직접 생성해 사용한다는 뜻이다. 다음 코드를 보자.

public class SpellChecker {

    private final Dictionary dictionary = new DefaultDictionary(); // 자원을 직접 명시한 경우

    private SpellChecker() {}

    public static final SpellChecker INSTANCE = new SpellChecker();

    public boolean isValid(String word) {
        // TODO 여기 SpellChecker 코드
        return dictionary.contains(word);
    }

    public List<String> suggestions(String typo) {
        // TODO 여기 SpellChecker 코드
        return dictionary.closeWordsTo(typo);
    }
}

   위 코드에서 SpellChecker 객체는 DefaultDictionary 객체를 내부에서 직접 생성하여 사용하고 있다.

자원을 직접 명시하면 좋지 않은 이유

   허나 이것은 좋지 않은 코드라고 할 수 있겠다. 그 이유를 살펴보기에 앞서 SpellChecker 클래스의 용도를 알아야 하는데, SpellChecker 객체는 단어를 확인하는 역할을 담당하고 있다. 단어를 확인하기 위해 사전 즉, Dictionary 객체를 이용해야 한다. 위 코드에서 SpellChecker 클래스는 내부 필드로 Dictionary 객체를 직접 생성하여 다룬다.

   그렇다면 사전은 단 하나인가? 사전은 언어별로 다를 수도 있고 심지어 테스트를 위해 가짜 사전 객체를 넣어주어야 할 때도 있을 것이다. 위의 SpellChecker 객체에는 다른 사전 객체를 넣어줄 수가 없다(dictionary 필드를 바꿀 수 있는 메서드를 제공할 수도 있으나 매우 비효율적이며 특히 멀티 쓰레드 환경에서 많은 버그를 발생시킨다). 이런 설계는 OCP 원칙에도 위배된다. 사전이 추가되더라도 SpellChecker 클래스는 재사용할 수 없고 SpellChecker 클래스와 동일한 용도의 또 다른 클래스를 정의해야 할 것이다.

   이렇게 어떤 자원(객체)에 따라 유동적인 동작을 해야하는 클래스는 싱글톤이나 유틸리티 방식이 적합하지 않다. 이런 클래스는 의존 객체 주입을 사용하는 것이 아주 효율적이다.

의존 객체 주입을 사용할 때 장점

의존 객체 주입이란?

   객체를 내부에서 직접 명시하는 것이 아니라 외부에서 주입해주는 방식을 말한다.

public class SpellChecker {

    private final Dictionary dictionary;

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

    public boolean isValid(String word) {
        // TODO 여기 SpellChecker 코드
        return dictionary.contains(word);
    }

    public List<String> suggestions(String typo) {
        // TODO 여기 SpellChecker 코드
        return dictionary.closeWordsTo(typo);
    }
}

   위 코드에서 SpellChecker 클래스는 Dictionary 객체를 주입 받아서 생성된다. 물론 Dictionary 객체는 추상 클래스 혹은 인터페이스 타입이라야 적절할 것이다(그래야 다형성을 활용한 여러 하위 타입의 객체를 받을 수 있기 때문). 이 클래스는 어떤 사전을 가져오더라도 활용될 수 있다. 즉, 재사용 가능한 클래스가 된다. 영어 사전, 한글 사전 등 언어별로 다른 사전 객체 뿐만 아니라 테스트를 위한 가짜 사전 객체도 주입해줄 수 있다. 이 코드는 아주 유연하며 사전 객체를 매우 쉽게 확장할 수 있게 도와주고 테스트도 용이하다.


[참고]
백기선, inflearn 강의 이펙티브 자바 완벽 공략 1부
Joshua Bloch, 이펙티브 자바

<== Prev                                                Next ==>