티스토리 뷰

RequstBody, RequestParam, ModelAttribute란?

@RequestParam

@RequestParam은 1개의 HTTP 요청을 받기 위해 사용합니다. @RequestParam은 필수 여부가 true이기 때문에 반드시 파라미터가 전송되어야 합니다.

 

파라미터가 전송되지 않을 시 400 Error가 발생합니다. 반드시 필요한 값이 아니라면 required 옵션을 false로 지정하면 되고 defaultValue 옵션을 사용하면 기본 값을 지정할 수 있습니다.

 

 

@RequestBody

@RequestBody는 클라이언트가 전송하는 JSON 형태의 HTTP Body를 Java 객체로 변환시켜 주는 역할을 합니다.

 

@RequestBody로 받는 데이터는 Spring에서 관리하는 Message Converter 중 하나인 MappingJackson2HttpMessageConverter를 통해 Java 객체로 변환하는데, 이는 ObjectMapper 라는 클래스를 사용합니다.

물론, 데이터 형식이 JSON이 아닐 수도 있습니다.

ObjectMapper의 동작 과정
ObjectMapper는 JSON 메세지를 자바 객체로 변환하는 과정에서 객체의 기본 생성자를 통해 객체를 생성하고, 내부적으로 Reflection을 사용합니다.그래서 반드시 @Setter가 필요한 것은 아니지만 @Getter나 @Setter, @JsonInclude 등 필드에 있는 변수들의 이름을 찾기 위한 메서드를 필요로 합니다.
그러므로 기본생성자 + @Getter로 클래스를 구현해주면 @Setter가 없어도 값이 바인딩 됩니다.

 

 

@ModelAttribute

@ModelAttribute는 클라이언트가 전송하는 <form> 형태의 Http Body와 요청 파라미터들을 생성자나 @Setter로 바인딩하기 위해 사용됩니다.

 

@ModelAttribute에는 매핑시키는 파라미터의 타입이 객체의 타입과 일치하는지 등을 포함한 다양한 검증 작업이 추가적으로 진행됩니다. 예를 들어 int형의 index 라는 변수에 “인덱스” 라는 String형을 넣으려고 한다면, BindException이 발생합니다.

 

@ModelAttribute를 사용해서 특정 Parameter 값만 가져올 수도 있습니다. 만약 우리가 다음과 같은 형태로 전송된 데이터에서 @ModelAttribute(’writer’) String writer 를 사용하면 writer 변수에 레토라는 값을 얻을 수 있습니다.

 

 

 

@ModelAttribute의 동작 과정에 대해 간략히 설명하자면, ModelAttribute는 먼저 Reflection을 사용하여 필드를 인자로 받을 생성자가 있는지 확인합니다. 있다면, 해당 생성자를 이용해 값을 세팅하고 없다면 @Setter를 이용하여 값을 세팅합니다.

 

예를 들어 모든 필드를 인자로 받는 생성자가 있다면 해당 생성자로 값을 주입합니다. 없다면 일부 필드를 인자로 받는 생성자를 찾아 사용하고, 이마저도 없다면 기본 생성자를 통해 객체를 생성합니다. 그리고 생성자로 주입하지 못한 남은 변수들은 @Setter를 이용하여 값을 할당합니다.

예를 들어 Board(1, “글쓴이”)를 이용해 Board 객체가 생성되고, 다음에 Setter를 이용해 contents에 값이 주입됩니다.

@Getter
@Setter
@ToString
public class Board {

    private int index;
    private String writer;
    private String contents;

    public Board(int index) {
        this.index = index;
    }

    public Board(int index, String writer) {
        this.index = index;
        this.writer = writer;
    }
}

RequestBody, ModelAttribute, RequestParam 활용 예시

다음과 같은 Board 클래스가 있다고 가정하겠습니다.

@Getter
@Setter
@ToString
public class Board {

    private int index;
    private String writer;
    private String contents;

}

 

Spring에서 활용 예시

@RestController
@RequestMapping("/board")
public class BoardController {

    @PostMapping("/requestBody")
    public ResponseEntity<Board> requestBody(@RequestBody Board board) {
        // @RequestBody는 MessageConverter를 통해 Json 형태의 HTTP Body를 Java 객체로 변환시킨다.
        return ResponseEntity.ok(board);
    }

    @PostMapping("/modelAttribute")
    public ResponseEntity<Board> modelAttribute(@ModelAttribute Board board) {
        // @ModelAttribute는 폼(form) 형태의 HTTP Body와 요청 파라미터들을 객체에 바인딩시킨다.
        return ResponseEntity.ok(board);
    }

    @GetMapping("/list")
    public ResponseEntity<List<Board>> requestParam(
            @RequestParam(value = "searchKeyWord1", required = false, defaultValue = "MangKyu") String searchKeyWord) {

        // searchKeyWord는 required가 false이기 때문에 없을 수도 있으므로, 없다면 기본값이 할당된다.
        return ResponseEntity.ok(boardService.getBoardList(searchKeyWord1));
    }

}

 

앞서 말한 내용에 따르면 ModelAttribute는 multipart/form-data 형태의 HTTP Body와 파라미터들을 생성자나 Setter로 바인딩 시킵니다. 그렇기에 요청이 다음과 같은 경우라도 객체의 모든 데이터는 정상적으로 바인딩 됩니다.

Request URL: http://localhost:8080/board/modelAttribute?contents=Contents

Request Body:
  - type: application/x-www-form-urlencoded
  - data: {
      "index": 1,
      "writer": "Retto"
    }
    
    
Response Body:
  - data: {
      "index": 1,
      "writer": "Retto",
      "contents: "Contents"
    }

정리

RequestParam

  • 1개의 HTTP 파라미터를 얻기 위해 사용되며 기본값을 지정할 수 있습니다.
  • 필수 여부가 true이기 때문에 반드시 필요한 경우가 아니라면 required = false 설정이 필요합니다.

 

RequestBody

  • JSON 형태의 HTTP Body 데이터를 MessageConverter를 통해 Java 객체로 변환시킵니다.
  • 기본 생성자로 객체를 만들고, Getter나 Setter 등의 메소드로 필드를 찾아 Reflection으로 값을 설정합니다.

 

ModelAttribute

  • <form> 형태의 HTTP Body와 요청 파라미터들을 객체에 바인딩 시킵니다.
  • 기본적으로 생성자로 값이 설정되고, 생성자로 설정되지 않은 필드는 Setter로 설정됩니다.

'Spring' 카테고리의 다른 글

[Spring]logging  (0) 2024.09.12
[Spring]DAO와 DTO, VO  (0) 2024.09.12
[Spring]@No/All/RequiredArgsConstructor  (0) 2024.09.12
[Spring Data JPA]JPA Repository란? (+ 사용법, Method)  (0) 2024.09.10
[Spring Data JPA]JPA 복합키 사용하기  (0) 2024.09.10
공지사항
최근에 올라온 글
Total
Today
Yesterday