거누의 개발노트

[Spring] DI(Dependency Injection)를 사용하는 이유 본문

Spring

[Spring] DI(Dependency Injection)를 사용하는 이유

Gogozzi 2022. 6. 7. 17:52
반응형

Spring boot에서 DI를 사용하게된 이유를 알려면 강한결합과 느슨한결합에 대해서 알아야한다.

강합결합과 느슨한결합 중 강한 결합은 문제가 있는데, 어떤 문제인지 예제를 통해서 알아보면

먼저 Controller1에서 Service1 객체를 생성해서 사용했다.

public class Controller1 {
    private final Service1 service1;

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

그리고 Service1은 Repository1 객체를 생성해서 사용했다.

public class Controller1 {
    private final Service1 service1;

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

Repostiroy1 객체가 이렇게 되어있다가

public class Repository1 { ... }

아래 처럼 데이터베이스의 ID와 PW가 필요해졌다.

public class Repository1 {

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

위에서 Repository1의 코드가 변경되어서 아래 처럼 모든 Controller를 수정해야하는 경우가 발생한다.

이렇게 되면 유지보수가 어려워 진다.

그렇다면 이러한 문제를 해결할 방법은 어떤것이 있을지 생각해보자

우리가 해야할 일을 정리해 본다면

  • 각 객체에 대한 객체 생성은 딱 1번만 하고 싶다.
  • 생성된 객체를 모든 곳에서 재사용 하고 싶다.

위 방법을 적용하려면, repository1에서 new 객체를 생성하고 Service와 Controller는 생성되어있는 객체를 사용하기만 하면되는 것이다.

예시를 들어서 생각해보자

Repositroy1에서 객체를 생성했다.

public class Repository1 { ... }

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

그림으로 표현한다면 이렇게 표현이 될 것이다.

그런다음 Service1 클래스 선언 및 객체 생성 해보자.

Class Service1 {
    private final Repository1 repitory1;

    // repository1 객체 사용
    public Service1(Repository1 repository1) {
        //this.repository1 = new Repository1();
        this.repository1 = repository1;
    }
}

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

위 코드를 그림으로 표현해보면 아래 처럼 될 것이다.

service는 repository1 객체를 가지고 있고 이 객체는 생성되있는 객체를 다시 사용한 것이다.

Controller까지 변경해주자

Class Controller1 {
	private final Service1 service1;

	// service1 객체 사용
	public Controller1(Service1 service1) {
		//this.service1 = new Service1();
		this.service1 = service1;
	}
}

그리고 아까와 같이 데이터베이스 연결을 해야하는데, id와 pw가 필요하다면?

public class Repository1 {

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

// 객체 생성
String id = "sa";
String pw = "";
Repository1 repository1 = new Repository1(id, pw);

이렇게만 변경해주면 Service, Controller는 변경하지 않고도 원하는 로직이 수행 가능해 졌다.

이렇듯 repository1가 변경되어도 Service와 Controller에 있는 코드는 정상적으로 돌아가게 된다.

그리고 이렇게 변경된 결합을 느슨한 결합이라고 한다. (강한결합 -> 느슨한 결합)

 

그럼이제 DI에 대해서 공부해보자

IoC(IoC: Inversion of Control) ; 제어의 역전

뜻은 프로그램의 흐름이 뒤바뀌었다는 의미이다.

위에서 봤던 그림들로 이해해 보자면

먼저 왼쪽에있는 그림은 Controller에서 Service를 생성하고 Service에서 respository를 생성하여 사용했다.

오른쪽은 Repository에서 생성된 객체를 Service에서 재사용해서 Service를 생성하고 다시 Controller에서 Service를 재사용 했다.

이러한 상황을 제어의 역전(IoC)라고 한다.

  • Controller -> Service -> Repository
  • Repository -> Service -> Controller

그리고 이렇게 용도에 맞게 객체를 그냥 가져다 사용하는것을 DI라고 한다.

위에서 차근차근 알아봤듯이 DI는 유연성을 확보하고 결합도를 낮출수 있는것이다.

 

DI, IoC에 대해서 어느정도 이해는 가지만 실제로 코드로 적용하려면 IoC컨테이너와 Bean에대해서 알아야한다.

다음 주제는 정해졌다.

컨테이너와 Bean에 대해 공부해 봐야곘다.

https://geonoo.tistory.com/156?category=1077864 

 

[Spring] 스프링 컨테이너와 빈

스프링 컨테이너와 빈 스프링 컨테이너는 자바 객체의 생명 주기를 관리하며, 생성된 자바 객체들에게 추가적인 기능을 제공하는 역할을 한다. 여기서 말하는 자바 객체를 스프링에서는 빈(Bea

geonoo.tistory.com

반응형
Comments