Backend/Spring

[Spring] HTTP 요청 매핑 어노테이션(@RequestMapping)

제이동 개발자 2023. 7. 1. 16:48
728x90

HTTP 요청 매핑 어노테이션(@RequestMapping)

 HTTP 요청 매핑 어노테이션에 대해 알기 위해서는 REST API에 대해서도 알아야 합니다. REST API를 간단히 설명하자면 Representational State Transfer의 약자로 자원을 이름으로 구분하여 해당  자원의 상태를 주고받는 모든  것을 말하며 웹 서비스 간에  데이터를 주고받기 위한 표준화된 방법을 제공하는 프로토콜입니다.

 

주요 특징

  1. 자원(Resouce)
    - REST API는 자원을  고유한 식별자인 URI(Uniform Resource Identifier)를 통해 표현
    - ex) /member → 멤버 자원, /products → 제품 자원 
  2. HTTP methods
    - REST API는 HTTP methods를 사용하여 자원에 대한 작업(행위)을 수행
    - 대표 methods로는 GET(조회), POST(생성), PUT(수정), PATCH(수정), DELETE(삭제)
    - REST  API 설계 규칙에 맞게 적절한 methods를 사용
  3. 상태 무관성(Stateless)
    - REST API는 상태를 유지하지 않는 특징이 있어 각 요청이 서버에 독립적으로 처리
    - 각 요청은 클라이언트의 인증 정보와 함께 충분한 데이터를 포함해야 한다.
    - 즉, 서버 측에서는 클라이언트의 상태를 관리하는 Session을 유지하지 않는 것을 의미한다.
  4. 인터페이스 일관성
    - 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을 사용하였습니다.

요청 URL = http://localhost:8080
요청 URL = http://localhost:8080/member

 

 

 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";
    }
}

요청 URL = http://localhost:8080/order
요청 URL = http://localhost:8080/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";
    }
}

 

728x90