[Spring] @RequestBody란?

artp·2025년 5월 21일

spring

목록 보기
3/11
post-thumbnail

@RequestBodyHTTP 요청 바디(body)에 담긴 JSON, XML, 기타 데이터를 자바 객체로 자동 변환해주는 Spring MVC 애노테이션입니다.

보통 REST API에서 클라이언트가 JSON 형식으로 데이터를 전송할 때 사용합니다.

클라이언트가 보낸 JSON 데이터를 Java 객체로 바꿔주는 역할을 수행합니다.

흐름

  1. 클라이언트(브라우저, 모바일 앱 등)가 JSON 데이터를 서버로 전송
  2. Spring이 요청을 받고, @RequestBody로 처리해야겠다고 판단
  3. HTTP 요청의 본문(JSON)을 읽어서 자바 객체로 변환
  4. 변환된 객체를 컨트롤러 메서드의 파라미터로 전달

동작 방식

정확한 동작 방식은 다음과 같습니다.

  • HTTP 요청의 Content-Type이 application/json일 경우
  • 요청 바디의 JSON 데이터를 자바 객체로 매핑
  • 내부적으로 Jackson(ObjectMapper)을 사용하여 역직렬화
// 요청 바디 예시
{
  "title": "뉴스 제목",
  "content": "뉴스 내용"
}
@PostMapping("/api/news")
public ResponseEntity<?> createNews(@RequestBody NewsDTO newsDTO) {
    // newsDTO.getTitle() → "뉴스 제목"
    // newsDTO.getContent() → "뉴스 내용"
}

실제 사용 예시 (요청-응답 흐름)

클라이언트에서 보낸 JSON (요청 바디)

{
  "title": "Spring 뉴스",
  "content": "Spring Boot의 @RequestBody 정리"
}
  • 클라이언트(예: React, Postman, 모바일 앱)는 서버에 JSON 데이터를 전송합니다.
  • 이 JSON은 서버에서 @RequestBody를 통해 DTO 객체로 자동 매핑됩니다.
  • 필드 이름 "title"과 "content"는 DTO 클래스의 필드명과 정확히 일치해야 합니다.

DTO 클래스 (Data Transfer Object)

@Getter @Setter
public class NewsDTO {
    private String title;
    private String content;
    
    // 기본 생성자 (Jackson이 내부적으로 사용)
    public NewsDTO() {}
    
    // toString() 메서드를 추가하면 디버깅 시 편리함
    @Override
    public String toString() {
        return "NewsDTO{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }
}
  • @RequestBody는 내부적으로 Jackson(ObjectMapper)을 사용해 JSON → 객체로 변환합니다.
  • 이때 DTO는 반드시 기본 생성자 + getter/setter가 있어야 합니다.
  • toString()은 디버깅 시 JSON → DTO 변환이 잘 됐는지 확인할 때 유용합니다.

컨트롤러 메서드

@RestController
@RequestMapping("/api")
public class NewsController {

    private final NewsService newsService;
    
    // 생성자 주입 (권장 방식)
    public NewsController(NewsService newsService) {
        this.newsService = newsService;
    }

    @PostMapping("/news")
    public ResponseEntity<String> addNews(@RequestBody NewsDTO newsDTO) {
        // 여기서 newsDTO는 이미 JSON에서 변환된 Java 객체임
        System.out.println("받은 데이터: " + newsDTO.toString());
        
        // 서비스 레이어로 전달하여 비즈니스 로직 처리
        newsService.saveNews(newsDTO);
        
        // 응답 반환
        return ResponseEntity.ok("제목: " + newsDTO.getTitle() + "인 뉴스가 저장되었습니다");
    }
}
  • @RequestBody는 JSON 요청 바디를 newsDTO 객체에 자동 매핑합니다.
  • 컨트롤러는 이 DTO를 받아서, 실제 저장 처리는 NewsService에 위임합니다.
  • 처리 후 ResponseEntity.ok(...)를 통해 HTTP 200 응답과 함께 메시지를 반환합니다.

API 호출 (Postman)

POST /api/news HTTP/1.1
Host: localhost:8080
Content-Type: application/json

{
  "title": "뉴스 제목",
  "content": "뉴스 내용"
}
  • 요청 헤더 Content-Type: application/json은 반드시 포함되어야 합니다.
  • 이 헤더가 있어야 Spring이 요청 본문을 JSON으로 인식하고 @RequestBody가 동작합니다.
  • 위 JSON은 DTO의 필드와 1:1로 매핑되므로, 누락되거나 이름이 다르면 400 오류가 발생합니다.

내부 원리 (Spring이 하는 일)

Spring은 요청이 들어오면 다음과 같은 과정을 거칩니다.

  1. HTTP 요청 바디를 읽음 (InputStream으로 raw 데이터 읽기)
  2. Content-Type 헤더를 확인 (application/json인지 체크)
  3. 적절한 HttpMessageConverter를 찾아서 적용
    • JSON의 경우 MappingJackson2HttpMessageConverter 선택
    • XML의 경우 MappingJackson2XmlHttpMessageConverter 선택
  4. Converter가 JSON 문자열을 Java 객체로 변환 (Jackson의 ObjectMapper 사용)
  5. 변환된 객체를 컨트롤러 메서드에 파라미터로 전달
    • 매핑 실패 시 HttpMessageNotReadableException 발생

Jackson이 JSON을 객체로 변환할 때 프로퍼티 이름 매칭, 기본 생성자 호출, setter 메서드 호출 등의 과정을 거칩니다. 따라서 DTO 클래스에는 반드시 기본 생성자와 setter 메서드가 있어야 합니다.

@RequestBody vs 다른 애노테이션 비교

애노테이션데이터 출처데이터 형식용도실제 예시
@RequestBody요청 바디JSON/XMLREST API회원가입, 게시글 작성 등
@RequestParam쿼리스트링key=value단순 파라미터검색어, 페이지 번호 등
@PathVariableURL 경로URL의 일부RESTful URL회원 ID, 상품 ID 등
@ModelAttribute요청 파라미터폼 데이터HTML 폼 처리로그인 폼, 회원정보 수정 등

예시: @RequestBody vs 다른 애노테이션 비교

@RequestBody

@RequestBody: 
POST http://api.example.com/users
Content-Type: application/json
{"name":"홍길동","email":"hong@gmail.com"}

@RequestParam

@RequestParam: 
GET http://api.example.com/search?keyword=스프링&page=1

@PathVariable

@PathVariable: 
GET http://api.example.com/users/123

@ModelAttribute

@ModelAttribute: 
POST http://example.com/login
Content-Type: application/x-www-form-urlencoded
username=user&password=pass

주의사항

  1. @RequestBodyapplication/x-www-form-urlencoded에서는 동작하지 않음
    → HTML의 <form> 태그 기본 전송 방식과 호환되지 않음
    → 이 경우 400 Bad Request 에러 발생
    → 해결책: @ModelAttribute 사용 또는 JavaScript로 JSON 변환 후 전송

  2. @RequestBodymultipart/form-data (파일 업로드) 와 호환되지 않음
    → 파일 업로드는 반드시 @RequestParam MultipartFile 사용
    → 또는 DTO 안에 MultipartFile 필드를 두고 @ModelAttribute로 받기
    클라이언트의 JSON 구조가 DTO와 맞지 않으면 에러 발생

  3. 유효성 검증 방법
    @Valid 또는 @Validated와 함께 사용

@PostMapping("/api/news")
public ResponseEntity<?> save(@RequestBody @Valid NewsDTO dto, BindingResult result) {
    if (result.hasErrors()) {
        // 유효성 검증 실패 처리
        return ResponseEntity.badRequest().body("유효하지 않은 입력입니다.");
    }
    // 정상 처리
    return ResponseEntity.ok("저장 성공");
}
  1. 필수 여부 설정
    → 기본적으로 @RequestBody는 필수 파라미터
    required=false로 설정하면 요청 바디가 없어도 됨 (Spring 5.1 이상)
@PostMapping("/api/optional-body")
public ResponseEntity<?> process(@RequestBody(required=false) InfoDTO info) {
    // 요청 바디가 없으면 info는 null
    if (info == null) {
        return ResponseEntity.ok("요청 바디가 없습니다");
    }
    return ResponseEntity.ok("처리 완료: " + info.getName());
}
profile
donggyun_ee

0개의 댓글