Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archives
Today
Total
관리 메뉴

The Office Lover

의존 역전 원칙 - dependency inversion principle 본문

Design Patterns

의존 역전 원칙 - dependency inversion principle

Michael Gary Scott 2023. 8. 10. 10:50

소개

단일 책임 원칙과 개방 폐쇄 원칙은 이론적으로는 이해하기 쉬울 수 있지만 실제로 사용하는 데 어려움이 있습니다. 반면 의존 역전 원칙은 사용하기는 쉬우나 이해하는데 어려울 수 있습니다.

 

2023.07.27 - [Design Patterns] - 단일 책임 원칙 - single responsibility principle, SRP

 

단일 책임 원칙 - single responsibility principle, SRP

소개 객체지향 프로그래밍은 유지보수성과 재사용성으르 높이기 위해 다양한 설계 원칙을 제공합니다. 이 중에서도 '단일 책임 원칙'은 클래스나 모듈이 하나의 책임만을 가져야 한다는 원칙으

daniel6364.tistory.com

 

2023.06.08 - [Design Patterns] - 디자인 패턴 - 개방 폐쇄 원칙

 

디자인 패턴 - 개방 폐쇄 원칙

확장할 때는 개방, 수정할 때는 폐쇄 개방 폐쇄 원칙은 코드의 확장성 문제로 볼 수 있다. 추후 변경되는 요구 사항에 대응할 때 코드가 확장할 때는 개방, 수정할 때는 폐쇄될 수 있다면 해당 코

daniel6364.tistory.com

 

 

 

 

 

역전의존원칙

의존성 주입과 의존 역전이란?

 

1. 의존성 주입(Dependency Injection)

  • 의존성(Dependency)은 한 클래스나 모듈이 다른 클래스나 모듈에 의존하는 것을 의미합니다. 이것은 한 요소의 변경이 다른 요소에 영향을 미칠 수 있다는 것을 나타냅니다.
  • 의존성 주입(Dependency Injection)은 특정한 프로그래밍 기술로써 이해하거나 적용하기 쉽고 매우 유용합니다.
  • 의존성 주입을 한 문장으로 요약하면 new 예약어를 사용하여 클래스 내부에 종속되는 클래스의 객체를 생성하는 대신, 외부에서 종속 클래스의 객체를 생성한 후 생성자, 함수의 매개변수 등을 통해 클래스에 주입하는 것을 의미합니다.

2. 의존 역전(Dependency Inversion)

  • 의존 역전(Dependency Inversion)은 상위 모듈이 하위 모듈에 의존하지 않도록 하며, 두 모듈 모두 추상화에 의존하도록 설계하는 원칙입니다. 즉, 상세한 구현이 아니라 추상화에 의존함으로써 모듈 간의 결합도를 낮추고 유연성을 높입니다.
  • 상위 모듈과 하위 모듈의 구분은 간단히 말하자면 호출자는 상위 모듈에 속하고, 수신자는 하위 모듈에 속합니다.
  • Tomcat을 예로 들어보면 Tomcat은 자바 웹 애플리케이션을 실행하기 위한 컨테이너입니다. 웹 애플리케이션 코드는 Tomcat 컨테이너에 배포만 하면 별도의 작업이 필요 없이 Tomcat 컨테이너에서 호출하고 실행할 수 있습니다. 여기서 상위 모듈이 Tomcat이고 하위 모듈이 웹 애플리케이션에 해당됩니다. 둘 사이에는 직접적인 의존성이 없고 동일한 추상인 서블릿 사양에 의존합니다. 

 

[비효율적인 초기 코드 설계 예시]

class MessageSender {
    public void sendMessage(String message) {
        // 메시지 전송 로직
    }
}

class MessageReceiver {
    public String receiveMessage() {
        // 메시지 수신 로직
    }
}

class Application {
    private MessageSender sender;
    private MessageReceiver receiver;

    public Application() {
        sender = new MessageSender();
        receiver = new MessageReceiver();
    }

    public void run() {
        String message = receiver.receiveMessage();
        sender.sendMessage(message);
    }
}

위 예시에서는 Application 클래스가 MessageSender와 MessageReceiver에 의존하고 있습니다. 이는 의존성이 상세한 구현에 직접적으로 연결되어 있어 유연성이 떨어집니다.

 

 

[의존 역전을 적용한 코드 설계 예시]

interface MessageService {
    void sendMessage(String message);
    String receiveMessage();
}

class MessageSender implements MessageService {
    @Override
    public void sendMessage(String message) {
        // 메시지 전송 로직
    }

    @Override
    public String receiveMessage() {
        throw new UnsupportedOperationException("Sender cannot receive messages");
    }
}

class MessageReceiver implements MessageService {
    @Override
    public void sendMessage(String message) {
        throw new UnsupportedOperationException("Receiver cannot send messages");
    }

    @Override
    public String receiveMessage() {
        // 메시지 수신 로직
    }
}

class Application {
    private MessageService service;

    public Application(MessageService service) {
        this.service = service;
    }

    public void run() {
        String message = service.receiveMessage();
        service.sendMessage(message);
    }
}

위 예시는 Application 클래스가 MessageService 인터페이스에만 의존하도록 변경되었습니다. 이를 통해 상위 모듈(Application)과 하위 모듈(MessageSender, MessageReceiver) 간의 결합도가 줄어들었습니다.

 

 

 

 

역전의존원칙

결론

  • 의존 역전 원칙을 따르는 것은 소프트웨어의 유지보수성과 확장성을 높이는 데에 큰 도움을 줍니다. 
  • 추상화와 인터페이스를 통해 모듈 간의 결합도를 낮추고 코드의 재사용성을 높이는 결과를 얻을 수 있습니다.