웹 애플리케이션에서 가장 기본이 되는 기능 중 하나는 클라이언트가 보낸 데이터를 서버에서 받는 것이다.
예를 들어 회원 가입 화면에서 이름과 나이를 입력하고 제출하면, 그 값들은 서버에 쿼리 파라미터나 폼 데이터로 전달된다.
스프링 MVC는 이런 요청 파라미터를 처리하는 여러 가지 방법을 제공한다.
이번 글에서는 그 방법들을 1) 서블릿 API로 직접 조회 → 2) @RequestParam 사용 → 3) @ModelAttribute 사용 순서로 살펴본다.
1. 서블릿 API로 직접 조회
가장 기본적인 방식은 HttpServletRequest 에서 값을 직접 꺼내는 것이다.
@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");
}
- 요청 예시:
GET /request-param-v1?username=hello&age=20 - 처리 과정:
- request.getParameter("username") 으로 hello 를 가져온다.
- request.getParameter("age") 로 20 을 가져와 숫자로 변환한다.
- 응답도 response.getWriter().write("ok") 로 직접 작성한다.
가능하지만 코드가 장황하고 불편하다. 스프링은 이 과정을 단순화할 수 있는 어노테이션을 제공한다.
2. @RequestParam: 단일 값 매핑
스프링에서는 @RequestParam 으로 요청 파라미터를 메서드 매개변수에 바로 바인딩할 수 있다.
2-1. 기본 사용
@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(
@RequestParam("username") String memberName,
@RequestParam("age") int memberAge) {
log.info("username={}, age={}", memberName, memberAge);
return "ok";
}
- 요청 예시:
GET /request-param-v2?username=hello&age=20 - 결과:
- username=hello → memberName="hello"
- age=20 → memberAge=20
즉, 쿼리 스트링으로 넘어온 값이 그대로 매개변수로 들어온다.
2-2. 변수명과 파라미터명이 같을 때
@ResponseBody
@RequestMapping("/request-param-v3")
public String requestParamV3(@RequestParam String username, @RequestParam int age) {
log.info("username={}, age={}", username, age);
return "ok";
}
파라미터명과 변수명이 같으면 어노테이션의 이름을 생략할 수 있다.
2-3. 어노테이션 생략 (비추천)
@ResponseBody
@RequestMapping("/request-param-v4")
public String requestParamV4(String username, int age) {
log.info("username={}, age={}", username, age);
return "ok";
}
@RequestParam 자체를 생략할 수도 있다. 하지만 명시적으로 붙이는 것이 코드를 읽을 때 더 명확하다.
2-4. 필수 여부와 기본값
@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 "ok";
}
- required = true: 반드시 있어야 하는 파라미터
- required = false: 없어도 되는 파라미터
- 기본형 int 대신 Integer 를 사용해야 null 값 처리가 가능하다.
@ResponseBody
@RequestMapping("/request-param-default")
public String requestParamDefault(
@RequestParam(defaultValue = "guest") String username,
@RequestParam(defaultValue = "-1") int age) {
log.info("username={}, age={}", username, age);
return "ok";
}
값이 없을 경우 기본값이 적용된다. " " (빈 문자열)도 기본값으로 치환된다.
2-5. Map으로 전체 파라미터 조회
@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 형태로 한 번에 받을 수도 있다.
3. @ModelAttribute: 객체 바인딩
여러 개의 요청 파라미터를 하나의 객체로 묶어야 할 때는 @ModelAttribute 가 유용하다.
예를 들어 다음과 같은 DTO가 있다고 하자.
public class HelloData {
private String username;
private int age;
// getter, setter
}
컨트롤러는 이렇게 작성할 수 있다.
@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@ModelAttribute HelloData helloData) {
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return "ok";
}
- 요청 예시:
GET /model-attribute-v1?username=hello&age=20 - 처리 과정:
- HelloData 객체를 생성한다.
- 요청 파라미터 이름과 같은 필드를 찾아 setter 메서드를 호출한다.
- 완성된 객체를 컨트롤러 메서드에 전달한다.
즉, 클라이언트가 보낸 이름과 나이 값이 HelloData 객체 안에 자동으로 채워진다.
마무리하며
요청 파라미터를 처리하는 방법은 다양하다.
- 서블릿 API를 직접 사용하면 동작 원리를 이해할 수 있지만 코드가 불편하다.
- 단순 값은 @RequestParam 으로 받는 것이 가장 간단하다.
- 여러 값이 하나의 객체로 묶일 수 있다면 @ModelAttribute 를 사용하는 것이 효율적이다.
스프링 MVC가 제공하는 바인딩 기능을 활용하면, 브라우저에서 입력한 값이 곧바로 컨트롤러 메서드의 매개변수나 객체로 전달되기 때문에 개발자는 로직에 더욱 집중할 수 있을 것이다.
감사합니다.
'스프링' 카테고리의 다른 글
| [스프링] 메시지, 국제화 (0) | 2025.09.19 |
|---|---|
| [스프링] 스프링 MVC - 기본기능 (마지막) HTTP 요청 메시지: text와 JSON (1) | 2025.09.03 |
| [스프링] 스프링 MVC - 기본기능 (1) 로깅 (0) | 2025.09.03 |
| [스프링] 컬렉션 조회 최적화 (4) | 2025.07.31 |
| [스프링] 지연 로딩과 조회 성능 최적화 (3) | 2025.07.27 |
