티스토리 뷰

spring

Spring IoC Container

구삼칠오 2021. 9. 30. 01:26

Spring의 핵심 혹은 꽃이라 불리우는 IoC Container에 대해 알아보겠습니다. 무언가의 정의에 대해 알기 위해선 공식 문서를 참고하는 것이 가장 좋겠지요. Spring에도 reference문서가 있습니다.

https://docs.spring.io/spring-framework/docs/5.3.x/reference/html/core.html

It(IoC or DI) is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.

reference문서는 먼저 IoC가 무엇인지에 대해 설명하고 있습니다. IoC는 의존성을 생성자의 파라미터, 팩토리 메서드의 파라미터 혹은 팩토리 메서드에서 생성되거나 반환된 후 객체 인스턴스에 설정된 프로퍼티를 통해서만 정의하는 프로세스입니다. Container는 이러한 의존성에 생성된 bean객체들을 주입합니다. 이렇게 bean객체를 스스로 생성하거나 컨트롤 하는 것이 아니라 외부로 부터 주입을 받기 때문에 의존성 역전(IoC, Inversion of Control)이라 부릅니다.

 

역시 한글로 설명하니 더 어렵게 느껴지는 것 같습니다. (아니면 허접한 번역 떄문에...)

코드를 통해 살펴보도록 하죠.

class Service {
    private Repository repository;
    
    public Service(Repository repository) {
    	this.repository = repository;
    }
    
    public setRepository(Repository repository) {
    	this.repository = repository;
    }
}

Service는 repository를 사용하고 있지만 repository를 초기화 하는 코드는 Service내부에선 찾아볼 수 없습니다. 단지 repository를 수동적으로 받기만 할 뿐이고, 받을 수 있는 방법들을 제공할 뿐이지요. 세 가지의 방법을 제공하고 있군요 1. 생성자 2. set method 3. property. 중요한 것은 어떤 방법으로 Repository 객체를 제공 받던 이건 Service가 어떻게 할 수 있는게 아니라는 것입니다. 어떤 Repository를 받을지, 어떻게 생성할지 등의 control을 외부에 넘겨주고 있기 때문에 control(의존성)의 역전, IoC라 부릅니다.

 

reference 문서를 조금 더 살펴보도록 하겠습니다.

The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory. It adds:

Easier integration with Spring’s AOP features
Message resource handling (for use in internationalization)
Event publication
Application-layer specific contexts such as the WebApplicationContext for use in web applications.

 

org.springframework.beans와 org.springframework.context패키지는 Spring Framework IoC container의 근간을 이루고 있습니다. BeanFactory interface는 모든 타입의 객체를 관리할 수 있는 configuration mechanism을 제공하고 ApplicationContext은 다음과 같은 기능들을 추가로 제공하는 BeanFactory의 sub-interface입니다. 1. AOP기능들을 간편하게 적용 2. 메세리 리소스 핸들링(localization) 3. 이벤트 발행 등...

 

앞서서 IoC는 객체를 사용하는 곳에서 control을 가져와 외부에서 주입해주는 것이라고 설명했습니다. 이때 의존성을 주입해 주는 역할을 IoC container가 담당합니다. 객체 관리에 대한 기본적인 기능들은 BeanFactory에서 제공하고 있지만 거의 사용되지 않고, reference에서도 ApplicationContext가 완전한 상위호환이기 때문에 ApplicationContext에만 초점을 맞추고 설명하고 있습니다. 따라서 저도 ApplicationContext를 IoC Container로 간주하고 설명하겠습니다.

 

The ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code.

IoC Container(ApplicationContext)는 bean의 인스턴스화, 구성(혹은 설정) 조립을 담당합니다. Container는 어떤 객체를 어떻게 구성하고 조립하여 인스턴스화 할지를 구성 정보를 통해 파악합니다. 이때 구성 정보는 XML이나 Annotation 혹은 자바 코드로 나타낼 수 있습니다. (이번 글에서는 Annotation에 대해서만 다루겠습니다)

 

여기서 잊지 말아야 할 것은 Container는 기본적으로 각 Bean객체들을 싱글톤의 형태로 보관하고 관리한다는 것입니다. Bean객체는 싱글톤이라는 특성 때문에 state-less한 설계가 필요합니다.

 

 

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

컨테이너를 만들기 위해선 다음과 같이 configuration이 인자로 필요합니다. configuration은 container구성에 대한 메타데이터로서 관리해야할 객체들, 필요한 의존성 등에 대한 정보를 담고 있습니다.

configuration에는 다음과 같이 구성정보를 담습니다.

@Configuration
public class AppConfig {

    @Bean
    public Repository repository() {
        return new Repository();
    }

    @Bean
    public MealService mealService() {
        return new MealService(memberRepository(), menuSelection());
    }

    @Bean
    public MenuSelection menuSelection() {
        return new KoreanMenuSelection();
    }
}

 

먼저 @Configuration을 통해 이것이 Container의 구성정보 임을 알려줍니다.

@Bean으로 이것이 Container가 관리해야 하는 객체임을 고지합니다.

MealService에 repository와 menuSelection에 대한 의존성이 주입되고 있음을 볼 수 있습니다. 앞서 이야기 했듯 Spring Container는 기본적으로 객체들을 싱글톤의 형태로 가지고 있습니다. menuSelection()을 통해 얻은 객체와 service 내부에 menuSelection객체는 동일한 Bean객체로서 spring은 바이트 조작을 통해 주입에 필요한 의존성 객체들을 생성한 뒤 주입해 줍니다.

 

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
MealService mealService = applicationContext.getBean("mealService", MealService.class);

이렇게 등록된 bean객체들은 getBean method로 꺼낼 수 있습니다. 이때 bean name("mealService")은 @Bean mehod의 이름이 기본으로 지정됩니다.

 

 

 

ref.

docs.spring.io

김영한 - 스프링 핵심 원리 (기본편)

'spring' 카테고리의 다른 글

Spring Component Scan  (0) 2021.10.05
SOLID와 Spring - 2  (0) 2021.09.25
SOLID와 Spring - 1  (0) 2021.09.24
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함