[Spring 입문] Spring 요청 데이터

박화랑·2025년 3월 18일

Spring_개념정리

목록 보기
16/17

Spring 요청 데이터 1강


1. 요청 데이터 전달 방법

클라이언트에서 서버로 데이터를 전달하는 방법은 크게 세 가지로 나뉜다.

  1. GET - Query Parameter (Query String)

    • URL의 쿼리 파라미터를 사용하여 데이터를 전달하는 방법.
    • 예: http://localhost:8080/request-params?key1=value1&key2=value2
    • 이를 처리하기 위해 @RequestParam을 사용한다.
  2. POST - HTML Form Data (x-www-form-urlencoded)

    • HTML Form에서 데이터를 보내는 방식.
    • content-type: application/x-www-form-urlencoded로 전달된다.
    • @RequestParam 또는 @ModelAttribute를 사용하여 데이터를 바인딩할 수 있다.
  3. HTTP Request Body (JSON, TEXT, XML 등)

    • 데이터를 HTTP Message Body에 담아서 전달하는 방식.
    • @RequestBody를 사용하여 데이터를 처리한다.
    • REST API에서는 주로 JSON 형식으로 데이터를 주고받는다.

2. @RequestParam 사용법

1) 기본 사용법

  • @RequestParam을 사용하면 URL에서 전달된 데이터를 메서드의 파라미터로 받을 수 있다.

  • 예제:

    @Slf4j
    @Controller
    public class RequestParamController {
    
        @ResponseBody
        @GetMapping("/v1/request-param")
        public String requestParamV1(@RequestParam("name") String userName,
                                     @RequestParam("age") int userAge) {
            log.info("name={}, age={}", userName, userAge);
            return "success";
        }
    }
  • 실행 시 URL에 http://localhost:8080/v1/request-param?name=sparta&age=20을 입력하면 로그가 출력된다.

2) @RequestParam 생략 가능

  • @RequestParam("name") String name에서 속성값과 변수명이 같으면 생략 가능하다.
    @ResponseBody
    @GetMapping("/v2/request-param")
    public String requestParamV2(@RequestParam String name,
                                 @RequestParam int age) {
        log.info("name={}, age={}", name, age);
        return "success";
    }
  • URL: http://localhost:8080/v2/request-param?name=sparta&age=20

3) @RequestParam 자체도 생략 가능

  • 단순 타입(int, String, Integer)일 경우 @RequestParam을 생략할 수 있다.
    @ResponseBody
    @GetMapping("/v3/request-param")
    public String requestParamV3(String name, int age) {
        log.info("name={}, age={}", name, age);
        return "success";
    }
  • 하지만 이 방식은 명확성이 떨어져 협업에 문제가 발생할 가능성이 높기 때문에 권장되지 않는다.
  • @RequestParam(required=false)의 기본 값이 true이므로 생략하면 필수 입력값이 된다.

4) @RequestParam의 required 속성

  • @RequestParam(required=true)가 기본값이다.
  • 요청 시 파라미터가 없으면 400 Bad Request 오류가 발생한다.
  • required=false로 설정하면 없어도 된다.
    @ResponseBody
    @GetMapping("/v4/request-param")
    public String requestParamV4(@RequestParam(required = true) String name,
                                 @RequestParam(required = false) Integer age) {
        log.info("name={}, age={}", name, age);
        return "success";
    }
  • http://localhost:8080/v4/request-param?name=sparta로 요청하면 age가 없어도 동작한다.
  • 주의! int agenull을 허용하지 않기 때문에 Integer로 변경해야 한다.

5) 기본값 설정 (@RequestParam defaultValue)

  • @RequestParam에 기본값을 설정할 수 있다.
    @ResponseBody
    @GetMapping("/v5/request-param")
    public String requestParamV5(@RequestParam(defaultValue = "sparta") String name,
                                 @RequestParam(defaultValue = "1") int age) {
        log.info("name={}, age={}", name, age);
        return "success";
    }
  • http://localhost:8080/v5/request-param?age=100으로 요청하면 name이 없지만 기본값 "sparta"가 들어간다.
  • 빈 문자열("")도 기본값으로 처리된다.

6) @RequestParam Map 사용

  • 여러 개의 파라미터를 Map<String, String>으로 받을 수 있다.
    @ResponseBody
    @GetMapping("/v6/request-param")
    public String requestParamV6(@RequestParam Map<String, String> map) {
        log.info("name={}, age={}", map.get("name"), map.get("age"));
        return "success";
    }
  • http://localhost:8080/v6/request-param?name=sparta&age=100
  • MultiValueMap<String, String>을 사용하면 같은 키에 여러 개의 값을 받을 수 있다.

3. @ModelAttribute 사용법

1) 기존 방식

  • 객체로 데이터를 받아야 할 때, @RequestParam을 사용하면 객체를 직접 생성해야 한다.

    @Data
    public class Tutor {
        private String name;
        private int age;
    }
    
    @Controller
    public class ModelAttributeController {
    
        @ResponseBody
        @PostMapping("/v1/tutor")
        public String requestParamV1(@RequestParam String name,
                                     @RequestParam int age) {
            Tutor tutor = new Tutor();
            tutor.setName(name);
            tutor.setAge(age);
            return "tutor name = " + name + " age = " + age;
        }
    }

2) @ModelAttribute 적용

  • @ModelAttribute를 사용하면 객체를 자동으로 바인딩해준다.
    @ResponseBody
    @PostMapping("/v2/tutor")
    public String modelAttributeV2(@ModelAttribute Tutor tutor) {
        return "tutor name = " + tutor.getName() + " age = " + tutor.getAge();
    }
  • URL: http://localhost:8080/v2/tutor
  • content-type: application/x-www-form-urlencoded
  • name=wonuk&age=100을 전달하면 자동으로 Tutor 객체가 생성된다.

3) @ModelAttribute 동작 방식

  1. @ModelAttribute가 있으면 Tutor 객체를 생성한다.
  2. 요청 파라미터의 이름과 객체 필드의 이름이 같으면 setter를 호출한다.
  3. name이면 setName(value)이 실행된다.
  4. Setter가 없으면 바인딩되지 않는다.

4) @ModelAttribute 생략 가능

  • @ModelAttribute를 생략해도 자동으로 매핑된다.
    @ResponseBody
    @PostMapping("/v3/tutor")
    public String modelAttributeV3(Tutor tutor) {
        return "tutor name = " + tutor.getName() + " age = " + tutor.getAge();
    }
  • 주의!
    • @RequestParam은 기본 데이터 타입(String, int, Integer)이면 자동 매핑된다.
    • 객체(Tutor)는 @ModelAttribute가 자동 적용된다.

정리

  • GET 요청 (Query Parameter) → @RequestParam
  • POST 요청 (Form Data) → @RequestParam, @ModelAttribute
  • 객체 바인딩 → @ModelAttribute
  • JSON 바인딩 → @RequestBody (다음 강의에서 다룸)

Spring 요청 데이터 2강


1. HTTP Message Body를 통한 데이터 전달

  • @RequestParam@ModelAttribute쿼리 파라미터 또는 HTML Form 데이터를 처리하는 방식이다.
  • 하지만 HTTP 요청 본문(Body)에 데이터를 담아 전송하는 경우에는 이를 처리하는 별도의 방법이 필요하다.
  • 대표적인 데이터 형식:
    • JSON
    • TEXT
    • XML
  • REST API에서는 JSON을 가장 많이 사용한다.
  • HTTP 요청 본문을 처리하려면 HttpServletRequest, InputStream, HttpEntity, @RequestBody 등을 사용할 수 있다.

2. HTTP 요청 본문 데이터 읽기

1) HttpServletRequest 사용

  • HttpServletRequest를 사용하면 요청 본문을 직접 읽을 수 있다.

  • 텍스트 데이터를 요청 본문에서 읽는 예제:

    @Slf4j
    @Controller
    public class RequestBodyStringController {
    
        @PostMapping("/v1/request-body-text")
        public void requestBodyTextV1(HttpServletRequest request,
                                      HttpServletResponse response) throws IOException {
            ServletInputStream inputStream = request.getInputStream();
            String bodyText = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
    
            log.info("bodyText={}", bodyText);
            response.getWriter().write("response = " + bodyText);
        }
    }
  • Postman 요청 예제

    • POST /v1/request-body-text
    • Body -> raw -> Text
    • Request Header: Content-Type: text/plain
    • 결과: bodyText=클라이언트에서 보낸 텍스트

2) InputStream & Writer 사용

  • InputStreamWriter를 직접 사용할 수도 있다.
    @PostMapping("/v2/request-body-text")
    public void requestBodyTextV2(InputStream inputStream,
                                  Writer responseWriter) throws IOException {
        String body = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
        responseWriter.write("response = " + body);
    }
  • Writer responseWriter를 사용하면 response.getWriter().write() 없이 직접 응답을 작성할 수 있다.

3) HttpEntity 사용

  • HttpEntity를 사용하면 요청 본문을 쉽게 읽을 수 있다.
    @PostMapping("/v3/request-body-text")
    public HttpEntity<String> requestBodyTextV3(HttpEntity<String> httpEntity) {
        String body = httpEntity.getBody();
        return new HttpEntity<>("response = " + body);
    }
  • HttpEntity의 특징
    • HttpEntity<T>는 요청 본문을 T 타입으로 변환해준다.
    • HttpMessageConverter가 내부적으로 동작한다.
    • 요청뿐만 아니라 응답에도 사용할 수 있다.

3. @RequestBody 사용하여 요청 본문 처리

1) @RequestBody String 사용

  • @RequestBody를 사용하면 HttpServletRequest 없이 요청 본문을 바로 읽을 수 있다.

    @RestController
    public class RequestBodyStringController {
    
        @PostMapping("/v5/request-body-text")
        public String requestBodyTextV5(@RequestBody String body,
                                        @RequestHeader HttpHeaders headers) {
            return "request header = " + headers + " response body = " + body;
        }
    }
  • 특징

    • @RequestBody String body: 요청 본문을 String으로 변환해준다.
    • @RequestHeader HttpHeaders headers: 요청 헤더를 받을 수 있다.
    • HttpMessageConverter가 자동으로 동작하여 본문을 변환한다.

4. JSON 요청 본문 처리

1) HttpServletRequest로 JSON 데이터 읽기

  • JSON 데이터를 요청 본문에서 읽고, ObjectMapper를 사용하여 객체로 변환할 수 있다.

    @Data
    public class Tutor {
        private String name;
        private int age;
    }
    
    @RestController
    public class JsonController {
    
        private final ObjectMapper objectMapper = new ObjectMapper();
    
        @PostMapping("/v1/request-body-json")
        public void requestBodyJsonV1(HttpServletRequest request,
                                      HttpServletResponse response) throws IOException {
            ServletInputStream inputStream = request.getInputStream();
            String requestBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
    
            Tutor tutor = objectMapper.readValue(requestBody, Tutor.class);
    
            response.getWriter().write("tutor name=" + tutor.getName() + ", age=" + tutor.getAge());
        }
    }
  • 작동 방식

    • 요청 본문에서 JSONString으로 변환.
    • ObjectMapper를 사용하여 Tutor 객체로 변환.

2) @RequestBody + ObjectMapper 사용

  • @RequestBody를 사용하면 ObjectMapper 없이 JSON을 객체로 변환할 수 있다.

    @RestController
    public class JsonController {
    
        private final ObjectMapper objectMapper = new ObjectMapper();
    
        @PostMapping("/v2/request-body-json")
        public String requestBodyJsonV2(@RequestBody String requestBody) throws IOException {
            Tutor tutor = objectMapper.readValue(requestBody, Tutor.class);
            return "tutor name = " + tutor.getName() + ", age = " + tutor.getAge();
        }
    }
  • Postman 요청 예제

    • POST /v2/request-body-json
    • Body:
      {
        "name": "sparta",
        "age": 25
      }
    • 결과:
      tutor name = sparta, age = 25

3) @RequestBody + 객체 변환 자동화

  • @RequestBody를 사용하면 자동으로 JSON을 객체로 변환한다.

    @RestController
    public class JsonController {
    
        @PostMapping("/v3/request-body-json")
        public String requestBodyJsonV3(@RequestBody Tutor tutor) {
            return "tutor name = " + tutor.getName() + ", age = " + tutor.getAge();
        }
    }
  • 내부적으로 HttpMessageConverter가 작동하여 변환한다.

4) @RequestBody 생략 불가

  • @RequestParam@ModelAttribute는 생략할 수 있지만, @RequestBody는 생략할 수 없다.
    @PostMapping("/v4/request-body-json")
    public String requestBodyJsonV4(Tutor tutor) {
        return "tutor name = " + tutor.getName() + ", age = " + tutor.getAge();
    }
    • 문제 발생: @ModelAttribute가 적용되어 요청 본문을 읽지 못한다.

5. HttpEntity를 사용하여 JSON 처리

  • HttpEntity<Tutor>를 사용하면 요청 본문을 자동으로 객체로 변환할 수 있다.

    @RestController
    public class JsonController {
    
        @PostMapping("/v5/request-body-json")
        public String requestBodyJsonV5(HttpEntity<Tutor> httpEntity) {
            Tutor tutor = httpEntity.getBody();
            return "tutor name = " + tutor.getName() + ", age = " + tutor.getAge();
        }
    }

정리

  1. 텍스트 데이터 처리 방법

    • HttpServletRequest
    • InputStream
    • HttpEntity<String>
    • @RequestBody String
  2. JSON 데이터 처리 방법

    • HttpServletRequest + ObjectMapper
    • @RequestBody + ObjectMapper
    • @RequestBody Tutor
    • HttpEntity<Tutor>

    Spring 요청 데이터 3강


1. HttpEntity란?

Spring에서 HTTP 요청(Request)과 응답(Response)을 다룰 때, HttpEntity<T>는 HTTP 헤더(Header)와 본문(Body) 데이터를 쉽게 다룰 수 있도록 도와주는 클래스다.

HttpEntity의 주요 특징

  • 요청(Request) 데이터 처리

    • HTTP Header와 HTTP Body 정보를 직접 다룰 수 있다.
    • @RequestParam이나 @ModelAttribute와 다르게 쿼리 파라미터(Query Parameter)를 사용하지 않는다.
    • HttpServletRequest 없이 요청 데이터를 읽을 수 있다.
  • 응답(Response) 데이터 처리

    • HTTP 응답의 본문과 헤더를 포함할 수 있다.
    • ResponseEntity<T>를 사용하면 응답 상태 코드도 설정할 수 있다.

2. HttpEntity를 사용한 요청 처리

HttpEntity을 사용하여 요청 본문 읽기

HttpEntity<String>을 사용하면 요청 본문 데이터를 String으로 받을 수 있다.

@RestController
public class HttpEntityController {

    @PostMapping("/http-entity")
    public HttpEntity<String> requestBodyText(HttpEntity<String> httpEntity) {
        String body = httpEntity.getBody();
        return new HttpEntity<>("Received: " + body);
    }
}

요청 예제

POST /http-entity
Content-Type: text/plain

Hello Spring!

응답 결과

HTTP/1.1 200 OK
Content-Type: text/plain

Received: Hello Spring!

HttpEntity를 사용하여 JSON 요청 처리

HttpEntity<T>를 사용하면 JSON 데이터를 자동으로 객체로 변환할 수 있다.

@Data
public class User {
    private String name;
    private int age;
}

@RestController
public class HttpEntityJsonController {

    @PostMapping("/http-entity-json")
    public HttpEntity<String> requestBodyJson(HttpEntity<User> httpEntity) {
        User user = httpEntity.getBody();
        return new HttpEntity<>("Received: " + user.getName() + ", age: " + user.getAge());
    }
}

요청 예제

POST /http-entity-json
Content-Type: application/json

{
  "name": "wonuk",
  "age": 25
}

응답 결과

HTTP/1.1 200 OK
Content-Type: text/plain

Received: wonuk, age: 25

HttpEntity 사용 시 주의점

  • HttpEntity<T>는 View를 반환하지 않는다.
  • @RequestParam이나 @ModelAttribute처럼 쿼리 파라미터(Query Parameter)를 처리하지 않는다.
  • 요청 데이터는 반드시 HTTP Body에 있어야 한다.

3. @RequestBody를 사용한 요청 처리

@RequestBodyHttpEntity와 비슷하지만 더 간단한 방식으로 요청 본문을 읽을 수 있다.
HttpEntity<T>보다 직관적으로 사용할 수 있기 때문에 일반적으로 @RequestBody를 더 많이 사용한다.


@RequestBody를 사용하여 String 요청 본문 읽기

@RestController
public class RequestBodyStringController {

    @PostMapping("/request-body")
    public String requestBodyText(@RequestBody String body) {
        return "Received: " + body;
    }
}

요청 예제

POST /request-body
Content-Type: text/plain

Hello Spring!

응답 결과

HTTP/1.1 200 OK
Content-Type: text/plain

Received: Hello Spring!

@RequestBody를 사용하여 JSON 요청 본문 처리

JSON 데이터를 @RequestBody를 사용하면 자동으로 객체로 변환할 수 있다.

@RestController
public class RequestBodyJsonController {

    @PostMapping("/request-body-json")
    public String requestBodyJson(@RequestBody User user) {
        return "Received: " + user.getName() + ", age: " + user.getAge();
    }
}

요청 예제

POST /request-body-json
Content-Type: application/json

{
  "name": "wonuk",
  "age": 25
}

응답 결과

HTTP/1.1 200 OK
Content-Type: text/plain

Received: wonuk, age: 25

@RequestBody 사용 시 주의할 점

  • @RequestBody는 쿼리 파라미터(Query Parameter)를 처리하지 않는다.
  • 요청 데이터는 반드시 Request Body에 포함되어야 한다.
  • @ModelAttribute와 다르게 Setter가 없어도 JSON 데이터가 매핑된다.
  • 내부적으로 HttpMessageConverter가 작동하여 JSON을 객체로 변환한다.

4. @ResponseBody를 사용한 응답 처리

@ResponseBody를 사용하면 View가 아니라 데이터 자체를 HTTP 응답 본문에 직접 반환한다.
@RestController를 사용하면 자동으로 모든 메서드에 @ResponseBody가 적용된다.
ResponseEntity<T>와 함께 사용하면 HTTP 상태 코드도 조정할 수 있다.


@ResponseBody를 사용하여 응답 반환

@RestController
public class ResponseBodyController {

    @GetMapping("/response-body")
    public String responseBody() {
        return "Hello, ResponseBody!";
    }
}

응답 결과

HTTP/1.1 200 OK
Content-Type: text/plain

Hello, ResponseBody!

JSON 데이터를 응답으로 반환

@RestController
public class ResponseBodyJsonController {

    @GetMapping("/response-body-json")
    public User responseBodyJson() {
        return new User("wonuk", 25);
    }
}

응답 결과

HTTP/1.1 200 OK
Content-Type: application/json

{
  "name": "wonuk",
  "age": 25
}

ResponseEntity를 사용하여 HTTP 상태 코드 반환

@RestController
public class ResponseEntityController {

    @GetMapping("/response-entity")
    public ResponseEntity<User> responseEntity() {
        User user = new User("wonuk", 25);
        return new ResponseEntity<>(user, HttpStatus.CREATED);
    }
}

응답 결과

HTTP/1.1 201 Created
Content-Type: application/json

{
  "name": "wonuk",
  "age": 25
}

5. 정리

요청 처리

  • 텍스트 데이터 처리 방법

    • HttpServletRequest
    • InputStream
    • HttpEntity<String>
    • @RequestBody String
  • JSON 데이터 처리 방법

    • HttpServletRequest + ObjectMapper
    • @RequestBody + ObjectMapper
    • @RequestBody DTO 객체
    • HttpEntity<DTO>

응답 처리

  • @ResponseBody를 사용하면 데이터를 직접 반환
  • ResponseEntity<T>를 사용하면 응답 상태 코드 조정 가능

profile
개발자 희망생

0개의 댓글