본문 바로가기

Memo

DI? DIP

DI , 의존성 주입 찾다가 엄청난 블로그를 발견하고 잊어버리지 않고 공유하기 위해 글을 쓴다. 

단순히 정리만 하려다가 밑의 글들을 보고 두 분이 댓글로 이야기하는 부분 다른 분들 댓글 보고 더 헷갈려졌다. 기초가 너무 없어서 그런 거 같다. 

http://jwchung.github.io/DI%EB%8A%94-IoC%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EC%95%8A%EC%95%84%EB%8F%84-%EB%90%9C%EB%8B%A4

 

DI는 IoC를 사용하지 않아도 된다

Dependency Injection(DI)을 얘기할 때 빠지지 않는 글이 있다. Martin Folwer의 Inversion of Control Containers and the Dependency Injection pattern이다. 이 글에서 DI란 용어가 생겨나게된 배경을 볼 수 있다. 관련한 내용

jwchung.github.io

https://justhackem.wordpress.com/2016/05/13/dependency-inversion-terms/

 

의존성 역전 원리(Dependency Inversion Principle) 관련 용어

의존성 역전 원리(Dependency Inversion Principle)는 모듈간 낮은 결합도(loose coupling)와 테스트 용이성(testability)을 확보하는데 유용한 디자인 방법입니다. 저는 확장 가능하고(scalable) 클라우드 환경에

justhackem.wordpress.com

일단 간단히 범주로 나눠서 생각을 해보면 DI는 DIP를 구현하는 방법 중 하나고, IoC는 DIP가 적용된 모듈의 조립을 도와주는 도구라고 한다. 그렇다고 또 DIP 디자인이 사용되었다고 IoC 컨테이너가 반드시 필요한 것은 아니라고 한다. 너어무 어렵다

 

DI부터 보자 다른 분들의 예시가 좋은 게 많은데 간단히 정리하면

내가 책을 수집하는 거에 관심이 많다. 그래서 책장이라는 클래스를 만들어서 책을 살 때마다 책을 책장에 넣어둔다.

여기서 내 책장은 책에 의존한다. 그래서 DI, 의존성 주입한다는 것은 인수로 의존관계가 있는 친구를 받겠다는 것이다. 여기서 대표적인 방법으로 생성자 주입이 있다.

왜 이게 필요한지부터 얘기하면 내가 책을 너무 좋아해서 책을 계속 사면 생성자에서 책 종류 별로 계속 생성해 내야 한다. 그럼 책을 책장에서 빼고 넣고 하는 동작을 할 때 그 책장의 코드가 계속 변경되어야 한다. 그래서 생성자 주입을 통해서 해결한다. 그럼 책장은 무슨 책이 들어오 든 중요하지 않다. 

결론적으로 추상화를 해치지 않는 선에서 의존성을 어떻게 인수로 넘겨줄까 고민하는 방법이라고 한다.

다음으로 DIP는 내가 느끼기에 좀 더 큰 개념인데 대표적인 정의를 보자

  • 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
  • 추상화는 세부 사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다.

책의 예시를 들어 다시 설명하자면, 내가 막상 책을 사다 보니까 정리가 너무 안되어서 책을 책장에 칸을 나눠서 책 카테고리 별로 나누고 싶어졌다. 카테고리는 확실히 나뉜다는 가정이 있다. 그래서 책장에 책을 넣는데 과학 서적, 문학 서적 넣을 때마다 다르게 처리를 해줘야 하는 거다. 

그럼 이것도 종류가 늘어나면 또 코드가 길어질 텐데 그럼 위의 가정을 어기게 된다. 그래서 자바에서는 interface라는 걸 만들어서 그걸 기반으로 각 클래스를 구현한다. 내 예시로 하면 인터페이스가 책이 되고 과학서적, 문학 서적 등이 만들 클래스가 될 거다. 이러면 책 종류에 상관없이 의존성 주입받아서 고쳐 주기만 하면 된다.

대략 코드는 아래처럼 쓸 거 같다. 참고해서 작성했다

Interface Book{
  String getCategory();
  String getPosition();
  void putIn();
}
class Science implements Book{
    private String category;    
    private int position;    

    @Override
    public String getCategory() {
        return this.category;
    }
    @Override
    public String getPosition() {
        return this.position;
    }
    @Override
    public void PutIn() {
        this.position = 1;
    }
}
public class Literature implements Book{
  ...
   @Override
    public void PutIn() {
        this.position = 2;
    }
}
public class Cartoon implements Book{
  ...
}
class BookShelf {
    private List<Book> books;
    public BookShelf(List<Book> books){
        this.books = books;
    }
    public void putIn(){
        for(Book book : books){
                if(book.getPosition()==-1){
                book.putIn();
            }
        }
    }
}

 

많은 분들 참고해서 썼는데 아직도 많이 헷갈린다 개념적으로만 봐서 또 OOP에 대해 모르니까 제대로 정리가 안된느낌이다. 시간을 두고 다시 정리해야겠다.

 

 

참고: https://songii00.github.io/2020/06/21/2020-06-19-DI,DIP,IOC/

 

DI와 DIP - 익숙해서 놓치기 쉬운 개념 정리 1탄

“DI와 DIP” 사실 프로그래밍을 공부하는 사람들 중에 DI, DIP 개념을 못들어본 사람은 거의 없을 것이다. 설사 개념을 모르고 있다고 하더라도 우리가 무심코 사용한 코드 사이를 자세히 훑어본

songii00.github.io

 

'Memo' 카테고리의 다른 글

서비스 계층과 도메인 서비스  (0) 2023.10.04
저장소 패턴  (0) 2023.09.29
React. UseMemo, useCallback, React.Memo  (0) 2022.01.22
TS. 덕타이핑  (0) 2022.01.21
asm (생각나는 대로 정리중)  (0) 2021.09.25