본문 바로가기
Back-end/Spring MVC 개념

17. Response 처리방법

by devraphy 2022. 3. 17.

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

댓글