동적인 웹 페이지를 생성하기 위해 사용되는 도구입니다. 템플릿을 기반으로 정적인 부분과 동적인 부분을 결합하여 HTML, XML 등의 문서를 생성하는 역할을 합니다.
흔히 말하는 UI를 만들고, SSR(Server Side Rendering)에 사용이 됩니다.
Java 코드로 HTML을 만들어 내는 것이 아닌, HTML 문서에 동적으로 변경해야 하는 부분만 Java 코드를 삽입하는 것이 더 편하기 때문입니다.
하나의 Servlet 또는 JSP로 처리하던 것들을 Model, View, Controller 영역으로 나눈 것입니다. 보통의 Web Application이 사용하는 패턴입니다.
Servlet의 동작 순서
- 사용자가 브라우저를 통해 서버에 HTTP Request, 즉, API 요청을 보냅니다.
- 요청을 받은 Servlet Container는 HttpServletRequest, HttpServletResponse 객체를 생성합니다.
- 설정된 정보(URL, HTTP Method)를 통해 어떤 Servlet에 대한 요청인지 찾습니다.
- 알맞은 Servlet에서 service 메서드를 호출한 뒤 브라우저의 요청 Method(doGet(), doPost() 등)에 따라 메서드를 호출합니다.
- 서버에서 응답을 생성한 뒤 HttpServletResponse 객체에 응답을 담아 브라우저에 반환합니다.
- 응답이 완료되면 생성되었던 HttpServletRequest, HttpServletResponse 객체는 소멸됩니다.
JSP의 구조
HTML 코드 안에 Java Code가 들어가 있는 형태입니다. 이에 반해 Servlet은 Java Code로 이루어져 있습니다.
Servlet이나 JSP만 가지고 비즈니스 로직과 View 모두 처리를 하게 된다면, 너무 많은 역할을 하게 되고 유지보수가 굉장히 까다로워집니다.
Servlet만을 사용한 경우는 View를 위한 코드와 비즈니스 로직이 모두 Servlet 안에 존재하기 때문에 유지보수가 어렵고,
JSP를 사용한 경우는 View를 분리하였어도, 비즈니스 로직의 일부가 JSP 파일 안에 남아있기 때문에 여전히 유지보수가 어렵습니다.
View가 분리된 이유의 핵심은 변경입니다.
기획이 변하지 않는다면 비즈니스 로직과 View의 수정 원인은 별개입니다. 이전에는 비즈니스 로직과 View가 한데 모여있었기 때문에 코드 자체를 수정해야 했지만, 로직과 View가 분리되어 있다면 수정이 필요한 부분만 수정을 하면 됩니다.
쉽게 말해서 서로 연관이 없는 코드끼리 붙어있던 것을 떼놓은 것입니다.

View에 출력할 Data를 저장하는 객체입니다.
책임이 분리되어 있기 때문에 View는 비즈니스 로직이나 Data 접근을 몰라도 되고 View Rendering에 집중하면 됩니다.
Model 객체에 담겨져 있는 Data를 사용하여 화면을 Rendering 합니다.
MVC 패턴을 적용했을 때 일어나는 일을 살펴보겠습니다.


Servlet(Controller)이 호출되기 전 공통 기능을 하나의 Servlet에서 처리해주는 패턴입니다. 프론트 컨트롤러(Servlet) 하나에 모든 요청이 들어오게 됩니다.
공통 처리 로직에 모든 Controller가 연결되려면, return의 형태가 동일해야 합니다.
하지만, Controller마다 return 형태는 다를 것이고, 이 형태를 동일하게 맞추려고 한다면 확장성과 유지보수성을 잃습니다.
응답별로 하나하나 처리할 수 있으나, 이렇게 된다면 공통 부분의 책임이 너무 커지게 됩니다. 그리고, Controller에서 반환 결과가 달라지게 되면, 공통 처리 부분의 변경 또한 불가피합니다.

다양한 Controller를 유연하게 만들기 위하여 도입된 패턴입니다. Controller들이 동일한 인터페이스를 구현하도록 하고, 해당 인터페이스와 공통 로직 사이에 어댑터를 둡니다.
Spring은 MVC 패턴에 프론트 컨트롤러 패턴과 어댑터 패턴이 적용된 구조를 가지고 있습니다.

Spring MVC의 프론트 컨트롤러는 Dispatcher Servlet입니다.
HttpServlet을 상속받아 사용하며 Servlet의 한 종류입니다.
Spring Boot는 Dispatcher Servlet을 서블릿으로 자동 등록하고 모든 URL 경로에 대하여 Mapping합니다. 여기서, 더 자세한 URL 경로가 더 높은 우선순위를 가져가게 됩니다. 그렇기 때문에, 개발자가 만드는 Servlet이 항상 우선순위가 더 높아 실행됩니다.
Spring MVC에서는 org.springframeworkd.web.servlet.mvc.Controller 인터페이스를 구현하여 컨트롤러를 만들 수 있습니다.
현재는 주로 @Controller와@RequestMapping 어노테이션을 기반한 방식을 사용합니다.
@Component("/example-controller")
public class ExampleController implements Controller {
@Override
public ModelAndView handlerRequest(HttpServletRequest request, HttpServletResponse resonse) throws Exception {
System.out.println("example-controller");
return null;
}
}
@Component("/example-controller")로 Spring Bean 이름을 URL로 등록하면, 해당 URL로 요청할 때, 이 컨트롤러가 호출됩니다.@RequestMapping에 사용됩니다.@RequestMapping에 사용됩니다.org.springframework.web.HttpRequestHandler 인터페이스를 구현한 컨트롤러도 만들 수 있습니다. 해당 방식은 Servlet과 비슷하게 작동하고, handleRequst() 메서드를 오버라이드합니다.
HandlerMapping에서 URL로 Bean을 찾고, HttpRequestHandlerAdapter가 이를 실행합니다.
컨트롤러에서 반환한 ModelAndView의 ViewName을 실제 뷰(Thymeleaf 등)로 변환하는 역할을 수행합니다.
DispatcherServlet이 ViewResolver를 호출하여 논리적인 ViewName을 물리적인 View 경로로 변환합니다.
Spring Boot에서는 필요한 ViewResolver가 자동으로 등록됩니다.
return new ModelAndBiew("test")로 논리적 뷰 이름을 반환합니다.자료 및 코드 출처: 스파르타 코딩클럽