Lombok 에너테이션 각 장단점
왜?
@Data를 간편하게 활용하는 것이 결국 보안적인 이슈를 생성하는 것을 알았다. 이유를 정리해보고 각각의 lombok에서 주로 쓰는 것들을 정리해보았다.
일단 @Data는 다음의 모든것이 한번에 정의되어있는것과 같다
- Getter, Setter, RequiredArgsConstructor, ToString, EqualsAndHashCode, Value
따라서 각자의 장단점을 알면 결국 @Data의 단점을 알수있을것이다.
spring4.3부터는 생성자가 존재시 기본적으로 @Autowired가 되며, setter로 주입하고싶다면, @Autowired(required=false)를 통해 기능을 해제해줘야한다.
AllArgsConstructor
클래스에 존재하는 모든 필드에 대한 생성자를 자동으로 생성한다.
발생할수있는 문제
이 애너테이션은 필드의 선언 순서대로 생성자 파라미터의 순서를 정한다. 따라서 개발자가 혹여나 필드의 선언 순서를 바꾸고 (혹시 타입까지 같다면) 에러가 없이 잘못동작할수있다.
1 | // @RequiredArgsConstructor도 마찬가지 |
만약 필드 선언 순서가 cancelPrice와 orderPrice의 위치가 바뀐다면,,, 대참사다
RequiredArgsConstructor
초기화 되지 않는 모든 final 필드 + @NonNull과 같이 제약조건이 설정되어있는 모든 필드들에 대한 생성자를 자동으로 생성한다.
발생할수있는 문제
위 @AllArgsConstructor와 동일한 문제 발생가능
EqualsAndHashCode
equals 메서드와 hashcode 메서드를 생성한다.
set에서 contains를 활용시 equals()를 사용하여, true를 찾는다.
발생할수있는 문제
동일한 객체임이도 Set
에 저장한 뒤에 필드 값을 변경하면 hashCode가 변경되면서 찾을 수 없게 되어버린다. 이는 @EqualsAndHashCode
의 문제라기 보다는 변경가능한 필드에 이를 남발함으로써 생기는 문제이다.
1 |
|
참고로 hashCode()와 equals() 관계
- 두 객체가 같으면(
equals()
가 true 리턴),hashCode()
는 같은 값을 리턴해야 합니다. - 두 객체가 같지 않을 때 (
hashCode()
가 false),hashCode()
가 꼭 다른 값을 리턴해야하는 것은 아닙니다. 하지만 다른 값을 리턴하면 hash table의 성능이 향상됩니다. - hashcode가 다르면, 두개의 객체가 같지 않다
- hashcode가 같으면, 두개의 객체가 같거나 다를 수 있다→ hashcode가같다면 equals()로 다시검토하게됨. 하지만 hashcode 중복이 없을수록 성능좋아짐
NoArgsConstructor
파라미터가 없는 생성자를 생성한다.
그냥 빈 생성자 만들어줌
발생할수있는 문제
- 필드들이 final로 생성되어 있는 경우에는 필드를 초기화할수없기 때문에 생성자를 만들수없고 에러가 발생한다. → force=ture 옵션을 이용해 강제 초기화 시켜 생성자를 만들수있다
- @Nonnull 같은 필드에 제약조건이 설정되어있는경우, 추후 초기화를 진행하기전까지 생성자 내 null-check 로직이 생성되지않는다.
@Data 위험성
발생할수있는 문제
@Data는 다음과 같이 많은 것들이 함께 정의되는것이다
- Getter, Setter, RequiredArgsConstructor, ToString, EqualsAndHashCode, Value
@Getter @Setter 주의해야한다. 이유는?
- @Setter는 꼭 필요한 경우에만 설정해야 한다고 알고 있다. 값을 바꿀 수 있는 어노테이션이기 때문에, 값을 바꿀 필요가 있는 경우에만 설정하고 이외의 상황에는 절대 선언하면 안된다.
- @Getter도 필요한 경우에만 설정하는 것이 가장 좋지만, 남발해도 크게 위험하지 않는 것(?)으로 알고 있다. 값에 접근은 가능하나 변경할 수 없기 때문이다.
그 밖에 롬복 주로 사용하는것
@Getter
모든 각 필드에 해당하는 getXXX메서드 만들어줌
명시적으로 AccessLevel을 명시해주지 않으면, 접근 제한자는 public이 됩니다.
@Setter
모든 각 필드에 해당하는 setXXX메서드 만들어줌
주의할 사항은 Setter는 외부에서 필드를 수정할수있도록 하므로 경우에 따라서 보안에 취약
명시적으로 AccessLevel을 명시해주지 않으면, 접근 제한자는 public이 됩니다.
@ToString
- toString() 메서드를 작성해줌, exclude 속성사용시, 특정 필드를 toString()결과에서 제외시킬수있다.
1 | "password") (exclude = |
@Builder
- @Builder를 사용하면 객체 생성이 명확해진다. 가급적 클래스 보다는 직접 만든 생성자 혹은 static 객체 생성 메소드에 붙이는 것을 권장한다.
- @Builder를 붙이면 파라미터 순서가 아닌 이름으로 값을 설정하기 때문에 리팩토링에 유연하게 대응할 수 있고, 필드 순서를 변경해도 문제가 없다.
- 되도록 직접 만든 생성자에 붙이자
결론
잘알고 사용하자
실무 프로젝트에서는 가급적 @Getter, @Setter, @ToString 만 사용하고 그 외의 것들 사용은 자제하거나 매뉴얼을 잘 읽어보고서 보수적으로 사용한다.
@EqualsAndHashCode
는 Immutable 필드만 명시적으로 지정하면서 자제해서 사용하거나 가급적 IDE 코드 제너레이션등을 통해 코드를 직접 만든다.