• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

PostCreate 기본 생성자 문제 질문드립니다.

23.01.18 12:48 작성 조회수 532

3

우선 수업 잘 듣고 있습니다 호돌맨님! 많이 배우고 있어요 ㅎㅎ

제목에서와 같이 PostCreate 부분에서 기본 생성자에 관해 질문을 드립니다.

// @Setter
@Getter
@NoArgsConstructor // TODO: 왜 이게 꼭 있어야 하는 것일까?
public class PostCreateDto {

   @NotBlank(message = "타이틀을 입력해주세요.")
   private String title;

   @NotBlank(message = "내용을 입력해주세요.")
   private String content;

   @Builder
   public PostCreateDto(String title, String content) {
      this.title = title;
      this.content = content;
   }
}

우선 이건 제 코드입니다. 보시면 제 코드에는 @NoArgsConstructor 어노테이션이 있는데요. 이 부분이 없으면 제 PostControllerTest에서는 테스트 실패가 뜨더라구요.

에러 메시지는 다음과 같습니다.

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.blog.request.PostCreateDto (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

에러메시지를 읽어보니 생성자가 없다는 문제 같아서 @NoArgsConstructor 어노테이션을 붙여보니 정상적으로 작동을 하더군요.

이 부분이 궁금해서 찾아보니 RequestBody로 넘어오는 데이터를 맵핑할 때 Jackson의 ObjectMapper가 사용되는데 이게 RequestBody를 생성할 때, DTO가 Property기반이 아니거나 Delegate를 한 상태가 아니라면 기본 생성자로 생성한다 라고 나와있네요. (https://velog.io/@conatuseus/RequestBody%EC%97%90-%EC%99%9C-%EA%B8%B0%EB%B3%B8-%EC%83%9D%EC%84%B1%EC%9E%90%EB%8A%94-%ED%95%84%EC%9A%94%ED%95%98%EA%B3%A0-Setter%EB%8A%94-%ED%95%84%EC%9A%94-%EC%97%86%EC%9D%84%EA%B9%8C-3-idnrafiw)

그리고 바인딩할 때 Setter가 없이도 자바 리플렉션을 통해서 DTO에 값이 들어간다고 하는 것도 이번에 알게 됐네요. 그래서 Setter를 지우고 Getter랑 @NoArgsConstructor 어노테이션만 붙이고 테스트를 돌려보니 통과가 잘 됩니다.

 

그런데 호돌맨님이 올려주신 코드를 보니 PostCreate 부분에 기본생성자가 없더라구요. 그런데도 테스트통과가 잘 되는 것을 보니까 신기하네요. 어떻게 그게 가능한 것인지 설명해주실 수 있나요?

답변 1

답변을 작성해보세요.

1

안녕하세요. 호돌맨입니다.
질문을 남겨주셔서 감사합니다.

한 줄 요약: @Setter는 필요없습니다.

1. Getter만 있는경우

@Getter
@ToString
public class PostCreate {

    @NotBlank(message = "타이틀을 입력하세요.")
    private String title;

    @NotBlank(message = "콘텐츠를 입력해주세요.")
    private String content;
}

값이 잘 입력됩니다. 기본 생성자가 있기때문에 문제 없을것같네요

2. 생성자가 있는경우

@Getter
@ToString
public class PostCreate {

    @NotBlank(message = "타이틀을 입력하세요.")
    private String title;

    @NotBlank(message = "콘텐츠를 입력해주세요.")
    private String content;

    @Builder
    public PostCreate(String title, String content) {
        this.title = title;
        this.content = content;
    }
}

생성자를 통해 값이 들어갑니다.

3. 그런데

테스트시 생성자가 없는경우 title, content 값을 어떻게 입력 해야할지는 고민을 해봐야겠네요.

참고링크

감사합니다.