둘의 차이점
@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 |