2021.08.05 기록장
ToDo
- 알고리즘 문제
- 책 읽기
- 토비의 스프링
- 7월 회고 쓰기
Done
- 토비의 스프링
- 책 읽기
Weekly goal
- 책 읽기
- 토비 스프링 코딩
토비의 스프링
153p.
컨테이너가 자동으로 등록하는 빈이 존재한다.
예로 컨테이너 자신을 빈으로 등록한다.
159p.
스프링 빈의 스코프 중 프로토타입이 있다. 요청당 하나의 빈이 만들어지는데 컨테이너는 빈의 생성에만 관여를 하고 그 이후는 관여를 하지 않는다.
클라이언트의 요청은 물론 @Autowired시에도 새롭게 생성된다.
근데 여태 나는 빈의 스코프를 조작해서 사용해본 적이 없다. 활용법은 무엇일까?
예로 클라이언트에게 정보를 받아서 DTO를 new로 만들어서 관리하는 경우가 있다.
근데 DTO가 빈을 사용하고 싶을 경우가 생길 수 있다. 이런 경우 사용한다.
예로 만들면 요청을 받아서 DTO를 만들고 서비스에 넘겨주고 그 정보로 유저를 찾는 Flow다.
근데 여기서 문제는 폼과 서비스가 연결되어있다고 볼 수 있는 것이다.
왜냐면 유저의 번호가 Request에 담겨있을 것이라는 것을 service는 이미 알고 있다. 그러니 find 할 때 유저의 번호를 사용하지.
근데 텍스트로 받는 정보가 테이블의 id를 넘겨주는 것으로 변경이 되면 service의 코드는 변경이 불가피하다.
변경할 방법은 서비스는 Customer 자체를 받는 것이다.
위와 같은 형태가 될 것이다. 근데 위처럼 진행하면 컨트롤러에서 DAO에 접근하는 것을 상상할 수 있다.
이제 DI를 이곳에 적용해 보자. 스코프는 프로토타입으로 할 것이기에 매번 DI 될 것이다.
프레젠테이션 계층이 뷰에서 입력방식이나 컨트롤러는 서로 붙어있을 수 있고 서비스 계층은 분리될 수 있다.
물론 @ModelAttribute를 사용하는 것이 아닌 ServletRequest에서 값을 꺼내서 사용하는데 이는 중간에 컨버터를 둬서 해결할 수 있을 것 같다.
근데 위도 마음에 들지 않는 부분은 로우 레벨의 ApplicationContext를 사용한다는 것이다. 또 POJO로 유지되는 것이 아닌 스프링의 기능을 사용하는 것이다.
169p.
DI와 DL
그럼 어떻게 프로토타입의 빈을 꺼내서 사용할 수 있을까? DI를 통해서는 사용불가다 빈의 DI는 처음에만 이뤄지고 빈은 그럼 프로토타입의 빈이 박히는 것이기에 다른 방법을 생각해봐야 한다.
ServiceRequest를 직접 DI 하는 것이 아닌 중간에 객체를 두자. 마치 데코레이션 패턴처럼 이럼 DI가 가능해진다.
오브젝트 팩토리를 사용 or ServiceLocatorFactoryBean을 사용할 수 있다.
근데 추천하는 방법은 @Inject와 함께 javaX의 Provider를 사용하라는 것이다.
Provider는 java EE 6에 추가된 표준 인터페이스이다. get이라는 팩토리 메서드를 가지고 있어 사용하기 쉽다.
빈으로 등록된 Provider를 사용하는데 내부는 ApplicationContext를 DI 받아서 get 하는 데 사용한다. 그렇기에 new로 생성하는 것과는 다르게 컨테이너의 관리하에 생성되는 것이다. 그러니 프로토타입과 DI가 이뤄진 객체가 오는 것이다.
178p.
빈의 스코프 중에는 세션 스코프도 있다.
Http의 세션과 같은 스코프를 가지는 것이다.
세션이 유지되는 동안에는 같은 오브젝트를 사용할 수 있다.
DI 방식으로 변경하려면 위의 Provider처럼 중간에 뭘 둬야 할 듯하다.
근데 매번 새롭게 생성되는 것이 아닌 유지되어야 하는 정보이므로 최소한 우리가 익숙한 DI형태를 띠고 있어야 한다.
프록시를 사용해보자.
위와 같은 형태이다.
다른 사람이 LoginUser에 대해 잘 모르면 상태를 가진 bean이라며 의아해 할 수 있다.
192p.
빈의 종류에는 3가지가 있다.
애플리케이션 로직 빈 : 우리가 익히 알고 있는 컨테이너에 의해 생성되고 관리되는 빈, 우리가 만들어 사용한 DAO, 서비스 등
애플리케이션 인프라 빈 : 위와 같은 거 이외에도 DataSource 등 개발자의 로직이 들어가지 않은 애플리케이션을 도와준다.
컨테이너 인프라 빈 : 위 2가지 이외에도 컨테이너에 등록되는 빈들이다. DefaulAdvisorAutoProxyCreator를 사용했던 기억이 있다. 빈의 관계를 맺어주고 부가 기능으로 사용된다. ioc/di컨테이너의 기능을 확장해서 사용된다.
여태 ioc컨테이너가 @Autowired나 @Configuration/@Bean을 통해 빈을 등록하고 관계를 맺어주는지 알았는데
이것들은 인프라 빈의 도움으로 관리되는 것이다. AutowiredAnnotationBeanPostProcessor 등 전용 컨테이너 인프라 빈들이 후처리를 담당하는 것이다.
우리가 @Configuration/@Bean으로 메타정보를 만들고 컴포넌트 스캔으로 Configuration을 잡아서 빈으로 등록하기 전에 인프라 빈 configurationclasspostprocessor가 먼저 등록되어 @Configuration/@Bean애들을 빈으로 만들어 준다.
등등 ioc컨테이너의 기능을 확장해서 사용된다. 컨테이너는 위의 빈들을 이용해서 빈 생성, 관계를 맺어주는 듯하다.
흔히들 ioc컨테이너를 설명할 때 메타정보를 바탕으로 빈들을 생성, 관계를 맺어주는 역할을 한다고 말한다. 맞는 말이다. 컨테이너는 Reader를 통해 메타정보들을 BeanDefinition으로 만들고 이 정보들은 인프라 빈들을 사용해서 관계를 맺어주는 것 뿐이다.