Spring Boot의 @RequestMapping은 Spring MVC에서 HTTP 요청을 특정 컨트롤러 메서드에 매핑하기 위해 사용됩니다. 웹 애플리케이션 개발에서 URL 경로와 해당 경로를 처리할 메서드를 연결하는 중요한 어노테이션입니다.
| 속성 | 설명 | 예시 |
|---|---|---|
value 또는 path | 요청 URL 경로를 지정. 단일 경로나 배열 형태로 가능. | @RequestMapping("/users") |
method | HTTP 메서드 지정 (GET, POST, PUT, DELETE 등). 여러 개 지정 가능. | @RequestMapping(value = "/users", method = RequestMethod.GET) |
params | 요청에 특정 쿼리 파라미터가 포함되어야 매핑되도록 설정. | @RequestMapping(value = "/users", params = "active=true") |
headers | 요청 헤더 조건에 따라 매핑. | @RequestMapping(value = "/users", headers = "X-Header=abc") |
consumes | 요청 본문(Content-Type) 조건을 지정 (JSON, XML 등). | @RequestMapping(value = "/users", consumes = "application/json") |
produces | 응답 본문(Content-Type)을 지정. 클라이언트가 기대하는 데이터 형식을 명시. | @RequestMapping(value = "/users", produces = "application/json") |
@RequestMapping은 HTTP 메서드를 명시적으로 지정하지 않으면 모든 메서드(GET, POST, etc.)를 처리합니다.
하지만 더 명확한 코드 작성과 유지보수를 위해 각 HTTP 메서드에 특화된 매핑 어노테이션을 사용하는 것이 일반적입니다:
| 어노테이션 | 설명 |
|---|---|
@GetMapping | HTTP GET 요청을 처리. |
@PostMapping | HTTP POST 요청을 처리. |
@PutMapping | HTTP PUT 요청을 처리. |
@DeleteMapping | HTTP DELETE 요청을 처리. |
@PatchMapping | HTTP PATCH 요청을 처리. |
클래스 레벨에서 공통 경로를 지정하고, 메서드 레벨에서 세부 경로를 설정할 수 있습니다.
@RestController
@RequestMapping("/api/users")
public class UserController {
// GET /api/users
@GetMapping
public List<String> getUsers() {
return List.of("홍길동", "박문수", "이몽룡");
}
// GET /api/users/{id}
@GetMapping("/{id}")
public String getUserById(@PathVariable Long id) {
return "User ID: " + id;
}
// POST /api/users
@PostMapping
public String createUser(@RequestBody Map<String, String> user) {
return "User created: " + user.get("name");
}
}
특정 HTTP 메서드만 처리하도록 설정할 수 있습니다.
@RequestMapping(value = "/products", method = RequestMethod.POST)
public String addProduct() {
return "Product added!";
}
요청에 특정 쿼리 파라미터가 포함된 경우에만 매핑됩니다.
@RequestMapping(value = "/search", params = "keyword")
public String search(@RequestParam String keyword) {
return "Search result for: " + keyword;
}
특정 요청 헤더가 포함된 요청만 처리합니다.
@RequestMapping(value = "/header-test", headers = "X-Special-Header=Valid")
public String headerTest() {
return "Header matched!";
}
Content-Type이 특정 조건을 만족해야 매핑됩니다.Content-Type을 지정합니다.@RequestMapping(value = "/json-endpoint", consumes = "application/json", produces = "application/json")
public Map<String, String> jsonEndpoint(@RequestBody Map<String, String> input) {
input.put("status", "processed");
return input;
}
| 단축 어노테이션 | @RequestMapping 사용 시 동일 코드 |
|---|---|
@GetMapping("/users") | @RequestMapping(value = "/users", method = RequestMethod.GET) |
@PostMapping("/users") | @RequestMapping(value = "/users", method = RequestMethod.POST) |
@PutMapping("/users") | @RequestMapping(value = "/users", method = RequestMethod.PUT) |
단축 어노테이션을 사용하면 코드가 간결해지고, HTTP 메서드를 더 명확하게 표현할 수 있습니다.
URI의 변수 값을 추출하여 메서드 매개변수로 전달합니다.
@GetMapping("/users/{id}")
public String getUser(@PathVariable("id") Long id) {
return "User ID: " + id;
}
쿼리 파라미터 값을 추출합니다.
@GetMapping("/search")
public String search(@RequestParam("q") String query) {
return "Searching for: " + query;
}
요청 본문(JSON 또는 XML)을 매핑하여 객체로 변환합니다.
@PostMapping("/users")
public String createUser(@RequestBody User user) {
return "User created: " + user.getName();
}
@RequestMapping은 RESTful API 설계에 적합하며, 리소스 경로(URL)와 HTTP 메서드를 조합해 일관된 인터페이스를 제공합니다./)로 구분된 URL의 한 조각을 의미합니다./users/* → /users/홍길동은 매칭되지만 /users/admin/settings은 매칭되지 않음.*는 슬래시(/) 사이에 있는 하나의 경로 조각만 대체할 수 있습니다.@RequestMapping("/files/*")
public String handleSingleWildcard() {
return "Matches any single segment under /files/";
}
예시:
/files/image, /files/document/files/images/picture, /files/*와 @PathVariable을 조합해 와일드카드로 추출된 경로 세그먼트를 변수로 받을 수 있습니다.@RequestMapping("/users/*")
public String handleUserWildcard(@PathVariable String id) {
return "User ID: " + id;
}
주의: Spring MVC에서는 *를 사용할 경우, PathVariable의 이름을 명시적으로 지정할 수 없습니다. URL의 매칭 부분을 동적으로 처리하려면 더 구체적인 패턴 매칭이 필요합니다.
*를 배열로 사용하여 다양한 경로를 한 번에 매핑할 수 있습니다.@RequestMapping({"/users/*", "/admins/*"})
public String handleMultipleWildcards() {
return "Matches both /users/* and /admins/*";
}
/files/* → 정확히 한 세그먼트만 대체 가능./files/*/edit → 중간 세그먼트 하나만 대체./) 경계*는 슬래시(/)를 포함하지 않는 경로 조각만 대체합니다./users/*는 /users/홍길동과 매칭되지만 /users/홍길동/프로필과는 매칭되지 않습니다.*와 **의 차이점**Spring MVC에서는 *와 **가 다른 방식으로 작동합니다.
| 기호 | 의미 | 예시 |
|---|---|---|
* | 단일 경로 세그먼트를 대체. | /files/* → /files/image, /files/doc |
** | 다중 경로 세그먼트를 대체. 중첩된 경로 전체를 포함. | /files/** → /files/image/picture/doc |
@RequestMapping("/files/**")
public String handleDoubleWildcard() {
return "Matches any nested path under /files/";
}
* 활용 예시:/files/** → /files/images/picture, /files/docs/notes (모두 매칭).PathVariable과의 조합
*는 단일 세그먼트를 대체하지만, @PathVariable로 사용하려면 명시적인 경로 지정이 필요합니다. 불명확한 매핑은 런타임 오류를 초래할 수 있습니다.우선순위 문제
여러 매핑이 동일한 패턴을 가지거나 유사할 경우, Spring은 보다 구체적인 경로를 우선 처리합니다.
예: /files/image와 /files/*가 동시에 정의된 경우 /files/image가 먼저 매칭됩니다.
유효하지 않은 매칭
*는 반드시 단일 경로 세그먼트를 의미하므로, 빈 세그먼트(//)나 중첩된 세그먼트에는 매칭되지 않습니다.@RestController
@RequestMapping("/api")
public class FileController {
// 단일 세그먼트 매칭
@RequestMapping("/files/*")
public String handleSingleSegment() {
return "Single segment matched!";
}
// 다중 세그먼트 매칭
@RequestMapping("/files/**")
public String handleNestedSegments() {
return "Multiple segments matched!";
}
// PathVariable과 결합
@RequestMapping("/users/*")
public String handleUserWildcard(@PathVariable String id) {
return "User ID matched with wildcard: " + id;
}
}