@Data 어노테이션은 @Getter/Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor 를 합쳐놓은 어노테이션이다.
POJO와 bean과 관련된 모든 모일러 플레이트를 생성한다.
@Getter
@Setter
@ToString(includeFieldNames = true)
@EqualsAndHashCode
@RequiredArgsConstructor
public class Human {
private String name;
private int age;
}
// 👇 위와 같은 코드를 아래처럼 사용할 수 있다.
@Data
public class Human {
private String name;
private int age;
}
Java
복사
@Data 과연 안전한가?
@Setter가 존재한다
외부에서 필드의 값을 변경하기 위해 접근할 때 필드의 값을 변경하려는 목적을 제대로 파악하는 것이 중요하다.
setter를 사용하게 되면 값을 변경하는 의도가 불분명한 단점이 있다.
또한, setter가 있다는 것은 외부에서 값을 변경할 수 있다는 말과 동일하다.
값의 일관성을 유지하기 어렵기 때문에 side effect를 발생시킬 수 있다.
생성자의 인자 순서가 중요하다.
@AllArgsConstructor 와 @RequiredArgsConstructor 가 포함되어 있는 @Data 어노테이션은 생성자를 통해 객체를 생성할 때, 인자의 순서가 굉장히 중요하다.
인자의 순서가 변경되면 원하는 값이 들어가지 않을 수 있으며, 치명적인 버그를 발생시킬 수 있다.
Data 어노테이션 필요없는 것인가?
코드 작성 시 간결성은 가독성이 있는 코드를 작성하는데 큰 도움을 준다. 좋은 코드를 작성하는 가장 큰 이유는 유지보수성을 높이고, 코드를 읽는 개발자의 빠른 이해를 돕기 위해서다.
@Data 어노테이션을 사용하여 가독성을 올리는 대신 내부적으로 규칙을 정해 사용하게 된다면 @Data 어노테이션을 적절하게 잘 사용할 수 있지 않을까 싶다.
규칙 1. Entity에서는 사용하지 않는다.
아무리 가독성이 올라간다고 하더라도 가장 중요한 로직을 가지고 있으며, DB와 밀접한 관계를 가지고 있는 Entity에서 사용할 경우 매우 위험할 수 있다.
Entity에서는 Builder 패턴을 사용하여 객체를 만드는 것이 가장 안전하고, 명확한 코드를 작성할 수 있다.
규칙 2. DTO에서만 사용한다.
데이터 전송을 위한 객체인 DTO에서만 사용하는 것이 좋다. DTO는 테스트 과정에서 메모리 주소를 받아 확인을 할 때가 있으며, @Getter 와 @ToString 등 객체, 값을 확인하기 위한 어노테이션을 가지고 있으면 좋다. 또한, 모든 DTO가 통일성을 가지고 있어 일관성을 유지할 수 있다.
규칙 2-1. Setter는 DTO 내부 메소드에서만 사용한다.
@Data
@Accessors(chain = true)
public class HumanResponse {
private String name;
private int age;
public HumanResponse fromEntity(Human entity) {
return new HumanResponse()
.setAge(entity.getAge())
.setName(entity.getName());
}
}
Java
복사
실제로 setter를 DTO 내부에서만 사용할 수 있게 규칙을 정했다. 내부 메소드를 만들어 사용한다면 @Setter를 사용할 때 나올 수 있는 “명확하지 않다” 라는 문제를
메소드 이름을 통해 해결할 수 있다. 또한, 내부 메소드에서만 setter를 관리한다면 값의 일관성을 유지할 수 있는 가능성이 높아진다.
참고링크: