Model View Controller 의 약자로, 소프트웨어 디자인 패턴 중 하나
Model
데이터와 비즈니스 로직을 담당
데이터베이스와 연동하여 데이터를 저장하고 불러오는 등의 작업을 수행
View
사용자 인터페이스를 담당
사용자가 보는 화면과 버튼, 폼 등을 디자인하고 구현
Controller
Model 과 View 사이의 상호작용을 조정하고 제어
사용자의 입력을 받아 Model에 전달하고 Model의 결과를 바탕으로 View를 업데이트
Servlet API를 기반으로 구축된 독창적인 웹 프레임워크
스프링에서 MVC 디자인 패턴을 적용하여 HTTP 요청을 효율적으로 처리하고 있다.
DispatcherServlet이 중앙에서 HTTP 요청을 처리해주는 , Front Controller 패턴으로 설계되어 있다.
DispatcherServlet와 FrontController에 대해 알아보자
Servlet(서블릿)은 자바를 사용하여 웹 페이지를 동적으로 생성하는 서버 측 프로그램을 말한다.
클라이언트가 HTTP API 요청했을 때 서버의 서블릿이 어떻게 동작할까?
서블릿의 동작 원리
클라이언트가 서버에 HTTP Request, API 요청을 보낸다.
요청 받은 Servlet 컨테이너는 HttpServletRequest, HttpServletResponse 객체를 생성한다.
설정 정보를 통해 어떤 Servlet에 대한 요청인지 찾는다.
찾은 Servlet의 service() 메서드를 호출하여 브라우저의 요청 Method에 따라 doGet() 혹은 doPost() 등 메서드를 호출한다.
호출한 메서드들의 결과를 그대로 반환하거나 동적 페이지를 생성한 뒤, HttpServletResponse 객체에 응답을 담아 클라이언트에게 반환한다.
응답이 완료되면 생성된 HttpServletRequest, HttpServletResponse 객체를 소멸시킨다.
위의 Servlet의 동작 방식을 기반으로 Spring에서 사용되는 Front Controller 패턴에 대해 알아보자.
클라이언트에서 HTTP 요청이 들어오면 DispatcherServlet 객체가 요청에 대해 분석을 한다.
DispatcherServlet 객체는 분석한 데이터를 토대로 Handler mapping을 통해 Controller를 찾아 요청을 전달해준다.
[Sample]
GET /api/hello -> HelloController 의 hello() 함수
GET /user/login → UserController 의 login() 함수
GET /user/signup → UserController 의 signup() 함수
POST /user/signup → UserController 의 registerUser() 함수
매핑된 데이터를 토대로 Controller 안의 메서드를 호출한다.
호출된 메서드를 통해 로직을 처리 완료 후, 데이터(Model)와 View 정보를 Dispatcher에 전달한다.
Dispatcher는 ViewResolver를 통해 View에 데이터(Model)을 적용 후에 View를 클라이언트에게 응답으로 전달한다.
@Controller
public class UserController {
}
@Controller 어노테이션을 이용하여 해당 클래스가 Controller 역할을 수행할 수 있도록 스프링 컨테이너에 등록을 한다.
@GetMapping( )
@GetMapping("/api/get")
@ResponseBody
public String get() {
return "GET Method 요청"
}
GET Method 타입 요청이 들어올 때 사용되는 에노테이션
/api/get 으로 들어오게 되면 해당 매칭되는 메서드 get()을 호출한다.
@ResponseBody는 반환 타입 문자 그대로를 응답 데이터에 보낸다.
@PostMapping( )
@PostMapping("/api/post")
@ResponseBody
public String post() {
return "POST Method 요청"
}
POST Method 타입 요청이 들어올 때 사용되는 에노테이션
/api/post 으로 들어오게 되면 해당 매칭되는 메서드 post()을 호출한다.
@PutMapping( )
@PutMapping("/api/put")
@ResponseBody
public String put() {
return "PUT Method 요청"
}
PUT Method 타입 요청이 들어올 때 사용되는 에노테이션
/api/put 으로 들어오게 되면 해당 매칭되는 메서드 put()을 호출한다.
@DeleteMapping( )
@DeleteMapping("/api/delete")
@ResponseBody
public String delete() {
return "DELETE Method 요청"
}
DELETE Method 타입 요청이 들어올 때 사용되는 에노테이션
/api/delete 으로 들어오게 되면 해당 매칭되는 메서드 delete()을 호출한다.
위의 Mapping( ) 에노테이션에 중복으로 발생되는 /api를 줄일 수 있다.
@Controller
@RequestMapping("/api")
public class HelloController {
}
@RequestMapping은 중복되는 URL을 단축시켜줄 수 있다.
따라서 위에 @RequestMapping을 쓰면 "/api"을 제외한 get, post, put, delete만 써서 글자를 줄일 수 있다.