제어의 역전(IoC)과 Bean

시루봉로·2023년 2월 14일
0

스프링 입문

목록 보기
3/4
post-thumbnail

IoC

일반적으로 의존성에 대한 제어권은 직접 의존성을 만드는 개발자에게 있다. 그러나 직접적으로 의존성을 만들지 않고, 외부에서 의존성을 가져오는 경우가 있다. 이를 제어의 역전(IoC, Inversion of Control)이라고 한다. 이때, 밖에서 나에게 의존성을 주입하는 것을 DI라고 한다. 따라서 DI는 IoC의 일종이라고 생각할 수 있다.

  • 자바 프로그램에서는 각 객체들이 프로그램의 흐름을 결정하고 각 객체를 직접 생성하고 조작하는 작업을 한다. 즉, 모든 작업을 사용자가 제어하는 구조이다.
  • IoC가 적용된 경우, 객체의 생성을 특별한 관리 위임 주체(IoC 컨테이너)에게 맡긴다. 사용자는 객체를 직접 생성하지 않고, 객체의 생명 주기를 컨트롤하는 주체와는 다른 주체가 된다.

Spring Bean과 IoC 컨테이너

스프링 프레임워크에서는 주입 대상이 되는 의존성 객체를 Bean이라고 한다. Bean은 스프링 IoC 컨테이너가 객체를 만든 뒤 Bean으로 등록하고, 의존성을 관리한다. 여기서 스프링 IoC 컨테이너는 ApplicationContext 또는 BeanFactory를 사용하는데, ApplicationContext는 BeanFactory를 상속 받기에 둘 다 같은 일을 한다. Bean의 구성 요소는 아래와 같다.

  • class: Bean으로 등록할 Java 클래스
  • id: Bean의 고유 식별자
  • scope: Bean을 생성하기 위한 방법 (싱글톤, 프로토타입 등)
  • constructor-arg: Bean 생성 시 생성자에 전달할 파라미터
  • property: Bean 생성 시 setter에 전달할 인수

그러나 Bean으로 등록까지는 개발자의 몫이다. 등록되지 않은 객체에는 의존성 주입을 해주지 않기에 이 점을 주의해야 한다.

Bean으로 등록하는 방법

@Bean 어노테이션과 @Configuration 어노테이션

예를 들어 다음과 같은 클래스가 있고, 이를 스프링 컨테이너에 등록하고자 한다.

public class SirubongResource {
	...
}

이 클래스를 빈으로 등록하기 위해선 명시적으로 설정 클래스에서 @Bean 어노테이션을 사용해 수동으로 스프링 컨테이너에 빈을 등록하는 방법이 있다. 설정 클래스는 다음과 같이 @Configuration 어노테이션을 클래스에 붙여주면 되는데, @Bean을 사용해 수동으로 빈을 등록해줄 때에는 메소드 이름으로 빈 이름이 결정된다. 그러므로 중복된 빈 이름이 존재하지 않도록 주의해야 한다.

@Configuration
public class ResourceConfig {
	@Bean
    public SirubongResource sirubongResource() {
    	return new SirubongResource();
    }
}

스프링 컨테이너는 @Configuration이 붙어있는 클래스를 자동으로 빈으로 등록해두고, 해당 클래스를 파싱(어떤 자료에서 원하는 정보만 가공하고 뽑아서 원하는 때에 불러올 수 있게 하는 것)해서 @Bean이 있는 메서드를 찾아서 빈을 생성해준다. @Configuration 안에서 @Bean을 사용하면 싱글톤을 보장받을 수 있기에 @Bean 어노테이션은 반드시 @Configuration과 함께 사용해야 한다.

이러한 방법은 수동으로 빈을 직접 등록해줘야 하는 상황인데, 주로 다음과 같을 때 사용한다.

  • 개발자가 직접 제어가 불가능한 라이브러리를 활용할 때
  • 애플리케이션 전범위적으로 사용되는 클래스를 등록할 때
  • 다형성을 활용하여 여러 구현체를 등록해주어야 할 때

이때, 애플리케이션 전범위적으로 사용되는 클래스와 다형성을 활용하여 여러 구현체를 등록할 때 @Bean을 사용하면 좋은 이유는 한 눈에 파악하여 유지보수하기 좋기 때문이다. 예를 들어 여러 구현체를 빈으로 등록할 때 어떠한 구현체들이 빈으로 등록되는지를 파악하려면 소스 코드를 찾아볼 필요 없이 해당 @Configuration 클래스만 보면 되기 때문이다.

@Component 어노테이션

하지만 수동으로 직접 빈을 등록하는 방식은 빈으로 등록할 객체가 많아질 수록 비효율적이다. 그래서 스프링에서는 특정 어노테이션이 있는 클래스를 찾아서 빈으로 등록해주는 컨포넌트 스캔 기능을 제공한다. 스프링은 컨포넌트 스캔(Component Scan)을 사용해 @Component 어노테이션이 있는 클래스들을 찾아 자동으로 빈 등록을 해준다. 스프링은 기본적으로 컴포넌트 스캔을 이용한 자동 빈 등록 방식을 권장한다.

@Component
public class SirubongResource {
	...
}

번외로 스프링에서는 @Controller, @Service, @Repository 어노테이션은 모두 @Component가 내재되어 있다. 따라서 이 어노테이션이 붙어있는 클래스들도 빈으로 등록된다.

  • @Controller: 해당 클래스를 스프링 MVC 모듈의 컨트롤러로 인식하게 해준다. @RequestMapping 어노테이션같은 어노테이션은 해당 어노테이션 밑에서만 사용할 수 있다. (웹 요청과 응답 처리)
  • @Service: 비즈니스 로직이나 Respository Layer를 호출하는 함수에 사용된다. 다른 어노테이션과 다르게 @Component에 추가된 기능은 없다. 그러나 추후 스프링에서 추가적인 Exception Handing을 해줄 수 있으니 비즈니스 로직에는 해당 어노테이션을 사용한다. (서비스 레이어, 내부에서 자바 로직 처리)
  • @Repository: 스프링에서 지원하지 않는 Exception을 Spring Exception으로 전환하기 위해서 사용한다. 주로 DAO(Data Access Object)에서 사용한다. (퍼시스턴스 레이어, DB나 파일같은 외부 I/O 작업을 처리)

참고 자료

본 글은 아래 링크를 기반으로 정리하였습니다.

profile
안녕하세요.

0개의 댓글