이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
- Spring MVC는 어떤 조건으로 요청을 handler method에 매핑하는가?
@GetMapping,@PostMapping은@RequestMapping과 어떤 관계인가?- 404, 405, 415, 406은 요청 매핑 관점에서 어떻게 나누어 볼 수 있는가?
개요
Spring MVC 공식 문서는 annotated controller가 @RequestMapping과 그 shortcut 애너테이션으로 요청을 handler method에 매핑한다고 설명한다. 매핑 조건은 path뿐 아니라 HTTP method, params, headers, consumes, produces를 포함할 수 있다. @GetMapping, @PostMapping 같은 애너테이션은 의도를 좁힌 composed annotation이다.
요청 바인딩을 이해하려면 먼저 “어떤 메서드가 선택되는가”를 알아야 한다. 파라미터 바인딩은 handler method가 선택된 다음 일어난다.
원리
@RestController
@RequestMapping("/api/members")
public class MemberController {
@GetMapping("/{id}")
public MemberResponse find(@PathVariable Long id) {
return memberService.find(id);
}
@PostMapping(consumes = "application/json")
public MemberResponse create(@RequestBody CreateMemberRequest request) {
return memberService.create(request);
}
}@RequestMapping("/api/members")는 클래스 레벨 공통 경로이고, @GetMapping("/{id}"), @PostMapping은 method 레벨 조건이다. Spring은 이 조건들을 합쳐 요청과 맞는 handler method를 찾는다.
Mapping 조건
주요 조건은 다음과 같다.
- path:
/members/{id} - HTTP method: GET, POST, PUT, DELETE
- params: 특정 query parameter 존재 여부
- headers: 특정 header 조건
- consumes: 요청 body media type
- produces: 응답으로 만들 수 있는 media type
이 조건을 구분하면 HTTP 오류도 더 잘 보인다. path가 맞지 않으면 404, path는 맞지만 method가 다르면 405, 요청 body media type이 맞지 않으면 415, 응답 media type 협상이 실패하면 406으로 볼 수 있다.
중요한 점은 “URL이 같다”만으로 handler가 선택되는 것이 아니라는 점이다. path는 맞아도 consumes가 application/json인데 form 요청이 들어오면 다른 결과가 나오고, produces가 application/json인데 클라이언트가 받을 수 없다고 선언하면 응답 협상에서 실패할 수 있다.
실전 팁
- URL이 맞는지보다 path, method, consumes, produces가 모두 맞는지 확인한다.
- REST API는 resource path와 HTTP method 조합으로 의미를 표현한다.
@RequestMapping하나에 모든 method를 열어두기보다@GetMapping,@PostMapping등으로 의도를 좁힌다.- 같은 메서드에 여러 mapping 애너테이션을 겹쳐 붙여 모호하게 만들지 않는다.
- class-level mapping과 method-level mapping이 합쳐진 최종 path를 확인한다.
- wildcard나 중복 path가 많아지면 mapping 충돌과 디버깅 비용이 커진다.
위험 신호!
- 같은 path에 비슷한 조건의 handler method가 여러 개 있다.
- GET 요청에 body를 기대하는 API를 설계한다.
- consumes/produces 조건 없이 JSON API와 form 요청을 섞는다.
- path만 보고 mapping 성공 여부를 판단하고 params, headers, consumes, produces 조건을 확인하지 않는다.
- 405를 Controller 내부 로직 문제로 디버깅한다.
- URL path에 action 동사를 과도하게 넣고 HTTP method 의미를 무시한다.
확인 질문
확인 질문
@GetMapping은 무엇의 축약형인가?
- GET method 조건을 가진
@RequestMapping의 축약형이다.- 415 Unsupported Media Type은 주로 어떤 조건과 관련되는가?
- 요청 body의
Content-Type과 handler의consumes조건 또는 converter 선택과 관련된다.- handler method 선택은 파라미터 바인딩보다 먼저인가?
- 먼저다. 어떤 method를 실행할지 결정된 뒤 그 method의 인자를 바인딩한다.