DesignPattern

의존성 역전 원칙(Dependency Inversion principle)

dev_roach 2023. 8. 13. 17:51
728x90

의존성 역전 원칙 (Dependency Inversion Principle)

의존성 역전 원칙(DIP)은 SOLID 원칙 중 하나입니다. SOLID는 객체 지향 디자인을 더욱 이해하기 쉽고 유연하며 유지보수 가능하게 만들기 위한 다섯 가지 디자인 패턴 집합입니다. 의존성 역전 원칙을 이해하기 위해서 우리는 반드시 제어의 역전의존성 주입 개념에 대해서 이해해야 합니다.

 

Inversion of Control (제어의 역전)

제어란 무엇일까요? 그리고 역전은 무엇을 의미할까요? 이러한 질문에 답해보겠습니다. 먼저 제어와 역전을 알아봅시다. 제어란 코드의 실행 순서를 결정하는 흐름을 말합니다. 아래의 예시와 같이 코드를 작성하면 코드는 위에서부터 아래로 예측 가능한 방식으로 실행됩니다.

a = 10
b = 20

print(a + b) // 20

이 코드의 결과를 쉽게 예측하고 코드가 어떻게 실행될지 이해할 수 있습니다. 이는 우리가 코드의 실행 순서를 제어하고 있기 때문입니다.

 

다음은 테스트 코드의 예입니다:

class MessengerTest {
  public static boolean doTest() {
    // 뭔가 수행
  }

  public static void main(String[] args) {
    if (doTest()) {
        System.out.println("테스트 성공");
    } else {
        System.out.println("테스트 실패");
    }
  }
}

위 코드도 비슷하게 위에서 아래로 동작합니다. 하지만 이러한 테스트 코드를 어떻게 일반화할까요? 다음과 같이 이 클래스를 추상화할 수 있습니다:

public abstract class TestCase {
    public void run() {
        if (doTest()) {
            System.out.println("테스트 성공");
        } else {
            System.out.println("테스트 실패");
        }
    }

    public abstract boolean doTest();
}

public class TestApplication {
    private static final List<TestCase> testCases = new ArrayList<>();

    public static void register(Testcase testCase) {
        testCases.add(testCase);
    }

    public static final void main(String[] args) {
        for (TestCase testCase: testCases) {
            testCase.run();
        }
    }
}

이 추상화를 통해 클라이언트는 코드를 추가하기만 하면 간단하게 테스트 케이스를 생성할 수 있습니다:

public class MessengerTest extends TestCase {
    @Override
    public boolean doTest() {
        // 뭔가 수행...
    }
}

TestApplication.register(new MessengerTest());

이제 제어의 역전이 발생한 것입니다. 이는 코드가 어떻게 동작하는지 완전히 이해하지 못할 수 있다는 것을 의미합니다. 이는 코드의 실행 흐름을 고려할 필요가 없기때문에 중요합니다. 대신 프레임워크의 규칙에 따라 코드를 추가하기만 하면 됩니다. 이제 의존성 주입에 대해 알아보겠습니다.

의존성 주입 (Dependency Injection)

의존성 주입은 간단합니다. 클래스의 의존성을 외부에서 주입하는 것을 의미합니다.

class Money {
    private final int amount;
    private final Calculator calculator;

    public Money(int amount, Calculator calculator) {
        this.amount = amount;
        this.calculator = calculator;
    }

    public Money exchange(Country country) {
       return this.calculator.exchange(this.amount, country);
    }
}

 

위 예시에서 Money 클래스는 외부에서 의존성을 받아들이며, Money 클래스에 수정 없이 어떤 Calculator 클래스든 주입할 수 있습니다.

public static void main(String[] args) {
    Calculator calculator = new KoreanCalculator();
    Calculator calculator2 = new EuropeCalculator();

    Money money = Money(100, calculator);
    Money money2 = Money(100, calculator2);
}

이제 의존성 주입과 제어의 역전에 대한 이해가 되었을 것입니다. 이제 의존 역전 원칙에 대해 자세히 알아보겠습니다.

 

의존성 역전 원칙

앞서 언급한 대로, 의존성 역전 원칙은 SOLID 원칙 중 하나입니다. 이 원칙은 고수준 및 저수준 계층이 있는 경우, 두 계층 모두 상위 계층이 필요로 하는 동작을 노출하는 추상화에 의존해야 한다는 것을 의미합니다.

제어의 역전과 의존성 주입을 이해했다면, 이 패턴을 쉽게 구현할 수 있을 것입니다.

 

원본글: https://getting-harder.blogspot.com/2023/08/what-is-dependency-inversion-principle.html (영어로 작성된 글)

- 제가 작성한 글입니다. 영어로 먼져 작성하고 GPT 를 통해 한국어로 다듬다 보니 약간 어투가 이상하게 번역되긴하네요.

728x90

'DesignPattern' 카테고리의 다른 글

팩토리 메소드 패턴  (0) 2021.10.30
싱글톤(Singleton) Pattern  (0) 2021.10.28