[스프링] IoC(Inversion of Control), DI(Dependency Injection), Spring Container, Bean 정리
Spring Boot

[스프링] IoC(Inversion of Control), DI(Dependency Injection), Spring Container, Bean 정리

728x90

 

 

의존성 역전(Inversion of Control)

IoC란 Inversion of Control의 약어로, 객체의 의존성을 역전시켜 객체 간의 결합도를 줄이고 유연한 코드를 작성하게 하여 가독성 및 코드의 중복, 유지보수를 편하게 할 수 있게 한다. 

 

의존성 주입(Dependency Injection)

DI란 Dependency Injection의 약어로, 번역하면 의존성을 주입한다는 말이다. 말 그대로 객체를 직접 생성하는 것이 아니라 외부에서 생성한 후 주입을 시켜주는 방식이다.

무슨 말인지 모르겠으니 아래의 예시를 통해 알아보자.

 


 

일반적으로 의존성에 대한 제어권은 객체 자기 자신이 갖는다. 아래의 코드는 Sample이라는 클래스에서 Apple 객체를 불러오는 예제이다. 의존관계는 간단히 말해 new라는 키워드를 통해 생성된다. 

class Sample{
    private Apple apple = new Apple();
}

 

아래는 SampleTest라는 클래스에서 Apple 객체를 생성한 뒤 Sample 클래스의 생성자로 주입시켜 준다. 여기서는 Sample이 직접 Apple을 생성하는 것이 아니라 생성자로 주입받는다.

class Sample{
    private Apple apple;
    
    public Sample(Apple apple){
    	this.apple = apple;
    }
}


class SampleTest{
	
    Apple apple = new Apple();
    Sample sample = new Sample(apple);

}

 

이처럼 첫 번째 예시에서는 Apple 객체의 제어권이 Sample에게 있었다면, 두 번째 예시에서는 Sample에게 있는 것이 아니라 SampleTest에게 있다. 이처럼 의존성을 역전시켜 제어권을 직접 갖지 않는 것을 IoC라고 하며, 의존성을 외부에서 주입시켜 주는 것을 DI라고 한다.

 

 

그렇다면 이게 대체 무슨 의미가 있는 것일까?

스프링에서는 Spring 컨테이너, IoC 컨테이너라는 개념을 사용한다. 컨테이너는 보통 인스턴스의 생명주기를 관리하며, 생성된 인스턴스들에게 추가적인 기능을 제공하도록 하는 것이라 할 수 있다.

다시 말해, 컨테이너란 당신이 작성한 코드의 처리과정을 위임받은 독립적인 존재라고 생각하면 된다. 컨테이너는 적절한 설정만 되어있다면 누구의 도움 없이도 프로그래머가 작성한 코드를 스스로 참조한 뒤 알아서 객체의 생성과 소멸을 컨트롤해준다.

스프링 컨테이너는 스프링 프레임워크의 핵심부에 위치하며, 종속객체 주입을 이용하여 애플리케이션을 구성하는 컴포넌트들을 관리한다. 이때 스프링 컨테이너에서 생성되는 객체를 Bean이라고 한다.

 

Bean

Bean은 Spring Bean Container에 존재하는 객체를 말한다. Bean Container는 의존성 주입을 통해 Bean 객체를 사용할 수 있도록 해준다. Bean은 보통 싱글턴으로 존재한다. Beans는 우리가 컨테이너에 공급하는 설정 메타 데이터(XML 파일)에 의해 생성된다.

 


 

그럼 스프링 컨테이너에 Bean은 어떻게 생성되는 것일까?

1. Component scan

스프링부트로 애플리케이션을 만들게 되면 가장 상위 클래스에 @SpringBootApplication이 있을 것이다.

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
    	SpringApplication.run(Application.class, args);
    }

}

 

인텔리제이 기준으로 command 키를 누른 상태로 @SpringBootApplication을 클릭하게 되면 @SpringBootApplication을 구현한 코드를 확인할 수 있다.

 

@ComponentScan은 @Component 어노테이션이나 stereotype(@Service, @Controller, @Repository 등) 어노테이션이 부여된 class를 찾아 자동으로 Bean으로 등록해주는 역할을 한다. 여기서 @ComponentScan을 해주는 범위가 해당 어노테이션이 붙은 위치보다 하위의 class들만 스캔해주기 때문에 @SpringBootApplication의 위치가 가장 상위 위치에 있어야 한다.

@Service, @Controller, @Repository 등의 어노테이션들도 command 키를 누른 후 클릭해보면 @Component가 있는 것을 확인할 수 있다.

 

추가적으로 Bean으로 등록하고 싶은 class가 있다면 @Component 어노테이션을 붙여줘도 상관 없다.

 

 

2. @Configuration에서 @Bean으로 등록

@Configuration 어노테이션을 사용해서 직접 @Bean을 등록해주는 방법이다. @Bean 어노테이션을 사용하면 자동으로 빈으로 등록된다.

@Configuration
public class HttpConfig {

    @Bean
    public RestTemplate createRestTemplate(){
        return new RestTemplate();
    }
}

 

 

 

마무리

스프링을 처음 공부한다면 IoC, DI 부분이 잘 이해가 되지 않을 것이다. 기존에 자바 코드를 작성시에 인스턴스를 생성한다면 항상 new를 붙이고 새로 생성해줬었다. 하지만 스프링에서는 스프링 컨테이너가 싱글턴 패턴을 사용해 Bean으로 객체를 관리한다. Service나 Controller 같은 한번만 호출해도 되는 객체들은 Bean으로 등록하여 관리한다면 결합도가 낮아져 유지보수에 용이할 것이다. 

 

 

출처: https://limmmee.tistory.com/13 [심플하게 개발]

728x90