JAVA

[JAVA/SpringBoot] DI (의존성 주입) 의 이해 (1-15)

wonderson 2022. 5. 28. 09:50
반응형

[여기에 적은 거는 강의 내용을 다 적은게 아니라서 강의자료 보면서 이 게시글 참고하자.]

[스프링 심화 강의 1주차 15강 DI (의존성 주입) 의 이해]

 

- springCore 프로젝트에서 실습

- 객체 이름은 주로 소문자 이용

 

- DI는 미리 만들어져있는 객체를 가져다가 사용하겠다.

 

 

강한 결합의 문제점

['강한 결합' 이해를 위한 예제]

 

1. Contoller1  Service1 객체를 생성하여 사용

public class Controller1 {
	private final Service1 service1;

	public Controller1() {
		this.service1 = new Service1();
	}
}

 

2.Service1 Repostiroy1 객체를 생성하여 사용

public class Service1 {
	private final Repository1 repository1;

	public Service1() {
		this.repository1 = new Repository1();
	}
}

 

3. Repostiroy1 객체 선언

public class Repository1 { ... }

 

만약, 다음과 같이 변경된다면

 

Repository1 객체 생성 시 DB 접속 id, pw 를 받아서 DB 접속 시 사용

  • 생성자에 DB 접속 id, pw 를 추가
public class Repository1 {

	public Repository1(String id, String pw) {
    // DB 연결
    Connection connection = DriverManager.getConnection("jdbc:h2:mem:springcoredb", id, pw);
  }
}

 

[**"강한 결합"**의 문제점]

  • Controller 5 개가 각각 Service1 을 생성하여 사용 중
  • Repository1 생성자 변경에 의해..
  • 모든 Contoller모든 Service 의 코드 변경이 필요

 

강한 결합 해결방법

  1. 각 객체에 대한 객체 생성은 딱 1번만!!
  2. 생성된 객체를 모든 곳에서 재사용!!!

👉 그렇다면 **"강한 결합"**을 해결할 방법이 없을까?

 

1. Repository1 클래스 선언 및 객체 생성repository1

public class Repository1 { ... }

// 객체 생성
Repository1 repository1 = new Repository1();

 

2. Service1 클래스 선언 및 객체 생성 (repostiroy1 사용)service1

Class Service1 {
	private final Repository1 repitory1;

	// repository1 객체 사용
	public Service1(Repository1 repository1) {
		// 이제 이걸 안 쓴다. this.repository1 = new Repository1();
		this.repository1 = repository1;
	}
}

// 객체 생성
Service1 service1 = new Service1(repository1);

 

[이건 뭘까? ]this.repository1 = new Repository1();

더보기

this.repository1 = new Repository1();
이 부분 계속 헷갈리는 데 repository1에 바로 객체 생성하는 건가?

Repository1 repository1 = new Repository1();

this.repository1 = repository1;

 

강의에서는 이렇게 적은 거 같은데 간편하게 합칠 수 있는건가?

 

그림 중요★★★

미리 생성된 객체를 받아서 쓰자!!

Service에서 repository1에 대한 new를 하는 것이 아니라

repository1이 Repository 클래스에서 new로 repository1 객체를 만들고

만들어진 repository1객체를 가져다가 new Service할 때 repository1을 넣어서 사용하자.

 

3. Contoller1 선언 ( service1 사용)

Class Controller1 {
	private final Service1 service1;

	// service1 객체 사용
	public Controller1(Service1 service1) {
		//이제 이걸 안쓴다. this.service1 = new Service1();
		this.service1 = service1;
	}
}

 

 

4. 만약, 다음과 같이 변경된다면,

Repository1 객체 생성 시 DB 접속 id, pw 를 받아서 DB 접속 시 사용

  • 생성자에 DB 접속 id, pw 를 추가

[개선 결과]

Repository1 생성자 변경은 이제 누구에게도 피해(?) 를 주지 않음

Service1 생성자가 변경되면? 모든 Contoller → Controller 변경 필요 X

결론적으로, 강한 결합 ⇒ 느슨한 결합


DI (의존성 주입)의 이해

[강의에서 들은 거]

더보기

흐름이 뒤바뀌었다. Controller에서 Repository로 가던 흐름이

Repository에서 Controller로 가고있다.

Service가 만들어질 때 repository1을 가져다가 사용

-> service1이 만들어졌다. 그러면 안에 repository1이 만들어져 있을거고 service1을 Controller들이 사용할 때 그냥 repository1을 가져다가 재사용하는 방식이다.

 

->원래는 Service가 Repository1에 의존성이 있는건데 거꾸로 의존성이 있는 거를 Repository에서 Service로 주입해준다.

 

느슨한 결합의 장점

service1이 repository1을 가져다가 사용하지만 repository1이 어떤 아이디와 패스워드를 가지고 만들어졌는지는 service1이 알 수 없다.

마찬가지로 Controller1, 2, 3, 4, 5에서도 service1이 어떻게 만들어졌는지 알 필요없고 알 수도 없다. 이 점이 중요한 부분이다.

 

"제어의 역전 (IoC: Inversion of Control)" 프로그램의 제어 흐름이 뒤바뀜

 

  • 일반적: 사용자가 자신이 필요한 객체를 생성해서 사용
  • IoC (제어의 역전)
    • 용도에 맞게 필요한 객체를 그냥 가져다 사용
      • "DI (Dependency Injection)" 혹은 한국말로 "의존성 주입"이라고 부릅니다.
    • 사용할 객체가 어떻게 만들어졌는지는 알 필요 없음
    • 실생활 예제) 가위의 용도별 사용
      • 음식을 자를 때 필요한 가위는? → 부엌가위 (생성되어 있는 객체 kitchenScissors)
      • 무늬를 내며 자를 때 필요한 가위는? → 핑킹가위 (생성되어 있는 객체 pinkingShears)
      • 정원의 나무를 다듬을 때 필요한 가위는? → 전지가위 (생성되어 있는 객체 pruningShears)

 

DI 적용 시도

  • ProductRepository 객체 생성 시 DB 접속을 위한 url, id, passwrod 를 모두 받아서 생성
반응형