[여기에 적은 거는 강의 내용을 다 적은게 아니라서 강의자료 보면서 이 게시글 참고하자.]
[스프링 심화 강의 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. 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 를 모두 받아서 생성
'JAVA' 카테고리의 다른 글
[JAVA/SpringBoot] 스프링 3계층 Annotation 적용하기 (1-17) (0) | 2022.05.28 |
---|---|
[JAVA/SpringBoot] 스프링 IoC 컨테이너 사용하기 (1-16) (0) | 2022.05.28 |
TIL_항해99_19일차 (0) | 2022.05.28 |
[JAVA/SpringBoot] 객체 중복 생성 문제 해결 (1-14) (0) | 2022.05.27 |
[JAVA/SpringBoot] Controller, Service, Repository 역할 (1-12)★★ (0) | 2022.05.27 |