MyShop 애플리케이션은 JPA를 이용해 **MySQL(RDB)**과 연동해 사용하고 있다. 이에 따라 도메인을 모델링을 해보자

엔티티 클래스를 작성할 때 다음과 같이 어노테이션을 많이 쓴다. 하지만 이 엔티티 클래스에 작성된 어노테이션은 몇가지 문제가 있다.
@Getter
**@Setter // 문제 1**
**@NoArgsConstructor // 문제 2**
@Builder
**@AllArgsConstructor // 문제3**
@Entity
public class ExampleEntity
@Setter 어노테이션을 사용하게 되면 해당 필드의 값을 변경할 수 있게 되는데, 이렇게 되면 필드의 값이 불변하게 되는 객체지향의 개념에 어긋나게 된다.
또 스프링에서는 JPA를 이용해 데이터를 관리하기 때문에 @Setter 어노테이션을 사용하게 되면 의도하지 않은 엔티티 값의 변경이 일어나게 될 수 있다. 특히 엔티티에 @Setter를 사용하면 변경이 발생했을 때 추적하기 힘들어진다.
그렇기 때문에 값 변경이 필요하다면 의미 있는 메서드를 생성해 사용하는 것이 좋다.
@NoArgsConstructor 어노테이션을 사용해 파라미터가 없는 생성자를 만들게 되는데, 이 생성자는 외부에서 호출될 필요가 없어 접근 제어자를 Protected로 변경하는 것이 좋다.
이러면 해당 클래스를 상속받은 하위 클래스에서만 사용할 수 있어 안정성이 높아지게 된다.
즉 무분별한 객체 생성에 대해 한 번 더 체크할 수 있게 된다.
//@NoArgsConstructor(access = AccessLevel.PROTECTED)
ExampleEntity exampleEntity = new ExampleEntity(); **//컴파일 에러**
@AllArgsConstructor 어노테이션을 사용하여 모든 필드를 포함한 생성자를 만들게 되는데, 이 생성자는 JPA에서 사용되는 기본 생성자와 충돌할 수 있어 사용하지 않는 것이 좋다.
만약 **@AllArgsConstructor**를 작성하게 되면 인스턴스 멤버의 선언 순서에 영향을 받아 필드의 순서를 바꾸게 되면 생성자의 입력 값 순서도 바뀌게 되어 검출되지 않는 치명적인 오류를 발생시킬 수 있다.
이를 해결하기 위해 생성자에 @Builder를 사용해 @AllArgsConstructor를 사용하지 않도록 해야한다.