LostCatBox

AboutLombokAtSpring

Word count: 642Reading time: 4 min
2022/12/24 10 Share

Lombok 에너테이션 각 장단점

왜?

@Data를 간편하게 활용하는 것이 결국 보안적인 이슈를 생성하는 것을 알았다. 이유를 정리해보고 각각의 lombok에서 주로 쓰는 것들을 정리해보았다.

일단 @Data는 다음의 모든것이 한번에 정의되어있는것과 같다

  • Getter, Setter, RequiredArgsConstructor, ToString, EqualsAndHashCode, Value

따라서 각자의 장단점을 알면 결국 @Data의 단점을 알수있을것이다.

spring4.3부터는 생성자가 존재시 기본적으로 @Autowired가 되며, setter로 주입하고싶다면, @Autowired(required=false)를 통해 기능을 해제해줘야한다.

AllArgsConstructor

클래스에 존재하는 모든 필드에 대한 생성자를 자동으로 생성한다.

발생할수있는 문제

이 애너테이션은 필드의 선언 순서대로 생성자 파라미터의 순서를 정한다. 따라서 개발자가 혹여나 필드의 선언 순서를 바꾸고 (혹시 타입까지 같다면) 에러가 없이 잘못동작할수있다.

1
2
3
4
5
6
7
@AllArgsConstructor // @RequiredArgsConstructor도 마찬가지
public static class Order{
private long cancelPrice;
private long orderPrice;
}
//취소 금액 5000원, 주문금액 10000원
Order order = new Order(5000L, 10000L)

만약 필드 선언 순서가 cancelPrice와 orderPrice의 위치가 바뀐다면,,, 대참사다

RequiredArgsConstructor

초기화 되지 않는 모든 final 필드 + @NonNull과 같이 제약조건이 설정되어있는 모든 필드들에 대한 생성자를 자동으로 생성한다.

발생할수있는 문제

위 @AllArgsConstructor와 동일한 문제 발생가능

EqualsAndHashCode

equals 메서드와 hashcode 메서드를 생성한다.

set에서 contains를 활용시 equals()를 사용하여, true를 찾는다.

발생할수있는 문제

동일한 객체임이도 Set 에 저장한 뒤에 필드 값을 변경하면 hashCode가 변경되면서 찾을 수 없게 되어버린다. 이는 @EqualsAndHashCode의 문제라기 보다는 변경가능한 필드에 이를 남발함으로써 생기는 문제이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@EqualsAndHashCode
public static class Order {
private Long orderId;
private long orderPrice;
private long cancelPrice;

public Order(Long orderId, long orderPrice, long cancelPrice) {
this.orderId = orderId;
this.orderPrice = orderPrice;
this.cancelPrice = cancelPrice;
}
}

Order order = new Order(1000L, 19800L, 0L);

Set<Order> orders = new HashSet<>();
orders.add(order); // Set에 객체 추가

System.out.println("변경전 : " + orders.contains(order)); // true

order.setCancelPrice(5000L); // cancelPrice 값 변경
System.out.println("변경후 : " + orders.contains(order)); // false@EqualsAndHashCode

참고로 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

스크린샷 2022-08-13 오전 1.57.26.png

@Getter @Setter 주의해야한다. 이유는?

  • @Setter는 꼭 필요한 경우에만 설정해야 한다고 알고 있다. 값을 바꿀 수 있는 어노테이션이기 때문에, 값을 바꿀 필요가 있는 경우에만 설정하고 이외의 상황에는 절대 선언하면 안된다.
  • @Getter도 필요한 경우에만 설정하는 것이 가장 좋지만, 남발해도 크게 위험하지 않는 것(?)으로 알고 있다. 값에 접근은 가능하나 변경할 수 없기 때문이다.

그 밖에 롬복 주로 사용하는것

@Getter

모든 각 필드에 해당하는 getXXX메서드 만들어줌

명시적으로 AccessLevel을 명시해주지 않으면, 접근 제한자는 public이 됩니다.

@Setter

모든 각 필드에 해당하는 setXXX메서드 만들어줌

주의할 사항은 Setter는 외부에서 필드를 수정할수있도록 하므로 경우에 따라서 보안에 취약

명시적으로 AccessLevel을 명시해주지 않으면, 접근 제한자는 public이 됩니다.

@ToString

  • toString() 메서드를 작성해줌, exclude 속성사용시, 특정 필드를 toString()결과에서 제외시킬수있다.
1
2
3
4
5
6
7
@ToString(exclude = "password")
public class User {
private Long id;
private String username;
private String password;
private int[] scores;
}

@Builder

  • @Builder를 사용하면 객체 생성이 명확해진다. 가급적 클래스 보다는 직접 만든 생성자 혹은 static 객체 생성 메소드에 붙이는 것을 권장한다.
  • @Builder를 붙이면 파라미터 순서가 아닌 이름으로 값을 설정하기 때문에 리팩토링에 유연하게 대응할 수 있고, 필드 순서를 변경해도 문제가 없다.
  • 되도록 직접 만든 생성자에 붙이자

결론

잘알고 사용하자

실무 프로젝트에서는 가급적 @Getter, @Setter, @ToString 만 사용하고 그 외의 것들 사용은 자제하거나 매뉴얼을 잘 읽어보고서 보수적으로 사용한다.

@EqualsAndHashCode는 Immutable 필드만 명시적으로 지정하면서 자제해서 사용하거나 가급적 IDE 코드 제너레이션등을 통해 코드를 직접 만든다.

CATALOG
  1. 1. Lombok 에너테이션 각 장단점
  2. 2. 왜?
  3. 3. @Data 위험성
  • 4. @Getter @Setter 주의해야한다. 이유는?
  • 5. 그 밖에 롬복 주로 사용하는것
    1. 5.1. @Getter
    2. 5.2. @Setter
    3. 5.3. @ToString
    4. 5.4. @Builder
  • 6. 결론