Java/Spring

스프링 컨테이너

태감새 2023. 2. 5. 01:34

MVC

일반적인 MVC 패턴을 생각해보자.
요청을 받고 Controller가 요청에 해당하는 메서드를 실행시킨다.
Controller는 Service로 로직을 구현하고 Serivce는 Repository를 통해 데이터를 얻어온다.
즉, 각 클래스는 필요한 객체를 생성하게되고 의존관계를 맺게된다.

의존관계

각 인터페이스를 구현한 클래스들이 구현하겠지만 그러면 그림이 복잡해질거같아서  간단하게 그렸다. 

현재 상황은 각 클래스들이 구현체에 의존하고 있는 상황이다. 그러면 SOLID원칙 중 하나인 DIP를 위배하게 된다.  위의 예시에서 Repository를 변경해야 한다면 Service 인터페이스를 구현하고 있는 클래스들을 모두 변경해야하는 일이 발생한다.

클래스들의 구성을 어떻게 바꿔야지 의존성을 낮출수 있을까?

새로운 클래스 생성

문제가 되는 것은 객체 생성자다. 객체 생성을 구현체에서 하지 않고 외부 클래스에서 생성하면 된다.

AppConfig

@Configuration 
public class AppConfig { 
	
	@Bean 
	public MemberService memberService() { 
		return new MemberServiceImpl(memberRepository()); 
	} 
	
	@Bean
    public OrderService orderService() { 
		return new OrderServiceImpl(memberRepository(), discountPolicy()); 
	} 
	
	@Bean
    public MemberRepository memberRepository() {
		return new MemoryMemberRepository(); 
	} 
	
	@Bean 
	public DiscountPolicy discountPolicy() { 
		return new RateDiscountPolicy(); 
	} 
}
// 예시

AppConfig 클래스 같이 객체 생성을 해주는 클래스를 만들어서 필요 클래스에 넣어주면 된다. 각 클래스는 생성자를 만들어서 필요한 객체를 AppConfig의 메서드를 통해서 받으면 된다. 

그러면 의존성 역전원칙을 지킬 수 있다. 더이상 구현체에 과하게 의존하지 않고 변경사항이 생겨도 AppConfig의 메서드만 변경하면 대상들에 모두 적용된다. AppConfig처럼 객체를 생성하고 관리하면서 의존관계를 연결해주는 것을 IoC(Inversion Of Control)컨테이너 혹은 DI(Direct Injection)컨테이너라고 한다. (또는 어셈블러, 오브젝트 팩토리 등으로 불리기도 한다.)

 

스프링 컨테이너

스프링에서 자바의 객체를 관리하는 공간을 뜻한다. 자바의 객체를 스프링에서는 Bean이라고 한다. 스프링 컨테이너는 이 빈을 개발자 대신 관리해주는 곳이다. ApplicationContext 를 스프링 컨테이너라고한다.

사실 위의 예시 코드는 스프링의 예시다. 다른건 다 같지만 어노테이션이 붙은것만 다르다.

 

@Configuration : AppConfig에 설정을 구성한다는 의미
@Bean : 해당 애너테이션이 붙은 메서드를 스프링 컨테이너에 빈으로 등록

 

스프링에서는 AppConfig의 역할을 스프링 컨테이너가 한다. 스프링 컨테이너는 @Configuration가 붙은 클래스를 설정 정보로 사용하고 @Bean이 붙은 메서드의 반환 객체를 스프링 빈에 저장한다. 스프링 빈은 관례적으로 메서드명을 빈의 이름으로 사용한다.
applicationContext의 getBean() 메서드를 사용하면 빈을 찾을 수 있다.
기존에는 개발자가 직접 구성영역(AppConfig)를 만들어서 의존관계를 주입해 줬다면 스프링에서는 스프링 컨테이너에 스프링 빈(@Bean)을 등록하여 스프링 컨테이너에서 스프링 빈을 찾아 사용하도록 만들었다.

스프링 빈 등록

1. 스프링 빈 직접 등록
위의 예시와 같이 @Configuration, @Bean 어노테이션을 이용해서 클래스와 메서드에 직접 입력하는 방식이다.
2. 컴포넌트 스캔
@Component 어노테이션을 활용한 방법이다. 직접 등록하는 방식은 클래스를 하나 만들고 메서드를 하나씩 가져와서 어노테이션을 붙여야하지만 컴포넌트 스캔을 사용하면 사용 클래스 위에 어노테이션만 붙이면 된다. 
@Controller
@Service
@Repository
어노테이션도 Component를 포함하고 있으므로 컴포넌트 스캔의 범위에 들어간다.
그리고 생성자에 @AutoWired 어노테이션을 입력하면 생성된 클래스의 관계를 연결해준다.

'Java > Spring' 카테고리의 다른 글

SpringMVC (1) - WAS와 WebServer  (0) 2023.04.19
스프링 배치 이해하기  (0) 2023.04.18
애너테이션  (0) 2023.02.05
Spring MVC  (0) 2023.02.04
JPA 기초  (0) 2023.02.04