이번 시간에는 스프링과 스프링 부트가 무엇이며, 스프링 부트는 어떻게 동작하는 지에 대한 공부를 해보겠습니다.
스프링 부트의 기본 의존성 중 하나인 spring-boot-starter-web 모듈을 사용하면, 기본적으로 내장 톰캣을 사용하는 스프링 MVC 구조를 기반으로 동작합니다. 클라이언트의 요청이 들어오면 서블릿이 이를 처리해야 하는데, 서블릿은 서블릿 컨테이너에서 관리하고, 톰캣이 서블릿 컨테이너의 역할과 WAS 역할을 담당합니다.
서블릿(Servlet)
클라이언트의 요청을 처리하고, 결과를 반환하는 자바의 웹 프로그래밍 기술입니다. 서블릿 객체를 생성, 초기화, 호출, 종료하는 생명주기를 관리합니다. 서블릿 객체는 싱글톤 패턴으로 관리되며, 멀티 스레딩을 지원합니다.
DispatcherServlet이란?
스프링에서는 DispatcherServlet이 서블릿의 역할을 담당합니다. 클라이언트로부터 HTTP 요청을 받아서 서블릿 컨테이너에서 관리되는 DispatcherSevlet이 요청을 처리하고 반환하는 것입니다.
HTTP와 웹 브라우저에 대한 간단한 설명
웹 브라우저
https://en.wikipedia.org/wiki/Web_browser
웹 브라우저는 사용자와 웹 서버의 양방향 통신을 도와주는 역할을 하며 HTML 문서나 파일을 출력하는 그래픽 사용자 인터페이스 기반의 응용 소프트웨어입니다. 특정 웹 사이트로부터 사용자가 웹 페이지를 요청할 때, 브라우저는 웹 서버로부터 자사의 파일들을 회수하고 유저의 화면에 해당 페이지를 보여줍니다.
주요 웹 브라우저로는 구름 크롬, 사파리, 모질라 파이어폭스 등이 있다. 최초의 웹 브라우저는 1990년에 팀 버너스 리가 발명하였습니다.
웹 브라우저는 웹 페이지를 가져오기 위해 대부분의 웹 서버가 사용하는 HTTP로 통신합니다.
웹 서버
웹 브라우저와 같은 클라이언트로부터 HTTP 요청을 받아들이고, HTML 문서와 같은 웹 페이지를 반환하는 컴퓨터 프로그램입니다. 주된 기능은 웹 페이지를 클라이언트로 전달하는 것이며, 주로 CSS, 자바스크립트를 포함한 HTML 문서를 전달합니다.
HTTP 프로토콜
https://datatracker.ietf.org/doc/html/rfc2616
하이퍼텍스트 전송 규약(HTTP)은 분산정보시스템, 종합 정보시스템 및 하이퍼미디어 정보시스템에서 사용하는 응용 게층 규약으로써 요구 방법의 확장을 통해 네임서버와 분산 객체 관리 시스템과 같은 수많은 작업에 사용될 수 있는 보편적인 객체지향형 규약입니다. 이 규격은 HTTP/1.1 로 언급되는 규약을 정의하고 있습니다.
목적
HTTP/0.9 로 언급되는 HTTP의 첫 버전은 인터넷 상에서 저장되어 있는 raw data를 전송하기 위한 단순 규약이었습니다. 하지만 인터넷이 발전되면서 엄격한 전송 규약이 필요해졌고, HTTP/1.1로 불리우는 하이퍼텍스트 전송 규약이 현재까지 쓰이고 있습니다. ..
자세한 내용은 해당 링크에서 자세히 볼 수 있습니다.
HTTP 프로토콜 RFC2616 번역 스크랩 : https://12bme.tistory.com/326
HTTP 프로토콜은 하이퍼텍스트를 교환하기 위한 프로토콜의 일종으로, 서버와 클라이언트의 사이에서 어떻게 메시지를 교환할지를 정해 놓은 규칙입니다. Request와 Response로 구성되어 있으며, 일반적으로 80번 포트를 사용합니다.
예를 들면 클라이언트가 웹 페이지에서 링크(ex : http://localhost:8080)가 걸려있는 텍스트(하이퍼 링크)를 클릭(요청)하면 링크를 타고 새로운 페이지로 넘어갑니다(응답). 따라서 우리가 사용하는 웹 브라우저에서 인터넷 주소 맨 앞에 들어가는 http:// 가 바로 이 프로토콜을 사용해서 정보를 교환하겠다는 표시인 것입니다.
DispatcherServlet의 동작 과정
- 클라이언트의 요청을 DispatcherServlet에 전달
- 요청한 URL에 맞는 Controller를 찾아서 Handler Mapping에 전달
- 조회한 Handler를 실행할 수 있는 HandlerAdapter 조회, Controller 호출
- Controller에서 요청을 처리하고, 응답을 다시 HandlerAdapter로 반환
- HandlerAdapter에서 ModelAndView 객체로 변환하여 DIspatcherServlet에 전달
- DispatcherServlet에서 전달받은 객체를 이용하여 매핑되는 View 검색
- ViewResolver에서 처리 결과를 View에 전달
- 처리 결과가 포함된 View를 DispatcherServlet에 전달
- DispatcherServlet에서 최종 응답 결과를 클라이언트에게 반환
- @Controller
- View Resolver를 찾고 실행한다.
- View Resolver는 View의 논리 이름을 물리 이름으로 바꾸고, 랜더잏 역할을 담당하는 View 객체를 반환한다.
- View를 랜더링하여 클라이언트에 반환한다.
- @RestController
- View와 View Resolver를 거치지 않는다.
- Controller로부터 반환 받은 데이터를 MessageConverter를 거쳐서 JSON 형식으로 반환한다.
- JSON을 ResponseBody로 응답한다.
디버깅을 통해 알아보기
1. Servlet이 호출되면 아래와 같이 doService() 메서드가 호출되고, try문 내부의 doDispatch() 메서드가 호출됩니다.
2. doDispatch()에서는 클라이언트의 요청에 해당하는 핸들러를 먼저 조회하고, 해당 핸들러를 받기 위한 어댑터를 조회합니다.
3. 위에서 찾은 핸들러 어댑터의 handle() 메서드 호출
- ModelAndView 반환 (과정에서의 5번)
- 그리고 아래에서 processDispatchResult() 메서드 호출
4. 뷰 렌더링 호출
- processDispatchResult() 메서드는 안에서 render() 메서드를 또 다시 호출
5. 뷰 렌더링
- render() 메서드 안에서 뷰 리졸버를 통해 view를 찾고, 해당 view를 반환받음
- 마지막으로 뷰를 실제로 렌더링 → 전달
참고 자료