일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- spring boot
- nestjs auth
- 카카오
- 카카오 코테
- 코딩테스트
- nestJS
- git
- 구조체배열
- nestjs typeorm
- C언어
- 컴포넌트스캔
- 코테
- python
- AWS
- @Autowired
- 스프링
- Spring
- 해시
- 가상면접사례로배우는대규모시스템설계기초
- 알고리즘
- OpenCV
- @Component
- 카카오 알고리즘
- C++
- thymeleaf
- 파이썬
- Nodejs
- 시스템호출
- 프로그래머스
- TypeORM
- Today
- Total
공부 기록장 💻
[Spring] 스프링으로의 전환, 스프링 컨테이너 생성과 스프링 빈 등록 과정 (@ApplicationContext, @Configuration, @Bean) 본문
[Spring] 스프링으로의 전환, 스프링 컨테이너 생성과 스프링 빈 등록 과정 (@ApplicationContext, @Configuration, @Bean)
dream_for 2023. 1. 26. 10:03
그동안 설정(구성) 정보 클래스인 AppConfig에서 객체를 생성하고, 객체들 간의 의존 관계를 구성하며 주입하였다.
그리고 애플리케이션에서 사용하고자 하는 서비스는, AppConfig에서 생성한 서비스 객체를 참조하는 방식을 이용했다.
Java Code를 통해 직접 DI를 주입했다면, 이번에는 스프링 컨테이너를 생성하고, 객체들을 스프링 빈으로 등록하여 스프링 컨테이너가 직접 객체들을 관리할 수 있도록 전환해보자.
본격적으로 스프링으로 전환을 해보도록 하자.
스프링 컨테이너의 계층 구조, BeanFactory와 ApplicationContext
우선 스프링 컨테이너의 계층 구조부터 살펴보자.
스프링 컨테이너의 상속, 계층 구조를 나타내면 다음과 같다.
BeanFactory
- 스프링 컨테이너의 최상위 인터페이스
- 스프링 빈을 관리하고 조회하는 역할을 담당
- getBean() 메서드를 제공
ApplicationContext
- BeanFactory의 기능을 모두 상속받아 제공
- 애플리케이션을 개발할 때 빈을 관리하고 조회하는 BeanFactory의 기능과 더불어, 수많은 부가 기능을 제공
ApplicationContext가 제공하는 부가 기능들
MessageSource
- 메시지소스를 활용한 국제화 기능
- 한국 웹브라우저에서 들어오면 한국어로, 영어권 브라우저에서 들어오면 영어로 출력
EnvironmentCapable
- 로컬, 개발(실제 테스트 서버 이용), 운영(실제 production 환경), staging 환경 등을 구분해서 처리하는 환경 변수 관리
- 각 환경 별로 어떤 데이터베이스를 연결해야 할 지 등의 정보를 처리해주는 기능
ApplicationEventPiublisher
- 애플리케이션 내 이벤트를 구독하고 관리하는 기능
ResourceLoader
- 파일, 클래스패스, 외부 등에서 들어오는 리소스를 추상화하여 편리하게 조회할 수 있도록 제공하는 기능
즉 정리하면, BeanFactory, ApplicationContext를 스프링 컨테이너라 한다.
BeanFactory의 모든 기능을 상속받는 ApplicationContext는 Bean을 관리하는 기능 뿐 아니라 편리한 여러 부가 기능들을 제공한다. 부가 기능이 포함된 ApplicationContext를 주로 사용하지, BeanFactory를 직접 사용할 일은 거의 없다.
다양한 설정 형식 지원
스프링 컨테이너는 다양한 형식의 설정 정보를 받아들일 수 있도록 유연하게 설계 되어 있는데, 자바 코드, XML, Groovy 등의 방식이 존재한다.
AppConfig.class
- AppConfig 클래스를 통해, 애노테이션 기반의 자바 코드로 설정하는 방식
appConfig.xml
- 과거에 많이 사용하던 방식으로, xml 문서를 설정 정보로 사용하는 방식
스프링 컨테이너가 어떻게 생성되는지 구체적인 과정을 코드와 과정의 각 단계를 그림을 통해 이해해보도록 하자.
스프링 컨테이너 생성 코드 - ApplicationContext 사용
스프링 컨테이너는 다음의 코드로 생성할 수 있다. 이는 애노테이션 기반의 자바 설정 클래스로 스프링 컨테이너를 만드는 코드이다. (XML 기반으로 만들 수 있지만, 현재는 대부분 편리한 애노테이션 기반 방식을 사용)
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
여기서 인터페이스인 ApplicationContext 를 스프링 컨테이너라 한다.
스프링 컨테이너는 AnnotationConfigApplicationContext 구현체의 생성자 파라미터로 전달한, @Configuration 어노테이션을 작성한 AppConfig 클래스에서 등록한 구성 정보를 활용하게 된다.
스프링 컨테이너의 생성 과정
스프링 컨테이너가 생성되고, 설정 정보를 참고하여 스프링 빈이 등록되고, 의존 관계가 설정되는 단계를 각각 살펴보자.
1. 스프링 컨테이너 생성 단계
- new AnnotationConfigApplicationContext(Appconfig.class) 를 통해 AppConfig의 정보를 전달하면, 스프링 컨테이너가 생성된다.
- 스프링 컨테이너 내에는 키가 빈 이름이고, 값이 빈 객체인 스프링 빈 저장소가 있다.
- 스프링 컨테이너는 AppConfig의 구성 정보를 활용하게 된다.
2. 스프링 빈 등록 단계
- 스프링 컨테이너는 스프링 빈 저장소에 빈을 등록한다.
- @Bean 애노테이션이 메서드를 모두 호출하여, 메서드의 이름을 빈 이름(키)으로, 반환되는 객체를 빈 객체(값)로 등록한다.
빈의 이름은 기본적으로 메서드 이름을 사용하지만, @Bean(name="memberService2")와 같이 빈 이름을 직접 부여할 수도 있다.
주의 할 점은, 빈 이름은 항상 각각 다른 이름을 부여해야 한다는 점이다.
3. 스프링 빈 의존 관계 설정 - 준비 단계
스프링 빈이 생성 되고, 의존 관계를 설정할 준비를 하게 된다.
4. 스프링 빈 의존 관계 설정 - 완료 단계
- memberService 구현체는 memberRepository를 의존한다.
- orderService 구현체는 memberRepository, 그리고 discountPolicy 를 동시에 의존한다.
이러한 설정 정보를 참고하여, 스프링 컨테이너는 생성자를 호출하며 의존 관계를 주입(DI)한다.
스프링 빈, 즉 객체의 참조값들이 다음과 같이 연결이 된다.
애노테이션 기반의 자바 코드 설정
AppConfig
AppConfig 클래스 이름 위에 @Configuration 어노테이션을 추가하여, 설정을 구성하는 Bean 이 존재하는 클래스임을 스프링 컨테이너에게 알리도록 하자.
그리고 각 메서드에 @Bean을 붙이자. 스프링 컨테이너에 각 객체는 스프링 빈으로 등록이 된다.
ApplicationContext 를 스프링 컨테이너라고 한다. 기존에는 AppConfig를 사용하여 직접 객체를 생성하고 의존 관계 주입(DI)를 했지만, 이제부터 스프링 컨테이너를 통해 DI를 수행하도록 구현한 것이다.
스프링 컨테이너는 @Configuration이 붙은 AppConfig 를 설정 정보로 사용하며, @Bean이라 적힌 메서드를 모두 호출하여 반환된 객체를 스프링 컨테이너에 등록함으로써, 스프링 컨테이너에서 각 객체들을 관리하게 된다. 이렇게 스프링 컨테이너에 등록된 객체를 스프링 빈이라 한다.
MemberApp, OrderApp
이제 MemberApp과 OrderApp에서 각각 사용하는 MemberService, OrderService 객체를 AppConfig에서 생성한 값을 참조하지 않고, 스프링 컨테이너인 ApplicationContext에 등록한 스프링 빈 객체를 가져와 사용하도록 하자.
ApplicationContext 인터페이스에, AnnotationConfigApplicationContext 클래스를 통해 @Configuration 어노테이션을 붙여 등록한 AppConfig 설정 클래스 참조 값을 가져오고, getBean() 메서드를 통해 MemberService와 OrderService의 객체를 가져오도록 하자.
스프링 빈은 memberService, orderService와 같이 @Bean 이 붙은 메서드 명을 스프링 빈의 이름으로 사용한다.
이전에는 개발자가 필요한 객체를 AppConfig를 사용해 직접 조회했다면, 이제부터는 스프링 컨테이너를 통해 필요한 스프링 빈(객체)를 찾아오도록 하면 된다.
applicationContext.getBean()의 name 파라미터에는 메서드의 이름을 전달해줌으로써 등록한 스프링 빈을 찾을 수 있다.