개발일지/스프링

스프링 IoC, DI, Bean 이란

티에리앙리 2022. 1. 30. 15:53

우선 Ioc, DI, Bean에 대해 알아 보기전에

자바에서 Class, Object, Instance 개념에 대해서 알아보자

Class -> 설계도

Object -> 실체화가 가능한 것

Instance -> 실체화가 된것

 

class abstract class
마린 (object)
 - 변수
 - 변수
유닛
(추상적인 의미)


즉, object가 사용되면 instance 이다.

 

IoC ( Inversion of Control )와 DI

간단히 말하면 객체 지향 프로그램에서 다른 객체를 사용하는 것을 의존성 주입(DI : Dependency Injection)이라 한다.

(필요한 곳에서 가져가서 사용하는 것) (다른 객체에 의존한다.)

다른 객체를 사용하기 위해서는 객체를 생성하거나 생성되어 있어야 하는데

내가 직접 생성하여 사용할 수도 있고,

미리 만들어져 있는 것을 할당 받아서 사용할 수도 있다.

 

1.A가 '갑' B,C가 '을'인 경우

// A객체가 B,C 객체를 직접 생성한다.
new B()  new C()

A는 B,C의 기능을 사용한다(B,C의 기능에 의존한다.)

 

2. A가 '을'이고 B,C를 가지고 있는 누군가(Z)가 '갑'인 경우

// B,C 객체가 외부에 생성되어 A객체에 주입된다.
setter or construct()
   ^        ^
   |        |
new B()  new C()

A가 B,C의 기능이 필요해 Z에게 요청하면 Z가 B,C의 기능을 주입시켜주는 구조

여기서 객체를 생성하고 라이프사이클을 관리하고 다른 필요한 객체의 의존 주입을 관리해주는 누군가를 컨테이너라 부르는데

스프링이 컨테이너의 역할을 한다.

이 컨테이너의 역할을 개발자입장에서 보면 개발자가 객체를 제어하지 않고 스프링 컨테이너로 객체의 제어권이 넘어갔다는 의미로 ioc(Inversion of Controll)(제어의 역전) 이라고 한다.

정리

1번 A는 B,C의 기능에 의존하고 있다. (강한 결합)

2번 컨테이너가 의존을 주입하고 있다. (약한 결합)

이처럼 객체간의 의존관계에서 객체를 직접생성하면 생성부터 메모리 관리를 위한 소멸까지 해당 객체의 라이프사이클을 개발자가 다 관리해야 하므로 강한 결합이 되는 것이고

이미 누군가가 생성한 객체를 주입받으면 사용만 하면 되기 때문에 약한 결합이 된다.

객체지향 프로그래밍에서

약한 결합을 사용하면 개발자가 관리할 것이 적어지는 장점이 있다.

예시)

//의존해야하는 기능이 있는 클래스
public class UserstandDI(){

    // api나 프레임워크에서 제공하는 기능들도 강한결합, 약한결합을 만들 수 있음
    public static void main(String[] args){
        // 강한 결합
        Date date = new Date();
        System.out.println(date);
    }

    public static void getDate(Date d) {
        // 약한 결합
        Date date = d;
        System.out.println(date);
    }

    public static void memberUse1() {
        // 강한 결합 : 직접 생성
        Member m1 = new Member();
    }

    public static void memberUse2(Member m){
        // 약한결합은 의존할 객체를 주입받아야 하므로 파라미터로 받아들여 객체에 할당
        // 약한 결합 : 생성된 것을 주입받음(Dependency Injection)
        Member m2 = m;
    }
}

// 멤버 클래스를 사용하는 메서드
Class Member{
    String name;
    String nickname;
    public Member(){}
    private Member() {}    // 만약에 여기가 private이면 강한 결합은 사용할 수 없다
    // 이미 만들어진걸 주입받기 때문에 만들어질지 안만들어질지 걱정할 필요가 없기 때문에
    // 이처럼 약한 결합을 사용하는 프로그래밍은 다른 클래스의 변화에 더 안전하고 유연하게 대처할 수 있다.
}

결론적으로 강한결합이 아닌 약한결합을 사용한다.

 

Bean 이란

스프링 Ioc 컨테이너가 관리하는 자바 객체를 Bean이라고 한다.

 

 

스토리 텔링하면서 설명하기

IOC란 object를 직접 new로 생성해서

heap이라는 메모리 공간에

ex) 개발자가 객체를 직접 생성

Marine marine = new Marine();

해서 heap이라는 메모리 공간에 올리게 되면

heap 에 있는 marine의 주소는

new를 만든 해당 스택인 method에서 관리하게 된다.

즉, marine 에서 관리하게 된다.

 

public void make1(){

     Marine marine = new Marine();

}

그런데 여기서 marine은 메서드가 실행된 순간에만 메모리에 있다

 

다른 메서드에서

public void make2(){

     Marine marine = new Marine();

}

이렇게 만들면 make1과 make2 에서 만든 marine은 다른 것이 되므로

각각의 메서드가 서로 다른 marine을 관리하기 때문에

공유하기가 힘들다.

즉, make1 에서 만든 marine을 다른 메서드에서 사용하고 싶으면 공유하기가 쉽지않고 비효율적이다.

이러한 로직을 구현하기가 힘들기 때문에

그러므로 스프링 내가 만든 오브젝트를 관리해준다.

 

즉, 오브젝트들이 어려개 있는데

ex) 의자, 마린, 붕어빵, 사자

이러한 오브젝트를 클래스로 다 만들어 놨는데

스프링이 이 객체들을 스캔해서 직접 메모리에 올려준다.

이것이 IOC 이다.

 

 

DI란

예전에는 내가 new를 해서 그 객체의 주소를 관리를 했다면

이제는 스프링이 object를 스캔해서 메모리에 넣었기 때문에

이 메모리에 있는 것들을 내가 관리하는게 아니라 스프링이 관리한다.

이것을 IoC라 하는데

그러면 스프링이 관리하는 객체를 내가 원하는 모든곳(모든 클래스의 메서드)에서

메모리에 있는 객체를 가져와서 사용할 수 있다.

 

즉, 메서드A, 메서드B, 메서드C 에서

메모리에 있는 마린 객체를 가져와서 사용하는데

각 메서드에서 사용하는 마린 객체는 같은 객체이다.

한마디로 싱글톤으로 관리한다.

즉, 스캔을 하면 마린이 딱 한번만 heap 메모리에 뜨고

그 마린을 공유해서 사용할 수 있어야한다.

즉, 이렇게 필요한 곳에서 객체를 가져가서 사용하는 것을 DI(Dependency Injection) 이라고 한다.

그러면 스프링이 관리하는 이 자바 객체를 Bean이라고 한다.