Spring

Spring MVC - 요청과 관련된 사용법 정리

Tommy__Kim 2023. 7. 6. 19:43

RequestMapping

@RequestMapping("URL")

Spring Controller를 사용할 때 특정 URL 경로에 대해 요청이 들어오는 경우 메서드가 실행할 수 있게 끔 매핑해 줍니다.

/**
     * RequestMapping에 별다른 method를 지정하지 않는 경우
     * 모든 HttpMethod 허용
     * 
     * 권장하지 않는 방식
     */
    @RequestMapping("/request-mapping")
    public String requestMapping() {
        log.info("requestMapping 실행");
        return "ok";
    }

RequestMapping을 적용하고자 하는 메서드 위에 @RequestMapping 어노테이션을 기입해 주면 됩니다.
괄호 안의 "/request-mapping" 특정 URL에 대해 동작을 수행하도록 지정하는 것입니다.
❗️ 위와 같이 사용하는 방식은 권하지 않는 방식입니다.
단순히 @RequestMapping만 사용하는 경우 모든 HttpMethod에 대해 동작을 수행합니다.

예를 들어 개발자는 GET메서드에 대해서만 호출이 되도록 의도했다고 가정해 보겠습니다.
그렇지만 별다른 제어가 없기 때문에 모든 HTTP Method에 대해 동작을 수행합니다.

@RequestMapping("URL", method = )

보통 API를 설계할 때에는 모든 HTTP Method에 대해서 고려하기보단 특정 HTTP Method에 대해서 설계를 진행합니다.
보다 상세한 통제를 하기 위해서 @RequestMapping에 method를 지정할 수 있습니다.

    /**
     * HttpMethod 중 GET 만 허용
     *
     * 그 외 다른 메서드가 호출되면 405 Method Not Allowed 응답.
     */
    @RequestMapping(value = "/request-mapping/get", method = RequestMethod.GET)
    public String requestMappingGet() {
        log.info("requestMappingGet 실행");
        return "ok";
    }

이렇게 method를 직접 명시해 준 경우에는 다른 HTTP Method가 호출되었을 때 405 Status Code를 응답합니다.

HTTP 메서드 매핑 축약

매번 @RequestMapping("호출할 URL", method = {지정할 Method}) 를 사용하는 경우 코드를 몇 자 더 쳐야 합니다.
이러한 귀찮음을 줄이기 위해 Spring은 다른 방식을 지원합니다.

@Slf4j
@RestController
public class HttpMethodMappingAbstract {

    @GetMapping("/abstract/get-mapping")
    public String getMapping() {
        log.info("getMapping 실행");
        return "ok";
    }

    @PutMapping("/abstract/put-mapping")
    public String putMapping() {
        log.info("putMapping 실행");
        return "ok";
    }

    @DeleteMapping("/abstract/delete-mapping")
    public String deleteMapping() {
        log.info("deleteMapping 실행");
        return "ok";
    }
}

앞서 살펴본 예제들과 달리 @GetMapping, @PutMapping, @DeleteMapping 어노테이션을 사용하는 것을 확인할 수 있습니다.
사실 각 어노테이션들을 확인해 보면 @RequestMapping(method = )이 구현되어 있습니다.

클래스 단위 RequestMapping, HTTP 메서드 매핑 축약 조합

위의 예제에서 URL의 경로에 공통적으로 "/abstract"가 들어가는 것을 확인할 수 있습니다.
이러한 경우 클래스 단위에서 @RequestMapping을 사용해 메서드에서 반복되는 경로의 입력을 줄일 수 있습니다.

@Slf4j
@RestController
@RequestMapping("/abstract2")
public class HttpMethodMappingAbstract2 {

    @GetMapping("/get-mapping")
    public String getMapping() {
        log.info("getMapping 실행");
        return "ok";
    }

    @PutMapping("/put-mapping")
    public String putMapping() {
        log.info("putMapping 실행");
        return "ok";
    }

    @DeleteMapping("/delete-mapping")
    public String deleteMapping() {
        log.info("deleteMapping 실행");
        return "ok";
    }
}

공통되는 경로에 대해서는 Class위에 @RequestMapping을 사용해 경로를 지정해 줍니다.
이러한 경우 클래스의 @RequestMapping에 있는 URL과 메서드에 있는 URL이 결합됩니다.

  • "abstract2" + "/get-mapping" -> "/abstract2/get-mapping"
  • "abstract2" + "/put-mapping" -> "/abstract2/put-mapping"
  • "abstract2" + "/delete-mapping" -> "/abstract2/delete-mapping"

PathVariable

특정 리소스를 조회할 때 리소스 경로에 식별자를 넣는 경우가 많습니다.

  • /uesrs/1
  • /books/game-of-thrones

Spring에서는 @PathVariable을 통해 값을 가져올 수 있습니다.

단일 PathVariable 조회

    @GetMapping("/path-variable/{userId}")
    public String singlePathVariable(@PathVariable String userId) {
        log.info("userId = {}", userId);
        return "userId = " + userId;
    }

단일 PathVariable 조회의 경우 메서드의 파라미터에 @PathVariable을 사용하고 원하는 타입을 지정해 주면 됩니다.
✅ @GetMapping에 정의한 {} 안 단어와 동일하게 사용을 해야 값을 불러올 수 있습니다.

다중 PathVariable 조회

    @GetMapping("/path-variable/users/{userId}/orders/{orderId}")
    public String multiplePathVariable(@PathVariable String userId, @PathVariable String orderId) {
        log.info("userId = {}, orderId = {}", userId, orderId);
        return "userId = " + userId + " orderId = " + orderId;
    }

다중 PathVariable 조회의 경우 메서드의 파라미터에 원하는 개수만큼 @PathVariable을 사용해 지정해 주면 됩니다.


HTTP Request Parameter

클라이언트가 서버에 데이터를 전달하는 경우 주로 3가지 방법을 사용합니다.

  • GET
    • 쿼리 파라미터
      • /members?username=Tommy&age=30
      • URL의 쿼리 파라미터에 데이터를 포함해서 전달하는 방식입니다.
  • POST
    • HTML FORM
      • 메시지 바디에 쿼리파라미터 형식으로 전달합니다.
      • username=Tommy&age=30
  • Message Body
    • HTTP API에서 주로 사용하는 방식
    • JSON, XML, TEXT를 사용합니다.
    • 데이터 형식은 주로 JSON을 사용합니다.

쿼리 파라미터

💡 GET 방식의 쿼리파라미터 방식과 HTML FORM으로 보내는 POST 방식 모두 쿼리파라미터 방식으로 전달됩니다.

HttpServletRequest

    @GetMapping("/request-param/v1")
    public String v1(HttpServletRequest request) {
        String username = request.getParameter("username");
        log.info("username = {}", username);
        return "username = " + username;
    }

HttpServletRequest에서 getParameter 메서드를 사용하면 쿼리파라미터 값을 읽어올 수 있습니다.

@RequestParam

Version 1

@RequestParam("파라미터 이름")

    @GetMapping("/request-param/v2")
    public String v2(@RequestParam("username") String username) {
        log.info("username = {}", username);
        return "username = " + username;
    }

예를 들어 username이라는 파라미터값을 조회하고 싶을 때에는
@RequestParam("username")이라고 지정을 하고 갖고 오려고 하는 파라미터의 값 타입과 변수명을 붙여주면 됩니다.

Version 2

@RequestParam

    @GetMapping("/request-param/v3")
    public String v3(@RequestParam String username) {
        log.info("username = {}", username);
        return "username = " + username;
    }

조회하고자 하는 쿼리 파라미터의 변수명과 Controller에서 사용하고자 하는 변수명이 같을 경우 다음과 같이 사용할 수 있습니다.
@ReqeustParam String username

Version 3

@RequestParam(required=false)

    @GetMapping("/request-param/v4")
    public String v4(@RequestParam(required = false) String username) {
        log.info("username = {}", username);
        return "username = " + username;
    }

쿼리파라미터에 파라미터가 있어도 되고 없어도 된다면 required = false를 넣어주면 됩니다.
만약 파라미터가 존재하지 않는다면 null이 할당됩니다.
❗️ required = false 옵션을 사용할 경우 primitive type은 null을 가질 수 없으므로 사용하면 안 됩니다.
💡 대신 래퍼 클래스들을 사용해 주면 됩니다.

Version 4

@RequestParam(defaultValue=)

    @GetMapping("/request-param/v5")
    public String v5(@RequestParam(defaultValue = "default NickName") String username) {
        log.info("username = {}", username);
        return "username = " + username;
    }

쿼리파라미터에 파라미터가 존재하지 않을 때 기본 값을 할당하고 싶다면 defaultValue=를 사용하면 됩니다.

@ModelAttribute

    @PostMapping("/model-attribute")
    public Member modelAttribute(@ModelAttribute Member member) {
        return member;
    }

    ---
    @Data
    public class Member {
        private String username;
        private Integer age;
    }

SpringMVC는 쿼리파라미터를 사용해 객체를 바로 받아올 수도 있습니다.
@ModelAttribute가 존재하는 경우 다음과 같이 실행됩니다.

  • Member 객체를 생성
  • 파라미터 이름으로 Member 객체의 프로퍼티를 찾는다.
  • setter를 호출해 파라미터의 값을 바인딩.

MessageBody

    @PostMapping("request-body")
    public String requestBody(@RequestBody String messageBody) {
        log.info("message Body = {}", messageBody);
        return messageBody;
    }

JSON으로 데이터를 요청받는 경우 @RequestBody를 사용해 받아올 수 있습니다.


출처 : 김영한 - Spring MVC 1편

'Spring' 카테고리의 다른 글

[Spring] @Retryable, Event 적용기  (1) 2023.12.04
Spring, 그리고 Test  (4) 2023.10.11
Junit에서 TestInstance의 생명주기  (0) 2023.07.03
NamedParameterJdbcTemplate  (0) 2023.07.01
JdbcTemplate 사용 방법에 대해서  (0) 2023.07.01