본문 바로가기
Java/Spring

[Spring] 제어의 역전 IoC(Inversion of Control)와 bean

by 전재경 2022. 12. 4.

제어의 역전 IoC(Inversion of Control)

 

구현 객체가 프로그램의 제어 흐름을 스스로 컨트롤하는 것은 개발자 입장에서는 당연한 자연스러운 흐름이지만

외부에서 관리하는 것을 제어의 역전이라한다.

프레임워크가 내가 작성한 코드를 제어하고, 대신 실행하면 그것은 프레임워크가 맞지만

내가 작성한 코드가 직접 제어의 흐름을 담당하면 그것은 라이브러리

 

한마디로, 스프링 프레임워크가 프로그램을 제어하는 것을 제어의 역전이라 한다.

 

  • 프로그램의 진행 흐름과 구체적인 구현을 분리시킬 수 있다.
  • 개발자는 비즈니스 로직에 집중할 수 있다.
  • 구현체 사이의 변경이 용이하다.
  • 객체 간 의존성이 낮아진다.

 

의존성은 쉽게 말해 어떤 객체가 사용해야 할 객체라고 할 수 있고, 이것을 직접 new 등을 써서 만들어 쓰면 의존성을 자기가 직접 만들어 쓴다고 할 수 있습니다.

public class OwnerController {
	private OwnerRepository ownerRepository = new OwnerRepository();
}
// OwnerController가, 필요한 OwnerRepository의 객체를 직접 생성하는 경우

 

밖에서 나에게 의존성을 주입해주는 것을 DI(Dependency Injection) 라고 한다.

따라서 DI는 IoC의 일종이라고 생각하면 된다.

 

[Spring] 의존관계 주입(Dependency Injection), 의존성 주입, DI

DI를 알기 전 의존관계에 부터 말하자면 의존관계 의존 대상 B가 변하면, 그것이 A에 영향을 미칠 때 A는 B와 의존관계라 한다. 쉽게 말해 B가 변경되었을 때 그 영향이 A에 미치는 관계 피자 가게

jkadv.tistory.com

 

bean

Spring IoC 컨테이너가 관리하는 자바 객체를 빈(Bean)이라는 용어로 부른다.

우리가 new 연산자로 어떤 객체를 생성했을 때 그 객체는 빈이 아니다.

ApplicationContext.getBean()으로 얻어질 수 있는 객체는 빈이다.

즉 Spring에서의 빈은 ApplicationContext가 알고있는 객체, 즉 ApplicationContext가 만들어서 그 안에 담고있는 객체를 의미한다.

여기서 말한 스프링 컨테이너는 스프링 빈의 생명 주기를 관리하고, 생성된 스프링 빈들에게 추가적인 기능을 제공

IoC와 DI의 원리가 스프링 컨테이너에 적용

개발자는 new 연산자, 인터페이스 호출, 팩토리 호출 방식으로 객체를 생성하고 소멸

스프링 컨테이너를 사용한다면 해당 역할을 대신해준다, 즉 제어 흐름을 외부에서 관리

객체들 간의 의존 관계를 스프링 컨테이너가 런타임 과정에서 만들어준다.

 

Bean 생성 방식

 

Component Scanning

Spring IoC Container가 IoC Container를 만들고 그 안에 Bean을 등록할때 사용하는 Interface들을 Life Cycle Callback이라고 부른다.

Life Cycle Callback 중에는 @Component이 붙어있는 모든 Class의 Instance를 생성해 Bean으로 등록하는 작업을 수행하는 Annotation Processor가 등록 돼있다.
Instance : 일반적으로 실행 중인 임의의 프로세스, 해당 클래스의 구조로 컴퓨터 저장공간에서 할당되어 현재 생성된 Object를 의미.

이때, @ComonentScan Annotation이 붙어있는 Class가 이에 해당한다.

 

즉, @ComponentScan, @Component Anotation을 사용해서 Bean을 등록하는 방법이다.

 

@ComponentScan은 어느 지점부터 Component를 찾으라고 알려주는 역할을 하고,

@Component는 실제로 찾아서 Bean으로 등록할 Class를 의미한다.

 

@ComponentScan은 @Component이 부여된 Class를 찾아 자동으로 Bean으로 등록해주는 역할을 한다.

@ComponentScan이 붙어있는 Class가 있는 package에서부터 모든 하위 package의 모든 Class를 찾아 다니며,

@Component나 @Component를 사용하는 다른 Annotation을 사용하는 Class를 찾는다.
[EX] Stereotype Annotation(@Controller, @Service, @Repository 등)
Stereotype Annotation들은 내부적으로 @Component Annotation을 사용한다.

Configuration

Configuration을 이용한 Bean 등록 방법은, XML에 설정하는 방법과 Java Class에 설정하는 방법이 있다.
Bean 설정파일은 XML과 자바 설정파일로 작성할 수 있는데 일반적으로는 XML에 설정하지만, 최근 추세는 자바 설정파일을 좀 더 많이 사용한다.

 

@Configuration 사용, @Bean 정의

먼저 Java class에서 @Configuration Annotation을 사용해서 직접 @Bean을 등록해주는 방법이다.
일반적으로 xxxxConfiguration와 같이 명명한다.

@Bean Annotation을 사용해 직접 Bean을 정의하면 자동으로 Bean으로 등록된다.

이렇게 Bean을 직접 정의해서 등록하면 @Component Annotation을 붙이지 않아도 된다.

@Configuration
public class ExampleConfiguration {
    @Bean
    public ExampleController exampleController() {
        return new ExampleController;
    }
}

exampleController()에서 리턴되는 객체(ExampleController)가 IoC Container 안에 Bean으로 등록된다.

 

@Configuration Annotation을 보면 이 Annotation도 내부적으로 @Component를 사용하기 때문에 @ComponentScan의 검색 대상이 되고,
그에 따라 Bean을 정의한 @Configuration이 읽힐때 그 안에 정의한 Bean들이 IoC Container에 등록되는 것이다.

 

XML 파일에 설정

XML 파일에 직접 Bean을 등록하여 Application의 Bean을 설정하는 방법이다.

 

XML 방식으로 Bean을 정의하는데 필요한 속성들은 아래와 같다.

  • class(필수) : 정규화된 자바 class 이름
  • id : bean의 고유 식별자
  • scope : 객체의 범위 (sigleton, prototype 등)
  • constructor-arg : 생성 시 생성자에 전달할 인수
  • property : 생성 시 bean setter에 전달할 인수
  • init-method, destroy-method

기본적인 양식은 아래와 같다.

<!-- A simple bean definition -->
<bean id="..." class="..."></bean>

<!-- A bean definition with scope-->
<bean id="..." class="..." scope="singleton"></bean>

<!-- A bean definition with property -->
<bean id="..." class="...">
	<property name="message" value="Hello World!"/>
</bean>

<!-- A bean definition with initialization method -->
<bean id="..." class="..." init-method="..."></bean>

 

실제 사용되는 예시는 아래와 같다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

    <bean id="dog" class="com.spring.Dog">
        <property name="myName" value="poodle"></property>
    </bean>

    <bean id="cat" class="com.spring.Cat">
        <property name="myName" value="bella"></property>
    </bean>

    <bean id="petOwner" class="com.spring.PetOwner" scope="singleton">
        <constructor-arg name="animal" ref="dog"></constructor-arg>
    </bean>
</beans>

 

Bean Scope

Spring은 기본적으로 모든 Bean을 Singleton으로 생성하여 관리한다.
Singleton Bean은 Spring Container에서 한 번 생성 후, Container가 사라질 때 Bean도 제거.

생성된 하나의 Instance는 Single Beans Cache에 저장되고, 해당 Bean에 대한 요청과 참조가 있으면 캐시된 객체를 반환.
하나만 생성되기 때문에 동일한 것을 참조, 기본적으로 모든 Bean은 Scope가 명시적으로 지정되지 않으면 Singleton.

구체적으로는 Application 구동 시 JVM 안에서 스프링이 Bean마다 하나의 객체를 생성하는 것을 의미한다.

그래서 Spring을 통해서 Bean을 주입 받으면 언제나 주입받은 Bean은 동일한 객체라는 가정하에서 개발 한다.

request, session, global session의 Scope는 일반 Spring Application이 아닌, Spring MVC Web Application에서만 사용

 

 

 

참고 블로그

 

 

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

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

leveloper.tistory.com

 

 

[Spring] Spring Bean의 개념과 Bean Scope 종류 - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

 

 

[Spring] IoC,DI, 스프링 컨테이너(Container), 스프링 빈(Bean)이란?

IoC(Inversion of Control)란? IoC는 제어의 역전이라는 뜻으로 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것을 말한다. 이전에는 개발자가 객체를 생성하고 관리하며 프로

code-lab1.tistory.com

 

댓글