이어달리기 프로젝트 회원가입 API를 하게 되면서 공부하게 된 스프링 security & jwt!
공부하면서 알게 된 DispatcherServlet 클래스는 Servlet, Spring MVC의 중심이다.
DispatcherServlet이 뭔지, 그리고 적용한 예제에 대해 알아보자.
DispatcherServlet이란
Dispatcher Servlet에서 Dispatch의 의미는 급파하다, 파견 등의 의미로 해석해보면 받은 요청을 어딘가로 빨리빨리 보내는 서블릿이라는 뜻이다. 또한 프론트 컨트롤러라고 불리기도 한다.
과연 어디로 보내는 것이고 프론트 컨트롤러라면 컨트롤러의 종류 중 하나인걸까?
## 서블릿이란?
클라이언트의 요청을 처리하고, 그 결과를 반환하는 Servlet 클래스의 구현 규칙을 지킨 자바 웹 프로그래밍 기술
간단히 말해서, 서블릿이란 자바를 사용하여 웹을 만들기 위해 필요한 기술이다.
클라이언트가 어떠한 요청을 하면 그에 대한 결과를 다시 전송해주어야 하는데, 이러한 역할을 하는 자바 프로그램이다.
예를 들어, 어떠한 사용자가 로그인을 하려고 할 때. 사용자는 아이디와 비밀번호를 입력하고, 로그인 버튼을 누른다. 그때 서버는 클라이언트의 아이디와 비밀번호를 확인하고, 다음 페이지를 띄워줘야 하는데 이러한 역할을 수행하는 것이 바로 서블릿(Servlet)이다.
그래서 서블릿은 자바로 구현 된 *CGI라고 흔히 말한다
(CGI(Common Gateway Interface): CGI는 특별한 라이브러리나 도구를 의미하는 것이 아니고, 별도로 제작된 웹서버와 프로그램간의 교환방식이다)
0. 배경
JAVA 런타임에서는 컨트롤러가 존재하지 않는다.
따라서 서블릿 객체를 생성하고, 이를 web.xml에다 일일히 다 등록해줘야 했다.
<!-- 서블릿1 등록 -->
<servlet>
<servlet-name>서블릿1</servlet-name>
...
</servlet>
<servlet-mapping>
<servlet-name>서블릿1</servlet-name>
...
</servlet-mapping>
<!-- 서블릿2 등록 -->
<servlet>
<servlet-name>서블릿2</servlet-name>
...
</servlet>
<servlet-mapping>
<servlet-name>서블릿2</servlet-name>
...
</servlet-mapping>
<!-- 서블릿3 등록 -->
<servlet>
<servlet-name>서블릿3</servlet-name>
...
</servlet>
<servlet-mapping>
<servlet-name>서블릿3</servlet-name>
...
</servlet-mapping>
하지만 웹사이트를 이용해봤다면 알겠지만, 우리가 접속하는 페이지는 한두개가 아니다.
게다가 컨트롤러와는 달리 서블릿 객체 하나는 하나의 경로만 담당한다.
이렇게 되면 10개보다 더 늘어날 것이고 프로젝트 문서는 온통 서블릿 객체로 넘쳐날 것이다.
서블릿의 단점
1. 높은 의존성
Servlet 객체는 HttpServlet를 확장한 객체이다.
이렇게 되면 HttpServlet 기능을 필수로 Override 해야 하고, 더이상 일반 객체로 사용할 수 없다.
즉, 클래스끼리 값을 주고받기가 까다로워진다.
2. 중복되는 작업
모든 서블릿이 공통으로 처리하는 작업이나, 가장 우선시 되야하는 작업이 분명 있을 것이다.
이런 것을 서블릿 객체로 처리하기란 불가능하고, 매우 까다로울 것이다.
DispatcherServlet은 이러한 단점들을 모두 해소해주고, 간편하게 사용할 수 있다.
1. Controller
서블릿을 더이상 HttpServlet을 확장하지 않고, POJO를 사용한다.
@Controller 어노테이션을 붙여서 간편히 사용할 수 있으며, 의존성이 낮아져서 다른 객체들과 연계가 자유롭다.
- Servlet 객체
/* Servlet 객체 */
@WebServlet("/user")
public class testServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// GET 작업 처리
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// POST 작업 처리
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 서블릿 동작 처리
}
}
- Controller 객체
@Controller
public class testController {
@PostMapping("/user")
public String userPage() {
// POST 처리
}
@GetMapping("/user")
public String userPage() {
// GET 처리
}
}
2. 2차 컨트롤러 구조
Controller가 생겨났음에도 불구하고, 여전히 web.xml에 일일히 등록해야 했다.
하지만 컨트롤러가 다음과 같은 구조를 띄면서 문제는 사라졌다.
위와 같은 구조를 필자는 2차 컨트롤러 구조라고 부른다.
기존에 web.xml에 각 컨트롤러를 모두 등록해야 하지만, DispatcherServlet이 모든 요청을 받고 세부 경로는 각 Controller에게 뿌려주는 프론트 컨트롤러의 역할을 함으로써, web.xml에 서블릿을 일일히 등록할 필요가 없어졌다.
Controller의 매핑은 DispatcherServlet이 담당하기 때문이다.
3. 공통/최우선 작업 처리
공통적으로 진행되야 할 작업들을 우선적으로 처리해준다.
# 레퍼런스
https://velog.io/@seculoper235/2.-DispatcherServlet-%EC%9D%B4%EB%9E%80