⚙️ 개발/Spring

@RequestParam, @ModelAttribute

지구용사 2024. 4. 25. 15:22

클라이언트에서 서버로 요청 데이터를 전달할 때 3가지 방법이 있다.

 

1. GET 메시지 바디 없이, URL의 쿼리파라미터에 데이터를 포함해서 전달하는 방식

보통 검색, 필터, 페이징 등에서 많이 사용된다.

http://localhost:8080/request-param-v1?username=hello&age=20

 

2. POST HTML Form으로 전달하는 방식

POST /request-param ...
content-type: application/x-www-form-urlencoded
username=hello&age=20

 

3. HTTP message body에 데이터를 직접 담아서 요청하는 방식

HTTP API에서 주로 사용되며, JSON / XML / TEXT가 있다. 이중 데이터는 주로 JSON 사용

 

이중에서 해당 글은 1, 2를 다룬다.

 

테스트하기에 앞서 테스트용 HTML Form을 만든다.

리소스는 /resources/static 아래에 두면 스프링 부트가 자동으로 인식한다.

http://localhost:8080/basic/hello-form.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/request-param-v1" method="post">
    username: <input type="text" name="username" />
    age:      <input type="text" name="age" />
    <button type="submit">전송</button>
</form>
</body>
</html>

 


 

HttpServletRequest의 request.getParameter()를 사용하면 GET 쿼리 파라미터, POST HTML Form 전송한 데이터을 조회할 수 있다. 2가지 모두 형식이 같으므로 구분없이 조회할 수 있다. 이것을 요청파라미터(request parameter) 조회라 한다.

 

HttpServletRequest가 제공하는 방식으로 요청 파라미터를 조회한다.

http://localhost:8080/request-param-v1?username=hello&age=20
@RequestMapping("/request-param-v1")
public void requestParamV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String username = request.getParameter("username");
    int age = Integer.parseInt(request.getParameter("age"));
    log.info("username = {}, age = {}", username, age);
    response.getWriter().write("WOW");
}

 


 

스프링이 제공하는 @RequestParam을 사용하면 요청 파라미터를 편리하게 조회할 수 있다.

@ResponseBody //REST
@RequestMapping("/request-param-v2")
public String requestParamV2(
        @RequestParam("username") String memberName, 
        @RequestParam("age") String memberAge) {
    log.info("username = {}, age = {}", memberName, memberAge);
    return "WOW";
}

 

@RequestParam은 파라미터 이름으로 바인딩된다.

@ResponseBody는 View 조회를 무시하고, HTTP message body에 직접 해당 내용을 입력한다.

 

HTTP 파라미터 이름과 변수 이름이 같으면 괄호를 생략할 수 있다.

 

@RequestParam.required 통해 파라미터의 필수 여부를 체크할 수 있다. 기본값은 파라미터 필수인 true이다.

int에 null 입력하면 500 예외가 발생한다. 따라서 null을 받을 수 있는 Integer를 사용한다.

@ResponseBody
@RequestMapping("/request-param-required")
public String requestParamRequired(@RequestParam(required = true) String username, 
                                   @RequestParam(required = false) Integer age) {
    log.info("username = {}, age = {}", username, age);
    return "WOW";
}

 

빈 값으로 통과

//통과
http://localhost:8080/request-param-required?username=wow

//빈값으로 통과
http://localhost:8080/request-param-required?username=&age=20

//400예외 발생
http://localhost:8080/request-param-required?age=20

 

파라미터에 값이 없는 경우 defaultValue를 사용하면 기본 값을 적용할 ㅜㅅ 있다.

따라서 기본값이 있기 때문에 required는 의미가 없다.

@ResponseBody
@RequestMapping("/request-param-default")
public String requestParamDefault(@RequestParam(required = true, defaultValue = "guest") String username, 
                                  @RequestParam(required = false, defaultValue = "1") int age) {
    log.info("username = {}, age = {}", username, age);
    return "WOW";
}

 


 

개발을 하다보면 요청 파라미터를 받아서 객체를 만들고 그 객체에 값을 넣어주어야 한다.

이 과정을 스프링에선 자동화 해주는 @ModelAttribute 기능을 제공한다.

 

우선 요청 파라미터를 바인딩 받을 객체 생성한다.

@Data
public class HelloData {
    private String username;
    private int age;
}

 

여기서 롬복의 @Data는 @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor를 자동으로 적용해준다.

 

HelloData 객체가 생성되고 요청 파라미터의 값이 모두 들어가 있다.

@ResponseBody
@RequestMapping("/model-attribute-v2")
public String modelAttributeV21(@ModelAttribute HelloData helloData) {
    log.info("username = {}, age = {}", helloData.getUsername(), helloData.getAge());
    log.info("helloData = {}", helloData);
    return "OK";
}

 

@ModelAttribute가 있으면 다음과 같이 실행된다.

1. HelloData 객체 생성

2. 요청 파라미터의 이름으로 HelloData 객체의 프로퍼티를 찾는다.

3. 해당 프로퍼티의 Setter를 호출해서 파라미터의 값을 입력(바인딩)한다.

 


 

🔗 강의 링크

https://inf.run/Gmptq