둘의 차이점

@ModelAttribute 와 @RequestBody 는 각각 다루는 HTTP 요청 데이터 차이가 있다.

 

@ModelAttribute 는 HTTP 요청 파라미터(URL 쿼리 파라미터, HTML Form)를 다룰 때 사용한다. 

@RequestBody 는 HTTP 메시지 바디의 데이터를 객체로 변환하며 주로 API JSON 요청을 다룰 때 사용한다.

 

둘은 DTO 객체를 통해 데이터를 받을 때도 차이가 있는데 요약하자면 다음과 같다.

  • URL 쿼리파라미터 혹은 x-www-form-urlencoded@ModelAttribute 로 받는다.
  • JSON 은 @RequestBody 로 받는다.

 

x-www-form-urlencoded와 JSON 의 차이점은 여기에 정리해두었다.

 

1. @ModelAttribute

아래 같은 HTTP 요청 파라미터를 다룬다.

 

URL 쿼리 파라미터

http://localhost:8080/request?username=hello&age=20

 

HTML Form  

message body:
username=hello&age=20

 

PostController

데이터를 받는 DTO 객체 PostCreate 를 하나 만들고 요청 데이터가 잘 받아지는지 확인해볼것이다.

DTO 에 값이 잘 담겼는지는 로그를 통해 확인한다. POST 요청이 성공하면 "Hello" 문자열을 반환한다.

@Slf4j
@RestController
public class PostController {

    @PostMapping("/posts/model")
    public String postModelAttribute(@ModelAttribute PostCreate params) {
        log.info("params = {}", params.toString());
        return "Hello";
    }
}

 

참고로 스프링의 기본 설정은 @ModelAttribute 이기 때문에 아래처럼 생략해도 정상 동작한다.

@Slf4j
@RestController
public class PostController {

    @PostMapping("/posts/model")
    public String postModelAttribute(PostCreate params) {
        log.info("params = {}", params.toString());
        return "Hello";
    }
}

 

PostCreate

public class PostCreate {

    public String title;
    public String content;

    public PostCreate(String title, String content) {
        this.title = title;
        this.content = content;
    }

    @Override
    public String toString() {
        return "PostCreate{" +
            "title='" + title + '\'' +
            ", content='" + content + '\'' +
            '}';
    }
}

 

PostControllerTest

("/posts") 로 POST 요청 시 상태코드 200 과 응답값으로 "Hello" 가 반환되는지 확인하는 테스트를 작성한다.

여기서는 HTML Form 에 쿼리 파라미터 형식으로 전달한다.

URL 에서 쿼리 스트링 형식으로 전달하는것도 @ModelAttribute 로 받을 수 있는데

해당 케이스는 이 글의 컨트롤러 테스트를 참고한다.

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest
class PostControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @DisplayName("/posts 요청 시 Hello 를 출력한다.")
    @Test
    void postModelAttribute() throws Exception {
        mockMvc.perform(
            post("/posts")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .param("title", "글 제목입니다")
                .param("content", "글 내용입니다 하하")
            )
            .andExpect(status().isOk())
            .andExpect(content().string("Hello"))
            .andDo(print());
    }
}

테스트는 성공하고 위 사진의 맨 윗줄의 params 에 값이 잘 담겼음을 확인할 수 있다.

 

2. @RequestBody

아래 같은 HTTP 메시지 바디 를 다룬다.

message body:
{
       "username": "hello",
       "age": 20
}

 

PostController

위와 같이 DTO 에 값이 잘 담겼는지는 로그를 통해 확인한다.

POST 요청이 성공하면 "Hello" 문자열을 반환한다. PostCreate 는 위의 ModelAttribute 케이스와 동일하다.

@Slf4j
@RestController
public class PostController {

    @PostMapping("/posts/request")
    public String postModelRequestBody(@RequestBody PostCreate params) {
        log.info("params = {}", params.toString());
        return "Hello";
    }
}

 

PostControllerTest

("/posts") 로 POST 요청 시 상태코드 200 과 응답값으로 "Hello" 가 반환되는지 확인하는 테스트를 작성한다.

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest
class PostControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @DisplayName("/posts 요청 시 Hello 를 출력한다. @requestBody")
    @Test
    void postModelRequestBody() throws Exception {
        mockMvc.perform(
            post("/posts")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content("{\"title\" : \"글 제목입니다\", \"content\" : \"글 내용입니다 하하\"}")
            )
            .andExpect(status().isOk())
            .andExpect(content().string("Hello"))
            .andDo(print());
    }
}

테스트는 성공하고 위 사진의 맨 윗줄의 params 에 값이 잘 담겼음을 확인할 수 있다.

'백엔드 > Spring' 카테고리의 다른 글

Interceptor  (0) 2023.09.29
BeanValidation 써보기  (0) 2023.09.22
DispatcherServlet  (0) 2023.08.01
Thread Pool  (0) 2023.07.25
Servlet  (0) 2023.07.25

+ Recent posts