Item5 : 의존 객체 주입을 사용하라

Seunghan·2022년 4월 19일
0

Java

목록 보기
6/6

자바는 객체지향 언어다. 객체지향 언어는 객체로 이루어져 있고, 객체는 대부분 클래스로 표현된다.
클래스는 다른 클래스를 의존한다. 즉 클래스는 많은 의존관계를 가지고 있다.
다음 예제를 통해 왜 자원을 직접 명시하지 말고 의존 객체 주입을 사용 해야 하는지 알아보자

자원을 직접 명시한 잘못된 예

1. 정적 유틸리티

public class SpellChecker {
    private static final Lexicon dictionary = ...;

    private SpellChecker() {}
		
		public static boolean isValid(String word) {}
		public static List<String> suggestions(String typo) {}
}

2. 싱글턴(Singleton)

public class SpellChecker {
    private static final Lexicon dictionary = ...;

    private SpellChecker() {}
		public static SpellChecker INSTANCE = new SpellChecker();

    public static boolean isValid(String word) {}
		public static List<String> suggestions(String typo) {}
}

위의 두 예제가 잘못된 이유는 클래스의 의존관계를 명시적으로 선언한 뒤 메서드를 통해 반환해 주었다는 것이다.

자바는 OOP를 지향하며 사용하는 자원에 따라 동작이 달라지는 클래스들이 많다. 하지만 자원을 명시적으로 선언한다면 동작에 따라 다른 구현체들을 갈아끼우기 어려우며, 또한 해당 자원을 교체하는 setter 메서드를 추가해도 오류를 내기 쉬워진다. 또한 테스트 할 때도 해당 자원밖에 테스트 하지 못하는 단점이 있다.

이 조건을 만족시키는 간단한 패턴이 인스턴스를 생성할 때 생성자에 필요한 자원을 넘겨주는 방식이다. 위의 SpellChecker 예제에서는 클래스를 생성할 때 의존 객체인 사전을 주입해주면 된다. 이런 방식 DI(Dependency Injection) 의존관계 주입이라고 한다.

의존 객체 주입은 유연성과 테스트 용이성을 높여준다.

public class SpellChecker {
    private final Lexicon dictionary;
		
		// 생성자 주입 패턴
    public SpellChecker(Lexicon dictionary) {
        this.dictionary = Objects.requireNonNull(dictionary);
    }

    public static boolean isValid(String word) {}

    public static List<String> suggestions(String typo) {}
}

의존 객체 주입 패턴을 사용하면 dictionary라는 딱 하나의 자원만 사용하지만, 자원이 몇 개든 의존 관계가 어떻든 상관없이 유연하게 작동한다. 또한 불변을 보장하여 여러 클라이언트가 의존 객체들을 안심하고 공유할 수 있기도 하다. 의존 객체 주입은 생성자, 정적 팩터리, 빌더 모두에 똑같이 응용할 수 있다.

이 패턴의 쓸만한 변형으로, 생성자에 자원 팩터리를 넘겨주는 방식이 있다.(자바 8의 Supplier 인터페이스)

자바만으로는 규모가 큰 프로젝트에서 완벽한 의존 관계 주입을 작성하려면 코드가 많이 복잡해 질 수 있다.
자바에서는 스프링(Spring)과 같은 아주 좋은? 프레임워크가 있기 때문에 이 프레임워크를 잘 사용하면 의존 관계 주입을 편하게 할 수 있을 것이다.

요약

클래스가 내부적으로 하나 이상의 자원에 의존하고, 그 자원이 클래스 동작에 영향을 준다면 싱글턴과 정적 유틸리티 클래스는 사용하지 마라. 의존 관계 주입은 클래스의 유연성, 재사용성, 테스트 용이성을 개선해 주기 때문에 의존관계 주입(DI)를 잘 이해하고 Spring 프레임워크를 통해 잘 사용하도록 하자!

profile
주니어 백엔드 개발자입니다!

0개의 댓글