Spring 기본 정리
김영한님의 스프링 기본편을 완강하고, 전체적으로 배운 내용을 내멋대로 정리하는 포스트
나중에 스윽 다시 읽어보려고 최대한 개념위주로 정리하고, 알고있었던 것은 제외했다.
SOLID 5대 원칙
디자인 패턴 글이 아니므로 스프링과 관련된 원칙만 쓰겠다
OCP(Open-Close Principle)
코드는 확장에는 열려있어야 하고 변경에는 닫혀있어야 한다.
무슨 말인지 맨 처음에 이해가 안됐지만
결국에는 구현체에 의존하지 말고 추상체에 의존하라 이 말이었다.
구현체에 의존해 해당 구현체에만 존재하는 메소드를 사용하는 방식 말고,
interface를 적극 활용해 혹시 모를 확장에 유연하게 대처하는것이 좋다.
DIP(Dependency Injection Principle)
위에서 의존하는 추상체에 실제 구현체 인스턴스를, 클래스 외부에서 넣어주는것이 좋다
Configuration 역할을 하는 클래스를 따로 두어, 기획에 의해 구현체가 아예 바뀌는 상황에도
인스턴스를 사용하는 클래스의 코드 변경은 일어나지 않도록 해야 한다.
이는 스프링 컨테이너가 해주는 역할이되며 IoC(Inversion of Control)과도 비슷한 맥락이다
스프링 빈
스프링 안에서 사용할 객체, Bean
Bean으로 등록되어야 하는 객체들의 기준은 어떻게 될까?
- DI가 필요한 객체
- 추상화 되어있어 사용 하는 구현체가 바뀔 수 있는 상황
- Singleton이 필요한 객체
- Request를 처리하는 Service와 같은 객체는 Singleton으로 처리하는것이 적절
- 다만 이때 주의해야 할 점은 StateLess하게 설계 해야 한다는 점
- 여러곳에서 접근하기도 하고 State를 가지면 예기치 못한 버그 발생 가능성
- 스프링 컨테이너는 CGLIB Proxy를 이용해 싱글톤을 구현하고 보장해준다
- 바이트 코드 조작을 통해 빈으로 등록한 객체를 상속받는 새로운 객체를 생성
Bean에 실제로 접근하려면 어떻게 해야 할까?
스프링 컨테이너의 getBean() 메소드를 호출한다
getBean으로 가져올 때 부모 타입으로 가져오면 자식 타입도 같이 딸려온다! -> 상속에 의해 당연
Bean들의 이름은 Unique 해야 한다
스프링 컨테이너
스프링 안에서 사용할 객체(스프링 빈)들을 관리하는 컨테이너이다.
보통 Annotaition을 이용해 Bean을 등록하기 때문에
AnnotationConfigApplicationContext을 사용한다
Bean으로 등록할 객체를 찾는 기준은 해당 객체에 @Bean 혹은 @Component가 있는지 확인
컨테이너에 Bean으로 등록하는 방법은 수동이 있고 자동이 있는데
스프링 Configuration
Bean들을 수동으로 컨테이너에 등록해주려면 @Configuration이 필수
각종 Bean들을 여기서 @Bean으로 수식해 준다.
하지만 잘 사용하지 않음(Component Scan 방식이 더 자주 쓰임)
Component Scan 방식을 사용하려면 @Configuration 대신에 @ComponentScan을 달아준다
그리고 Bean을 등록할 객체들의 실제 클래스 코드 위에 @Component를 달아준다.
Component Scan을 이용하면 @Autowired를 통해 DI를 자동 주입할 수 있다.
Component Scan의 기본 탐색 위치는 해당 Configuration 클래스가 존재하는 패키지부터이다.
의존관계 자동 주입
무적권 생성자 주입을 선택한다. 생성자 호출시점에 딱 1번만 호출되어 불변성을 지니며 Safe 하다
필드에 final까지 쓰게 되면, 만약 생성자에서 초기화를 까먹고 안했어도 컴파일 에러가 나기에
바로 실수를 알아챌 수 있다.
중복 빈 조회
@Autowired로 주입해주어야 하는 빈이 2개 이상일 때,
필드명(camelCase) 으로 매칭을 시도한다
@Qualifier와 @Primary로 처리한다
@Qualifier는 Alias를 지정해주는것이지 실제 빈 이름을 바꾸는것이 아니다
@Primary는 해당 객체에 조회 우선순위를 부여한다
빈 라이프 사이클
컨테이너에 의해 관리되는 빈은 고유한 라이프사이클을 가진다.
컨테이너는 빈 객체 생성 및 의존관계 주입까지 끝나면 초기화 콜백을 호출해준다
콜백으로 등록할 메서드에 @PostConstruct를 달아주면 된다.
종료도 마찬가지로 콜백으로 등록할 메서드에 @PreDestroy를 달아주면 된다.
빈 스코프
빈 스코프는 @Scope를 빈 객체에 달아주어 지정할 수 있다
컨테이너에 등록되는 빈은 기본적으로 싱글톤이다
싱글톤이 필요없는 객체(getBean으로 가져올 때마다 인스턴스 생성)은 프로토타입 빈으로 불리며
컨테이너는 프로토타입 빈은 생성과 의존관계에만 관여하고, 이외의 작업(사용 및 종료)은 프로그래머의 몫이다.
따라서 프로토타입 빈은 @PreDestroy 콜백을 받을 수 없다
이때 기본(싱글톤) 빈과 프로토타입 빈을 함께 사용할 때 문제가 생길 수 있는데
만약 기본 빈이 참조로 프로토타입 빈을 가지고 있고, 해당 프로토타입 빈에 접근 했을 때,
프로토타입(요청할때 마다 생성)이 아닌 마치 싱글톤처럼 동작한다는 점이다. 조심!
이는 ObjectProvider를 이용해 해결한다
ObjectProvider는 DL(Dependency Look-up) 기능을 대신 해주어, 원래 의도대로
요청할때마다 그에 맞는 프로토타입 빈을 생성해서 던져준다
@Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;
public int logic() {
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
사실 실무에서 프로토타입 빈은 잘 사용되지 않고 다 기본 싱글톤 빈으로 사용하긴 한다고 한다
스프링 핵심 원리 - 기본편 - 인프런 | 강의
스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...
www.inflearn.com
'Back-End > Spring Boot' 카테고리의 다른 글
[Spring Boot] Spring 시작 (0) | 2022.07.27 |
---|