[스프링 부트 핵심 가이드] 책을 보고 정리한 내용입니다.
스프링 부트의 동작 방식
스프링 부트에서 spring-boot-starter-web 모듈을 사용하면 기본적으로 톰캣을 사용한 스프링 MVC 구조를 기반으로 동작한다.
아래 이미지는 일반적인 웹 요청이 들어왔을 때의 스프링부트 동작 구조이다.
서블릿(Servlet) 이란 클라이언트의 요청을 처리하고 결과를 반환하는 자바 웹 프로그래밍 기술이다. 일반적으로 서블릿은 서블릿 컨테이너(Servlet Container)에서 관리한다. 서블릿 컨테이너는 서블릿 인스턴스(Servlet Instance)를 생성하고 관리하는 역할을 수행하는 주체로서 톰캣은 WAS와 서블릿 컨테이너 역할을 모두 수행한다.
서블릿 컨테이너의 특징을 정리하면 다음과 같다.
- 서블릿 객체를 생성, 초기화, 호출, 종료하는 생명주기를 관리
- 서블릿 객체는 싱글톤 패턴으로 관리
- 멀티 스레딩을 지원
스프링에서는 DispatcherServlet이 서블릿 역할을 수행한다. 스프링 부트는 내장톰캣(Embeded Tomcat)을 사용하기 때문에 서블릿 컨테이너와 DispatcherServelet은 자동 설정된 web.xml의 설정값을 공유한다.
기존에는 모든 Servlet에 대해 URL 매핑을 활용하기 위해서 web.xml에 모두 등록하여야 했지만, DispatcherServlet이 해당 어플리케이션으로 들어오는 모든 요청을 핸들링하기 해주고 공통 작업을 처리하면서 상당히 편리하게 이용할 수 있게 되었다. 컨트롤러를 구현해두기만 하면 디스패처 서블릿가 알아서 적합한 컨트롤러로 위임을 해주는 구조가 되었다.
DispatcherServelet 동작
위에 [스프링 부트의 동작 구조] 이미지를 참고하여 설명한다.
(1) DispatcherServlet으로 요청(HttpServletRequest)이 들어오면 DispatcherServlet은 핸들러 매핑(Handler Mapping)을 통해 요청 URI에 매핑된 핸들러를 탐색한다. 여기서 핸들러는 컨트롤러를 의미한다.
(2) 핸들러 어댑터(HandlerAdapter)로 컨트롤러를 호출한다. (핸들러 어댑터는 요청을 컨트롤러로 위임하는 역할이다.)
(3) 핸들러 어댑터에 컨트롤러의 응답이 돌아오면 ModelAndView로 응답을 가공하여 반환한다.
(4) 뷰 형식으로 리턴하는 컨트롤러를 사용할 경우 뷰 리졸버(View Resolver)를 통해 뷰를 받아 리턴한다.
핸들러 매핑은 요청 정보 기준으로 어떤 컨트롤러를 사용할지 선정하는 인터페이스이다. 핸들러 매핑 인터페이스는 여러 구현체가 있으며, 대표적인 4가지는 다음과 같다.
BeanNameUrlHandlerMapping
- 빈 이름을 URL로 사용하는 매핑 전략
- 빈을 정의할때 슬래시('/')가 들어가면 매핑 대상이 된다.
- 예) @Bean("/hello")
ControllerClassNameHandlerMapping
- URL과 일치하는 클래스 이름을 갖는 빈을 컨트롤러로 사용하는 전략
- 이름 중 Contoller를 제외하고 앞부분에 작성된 suffix를 소문자로 매핑
SimpleUrlHandlerMapping
- URL 패턴에 매핑된 컨트롤러를 사용하는 전략
DefaultAnnotationHandlerMapping
- 어노테이션으로 URL과 컨트롤러를 매핑하는 방법
뷰 리졸버는 뷰의 랜더링 역할을 담당하는 뷰 객체를 반환한다.
만약 뷰가 없는 REST 형식의 @ResponseBody를 사용한 다면 뷰 리졸버를 호출하지 않고 MessageConverter를 거쳐 JSON 형식으로 변환해서 응답한다.
MessageConverter는 요청과 응답에 대해 Body 값을 변환하는 역할을 수행한다. MessageConverter 인터페이스를 기반으로 하는 다양한 구현체 클래스가 존재하며, Content-Type을 참고하여 Converter를 선정한다.
스프링부트를 사용할 경우 자동 설정되기 때문에 별도 설정이 필요하지 않다.
Reference
'Framework > Spring' 카테고리의 다른 글
[Spring] POST, PUT, DELETE API (0) | 2023.10.11 |
---|---|
[Spring] GET API를 구현하는 다양한 방법 (0) | 2023.10.06 |
[Spring] REST API 란? (0) | 2023.10.05 |
[Spring] 레이어드 아키텍처와 스프링의 레이어드 아키텍처 (0) | 2023.10.05 |
[Spring] 스프링 프레임워크 vs 스프링 부트 (0) | 2023.10.04 |