티스토리 뷰

웹/Spring

스프링 볶음밥 - 1장 - 7(IoC/DI/DL)

세댕댕이 2022. 7. 1. 17:50

+ 김영한의 스프링 핵심 기본원리 강의도 참고했습니다.

 

[이전글]

더보기

볶음밥 1장 - 1,2,3: 자바빈, 디자인 패턴(템플릿 메소드, 팩토리 메소드, 전략 패턴), 관심사의 분리, SOLID 및 객체지향 약간

볶음밥 1장 - 4,5,6: 제어의 역전, 프레임워크 vs 라이브러리, 스프링 IoC 및 용어 정리, 싱글톤, 동일성 vs 동등성, 빈의 스코프

 

[1-7] 의존관계 주입(DI)

IoC(제어의 역전)는 프로그램의 제어 흐름 구조가 뒤바뀌는 것이며, 객체를 생성하고 관계를 맺어주는 등의 제어 권한을 제 3자에게 위임하는데 이 제 3자 역할을 수행하는게 IoC 컨테이너라고 했었다.

여기서 IoC 대신에 의존관계를 맺는 것에 더 초점을 맞춰 더 깔쌈한 용어를 만들어내는데 그것이 바로 DI, 의존관계 주입이다. 

* DI는 IoC 개념 속에 포함된다

 

 

[의존관계란..]

의존하고 있다는 것 = B가 변하면 A에도 영향을 미친다는 것.

- A가 B를 사용하는 경우(B에서 정의된 메소드를 A에서 사용하는 경우, A ---> B) = "사용에 대한 의존관계"가 있다

- B의 메소드가 변하는 경우(형식 변경, 새로운 메소드 추가 등) A에도 영향을 미친다. 

- 의존관계에는 방향성이 있다. (A ---> B)

 

이전 글에서 역할(인터페이스)과 구현(구현 클래스)의 분리를 통해 클라이언트는 인터페이스에 대해서만 의존관계를 갖도록 해야 한다고 했었다. 클라이언트는 인터페이스에만 의존관계를 갖고있기 때문에 구현 클래스는 변경되더라도 클라이언트의 코드는 아무런 영향을 주지 않는다. (단 인터페이스가 변경되면 클라이언트의 코드도 변경되어야 한다)

 

- 설계 시점에 클라이언트가 인터페이스에만 의존관계를 맺고 있으면, 런타임 시점에 제 3자씨(컨테이너 or 팩토리)가 실제 구현 클래스를 결정, 주소값을 외부에서 제공(주입)해줌으로써 의존관계가 연결된다.

- 클라이언트는 설계 시점에서는 어떤 구현 클래스와 관계가 맺어지는지 존재를 알 수가 없다.

 

 

[의존관계 주입]이란 다음 3가지 조건을 충족하는 작업을 뜻한다

1. 클래스 모델, 코드에는 런타임 시점의 의존관계가 나타나지 않는다. 즉 인터페이스에만 의존하고 있어야 한다는 뜻이다.

- 설계 시점에 이미 구체적인 클래스의 존재를 알고있도록 하면 안된다.(런타임 시의 의존관계가 이미 코드 속에 다 들어있는 것은 IoC가 아니다...-> 제 3자씨에게 런타임 의존관계 결정 권한을 위임해야한다)

2. 런타임 시점의 의존관계는 컨테이너나 팩토리와 같은 제 3자씨가 결정해준다

3. 의존관계는 사용할 오브젝트에 대한 레퍼런스(주소값)을 외부에서 주입(전달)해줌으로써 연결된다

 

의존관계 주입의 핵심은 바로 설계 시점에서는 알 수 없었던 두 오브젝트간의 관계를 맺을수 있도록 해주는 제 3자씨가 있어야 한다는 것이다!!

컨테이너는 두 오브젝트간 런타임 의존관계를 설정하는 의존관계 주입 작업(DI)을 담당하며, 그와 동시에 스프링 빈의 생성과 초기화, 제공 등의 작업(IoC)을 수행한다. 내가 생각해 봐도 DI 개념을 위해서는 IoC 개념이 반드시 따라나와야한다.

 

1. IoC를 위해 객체의 생성 및 제어를 제 3자씨(컨테이너)에게 위임한다.

2. 컨테이너 역할은 빈 팩토리 혹은 애플리케이션 컨텍스트가 담당한다

3. 컨테이너는 @Configuration이 붙은 IoC 설정정보들을 등록한다

4. 설정정보 파일 내 @Bean이 붙은 메소드의 이름을 가져와 스프링 빈으로 등록한다

5. 등록된 스프링 빈들을 런타임 시점에 의존관계를 맺어주고, 생성자를 통해 주입(전달)한다 (DI)

 

-> 컨테이너는 IoC 개념과 DI 개념을 모두 담고 있다. IoC를 구현하는 방법으로 DI를 사용하는 느낌이기도 하다. 그래서 IoC/DI 컨테이너라고 부르기도 하고, 일반적으로는 DI 컨테이너, 혹은 스프링 컨테이너라는 이름으로 사용하게 된다. 스프링 컨테이너 없는 스프링은 앙꼬없는 찐빵 팥 없는 붕어빵!

 

 

[의존관계 주입은 어떻게?]

주입 = 외부에서 내부로 정보를 넘겨준다 = 파라미터를 이용해 오브젝트의 레퍼런스를 넣어주자!

-> 대표적인 방법이 바로 "생성자 주입"

- 이외에도 수정자(setter) 주입, 일반 메소드를 통한 주입, @Autowired 때려박기..등이 있다

- 프로젝트 해보면서 느낀건 그냥 롬복의 @RequiredArgsConstructor가 최고시다..bb

 

 

[의존관계 검색(DL, Dependency Lookup)]

IoC 구현 방법은 DI 뿐만 아니라 DL도 존재한다. 대충 외부에서 대신 주입해주는 것이 아니라, 생성자 내부에서 직접 컨테이너(컨텍스트)를 생성하고 getBean() 메소드를 통해 스프링 컨테이너에 담겨있는 구현 클래스를 직접 가져오는 방식인 것 같다.

-> DI의 거의 모든 장점을 갖고있고, IoC 원칙도 성립한다. 다만, 더 간결한 DI가 있기에 굳이 사용할 필요가 없는 것이다.

 

DI: 깔끔쓰

+ 자기 자신 역시 스프링 빈이어야 한다!

public class UserDao {
    private ConnectionMaker connectionMaker;

    public UserDao(ConnectionMaker connectionMaker) {
        this.connectionMaker = connectionMaker;
    }
}

 

DL: 너저분.. 불편

+ 자기 자신은 굳이 스프링 빈이 아니어도 된다. 자기가 직접 getBean()을 통해 가져오는 방식이기 때문.

public class UserDao {
    private ConnectionMaker connectionMaker;
    
    public UserDao() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DaoFacory.class);
        this.connectionMaker = context.getBean("connectionMaker", ConnectionMaker.class);
    }
}

 

 

 

개념이란게 참 알듯 하면서도 돌아서면 까먹어서 쉽지않다..

 

[1-8] XML을 이용한 설정은 과감히 생략!

- XML을 이용해 DI 설정정보를 만드는 방법 등을 배운다. 이거 정리해봐야 나중에 다 까먹는다

 

 

 

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   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
글 보관함