x-www-form-urlencoded
방식으로 두 개의 객체를 받으려 했던 시도@ModelAttribute
와 @RequestParam
을 생략해도 필드명이 같으면 자동으로 바인딩된다는 내용을 접했다.application/x-www-form-urlencoded
를 사용했다.@ModelAttribute
를 통해 바인딩하는 것이 가능할지 확인.Key | Value |
---|---|
tutor.name | 김철수 |
tutor.age | 26 |
tutee.name | 박화랑 |
tutee.cost | 10000 |
@PostMapping("/v5/tutor")
public String requestParamV5(
@ModelAttribute Tutor tutor,
@ModelAttribute Tutee tutee
) {
return "tutor name = " + tutor.getName() + " age = " + tutor.getAge() +
" and tutee name = " + tutee.getName() + " cost = " + tutee.getCost();
}
@ModelAttribute
는 요청 파라미터에서 객체명을 기준으로 자동 매핑하지 않음.tutor.name
, tutee.name
을 Spring이 별도의 객체로 구분하지 않고, 필드명(name, age, cost)만 기준으로 매핑하려고 시도함.Tutor
와 Tutee
객체의 필드가 충돌하고, null
이 들어가는 문제 발생.tutor name = null age = 0 and tutee name = null cost = null
name
, age
, cost
같은 필드명이 여러 객체에서 중복되었지만, Spring이 이를 제대로 구분하지 못함.@ModelAttribute("tutor")
으로 변경@PostMapping("/v5/tutor")
public String requestParamV5(
@ModelAttribute("tutor") Tutor tutor,
@ModelAttribute("tutee") Tutee tutee
) { ... }
결과:
@ModelAttribute("tutor")
는 뷰(View)에서 사용할 때만 객체명을 설정하는 용도이며, 요청 데이터를 바인딩할 때는 영향을 주지 않음.tutor.name
을 Tutor
객체의 name
필드로 자동 매핑하지 않음.@ModelAttribute
+ DTO 방식@PostMapping("/v5/tutor")
public String requestParamV5(@ModelAttribute TutorAndTutee tutorTuteeDTO) {
Tutor tutor = tutorTuteeDTO.getTutor();
Tutee tutee = tutorTuteeDTO.getTutee();
return "tutor name = " + tutor.getName() + " age = " + tutor.getAge() +
" and tutee name = " + tutee.getName() + " cost = " + tutee.getCost();
}
결과: ✅ 정상 동작!
@RequestBody
방식으로 전환한 경우application/json
방식으로 요청 변경{
"tutor": {
"name": "김철수",
"age": 26
},
"tutee": {
"name": "박화랑",
"cost": "10000"
}
}
@PostMapping("/v5/tutor")
public String requestParamV5(@RequestBody TutorTuteeDTO request) {
Tutor tutor = request.getTutor();
Tutee tutee = request.getTutee();
return "tutor name = " + tutor.getName() + " age = " + tutor.getAge() +
" and tutee name = " + tutee.getName() + " cost = " + tutee.getCost();
}
@ModelAttribute
vs @RequestBody
비교구분 | @ModelAttribute + DTO | @RequestBody + DTO |
---|---|---|
요청 방식 | application/x-www-form-urlencoded | application/json |
내부 객체 지원 | ✅ 가능 (DTO 내부 객체 필드 자동 바인딩) | ✅ 가능 (JSON -> DTO 변환) |
유효성 검사 지원 | ✅ 가능 (@Valid 사용 가능) | ✅ 가능 (@Valid 사용 가능) |
복잡한 데이터 구조 | ❌ 어렵다 (중첩 객체가 깊어지면 복잡함) | ✅ 유연함 (JSON 구조로 깊이 있는 데이터 처리 가능) |
유지보수성 | ✅ (단순한 경우 적합) | ✅ (복잡한 경우 더 적합) |
@ModelAttribute
도 가능하지만, 중첩 객체가 많아지면 @RequestBody
+ JSON 방식이 더 적합함.@RequestBody
를 활용한 JSON 방식을 권장하며, 이를 사용하면 객체를 명확하게 구분할 수 있고, 유효성 검사가 쉬워짐.@ModelAttribute
는 단순한 경우 가능하지만, 데이터가 복잡하면 @RequestBody
가 더 적합함!