🌱 김영한님의 스프링 핵심 원리 - 기본편을 수강한 후 학습한 내용을 정리하고 기록하기 위해 작성하는 포스팅입니다.
스프링 컨테이너의 최상위 인터페이스는 BeanFactory이다. 빈을 관리하고 조회하는 메서드들이 다 여기에 정의되어 있고, ApplicationContext가 BeanFactory를 상속받아 기능을 확장하고 있다.
ApplicationContext가 가지는 부가 기능은 다음과 같다.
메세지소스를 활용한 국제화 기능
: 한국에서 들어오면 한국어로, 영어권에서 들어오면 영어로 출력
환경 변수
: 로컬, 개발, 운영 환경을 구분해서 처리
애플리케이션 이벤트
: 이벤트를 발행하고 구독하는 모델을 편리하게 지원
편리한 리소스 조회
: 파일, 클래스 패스, 외부 등에서 리소스를 편리하게 조회
스프링은 설정을 XML 및 java 파일 둘 다로 해줄 수 있다. 이것은 모두 BeanDefinition
이라는 추상화 덕분이다. 스프링에서는 XML, java 파일 등을 읽어서 BeanDefinition을 만든다. 그리고 이 BeanDefinition에 다양한 메타정보가 들어있어서, 스프링 컨테이너는 얘만 알면된다. 즉 실제 구현이 어떻게 되어있든, 스프링 컨테이너는 추상화(역할)에만 의존하고 있는 것이다. (DIP : Dependency Inversion Principle, 구현체에 의존하지 않음)
스프링에서는 빈을 생성하고 의존관계를 주입하는 역할을 스프링 컨테이너가 대신해서 수행해주는데, 이때 어떤 패키지부터 하위 패키지를 다 탐색할지를 basePackage로 지정해줄 수 있다.
basePackage를 따로 지정해주지 않으면 해당 클래스 파일이 있는 위치부터 하위에 있는 모든 패키지들을 탐색해서 bean을 생성해준다.
이때 권장되는 방법은, basePackage를 지정해주지 않고, Configuration 클래스를 최상단에 두어 모든 패키지를 다 탐색하게 하는 방식이다. 스프링 부트도 이 방법을 기본으로 제공한다. 이 방법이 좋은 이유는, 설정 정보라는 것이 결국은 프로젝트를 대표하는 정보가 들어가있는 파일이기 때문에 루트 위치에 두는 것이 향후 유지보수 관점에서도 좀 더 한눈에 파악하기 좋기 때문이다.
이렇게 하고, 탐색하지 않아도 되는 패키지만 제외해주는 것이 좋다. (---> 참고로 나는 이렇게 안해서 이번 프로젝트할 때 bean이 생성이 안돼서 고생을 좀 많이 했다...ㅎ...ㅎ)
cf)
@SpringBootApplication 안에 보면 ComponentScan이 붙어있고,
@Service, @Controller, @Repository, @Configuration도 내부를 살펴보면 다 @Component가 붙어있다.
-> 참고로 스프링의 내부 구현을 살펴보면 이처럼 어노테이션이 특정 어노테이션을 들고 있는 형식을 많이 살펴볼 수 있는데, 이는 자바가 지원하는 기능이 아니라 스프링이 지원하는 기능이다.
@Component
: Spring에서 관리되는 객체임을 표시하기 위해 사용하는 가장 기본적인 annotation이다.
아래의 어노테이션들은 모두 Component이면서 동시에 다른 논리적 의미를 지니고, 특정 기능을 수행한다.
@Repository
: 스프링이 해당 클래스를 데이터 접근 계층으로 인식하면서, 해당 계층의 예외를 스프링 예외로 추상화해서 변환해준다.
@Configuration
: 해당 클래스의 내용을 설정 정보로 인식하고, 내부에 명시된 빈이 싱글톤을 유지하도록 추가적 처리해준다.
@Controller
: Web MVC 코드에 사용되는 어노테이션이다. @RequestMapping은 해당 어노테이션이 붙은 클래스에서만 사용할 수 있다.
@Service
: 개발자들이 핵심 비즈니스 로직을 여기서 처리하겠구나 하고 인식할 수 있다는 논리적 의미밖에 없다.