0. 개요
- 이전 포스팅까지 HTTP Request를 처리하는 방법에 대해서 알아보았다.
- 요청을 GET 방식과 POST 방식으로 나누어 각각 처리하는 방법에 대해 배웠다.
- 이번 포스팅에서는 HTTP Response는 어떻게 처리하는지 알아보자.
1. HTTP Response의 종류
- HTTP Request에는 3가지 방식이 존재했다.
→ GET 방식을 사용한 URL parameter 전달
→ <form> 태그를 이용한 POST 방식의 URL parameter 전달
→ POST 방식을 사용한 Request body를 전달
- 이와 마찬가지로 HTTP Response 또한 3가지 방식이 존재한다.
→ 정적 리소스를 응답하는 방식
→ 동적 리소스(= view template)를 응답하는 방식
→ HTTP 메시지(= JSON)를 사용하여 응답하는 방식
2. Resource 경로
- Server가 제공하는 자원은 정적 또는 동적 resource로 구분된다.
- Spring MVC에서 제공하는 모든 자원은 src/main/resources 경로를 기본으로 사용한다.
- Spring MVC는 자원의 종류를 구분하여 사용하기 위해, 자원의 종류에 따라 다른 하위 경로를 제공한다.
a) Static resource
- 정적 리소스는 내용의 변경 또는 수정 없이, server에 저장된 그대로 제공되는 자원을 의미한다.
- Spring MVC는 src/main/resources/static 경로에 존재하는 자원을 정적으로 처리한다.
- 정적 리소스에 대한 기본 경로를 Spring MVC가 제공하므로 Client가 정적 리소스를 요청할 때
src/main/resources/static을 입력할 필요도, 이 경로를 알 필요도 없다.
- Client가 src/main/resources/static/hello.html 경로의 파일을 요청할 때, 다음과 같이 요청하면 된다.
→ http://localhost:8080/hello.html
- 추가적으로, Spring MVC는 다음과 같은 디렉터리의 자원을 정적으로 처리한다.
ex) /static, /public, /resources, /WEB-INF, /resources
b) Dynamic resource
- 동적 리소스는 요청하는 대상, 시점에 따라 내용이 변경 또는 수정되는 자원을 말한다.
- 일반적으로 HTML을 동적으로 처리하는 용도로 view template을 사용한다.
- Spring MVC는 view template의 경로를 src/main/resources/templates로 설정한다.
- Spring MVC는 Client가 해당 경로의 자원을 요청하면 동적으로 처리하여 제공한다.
- 동적 리소스에 대한 기본 경로를 Spring MVC가 제공하므로 Client가 동적 리소스를 요청할 때
src/main/resources/templates를 입력할 필요도, 이 경로를 알 필요도 없다.
- Client가 src/main/resources/templates/hello.html 경로의 파일을 요청할 때, 다음과 같이 요청하면 된다.
→ http://localhost:8080/hello.html
3. response 처리의 기본 형태
- Spring MVC의 response를 처리하는 방법은 다음과 같은 형태를 기본으로 한다.
a) String 반환형
- String 반환형은 view 객체 또는 HTTP 메시지를 직접 반환하는 형태를 말한다.
- @Controller가 있다면 Spring MVC는 기본적으로 메서드의 return 값을 view name으로 처리한다.
- 그러므로 반환된 view name을 이용하여 viewResolver를 실행하여 view를 찾아 랜더링 한다.
- 반환된 view name 또한 String이다. 다만, Spring MVC에서 이를 view name으로 인식할 뿐이다.
- 메서드에서 @ResponseBody 또는 HttpEntity를 사용하는 경우에도 메서드의 return값을 String으로 처리한다.
- 다만, 이 경우에는 view name이 아니라 HTTP message body에 String을 담아 Client에게 전달한다.
b) void 반환형
- void는 반환 값이 없는 메서드를 사용하는 방식이다.
- @Controller가 있으나, 메서드에 HttpServletResponse, Writer, ResponseEntity 등
HTTP message body를 처리하는 매개변수를 사용하지 않는 경우, 요청 URL을 논리 뷰 이름으로 사용한다.
→ 요청 URL: "/response/hello"
→ 논리 뷰 이름: "templates/response/hello.html"
- void 반환형은 잘 사용되지 않는 방식이며, 사용을 권장하지 않는다.
- 논리 뷰 경로에 해당 자원이 존재하지 않는 경우 문제가 발생하기 때문이다.
- 의도적으로 논리 뷰를 사용하기 위해 void 반환형을 사용하더라도, 코드의 명시성과 가독성이 너무 떨어진다.
c) HTTP message body 반환형
- @ResponseBody, HttpEntity를 사용하면 view template 대신 HTTP message body를 사용한다.
- HTTP message body에 직접 응답 데이터를 작성하여 반환하기 위해 사용된다.
4. view template을 이용한 response 처리방법
- 예시 코드에서 사용하는 template engine은 Thymeleaf를 사용하였다.
- view template을 이용하여 reponse를 처리하는 방법에 대해서 알아보자.
a) ModelAndView 객체 반환형
@Controller
public class ResponseController {
@RequestMapping("/response/modelandview")
public ModelAndView usingModelAndView() {
ModelAndView mav = new ModelAndView("response/hello")
.addObject("data", "response view using ModelAndView!");
return mav;
}
}
- ModelAndView 객체를 생성할 때, Model의 데이터를 사용할 view 경로를 입력한다.
- ModelAndView 객체를 생성한 후, addObject() 메서드를 통해 Model에 데이터를 저장한다.
- 반환된 ModelAndView 객체는 최초에 입력한 view 객체에게 전달된다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p th:text="${data}">empty</p>
</body>
</html>
- ModelAndView를 전달받은 view에서 Thymeleaf를 통해 Model에 저장된 데이터를 사용하여 view를 랜더링 한다.
b) Model 객체 반환형( = String 반환형)
@Controller
public class ResponseController {
@RequestMapping("/response/model")
public String usingModel(Model model) {
model.addAttribute("data", "response view using Model!");
return "response/hello";
}
}
- Model 클래스를 매개변수로 받아, addAttribute()를 사용하여 view 객체가 사용할 데이터를 저장한다.
- 반환 값으로 해당 Model 객체를 사용할 view의 경로를 반환한다.
c) void 반환형
- 위에서 void 반환형의 형태는 논리 뷰를 사용하는 방식이라고 소개했다.
- view template에서도 이 형태를 동일하게 적용할 수 있다.
- 다만, mapping URL과 view의 경로가 동일한 경우 사용한다.
@Controller
public class ResponseController {
@RequestMapping("/response/hello")
public void usingVoid(Model model) {
model.addAttribute("data", "hello, response using void!");
}
}
- 위의 예시 코드에서는 void 반환형을 가진 메서드를 사용하였다.
- view template을 사용하는 상태에서 void 반환형을 사용하는 경우, Spring MVC는 mapping URL을 view 경로로 인식한다.
- 그러므로 @RequestMapping()에 입력된 URL 주소가 view 경로와 동일해야 문제없이 사용이 가능하다.
- 다만, void 반환형은 가독성과 명시성이 좋지 않으므로 사용하지 않는 것을 권장한다.
5. HTTP message body를 이용한 response 처리방법
- HTTP API를 제공하는 경우, 데이터를 직접 전달해야 하므로 HTTP message body를 사용한다.
- 즉, 정적 리소스 또는 view template을 거치지 않고 HTTP response message를 사용하여 바로 응답하는 방식이다.
- HTML을 응답하든, JSON을 응답하든, 데이터의 반환 형식이 다를 뿐 모두 HTTP message body에 담겨서 전달된다.
a) @RestContoller
- HTTP message body를 사용하여 reponse를 처리하는 방법에서 사용되는 annoataion이다.
- @RestController는 쉽게 말해서, @Controller와 @ResponseBody를 합쳐놓은 것이라고 생각하면 된다.
- 그러므로 반환 값을 view name이 아닌 String으로 처리하며, HTTP message body에 반환된 String을 담아서 응답한다.
b) HttpServletResponse
@RestController
public class ResponseBodyController {
@GetMapping("/response-body/string")
public void usingString(HttpServletResponse response) throws IOException {
response.getWriter().write("response using HttpServletResponse");
}
}
- HttpServletResponse를 사용하여 HTTP message body에 직접 문자열을 입력하는 방법이다.
c) ResponseEntity
@RestController
public class ResponseBodyController {
@GetMapping("/response-body/response-entity")
public ResponseEntity<String> usingResponseEntity() {
return new ResponseEntity<>("response using ResponseEntity", HttpStatus.OK);
}
}
- HttpEntity는 HTTP message 헤더와 바디 정보를 설정할 수 있다.
- ResponseEntity는 HttpEntity를 상속받은 클래스로, 추가적으로 HTTP 응답 코드를 설정할 수 있다.
d) @ResponseBody
@RestController
public class ResponseBodyController {
@GetMapping("/response-body/response-body")
public String usingResponseBody() {
return "response using @ResponseBody";
}
}
- @ResponseBody를 사용하면 메서드의 반환 값을 String으로 처리한다.
- 그러니 위의 예시 코드에서는 클래스 레벨에 @RestContorller를 사용하고 있으므로, 따로 @ResponseBody를 명시하지 않아도 된다.
- 왜냐면 @RestContoller 내부에 @ResponseBody를 포함하고 있으므로, 기본적으로 메서드의 반환 값을 String으로 처리한다.
e) ResponseEntity를 이용한 JSON 반환
@Data
public class UserData {
private String username;
private int age;
}
- 우선 JSON 형태를 만들기 위해 Model 클래스를 생성한다.
@RestController
public class ResponseBodyController {
@GetMapping("/response-body/json/response-entity")
public ResponseEntity<UserData> jsonUsingResposneEntity() {
UserData userData = new UserData();
userData.setUsername("response JSON using ResponseEntity");
userData.setAge(2022);
return new ResponseEntity<>(userData, HttpStatus.OK);
}
}
- UserData라는 Model 클래스의 객체를 생성하고, 객체의 초기값을 설정한다.
- 그다음 ResponseEntity 객체를 생성하고 UserData 객체를 매개변수로 설정한다.
- 마지막으로 생성된 ResponseEntity 객체를 반환한다.
* ReponseEntity의 동작이 이해가 가지 않는다면 ResponseEntity의 내부 코드를 살펴보기를 권장한다.
f)@ResponseStatus, @ResponseBody를 이용한 JSON 반환
@RestController
public class ResponseBodyController {
@ResponseStatus(HttpStatus.OK)
@GetMapping("/response-bod/json/response-status")
public UserData UsingResponseStatus() {
UserData userData = new UserData();
userData.setUsername("response using @ResponseStatus & @ResponseBody");
userData.setAge(2022);
return userData;
}
}
- 위의 예시 코드는 @ResponseBody를 사용하여 Model 객체를 반환하는 방식이다.
- @ResponseBody를 사용했으므로 반환 값을 HTTP message body에 담아서 전달하게 된다.
- 이때 Model 객체를 반환하여, HTTP message body에 Model 객체를 담도록 하는 방법이다.
- 위의 코드에는 @ResponseBody를 명시하지 않았는데, 그 이유는 클래스 레벨에서 @RestController를 사용하기 때문이다.
- @ResponseStatus를 사용하면 HTTP message body의 응답 코드를 설정할 수 있다.
- 위의 예시 코드에서 확인할 수 있듯이, HttpStatus에 지정되어있는 상수를 사용하여 상태 코드를 설정한다.
'Back-end > Spring MVC 개념' 카테고리의 다른 글
Spring MVC를 마치며 (0) | 2022.03.21 |
---|---|
18. HTTP message converter (0) | 2022.03.18 |
16. Request - JSON 조회방법 (0) | 2022.03.16 |
15. Request - message Body 조회방법 (0) | 2022.03.15 |
14. Request - URL parameter 조회방법 (0) | 2022.03.14 |
댓글