@ModelAttribute

박영준·2023년 7월 19일
0

Spring

목록 보기
46/58

1. @RequestBody VS @ModelAttribute

controller 에서 게시글 작성부분을 보면서 테스트를 진행해봤다.

아래의 두 코드는 PostRequestDto 에 @RequestBody / @ModelAttribute 를 사용하는 것의 차이다.

@RequestBody

1) 코드

// 게시글 작성
@PostMapping
public ResponseEntity<PostResponseDto> createPost(@RequestPart(value = "image", required = false) MultipartFile multipartFile, @RequestBody PostRequestDto requestDto, @AuthenticationPrincipal UserDetailsImpl userDetails) {
    return ResponseEntity.ok(postService.createPost(multipartFile, requestDto, userDetails.getUser()));
    }
@Getter
@AllArgsConstructor
public class PostRequestDto {
    private String title;
    private String contents;
    private String username;
}

2) 테스트

이미지 파일과 json 형태로 데이터를 전송했으나, 실패했다.

그러나 JSON 형태로 따로 보내줄 경우, 정상적으로 데이터가 반환되었다.
물론, 이미지 파일이 같이 전송되지는 않았다.

@ModelAttribute

1) 코드

// 게시글 작성
@PostMapping
public ResponseEntity<PostResponseDto> createPost(@RequestPart(value = "image", required = false) MultipartFile multipartFile, @ModelAttribute PostRequestDto requestDto, @AuthenticationPrincipal UserDetailsImpl userDetails) {
    return ResponseEntity.ok(postService.createPost(multipartFile, requestDto, userDetails.getUser()));
}
@Getter
@AllArgsConstructor
public class PostRequestDto {
    private String title;
    private String contents;
    private String username;
}

2) 테스트

이미지와 함께 fom-data 형식으로 데이터를 전송했고, 정상적으로 반환되었다.

이는 @ModelAttribute 가 JSON 객체를 받아올 수 있기 때문이다.
단, body 에 데이터를 담을 경우엔 Content-Type 을 application/json 이 아닌 multipart/form-data 형태로 전송해야 한다.
참고: @RequestParam VS @ModelAttribute

결론

form-data 형태인 이미지 파일(MultipartFile)과 JSON 데이터를 함께 전송하기 위해, json 데이터를 @ModelAttribute 로 보낸 것이다.

2. @RequestParam VS @ModelAttribute

@RequestParam

1) 정의

  • 1:1 로 받는다

  • 파라미터 타입이 잘못 들어오면, 400 Bad Request 를 날린다

  • 생략 가능

    • 매개변수가 SimpleValue타입(원시타입(int), Wrapper타입(Integer), Date 등...)일 경우, 해당 어노테이션이 생략돼있다고 간주

2) 테스트


name과 age라는 파라미터에 값을 담아서 전송했더니, 올바르게 @ResponseBody를 거쳐 올바르게 JSON형식으로 값이 담겨서 왔다.

@ModelAttribute

1) 정의

  • Java의 객체로 데이터를 받아올 수 있다.

    • 도메인 오브젝트나 DTO 요청 파라미터를 바인딩해서 한번에 받는다.
  • 타입 변환에 실패하더라도, 작업은 계속 진행된다

  • 생략 가능

    • 매개변수가 그 외의 타입일 경우, 해당 어노테이션이 생략돼있다고 간주

2) 테스트

(1) Paramter 의 경우


parameter에 넣은 값들이 올바르게 JSON형식으로 Body에 반환

(2) Body 의 경우


값이 담기지 않았다.
@ModelAttribute 에서 Body를 이용해 전송하려면, Content-Type 을 application/json 이 아닌 multipart/form-data 형태로 전송해야 하기 때문이다.

(3) multipart/form-data 의 경우

name과 age에 값이 담겨서 반환

3. @ModelAttribute 와 @Setter

아래는 요청을 보내는 Dto 클래스다.
Controller 에서 @ModelAttribute 로 값을 넘길 때, 이 Dto 클래스에서는 어떤 어노테이션을 사용하면 좋을까.

public class PostRequestDto {
    private String title;
    private String contents;
    private String username;
}

1) @ModelAttribute

  • @ModelAttribute 는 요청 파라미터를 해당 메소드의 매개변수로 전달하거나 모델에 바인딩하는 데 사용한다.

  • 생성자가 1개면, 그 생성자를 통해 객체를 생성

    생성자가 2개 이상이면, 매개변수 없는 생성자를 통해 객체를 생성하고 Setter 로 값을 세팅

2) 방법

@ModelAttribute 를 통해, NULL 이 아닌 값을 입력받고 싶을 경우, 다음 2가지 방식을 사용할 수 있다.

방법 1

@Getter
@AllArgsConstructor
public class PostRequestDto {
    private String title;
    private String contents;
    private String username;
}
  • @AllArgsConstructor 만 사용

  • @AllArgsConstructor

    • 모든 필드를 매개변수로 받는 생성자를 자동으로 생성

방법 2

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class PostRequestDto {
    private String title;
    private String contents;
    private String username;
}
  • @NoArgsConstructor 이 있다면, @Setter 를 반드시 붙이자.

    • @NoArgsConstructor 로 객체를 생성하고, @Setter 로 값을 세팅한다.
  • AllArgsConstructor 와 NoArgsConstructor 를 같이 사용할 경우,
    NoArgsConstructor 이 객체를 생성하게 된다. 따라서, 이 땐 Setter 가 필요하게 된다.

  • @NoArgsConstructor

    • 파라미터가 없는 기본 생성자를 자동으로 생성

참고: [Spring] @RequestParam, @RequestBody, @ModelAttribute의 차이
참고: [Spring Boot] @ModelAttribute 객체값 Null일때 해결방법
참고: [Spring] AllArgsConstructor가 있는데 왜 @ModelAttribute 객체에 값이 할당되지 않는걸까? (feat. ModelAttributeMethodProcessor의 코드를 뜯어보자)

profile
개발자로 거듭나기!

1개의 댓글

comment-user-thumbnail
2023년 7월 19일

좋은 글 감사합니다!

답글 달기