스프링 컨테이너는 빈 생명 주기를 관리한다. 빈을 관리하기 위해 IOC가 이용된다.
스프링 컨테이너에는 빈 팩토리가 있고, ApplicationContext는 이를 상속한다. 이 두개의 컨테이너로 의존성이 주입된 빈들을 제어할 수 있다.
- WebApplication이 실행되면, WAS(Tomcat, ServletContainer per process)에 의해 web.xml이 로딩된다.
- web.xml에 등록되어있는 ContextLoaderListener가 자바 클래스 파일로 생성된다. ContextLoaderListener 요 친구는 ServletContextListener를 구현한 것으로써, Application Context(스프링 빈이 등록되고 공유되는 곳) 를 생성한다.
- ApplicationContext.xml 에 등록되어있는 설정에 따라 스프링 컨테이너가 구동되고, 이 때 개발자가 작성한 비즈니스 로직과 객체등이 생성된다.
- 클라이언트로부터 요청이 오면, 스프링 DispatcherServlet도 이 때 한 번만 생성된다. 처음에 요청이 들어오면, 무좍건 DispatcherServlet으로 간다.
- DispatcherServlet은 요청을 받고 적절한 Controller을 찾는다. 핸들러는 컨트롤러보다 더 큰 개념으로, 핸들러 매핑을 통해 요청에 맞는 컨트롤러를 찾아준다.
- 핸들러 매핑: Bean 이름으로 핸들러를 찾아준다. Bean 이름과 url을 매핑해주는 방식이 기본적이다.
이런식으로 개발자가 작성한 비즈니스 로직도 ServletContainer가 관리하게 되고, 스프링 MVC도 DispatcherServlet 이 관리하고 있는 서블릿 한 개로 칠 수 있다.
Servlet Container(톰캣)은 프로세스 하나의 배정 되어있고,
이에 따르는 요청들은 쓰레드 별로 처리하도록 쓰레드 풀에서 역할을 배정을 시키고,
클라이언트가 임의의 서블릿을 요청했는데 최초의 요청이면 Init()을 실행하고,
아니라면 새로 만들지 않고 메소드 영역의 서블릿을 참고해 service()를 실행시킨다.
이것도 하나의 개발자가 아닌, 프로그램에 의해 관리되므로 IOC라고 볼 수 있겠다!
스프링 부트는 어떻게 동작할까?
스프링 부트는 내장 톰캣 서버를 가지고 있다.
1. DispatcherServlet이 스프링에 빈으로 등록된다.
2. DispatcherServlet 컨텍스트에 서블릿을 등록한다.
3. 서블릿 컨테이너 필터에 등록 설정 해둔 필터들을 등록한다.
4. DispatcherServlet에 각종 핸들러 매핑(url)들이 등록된다.
Spring MVC의 동작 패턴
1. 클라이언트에서 요청이 발생하면, 이 요청은 필터를 걸친다. 필터는 인증, 로깅, 인코딩 등의 사전 처리 작업을 한다.
2. 필터를 통과하면 요청은 DispatcherServlet에 도착한다.
3. DispatcherServlet은 요청을 받으면, 이 요청이 어떤 컨트롤러에 매핑 되어야 하는지 결정하는 Handler Mapping 을 수행한다. 요청 URL에 해당하는 컨트롤러를 찾는다.
4. 매핑이 완료되면, DispatcherServlet 은 찾아낸 핸들러(일반적으로는 컨트롤러다.) 를 호출한다. 만약 이 과정에서 인터셉터가 등록되어있으면 먼저 인터셉터가 호출된다.
5. 인터셉터는 필터와 유사하게 요청 전 후에 추가적인 작업을 할 수 있다.
6. 이후 실제 요청을 처리하는 컨트롤러나 핸들러가 실행된다. 컨트롤러는 비즈니스 로직을 처리하고, 결과를 모델과 함께 ModelAndView 객체로 반환한다.
7. ModelAndView 객체에서 뷰 이름을 반환받고, DispatcherServlet은 이 뷰 이름을 실제 화면(View)으로 변환한다. 이때 뷰 리졸버가 사용된다.
- View Resolver는 뷰 이름을 실제 화면(HTML, JSP, Thymeleaf 템플릿 등)으로 매핑하는 역할을 한다.
8. View Resolver가 실제 뷰 파일을 찾으면, 해당 뷰 파일을 통해 모델(Model) 데이터를 바탕으로 화면을 생성.
9. 뷰가 최종적으로 생성되면, DispatcherServlet은 이 뷰를 클라이언트에게 응답(Response)으로 반환한다.
서블릿은 스프링 컨테이너와 어떻게 상호작용할까.
스프링 빈은 컨테이너가 Reflection을 통해 만들어낸 POJO(Plain Old Java Object 평범한 자바 객체이다.
POJO (Plain Old Java Object)
- 특정 프레임워크와 기술에 의존하지 않는다. 순수한 자바로 작성된다. 상속을 강제하지 않는다.
- 간단하고 직관적이다. 재사용성이 있다.
Reflection(리플렉션)이란?
- 자바의 런타임에 클래스, 메서드, 필드 등에 대한 정보를 동적 탐색하고 실행, 수정할 수 있는 매커니즘이다.
- 리플랙션을 사용하면 컴파일 시점이 아닌 실행 시점에 클래스나 객체의 구조를 알 수 있다.
- Spring, Hibernate 같은 프레임워크들은 리플렉션을 통해 런타임에 객체를 생성한다. JPA같은 것도 프록시 객체를 사용할 때 그렇게 했던듯..
스프링에서의 POJO, Reflection
스프링은 리플렉션을 사용해서 런타임에 클래스와 메서드를 검색한다. 그 정보를 바탕으로 POJO를 동적으로 생성하고, 필드 값을 설정하며, 해당 객체에 필요한 의존성을 주입한다. 이 과정을 통해 개발자는 코드에서 직접 객체를 생성하지 않고 스프링 컨테이너가 자동으로 객체를 생성하고 관리할 수 있다.
서블릿은 이런 POJO를 바탕으로 스프링 컨테이너에서 look-up(검색)해서 서블릿 컨테이너에 올려 마치 서블릿처럼 사용하도록 한다. 예를 들어, 스프링의 Object들이 HttpRequest를 listening 할 수 있도록 내부적으로 프록시 역할을 해준다.
Servlet과 Spring Bean
서블릿의 종류에는 @WebServlet과 Spring @Bean 이 있는데, 어디에서 관리하느냐에 차이가 있다. 서블릿은 톰캣이 관리하는 것이고 빈은 스프링이 관리한다.
""
Bean의 경우에는 POJO와 설정(Configuration Metadata)을 Spring이 제공하는 Container(DI Container, 또는 IoC Container)에 주입시키면 Bean으로 등록되고 사용이 가능하다. 결국 Spring을 쓴다는 것은 Spring으로 Servlet을 다루겠다는 뜻이다. Spring MVC 역시 Servlet Container가 관리하고 있는 Servlet이다.
""
이 글은 전부 이 블로그에서 따왔습니다 ..
'BACKEND > Spring Boot' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 영속성 컨텍스트 (0) | 2024.10.30 |
---|---|
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 1일 차 JPA에 대해서 (4) | 2024.10.21 |
Tomcat은 어떻게 동작하는가 (0) | 2024.09.22 |
테스트 스텁과 목 오브젝트의 차이점 (1) | 2024.09.19 |
JWT 에 대해서 (0) | 2023.11.07 |
안녕하세오 저는 똑똑해지고 싶은 버그 수집가에오
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!