Spring 모듈 중에는 웹 계층을 담당하는 몇 개의 모듈이 있다. Servlet API를 기반으로 클라이언트의 요청을 처리하는 모듈이 있는데, 이 모듈이 바로 Spring Web MVC이다.
Spring Web MVC를 Spring MVC라 부르고, Spring MVC가 웹 프레임워크의 한 종류이기 때문에 Spring MVC 프레임워크라고도 부른다.
우선, Spring MVC는 클라이언트의 요청을 처리해주는 편리한 프레임워크라고 기억하면 된다.
What is Servlet?
서블릿은 클라이언트의 요청을 처리하도록 특정 규약에 맞춰 Java 코드로 작성하는 클래스 파일이다.
아파치 톰캣(Apache Tomcat)은 서블릿들이 웹 애플리케이션으로 실행할 수 있게 해주는 서블릿 컨테이너 중 하나다.
Spring MVC 내부에서는 서블릿 기반으로 웹 애플리케이션이 동작하는 것을 기억하자.
Spring MVC에서 M은 Model이다.
모델이라 하면 나는 패션 모델이 떠오른다. 패션 모델은 디자이너의 작업 결과물을 관객들에게 보여주는 역할을 할 것이다.
Spring MVC의 Model도 비슷한 역할을 한다.
Spring MVC 기반의 웹 애플리케이션이 클라이언트의 요청을 전달 받고, 그 요청을 처리하기 위한 작업을 한다. 처리한 작업의 결과를 클라이언트에게 응답으로 돌려주어야 한다. 이때 클라이언트에게 응답으로 돌려주는 작업 처리 결과인 데이터를 Model이라 한다.
클라이언트의 요청 사항을 구체적으로 처리하는 영역을 서비스 계층, 실제로 요청 사항을 처리하기 위해 코드로 구현한 것을 비즈니스 로직이라 한다.
Spring MVC에서 V는 View이다.
View는 Model 데이터를 이용해 웹 브라우저 같은 클라이언트 애플리케이션의 화면에서 보여지는 리소스를 제공한다.
View의 형태
HTML 페이지의 출력
클라이언트 애플리케이션에 보여지는 HTML 페이지를 직접 렌더링하여 클라이언트 측에 전송하는 방식이다.
기본적인 HTML 태그로 구성된 페이지에 Model 데이터를 넣어 최종적인 HTML 페이지를 만들고 클라이언트 측에 전송한다.
PDF, Excel 등 문서 형태로 출력
Model 데이터를 가공해 PDF나 Exel 문서 등으로 만들어 클라이언트 측에 전송하는 방식이다.
문서 내에서 데이터가 동적으로 변경되어야 하는 경우 사용할 수 있다.
JSON, XML 등 특정 형식의 포맷으로 변환
Model 데이터를 특정 프로토콜 형태로 변환하여 변환된 데이터를 클라이언트 측에 전송하는 방식이다.
특정 형식의 데이터만 전송하며, 프론트엔드에서 해당 데이터를 기반으로 HTML 페이지를 만드는 방식이다.
JSON(JavaScript Object Notation)
JSON은 Spring MVC에서 클라이언트 애플리케이션과 서버 애플리케이션이 주고 받는 데이터 형식이다.
과거에는 XML 형식의 데이터를 많이 사용했는데, 현재는 XML보다 상대적으로 가볍고 복잡하지 않은 JSON 형식을 많이 사용한다.
JSON의 기본 포맷 형태는 {"속성":"값"}
이다.
// (1)
public class Coffee {
private String korName;
private String engName;
private int price;
public Coffee(String korName, String engName, int price) {
this.korName = korName;
this.engName = engName;
this.price = price;
}
}
// (2)
public class JSON_EX {
public static void main(String[] args) {
Coffee coffee = new Coffee("녹차라떼", "Green Tea Latte", 5000);
Gson gson = new Gson();
String jsonString = gson.toJson(coffee);
System.out.println(jsonString);
}
}
// 실행 결과
{"korName":"녹차라떼","engName":"Green Tea Latte","price":5000}
(1)은 자바로 Coffee 클래스를 작성한 코드다. 녹차라떼의 정보를 요청하면, 서버 애플리케이션 쪽에서 녹차라떼 정보를 JSON 형식으로 변환하여 전송해준다.
(2)는 Gson이란 라이브러리를 사용해 Coffee 클래스 객체를 JSON 포맷 형태로 출력하는 코드다.
Spring MVC에서 C는 Controller이다.
Controller는 클라이언트 측의 요청을 직접적으로 전달 받는 엔드포인트(Endpoint)이다. Model과 View 사이에서 상호작용을 해주는 역할을 한다.
클라이언트의 요청을 전달 받아 비즈니스 로직을 거친 후, Model 데이터가 만들어지면 이 Model 데이터를 View로 전달한다.
@RestController
@RequestMapping(path = "/v1/coffee")
public class CoffeeController {
...
@GetMapping("/{coffee-id}") // (1)
public Coffee getCoffee(@PathVariable("coffee-id") long coffeeId) {
return coffeeService.findCoffee(coffeeId); // (2)
}
}
(1)의 @GetMapping
애너테이션을 통해 클라이언트 측의 요청을 수신한다.
(2)의 CoffeeService 클래스의 findCoffee()
메서드를 호출해 비즈니스 로직을 처리한다. 처리 후 리턴 받는 Coffee가 Model 데이터가 된다.
Model, View, Controller의 처리 흐름
Client가 요청 데이터 전송
→ Controller에서 요청 데이터 수신 → 비즈니스 로직 처리 → Model 데이터 생성
→ Controller에게 Model 데이터 전달 → Controller가 View에게 Model 데이터 전달 → View가 응답 데이터 생성
위 그림은 클라이언트가 요청을 전송했을 때, Spring MVC가 내부적으로 요청을 어떻게 처리하는지를 보여준다.
클라이언트가 요청을 전송하면 Dispatcher Servlet
클래스에 요청이 전달된다.
Dispatcher Servlet
은 클라이언트의 요청을 처리할 Controller에 대한 검색을 Handler Mapping
인터페이스에 요청한다.
Handler Mapping
은 클라이언트의 요청과 매핑되는 핸들러 객체를 Dispatcher Servlet
에게 리턴한다.
요청을 처리할 Controller 클래스를 찾았으므로, 클라이언트 요청을 처리할 Handler 메서드를 찾아 호출해야 한다.
Dispatcher Servlet
은 Handler Adpater
에게 Handler 메서드 호출을 위임한다.
Handler Adpater
는 Dispatcher Servlet
에게 전달받은 Controller 정보를 기반으로 해당 Controller의 Handler 메서드를 호출한다.
전체 처리 흐름의 반환점을 돌았다. 이후 과정부터는 반대로 돌아간다.
Controller
의 Handler 메서드는 비즈니스 로직을 처리하고 리턴 받은 Model 데이터를 `Handler Adapter 에게 전달한다.
Handler Adapter
는 전달받은 Model 데이터와 View 정보를 다시 Dispatcher Servle
t에게 전달한다.
Dispatcher Servlet
은 전달 받은 View 정보를 다시 View Resolver
에게 전달해 View 검색을 요청한다.
View Resolver
는 View 정보에 해당하는 View를 찾아서 View를 다시 리턴해준다.
Dispatcher Servlet
은 View Resolver
로부터 전달 받은 View 객체를 통해 Model 데이터를 넘겨주면서 클라이언트에게 전달할 응답 데이터 생성을 요청한다.
View
는 응답 데이터를 생성해 다시 Dispatcher Servlet
에게 전달한다.
Dispatcher Servlet
은 View
에게 전달 받은 응답 데이터를 최종적으로 클라이언트에게 전달한다.
Dispatcher Servlet
의 역할
Spring MVC의 요청 처리 흐름을 살펴보면 Dispatcher Servlet
이 굉장히 자주 등장한다.
클라이언트로부터 요청을 전달 받으면 대부분의 Spring MVC 구성 요소들과 상호작용을 하고 있는 것을 알 수 있다.
Dispatcher Servlet
은 굉장히 바빠보이지만, 실제로 요청에 대한 처리는 다른 구성 요소들에게 위임하고 있다.
"Handler Mapping
아 Handler Controller를 찾아줘." 라고 하는 것과 같다.
Dispatcher Servlet
이 애플리케이션의 가장 앞에 위치해 다른 구성 요소들과 상호작용하며 클라이언트의 요청을 처리하는 패턴을 Front Controller Pattern이라 한다.