Spring/SpringMVC

HTTP 요청 파라미터 - 쿼리 파라미터, HTML Form & RequestParam

느리지만 꾸준하게 2022. 4. 29. 22:21

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

  • GET - 쿼리 파라미터
  • /url?username=hello&age=20
  • 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달
  • 예) 검색, 필터, 피이징등에서 많이 사용

 

  • POST - HTML Form
  • content-type: application/x-www-form-urlencoded
  • 메시지 바디에 쿼리 파리미터 형식으로 전달 username=hello&age=20
  • 예) 회원 가입, 상품 주문, HTML Form 사용

 

  • HTTP message body에 데이터를 직접 담아서 요청
  • HTTP API에서 주로 사용, JSON, XML, TEXT
  • 데이터 형식은 주로 JSON 사용
  • POST, PUT, PATCH

 

스프링으로 요청 파라미터를 조회하는 방법을 단계적으로 알아보자.

// RequestParamController Class

package hello.springmvc.basic.request;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
@Controller
public class RequestParamController {

    @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("ok");
    }
}

 

 

 

 

hello-form.html 파일도 static-basic 패키지 밑에 만들어 주자.

<!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>

Run창에 결과가 잘 나오는 것을 확인할 수 있다.

 

 

 

 

 

RequestParam에 대해서 알아보자.

스프링이 제공하는 `@RequestParam`을 사용하면 요청 파라미터를 편리하게 사용가능하다.

// RequestParamController Class

package hello.springmvc.basic.request;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
@Controller
public class RequestParamController {

    @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("ok");
    }
    @ResponseBody()
    @RequestMapping("/request-param-v2")
    public String requestParamV2(
            @RequestParam("username") String memberName,
            @RequestParam("age") int memberAge) {

        log.info("username={}, age={}", memberName, memberAge);
        return "ok";
    }
}

 

localhost:8080에서 잘 나오고 출력로그로 잘 나오는 것을 확인 할 수 있다.

2022-04-29 21:40:58.549  INFO 32483 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 7 ms
2022-04-29 21:40:58.592  INFO 32483 --- [nio-8080-exec-1] h.s.b.request.RequestParamController     : username=hello, age=20

 

  • @RequestParam: 파라미터 이름으로 바인딩
  • @ResponseBody : View 조회를 무시하고, HTTP message body에 직접 해당 내용 입력

 

  • @RequestParam의 name(value) 속성이 파라미터 이름으로 사용
  • @RequestParam("username") String memberName
  • -> request.getParameter("username")

 

 

 

request-param-v3으로는 위의 코드를 간단하게 나타내보자.

@ResponseBody()
@RequestMapping("/request-param-v3")
public String requestParamV3(
        @RequestParam String username,
        @RequestParam int age) {

    log.info("username={}, age={}", username, age);
    return "ok";
}
username=hello, age=20

HTTP 파라미터 이름이 변수 이름과 같으면 @RequestParam(name="xx") 생략 가능

 

 

 

 

 

 

request-param-v4로 더 간단하게 축약을 해보자.

@ResponseBody()
@RequestMapping("/request-param-v4")
public String requestParamV4(String username, int age) {
    log.info("username={}, age={}", username, age);
    return "ok";
}

 

 

 

 

파라미터 필수 여부 - requestParamRequired도 알아보자.

@ResponseBody
@RequestMapping("/request-param-required")
public String requestParamRequired(

        // username true니까 무조건 있어야 한다.
        @RequestParam(required = true) String username,
        @RequestParam(required = false) int age) {

    log.info("username={}, age={}", username, age);
    return "ok";
}

만약 필수값 username을 빼면? 에러가 난다.

 

age를 빼도 오류가 난다. 여기서 age를 int로 지정해줬는데 ints는 null값을 가지지 못하기 때문이다. Integer이라고 하면 오류없이 잘 동작한다.

@ResponseBody
@RequestMapping("/request-param-required")
public String requestParamRequired(

        // username true니까 무조건 있어야 한다.
        @RequestParam(required = true) String username,
        @RequestParam(required = false) int age) {

int age 일 때

 

@ResponseBody
@RequestMapping("/request-param-required")
public String requestParamRequired(

        // username true니까 무조건 있어야 한다.
        @RequestParam(required = true) String username,
        @RequestParam(required = false) Integer age) {

Integer age일 때

2022-04-29 22:05:35.978  INFO 32852 --- [nio-8080-exec-1] h.s.b.request.RequestParamController     : username=hello, age=null

 

 

  • @RequestParam.required
    파라미터 필수 여부
    기본값이 파라미터 필수( true )이다.

 

  • /request-param 요청
    username 이 없으므로 400 예외가 발생한다.

 

  • 파라미터 이름만 사용
    /request-param?username=
    파라미터 이름만 있고 값이 없는 경우 빈문자로 통과
2022-04-29 22:08:04.254  INFO 32852 --- [nio-8080-exec-5] h.s.b.request.RequestParamController     : username=, age=null

 

  • 기본형(primitive)에 null 입력
    /request-param 요청
    @RequestParam(required = false) int age

 

  • null 을 int 에 입력하는 것은 불가능(500 예외 발생)
    따라서 null 을 받을 수 있는 Integer 로 변경하거나, 또는 다음에 나오는 defaultValue 사용

 

 

 

 

 

기본 값 적용 - requestParamDefault에 대해서 보면

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

 

age를 뺐을 때 -1값이 들어가게 된다.

2022-04-29 22:12:17.493  INFO 32935 --- [nio-8080-exec-3] h.s.b.request.RequestParamController     : username=hello, age=-1

 

username을 빼도 실행이 되고 기본값으로 guest가 나가게 된다. 즉 required가 있든 없든 상관이 없다.

2022-04-29 22:13:12.357  INFO 32935 --- [nio-8080-exec-4] h.s.b.request.RequestParamController     : username=guest, age=-1

 

빈 문자열일때도 default값이 조회가 된다.

2022-04-29 22:14:41.694  INFO 32935 --- [nio-8080-exec-7] h.s.b.request.RequestParamController     : username=guest, age=-1

 

 

 

 

 

 

 

 

그리고 파라미터를 Map으로 조회를 해보자. - requestParamMap

@ResponseBody
@RequestMapping("/request-param-map")
public String requestParamMap(@RequestParam Map<String, Object> paramMap) {

    log.info("username={}, age={}", paramMap.get("username"), paramMap.get("age"));
    return "ok";
}
  • 파라미터를 Map, MultiValueMap으로 조회할 수 있다
  • @RequestParam Map ,
  • Map(key=value)

 

  • @RequestParam MultiValueMap(이런 경우는 그렇게 많지 않다. 보통 파라미터 1개다.)
  • MultiValueMap(key=[value1, value2, ...] ex) (key=userIds, value=[id1, id2])

 

  • 파라미터의 값이 1개가 확실하다면 Map 을 사용해도 되지만, 그렇지 않다면 MultiValueMap 을 사용하자.

 

 

 

 

 

 

 

 

 

 

 

 

<출처 김영한: 스프링 MVC 1편 - 벡앤드 웹 개발 핵심 기술>

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -

www.inflearn.com