HTTP 요청 매핑 어노테이션(@RequestMapping)
HTTP 요청 매핑 어노테이션에 대해 알기 위해서는 REST API에 대해서도 알아야 합니다. REST API를 간단히 설명하자면 Representational State Transfer의 약자로 자원을 이름으로 구분하여 해당 자원의 상태를 주고받는 모든 것을 말하며 웹 서비스 간에 데이터를 주고받기 위한 표준화된 방법을 제공하는 프로토콜입니다.
주요 특징
- 자원(Resouce)
- REST API는 자원을 고유한 식별자인 URI(Uniform Resource Identifier)를 통해 표현
- ex) /member → 멤버 자원, /products → 제품 자원 - HTTP methods
- REST API는 HTTP methods를 사용하여 자원에 대한 작업(행위)을 수행
- 대표 methods로는 GET(조회), POST(생성), PUT(수정), PATCH(수정), DELETE(삭제)
- REST API 설계 규칙에 맞게 적절한 methods를 사용 - 상태 무관성(Stateless)
- REST API는 상태를 유지하지 않는 특징이 있어 각 요청이 서버에 독립적으로 처리
- 각 요청은 클라이언트의 인증 정보와 함께 충분한 데이터를 포함해야 한다.
- 즉, 서버 측에서는 클라이언트의 상태를 관리하는 Session을 유지하지 않는 것을 의미한다. - 인터페이스 일관성
- REST API는 일관된 인터페이스를 제공
- 요청 : 자원을 알면 HTTP methods를 통해 일관된 작업(행위)을 유추가 가능
- 응답 : 상태 코드로 요청에 대한 작업(행위)에 대한 결과를 알 수 있음
위와 같은 REST API 원칙에 따른 요청에 대해 스프링 프레임워크에서는 컨트롤러에 매핑을 할 수 있는 어노테이션을 제공하는데 이것이 @RequestMapping
입니다.
1. @RequestMapping
클라이언트 요청을 특정 컨트롤러 메서드와 연결하여 요청을 처리할 수 있도록 도와주는 어노테이션입니다. 스프링 4.3 이전에 사용하던 어노테이션으로 스프링 4.3 이후 버전을 사용하는 현재는 좀 더 명시적으로 HTTP 메서드에 대한 매핑을 단순화한 어노테이션들을 사용합니다.(@GetMapping
, @PostMapping
, @PutMapping
, @DeleteMapping
등)
@RequestMapping
에서 주로 사용하는 속성은 value, path, method, params, headers 등이 존재합니다.
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
@Reflective(ControllerMappingReflectiveProcessor.class)
public @interface RequestMapping {
String name() default "";
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {};
}
@RequestMapping
어노테이션에서 사용되는 @Target({ElementType.TYPE, ElementType.METHOD})
어노테이션에서 알 수 있듯이 Class와 Method에서 모두 사용할 수 있습니다. Controller Class에 @RequestMapping
을 사용하게 되면 Controller Class 안 Method에 모두 적용이 된다는 특징이 있습니다.
2. @RequestMapping 주요 속성
2-1. value, path
value이나 path 속성은 특정 URL 경로와 컨트롤러 메서드를 매핑하며 default로는 현재 URL 경로가 됩니다.
@RestController
public class V1MappingController {
// 요청 URL = http://localhost:8080
@RequestMapping(value = "/")
public String defaultUrl() {
return "value = /";
}
// 요청 URL = "http://localhost:8080/member"
@RequestMapping(value = "/member")
public String valueUrl() {
return "value = /member";
}
}
테스트를 위해 Postman을 사용하였습니다.
Controller Class에 @RequestMapping
을 사용하게 되면 해당 Controller Class에 모두 적용되는 것을 볼 수 있습니다.
@RestController
@RequestMapping(value = "/order")
public class V2MappingController {
// 요청 URL = http://localhost:8080/order
@RequestMapping // 삭제해도 결과는 같다.
public String defaultUrl() {
return "value = order";
}
// 요청 URL = "http://localhost:8080/order/member"
@RequestMapping(value = "/member")
public String valueUrl() {
return "value = /order/member";
}
}
2-2. method
method 속성은 특정 HTTP method와 컨트롤러를 매핑해 줍니다. 따라서 하나의 URL에 GET, POST, PUT, DELETE를 각각 매핑할 수 있습니다. 만약 method 속성 값을 주지 않는다면 모든 HTTP method가 매핑되게 됩니다.
@RestController
@RequestMapping(value = "/order")
public class V3MappingController {
@RequestMapping(method = RequestMethod.GET)
public String getOrderList() {
return "method GET";
}
@RequestMapping(method = RequestMethod.POST)
public String saveOrder() {
return "method POST";
}
@RequestMapping(value = "/{order_id}", method = RequestMethod.GET)
public String getOrder(
@PathVariable("order_id") Long orderId
) {
return "method detail GET";
}
@RequestMapping(value = "{order_id}", method = RequestMethod.PUT)
public String updateOrder(
@PathVariable("order_id") Long orderId
) {
return "method POST";
}
@RequestMapping(value = "{order_id}", method = RequestMethod.DELETE)
public String deleteOrder(
@PathVariable("order_id") Long orderId
) {
return "method delete";
}
// GET, POST, PUT, PATCH, DELETE 모두 매핑이 된다
@RequestMapping(value = "/test")
public String testMethod() {
return "all method";
}
}
위와 같이 하나의 자원(resouce)인 "/order"가 GET, POST, PUT, DELETE 별로 매핑을 해줄 수 있습니다. 이렇게 REST API 규칙에 맞게 Method 별로 매핑을 하게 된다면 어떤 행위를 하게 되는지 한눈에 파악할 수 있다는 장점이 있습니다. 때문에 method 속성 값을 여러 개 지정할 수 있지만, 특별한 경우가 아니라면 각 HTTP method 별로 매핑하는 것이 좋습니다.
// 아래와 같이 사용하는 것은 특별한 경우를 제외하고는
// 사용하지 않는 것을 권장합니다.
@RequestMapping(value = "/product", method = { RequestMethod.POST, RequestMethod.PUT})
public String saveOrUpdateProduct() {
return "method POST or PUT";
}
2-3. params
params 속성을 사용하면 @RequestParam
어노테이션을 사용하여 요청 파라미터를 메서드 매개변수에 매핑할 수 있습니다. 또한, params가 생략이 되어도 핸들러 메소드에 의해 매개변수를 분석하여 요청 파라미터를 바인딩해 줍니다.
// paraams = "order_name" 생략 가능
@RequestMapping(method = RequestMethod.GET, params = "order_name")
public String getOrderList(
@RequestParam("order_name") String orderName
) {
return "method GET - orderName = " + orderName;
}
2-4. headers
headers 속성을 사용하면 @RequestHeader
어노테이션을 사용하여 요청의 특정 헤더 value 값을 메서드 매개변수에 매핑할 수 있습니다.
@RequestMapping(method = RequestMethod.POST)
public String saveOrder(
@RequestHeader("member_id") Long memberId
) {
return "method POST - memberId = " + memberId;
}
헤더에 key=member_id, value=123을 넣어 요청한 결과를 보면 value 값인 123을 정상적으로 가져온 것을 확인할 수 있습니다.
3. Spring 4.3 추가된 어노테이션
기존 @RequestMapping
을 사용하는데 별다른 이슈사항은 없었지만 가독성 측면이나 일일이 method를 지정해줘야 한다는 불편함이 있었습니다. 이를 개선하고자 Spring 4.3 부터 @GetMapping
, @PostMapping
, @PutMapping
, @PatchMapping
, @DeleteMapping
어노테이션이 추가되었습니다.
- @GetMaapping는 @RequestMapping(method = RequestMethod.GET)와 같음
- @PostMapping는 @RequestMapping(method = RequestMethod.POST)와 같음
- @PutMapping는 @RequestMapping(method = RequestMethod.PUT)와 같음
- @PatchMapping는 @RequestMapping(method = RequestMethod.PATCH)와 같음
- @DeleteMapping는 @RequestMapping(method = RequestMethod.DELETE)와 같음
따라서 Spring 4.3 버전 이상을 사용하고 계신다면 새로 추가된 어노테이션을 사용하는 것을 권장합니다.
@RestController
@RequestMapping(value = "/order")
public class V4MappingController {
@GetMapping(params = "order_name")
public String getOrderList(
@RequestParam("order_name") String orderName
) {
return "method GET - orderName = " + orderName;
}
@PostMapping
public String saveOrder(
@RequestHeader("member_id") Long memberId
) {
return "method POST - memberId = " + memberId;
}
@GetMapping("/{order_id}")
public String getOrder(
@PathVariable("order_id") Long orderId
) {
return "method detail GET";
}
@PutMapping("/{order_id}")
public String updateOrder(
@PathVariable("order_id") Long orderId
) {
return "method PUT";
}
@DeleteMapping("/{order_id}")
public String deleteOrder(
@PathVariable("order_id") Long orderId
) {
return "method delete";
}
}
'Backend > Spring' 카테고리의 다른 글
[TDD] Test Double (0) | 2025.08.03 |
---|---|
[Spring] @Value와 @ConfigurationProperties (0) | 2023.07.09 |
[Spring] Bean Validation과 Custom Validation (0) | 2023.07.08 |
[Spring] HTTP 요청 데이터 바인딩(@RequestParam, @ModelAttribute, @RequestBody, @RequestHeader) (0) | 2023.07.02 |