스프링을 이용해 미션 진행 중 client에서 오는 요청을 처리하기 위한 url을 매핑할 때 Spring의 @RequestMapping이라는 어노테이션을 사용했다. 매핑 과정이 궁금해 공부하던 중 DispatcherServlet이라는 것이 관여하고 있다는 것을 알게 되었고 그것의 전신인 Servlet이라는 것에 대해 공부해보았다.
Servlet 이란?
서블릿이란 클라이언트의 요청을 처리하고, 그 결과를 반환하는 동적인 웹 페이지를 만들 때 사용되는 자바 기반의 웹 애플리케이션 프로그래밍 기술이다.
웹에선 Http message를 통해 요청과 응답을 주고 받게 되는데, 이 과정에서 소켓 열고 닫기, Http 요청 메세지 파싱하기, 비지니스 로직 수행, Http 응답 메세지 생성 등 수많은 과정이 필요하다. 이 때, 서블릿은 이러한 흐름을 간단하게 만들어 개발자가 비지니스 로직에만 집중할 수 있게 해주는 역할을 한다.
Servlet의 구성
@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
- Servlet의 이름을 지정(위의 경우 helloServlet)
- urlPatterns(/hello)의 URL이 호출되면 서블릿 코드가 실행
- HTTP 요청 정보를 편리하게 사용할 수 있는 HttpServletRequest
- HTTP 응답 정보를 편리하게 제공할 수 있는 HttpServletResponse
- 개발자는 HTTP 스펙을 편리하게 사용
서블릿의 동작과정
- URL을 입력하면 HTTP Request message가 서블릿 컨테이너로 전송
- 요청을 전송받은 서블릿 컨테이너는 HttpRequest, HttpResponse 객체 생성
- 서블릿 컨테이너는 받은 요청에 대해 그에 맞는 서블릿을 선택
- 해당 서블릿은 service 메서드를 호출(HTTP 요청 메서드에 의해 여러 doXXX 메서드로 분기돼 처리
- 동적페이지를 생성한 후 HttpServletResponse에 응답을 보냄
- 응답 후 HttpServletRequest, HttpServletResponse를 소멸
//service 메서드에서 method 방식에 따라 doXXX 메서드를 호출함을 알 수 있다.
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < lastModified) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
Servlet Container(서블릿 컨테이너)
서블릿 컨테이너는 스스로 동작하지 않는 서블릿을 관리해주는 컨테이너이다.
서블릿 컨테이너는 클라이언트의 요청을 받고 응답 할 수 있도록 웹 서버와 소켓으로 통신한다.
Servlet Container 특징
- 톰캣처럼 서블릿을 지원하는 WAS(Web Application Server)를 서블릿 컨테이너라고 함
- 서블릿 컨테이너는 서블릿 객체의 생명주기를 관리
- 서블릿 객체는 싱글톤으로 관리
- 멀티 쓰레드 지원
Reference
- 김영한님의 스프링 MVC 1편 강의
'우아한테크코스 > prolog' 카테고리의 다른 글
스프링은 왜 쓸까? (feat. 끝장토론) (0) | 2022.05.09 |
---|---|
함수형 인터페이스의 위력(?) (0) | 2022.03.04 |
래퍼 클래스와 오토 박싱 & 언박싱 (1) | 2022.02.18 |