본문 바로가기
Java

DI(Dependency Injection)이 뭘까?

by Taron 2024. 1. 10.

이번 글에서 DI(Dependency Injection) 의존성 주입에 대해 설명하도록 하겠습니다.

DI란?

DI는 Dependency Injection에 줄임말로 의존성 주입이란 뜻을 가지고 있습니다. 의존성 주입을 알기 전에 의존성이 무엇인지에 대한 개념을 먼저 짚고 넘어가야 합니다.

 

Depencency(의존성) 이란

A 가 B에 의존하면 B 가 변경되었을 때 A에게 영향을 미친다.

 

예시를 들자면 요리사가 레시피에 의존하고 있을 때 레시피가 변경되면 요리사에게 영향을 끼친다는 것을 생각하면 이해하기 쉬울 것 같습니다.

코드적 관점으로 보면 A 클래스에서 B 클래스를 의존하고 있다면 B 클래스의 기능 혹은 변경사항이 있다면 그 영향이 A 클래스에게 미친다고 이해할 수 있습니다.

코드를 보면서 설명하도록 하겠습니다.

public class Main {
    public static void main(String[] args) {
        Computer computer = new Computer();
        
        computer.booting();
        computer.shutdown();

    }
}

 

public class Computer {
    private Windows os = new Windows();
    public void booting(){
        os.booting();
    }
    public void shutdown(){
        os.shutdown();
    }
}

 

public class Windows {
    public void booting(){
        System.out.println("윈도우 컴퓨터가 켜졌습니다.");
    }
    public void shutdown(){
        System.out.println("윈도우 컴퓨터가 꺼졌습니다.");
    }
}

실행 화면

 

위 코드에 대해 설명을 드리자면 Main 클래스에서 Computer 객체를 생성하고 booting 메서드와 shutdown 메서드를 호출해 컴퓨터를 켰습니다.

Computer 클래스 안에는 Windows 객체를 생성했고 booting 메서드가 실행되면 windows 객체 안에 booting 메서드를 호출합니다.

Windows 객체에 booting 메서드가 호출되면 "윈도우 컴퓨터가 켜졌습니다." 메시지를 출력합니다. 

 

위 코드는 Computer 클래스가 Windows 클래스에게 의존하고 있는 것을 확인할 수 있습니다.

그럼 이제 Dependency Injection 이 무엇인지 알아보도록 하겠습니다.

 

Dependency Injection 이란

외부에서 객체를 주입받아 사용하는 것을 의미합니다.

앞서 보여드린 코드를 보면 Computer 객체가 Windows 클래스를 의존하고 있는데 만약 os 가 Windows 가 아닌 Linux 나 MacOS로 변경 된다면 저 코드는 전체를 변경해야 하는 코드입니다.

이러한 문제를 해결하기 위해 나온 개념이 Dependency Injection입니다. Dependency Injection 은 여러 방법이 있겠지만 이번 글에서는 한 가지 방법만 알아보도록 하겠습니다. 

첫 번째 방법으로 Setter를 만들어 객체를 주입받는 방법입니다.

코드를 보면서 설명하도록 하겠습니다.

public class Os {
    public void booting(){}
    public void shutdown(){}
}

 

public class Computer {
    private Os os;

    public Computer(Os os) {
        this.os = os;
    }
    public void booting(){
        os.booting();
    }
    public void shutdown(){
        os.shutdown();
    }
}

 

 

public class Windows extends Os{
    @Override
    public void booting(){
        System.out.println("윈도우 컴퓨터가 켜졌습니다.");
    }
    @Override
    public void shutdown(){
        System.out.println("윈도우 컴퓨터가 꺼졌습니다.");
    }
}

 

public class Main {
    public static void main(String[] args) {
        Windows windows = new Windows();
        Computer computer = new Computer(windows);

        computer.booting();
        computer.shutdown();

    }
}

실행 화면

 

위 코드를 보면 결과는 똑같지만 Main 클래스에서 Windows 객체를 생성해 Computer 생성자 파라미터로 객체를 주입하는 것을 확인할 수 있습니다.

Windows는 Os 클래스를 상속받아 Override로 Os 클래스에 선언되어 있는 booting 메서드와 shutdown 메서드를 재정의 하는 것을 볼 수 있습니다.

이는 MacOS 나 Linux로 바뀌어도 Main에서만 바꿔주면 되는 코드로 코드를 재사용할 수 있는 코드로 바뀌었습니다!

그럼 이제 MacOS 클래스를 만들어 바꾸어 보겠습니다.

public class MacOS extends Os{
    @Override
    public void booting() {
        super.booting();
        System.out.println("맥북이 켜졌습니다.");
    }

    @Override
    public void shutdown() {
        super.shutdown();
        System.out.println("맥북이 꺼졌습니다.");
    }
}
public class Main {
    public static void main(String[] args) {
        MacOS macOS = new MacOS();
        Computer computer = new Computer(macOS);

        computer.booting();
        computer.shutdown();

    }
}

 

위에 코드와 달라진 것은 Windows에서 macOS로 바꾼 것 밖에 없지만 Os 가 변경되어도 Computer 클래스나 Os 클래스를 수정하지 않아도 실행 결과가 같은것을 확인 할 수 있습니다. 이외에 다른 코드는 수정하지 않았습니다.

이와 같이 Dependency Injection은 코드를 재사용 가능하게 하며 유지보수를 편하게 해주고 확장도 용이해집니다.

 

 

긴 글 읽어주셔서 감사합니다. 위 글에서 틀린 부분이나 개선할 부분을 알려주시면 참고하겠습니다.

감사하겠습니다!

 

'Java' 카테고리의 다른 글

JVM 메모리 구조에 대해 [JAVA]  (1) 2022.12.29
[Java]#9 개선된 for 문  (1) 2022.05.31
#8 예외 처리(Exception)  (0) 2022.04.17
#7 스레드(Thread)가 무엇인가?  (0) 2022.04.17
#6 자바 접근 제한자 종류와 차이점  (1) 2022.04.15

댓글