[TIL]Spring MVC Response와 Thymeleaf, Jackson 오류 처리

제이·6일 전

오늘 학습한 내용

Spring 입문 주차 강의를 통해 Spring MVC의 HTML을 반환하는 방법과 HTTP Response를 반환하는 방법, 그리고 Java 객체를 JSON으로 변환하는 과정을 학습함

  • Thymeleaf를 이용한 정적(Static)/동적(Templates) HTML 처리
  • Model을 이용한 데이터 전달
  • @ResponseBody와 @RestController
  • Java 객체를 JSON으로 변환하는 Jackson의 ObjectMapper
  • Path Variable과 Request Param의 차이

1. Thymeleaf에서 Model 데이터 전달

Controller에서 Model을 사용하면 HTML 템플릿에 데이터를 전달할 수 있다.

@GetMapping("/html/dynamic")
public String htmlDynamic(Model model) {
    visitCount++;
    model.addAttribute("visit", visitCount);

    return "hello-visit";
}

Thymeleaf에서는 Controller에서 지정한 이름과 동일한 이름으로 데이터를 가져와야 한다.

<span th:text="${visit}"></span>

처음에는 Controller에서 visit이라는 이름으로 데이터를 전달하면서 HTML에서는 ${visits}로 작성하여 방문자 수가 출력되지 않는 문제가 발생했다.

배운 점

Model에 데이터를 추가할 때 사용한 attribute 이름과 Thymeleaf에서 사용하는 변수 이름은 반드시 일치해야 한다.

model.addAttribute("visit", 값)
                ↓
          ${visit}

3. @Controller와 @ResponseBody 사용

Spring에서 @Controller가 붙은 클래스의 메서드가 String을 반환하면 기본적으로 해당 문자열을 View 이름으로 해석한다.

@Controller
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
}

이 경우 Spring은 hello.html이라는 Thymeleaf 템플릿을 찾는다.

반면 @ResponseBody를 사용하면 반환값을 View 이름이 아니라 HTTP Response Body로 전달한다.

@GetMapping("/hello")
@ResponseBody
public String hello() {
    return "Hello world";
}

따라서 다음과 같은 차이가 있다.

@Controller
return "hello"
        ↓
Thymeleaf의 hello.html 탐색

@Controller + @ResponseBody
return "Hello world"
        ↓
HTTP Response Body에 문자열 전달

@Controller는 기본적으로 View를 반환하는 Controller이다.

return "hello"
      ↓
Thymeleaf View 이름
      ↓
templates/hello.html
      ↓
HTML 응답

@Controller + @ResponseBody는 반환값을 HTTP Response Body에 직접 넣는 형태이다.

return "Hello World"
        ↓
HTTP Response Body
        ↓
Hello World

@RestController는 @Controller + @ResponseBody을 합쳐놓은 상태이다.

@RestController를 사용하면 클래스의 메서드에 기본적으로 @ResponseBody가 적용되므로 API를 만들 때 편리하다. 하지만 @Controller의 경우 Thymeleaf HTML 페이지 반환 시 사용되기도 하므로 용도에 맞게 잘 써야 한다는 것을 알았다.

3. Jackson과 ObjectMapper

Java 객체를 JSON으로 변환하기 위해 Jackson의 ObjectMapper를 사용할 수 있다.

Star star = new Star("Robbie", 95);

ObjectMapper objectMapper = new ObjectMapper();

String json = objectMapper.writeValueAsString(star);

변환 결과:

{
  "name": "Robbie",
  "age": 95
}

Spring에서는 Controller에서 객체를 반환할 때 Jackson과 HttpMessageConverter를 이용해 Java 객체를 JSON으로 변환하여 HTTP Response Body로 전달할 수 있다.

@GetMapping("/json/class")
@ResponseBody
public Star helloClassJson() {
    return new Star("Robbie", 95);
}

즉 직접 JSON 문자열을 만들지 않아도 Spring이 객체를 JSON으로 변환해준다.

4. Jackson 버전 차이

오늘 JsonProcessingException을 사용하는 과정에서 Jackson의 패키지 차이 때문에 오류가 발생했다.

기존 Jackson 2 계열에서는 일반적으로 다음과 같은 패키지를 사용한다.

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;

반면 현재 프로젝트 환경에서는 버전이 달라tools.jackson.databind.ObjectMapper가 사용될 수 있어 Jackson 버전에 따라 API와 패키지가 달라질 수 있다는 것을 알게 되었다.

배운 점

강의 코드의 import를 무조건 그대로 복사하기보다 현재 프로젝트의 Spring Boot와 Jackson 버전을 확인하고 사용하는 라이브러리의 패키지가 호환되는지를 봐야 한다.

5. Path Variable과 Request Param

URL을 통해 데이터를 전달하는 방법으로 Path Variable과 Request Param의 차이도 학습했다.

Path Variable

URL 경로 자체에 값이 포함되는 방식이다.

/users/10
@GetMapping("/users/{id}")
public String getUser(@PathVariable Long id) {
    return "user";
}

10이라는 값이 사용자를 식별하는 데 사용된다.

/users/{id}
        ↓
       10

Request Param

URL의 Query String을 통해 값을 전달한다.

/users?id=10
@GetMapping("/users")
public String getUser(@RequestParam Long id) {
    return "user";
}

한 줄 회고

오늘은 간단히 기능을 구현하는 것에서 벗어나 Controller의 반환값이 View로 처리되는지 HTTP Response Body로 처리되는지, 그리고 Spring이 객체를 JSON으로 변환하는 과정을 이해할 수 있었다.

profile
배운 것을 기록합니다.

0개의 댓글