인프런 커뮤니티 질문&답변

김회민님의 프로필 이미지

작성한 질문수

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술

Form 전송 객체 분리 - 개발

@Data의 @RequiredArgsConstructor에 관하여 질문이 있습니다.

해결된 질문

작성

·

604

0

@Data
public class ItemUpdateDto {
    @NotNull
    private Long id;

    @NotNull
    private String itemName;

    @NotNull
    @Range(min = 1000, max = 1000000)
    private Integer price;

    private Integer quantity;
}

이 코드를 보면 @RequiredArgsConstructor로 이용해서 생성자를 만드는 것을 확인할 수 있는데, 저 코드의 설명을 보면 final 필드나 @NonNull 애노테이션이 붙은 필드에 한해서 생성자를 만들어준다고 되어있습니다.

Generates a constructor with required arguments. Required arguments are final fields and fields with constraints such as @NonNull.

그런데, ItemUpdateDto에는 final 객체가 없어서 빈 생성자가 생성될거라고 예상이 됩니다.

실제로 코드에 빈 생성자를 넣으면, RequiredArgsConstructor에 빨간줄과 함께 이미 정의되었다고 표시도 됩니다.

그렇다면, Spring에서 폼데이터를 받을때, 생성자가 아닌, Setter를 이용해서 주입을 받는 것일까요? 그렇다면, 저번 수업에서 말씀하신대로 실제로 사용할때는 @Data 가 아닌, Getter, Setter만 제한적으로 적용하는게 맞을까요?

답변 2

1

안녕하세요, 김회민 님. 공식 서포터즈 y2gcoder 입니다.

먼저 Spring에서 폼 데이터를 받아 @ModelAttribute 를 이용해 매핑해주는 단계에서는

1) 파라미터가 있는 생성자

2) 기본 생성자 + setter

의 우선순위로 폼 데이터를 매핑해준다고 합니다. 그래서 @RequiredArgsConstructor를 사용해도 final 변수가 없으니 빈 생성자로 만들어지고, 그래서 우선순위에 따라 빈 생성자(기본 생성자) 와 setter를 사용해 요청을 매핑해주는 것으로 이해해주시면 될 것 같습니다!

실무에서 사용하는 방식에 대해서는 사람마다 다를 것 같습니다. 부족한 저의 개인적인 의견을 말씀드리자면 롬복을 사용할 것이라는 것을 전제로 하면

  • @Data에 있는 모든 기능이 필요하다 > @Data 사용

  • @Data에 있는 기능 중 일부만 필요하다 > 그 일부 기능에 해당하는 애노테이션만 사용

이렇게 사용하고 있습니다.

 


감사합니다.

추가적으로 질문해주신 사항에 대한 답변입니다 :)

먼저 현재 코드 아키텍처의 방향 <= 이를 영한님이 강의에서 사용하시는 프로젝트의 방향이 아닌 현재 자바를 사용한 실무 프로젝트 아키텍처의 방향이라는 의미로 해석했습니다.

영한님께서도 무분별한 setter를 지양하라고 말씀하고 계시고, 개인적으로 setter를 사용할 경우 해당 메서드의 의도를 정확하게 파악하기 어렵다는 단점이 있다고 생각합니다. 또한 DDD와 같은 설계 디자인이나 헥사고널 아키텍처와 같은 핫한 아키텍처에서도 풍부한 도메인 모델을 지향하기 때문에 응용서비스가 아닌 도메인 내에 요구사항과 비즈니스 기능을 넣고 있습니다.

얼마 전에 감명깊게 본 글에서도 실무에서 서비스 계층이 아닌 도메인 계층에 비즈니스 로직을 넣는 모습을 볼 수 있었습니다.

그래서 Item 내부에 상태를 변경하는 메서드를 만들어 도메인 내부에서 상태를 변경하는 것은 저는 개인적으로 좋다고 생각합니다.

김회민님의 프로필 이미지
김회민
질문자

와 자세한 답변 정말 감사드립니다.

제가 설계 디자인이나 아키텍쳐에 대한 지식이 부족해서 어떤 방식으로 코드를 짜는 것이 올바른 방향인지 고민이 많았습니다. 그런 상황에서 어떤 디자인이 있는지 알려주셔서 정말 감사하게 생각하고 있습니다. 이 부분은 제가 따로 찾아서 공부하겠습니다.

더불어 블로그도 추천해주시다니! 꼼꼼히 읽어서 지식을 익혀나가도록 하겠습니다.

다시 한번 감사의 말씀 드립니다!!

0

김회민님의 프로필 이미지
김회민
질문자

아, 그리고 추가적으로 궁금한게 있습니다.

ItemRepository의 update 메소드를 보면, findItem의 setter를 이용해 데이터를 업데이트하고 있는데, Item 도메인에 update 함수를 추가로 만들어서 repository가 아닌, Item 내부에서 값을 바꾸도록 하는 방법은 현재 코드 아키텍쳐의 방향과 어울리지 않는 것일까요?

아니면 나중에 추가로 인메모리가 아닌, 데이터베이스를 적용할 때 문제가 발생할 수 있나요?