최근 API 리팩토링 과정에서, 기존 코드를 분리 및 수정하는 작업을 진행했다.
배포 이후 정상 동작하는 것처럼 보였지만, 예상치 못한 잘못된 데이터 바인딩 현상이 발견되었다.
모델링과 URI 설계가 명확했다면 예방할 수 있었던 문제였기에, 사례를 정리해 공유하고자 한다.
상황
URL PathVariable 이름과 Request Model의 필드명이 동일할 경우,
Spring이 PathVariable 값을 Model의 필드에도 자동 바인딩하는 현상이 발생했다.
케이스별 테스트
class MappingModel {
private String testId;
...getter,setter
}
/* case 1 */
@GetMapping("/test1/{testId}")
public String test1(@PathVariable("testId") String testId, MappingModel model){
return "testId=" + testId + ", model.testId=" + model.getTestId();
}
result => testId=test4, model.testId=test4
/* case 2 */
@GetMapping("/test2/{testId}")
public String test2(@PathVariable String testId, MappingModel model){
return "testId=" + testId + ", model.testId=" + model.getTestId();
}
result => testId=test4, model.testId=test4
/* case 3 */
@GetMapping("/test3/{test_id}")
public String test3(@PathVariable("test_id") String testId, MappingModel model){
return "testId=" + testId + ", model.testId=" + model.getTestId();
}
result => testId=test4, model.testId=null
/* case 4-1 */
@GetMapping("/test4/{testId}")
public String test4(MappingModel model){
return "1 model.testId=" + model.getTestId();
}
result => 1 model.testId=test4
/* case 4-2 */
@GetMapping("/test4")
public String test5(MappingModel model){
return "2 model.testId=" + model.getTestId();
}
result => 2 model.testId=null
case 5
@PostMapping("/test6/{testId}")
public String test6(@PathVariable String testId, @RequestBody MappingModel model){
return "testId=" + testId + ", model.testId=" + model.getTestId();
}
result => testId=test4, model.testId=null
주의 깊게 볼만한 것은 case 2, 3의 상황이다.
@PathVariable의 경우 cammelCase인 경우 대개 case2번 처럼 name을 명시하지 않고 쓰는 경우가 많다.
만약 위의 URL처럼 testId값이 식별인자인데 파라미터로 받는 model에도 같은 이름의 testId란 멤버변수가 존재하는 상황이면?
-> 정의해둔 MappingModel의 testId와 pathvariable의 String testId 양쪽에 값이 binding되는 상황이 발생된다.
그러나 @PathVariable 어노테이션에 name을 명시(snakeCase or diff name)해 주면 변수명이 같아도 model 변수엔 binding되지 않고 원하는 결과값을 얻을수 있다.
@GetMapping("/test3/{test_id}")
public String test3(@PathVariable("test_id") String testId, MappingModel model){
return "testId=" + testId + ", model.testId=" + model.getTestId();
}
result => testId=test4, model.testId=null
결론
1. modeling 및 설계를 잘 하자!
2. 부득이하게 식별키 name과 model의 필드가 같을시엔 uri를 snakeCase 변경( {test_id} ) 및 @PathVariable에 구분 되게끔 name, value를 명시 해준다!
'트러블슈팅 & 삽질기록' 카테고리의 다른 글
| Apache HTTPD 버전 업그레이드 중 MPM 이슈와 해결 과정 (5) | 2025.07.20 |
|---|---|
| Spring Boot 3.4.3에서 Auto-configuration이 동작하지 않는 문제 해결 (0) | 2025.03.09 |
| IntelliJ 특정 버전 JDK 21 사용 시 컴파일 오류 (2) | 2025.02.22 |
| [spring] gradle build fail (0) | 2023.10.18 |
| [mac] 문제가 발생했기 때문에 컴퓨터를 종료했습니다. 경고창 뜨는 경우 대처법 (2) | 2023.09.07 |