[ Spring ] Content-Type에 따른 어노테이션 간단 정리 - 제약을 통한 정확한 의사소통
content-type에 따라 어떤 어노테이션을 써야하는지 매번 헷갈렸다.
램이 작은 나를 위해 아주 간단하고 명료하게 정리하려고한다.
content-type이란?
또 잊어버릴 미래의 나를 위해 content-type을 간단하게 설명하자면,
content-type이란 말 그대로 콘텐츠의 타입이다. 요청 보낼 콘텐츠의 타입은 이거야~! 라고 content-type에 명시해서 서버에 보내는 것이다.
그렇다면 왜 content-type을 보내야하지? 간단하게 요청 데이터가 어떤 타입인지 알아야 서버에서도 처리할 수 있기 때문이다.
대표적인 content-type의 종류와 그에 맞는 어노테이션
application/x-www-form-urlencoded -> @RequestParam || @ModelAttribute
쿼리 파라미터 또는 폼 데이터로 전달할 때의 content-type이다. application/x-www-form-urlencoded으로 서버에 요청을 보낼 경우 서버는 @ModelAttribute 또는 @RequestParam 를 쓰면 된다.
- @ModelAttribute 와 @RequestParam의 차이 : ModelAttribute의 경우는 받은 데이터를 객체로 변환할 때 사용하는 것이다.
코드로 확인!
// content-type : application/x-www-form-urlencoded -> @ReqeuestParam
@PostMapping("/requestParam")
public UserDto requestParam(@Valid @RequestParam("name") String name,@Valid @RequestParam("password") String password){
log.info("request 테스트 중");
UserDto user = new UserDto(name,password);
return user;
}
// content-type : application/x-www-form-urlencoded -> @ModelAttribute
@PostMapping("/modelAttribute")
public UserDto modelAttribute(@Valid @ModelAttribute UserDto user){
log.info("request 테스트 중");
return user;
}
application/json -> @RequestBody
json 형식의 데이터를 보낼 때 사용하는 content-type이며 서버에서는 @RequestBody로 데이터를 객체를 변환하여 사용할 수 있다.
// content-type : application/json -> @RequestBody
@PostMapping("/requestBody")
public UserDto requestBody(@Valid @RequestBody UserDto user){
log.info("request 테스트 중");
return user;
}
multipart/form-data -> @ReqeustPart || @ModelAttribute
멀티파트 요청을 할 때 쓰는 content-type이며(예를 들어 파일 업로드 등) , 서버에서는 @ReqeustPart 또는 @ModelAttribute로 데이터를 받을 수 있다.
// content-type : multipart/form-data -> @RequestPart
@PostMapping("/requestPart")
public UserDto requestPart(@Valid @RequestPart("name") String name,@Valid @RequestPart("password") String password){
log.info("request 테스트 중");
UserDto user = new UserDto(name,password);
return user;
}
// content-type : multipart/form-data -> @ModelAttribute
@PostMapping("/multipartMA")
public UserDto multipartMA(@Valid @ModelAttribute UserDto user){
log.info("request 테스트 중");
return user;
}
전체 테스트 코드
postMan으로 요청 테스트를 진행했다.
전체 컨트롤러 코드!
@Slf4j
@RestController
public class TestController {
/**
* content-type에 따른 어노테이션 사용 정리 예제 코드
* */
// content-type : application/x-www-form-urlencoded -> @ReqeuestParam
@PostMapping("/requestParam")
public UserDto requestParam(@Valid @RequestParam("name") String name,@Valid @RequestParam("password") String password){
log.info("request 테스트 중");
UserDto user = new UserDto(name,password);
return user;
}
// content-type : application/x-www-form-urlencoded -> @ModelAttribute
@PostMapping("/modelAttribute")
public UserDto modelAttribute(@Valid @ModelAttribute UserDto user){
log.info("request 테스트 중");
return user;
}
// content-type : application/json -> @RequestBody
@PostMapping("/requestBody")
public UserDto requestBody(@Valid @RequestBody UserDto user){
log.info("request 테스트 중");
return user;
}
// content-type : multipart/form-data -> @RequestPart
@PostMapping("/requestPart")
public UserDto requestPart(@Valid @RequestPart("name") String name,@Valid @RequestPart("password") String password){
log.info("request 테스트 중");
UserDto user = new UserDto(name,password);
return user;
}
// content-type : multipart/form-data -> @ModelAttribute
@PostMapping("/multipartMA")
public UserDto multipartMA(@Valid @ModelAttribute UserDto user){
log.info("request 테스트 중");
return user;
}
@Data
public static class UserDto{
private String name;
private String password;
public UserDto(String name, String password) {
this.name = name;
this.password = password;
}
}
}
정리
content-type 별로 쓸 수 있는 어노테이션을 정리했다. content-type이 있음으로 어떤 콘텐츠 타입인지 명확하게 표현함으로써 서버에서 어떻게 데이터를 받을지도 정확하게 정할 수 있었다. 어쩌면 콘텐츠 타입을 명시하는 것이 제약을 두는 것일 수 있다. 하지만 이 제약으로 인해서 클라이언트와 서버간의 정확한 소통이 가능하게 된다. 프로그램에서 애매한 것은 좋지 않다는 김영한 강사님의 말씀이 생각났다. 오늘 정리를 한 문장으로 표현하자면 제약을 통한 정확한 의사소통!