토이 프로젝트 배우게 된 것들 & 오류 해결🐰

Builder 패턴, @NoArgsConstructor, @AllArgsConstructor

j_estory 2022. 11. 14. 18:09

프로젝트에 본격적으로 들어가기 전에 평소에 자주 썼던 어노테이션들에 대해 정확히 알고 쓰고 싶어서 정리를 해보았다. 

실무를 할 때에도 @Builder 와 @NoArgsConstructor을 함께 쓰면 왜 안될까? 에 대해 깊숙히 알아보지 못해 지금 정리를 해보려고 한다!

 

☝🏻 일단 ! @Builder 패턴의 사용 이유를 알아보자!

 

🏷 빌더 패턴 사용 이유

1) 필요한 데이터만 설정할 수 있다. 

2) 유연성을 확보할 수 있다. 

  • 예를들어, 어떠한 클래스에 필드가 추가되었다면 기존에 정의해놓았던 기본생성자에 수정이 필요해 진다.
    하지만, builder 페턴을 사용하게 되면 수정 필요없이 해당 필드를 사용해야 하는 곳에 유연하게 추가가 가능하다.

3) 가독성을 높일 수 있다.

4) 변경 가능성을 최소화 할 수 있다. 

  • 많은 경우, 수정자 패턴(setter)을 흔히 사용한다. 
  • setter 을 사용 할 시, 단점
    • 불필요하게 변경 가능성을 열어둔다.
    • 유지보수 시, 값을 할당하는 지점을 찾기 힘들게 만들어, 불필요한 코드 리딩을 유발하게 된다. 
      만약, 값을 할당하는 시점이 객체 생성 시라면 그 지점을 찾기 쉬워진다.
  • 변경 가능성을 최소화 하기 위해서는 "final" 키워드를 사용한다. 
    • final을 구현할 수 없는 경우 setter을 구현하지 않으면 동일한 효과를 보장하게 된다. 
  • 객체 생성시에는 대부분의 경우 builder 패턴을 이용하는 것을 권장한다.
    • 하지만, 빌더의 남용은 오히려 코드를 비대하게 할 수 있으므로, 적절할 때 사용하는 것을 권장 
    • builder 패턴을 사용할 수 없는 예외적인 케이스
      • 1) 라이브러리로 객체의 생성을 위임하는 케이스
      • 2) 변수의 개수가 2개 이하이고, 변경 가능성이 적은 케이스

🏷 근본적으로 궁금했던, @builder 와 @NoArgsConstructor을 함께 썼을 때 오류가 나는 이유를 알아보자!

 

그 전에! @NoArgsConstructor과 @AllArgsConstructor 에 대해 알아보자!

 

✔️ @NoArgsConstructor

  • 기본 생성자를 생성해주는 어노테이션
  • @AccessLevel.protected 속성 부여
    • 무분별한 객체 생성에 대해 한번 더 체크 가능
    • 기본 생성자에 대한 접근 제어가 되어 IDE 단계에서 누락을 방지할 수 있다.
    • 즉, 기본 생성자 생성에 대한 방지를 해주고, 지정한 생성자를 통해 생성하도록 강제 한다. 🔜 완전한 객체 생성에 도움을 준다. 

✔️ @AllArgsConstructor

  • 모든 필드를 파라미터로 갖는 생성자를 생성해주는 어노테이션
  • Class에 선언된 필드 순서대로 생성자를 생성해준다. 

@builder 패턴의 특징 중에 기본생성자 및 다른 생성자가 존재하지 않을 때, 생성자를 자동으로 만들어주는 특징이 있다.

만약, 기본생성자나, 다른 생성자가 존재할 경우 모든 필드를 갖는 생성자를 수동으로 생성해줘야 한다. 

 

따라서, @builder 와, @NoArgsConstructor을 함께 사용하게 된다면, builder 패턴은 이미 기본 생성자가 존재하기 때문에,

자동으로 생성자를 생성하지 않는다. 

그렇기 때문에 @AllArgsConstructor 을 사용하여 전체 필드를 갖는 생성자를 생성해줘야 하는 것이다.

 

❓공부를 하다가 기본생성자는 왜 있어야 하는걸까? 에 대한 의문점이 생겨 부록으로 정리해 보겠다!

 

🏷 기본 생성자가 필요한 이유

  • 생성자를 호출하지 못하게 하는 용도가 있는게 아니라면, 기본 생성자를 없애는 방법은 그리 좋은 방법이 아니다.
  • 또한, 객체지향 관점에서도 모든 class는 자신의 기본 정보인 기본 생성자에 연결되도록 해야 한다. 

🏷 기본 생성자를 반드시 생성해줘야 되는 경우 몇가지를 소개

 

1) Jackson

  • RequestBody에 값을 DTO에 넣을때, jackson은 setter가 아니라 기본 생성자를 통해 값을 넣기 때문에 반드시 존재해야 한다.

2) JPA

  • Entity에 값을 셋팅하기 위해서 setter을 사용하는 것이 아니라 Reflaction을 사용하게 된다.
더보기

Reflaction 이란..?

 

구체적인 class 타입을 알지 못해도 그 클래스의 메소드, 변수, 타입에 접근할 수 있도록 해주는 자바 API

  • Reflaction 에서 Class.newInstance() 를 사용해서 생성자 코드를 만드는데, 이 생성자 코드가 바라보는게 기본 생성자이다.

❓ 기본 생성자만 있으면 값을 어떻게 셋팅하는지에 대한 질문은!

 

답 !! getter, setter을 이용해라 !!