반복적인 getter, setter 혹은 여러 개의 생성자를 어노테이션만으로 생성해주는 소중한 라이브러리가 바로 Lombok입니다.
평소 제공되는 기능을 단순히 기억하고 사용하다가 최근에 큰 혼란을 경험하여 제공되는 기능과 유의점에 대해 학습하고 정리한
내용입니다.
@Getter, @Setter
private로 선언된 필드에 접근하기 위해 사용하는 getter, setter는 특정 조건을 넣는 상황이 아니라면
단순 반복적인 코드가 작성돼야 하지만 @Getter, @Setter 어노테이션으로 대신할 수 있습니다.
@Getter @Setter
public class Movie {
private Long id;
private int attendance;
private String movieName; //@Getter @Setter -> 해당 필드에 대해 생성
}
클래스에 선언하면 클래스의 모든 필드에 대해 생성하고
필드에 선언하면 해당필드에 대한 setter, getter만 생성한다.
Getter, Setter 사용에 대한 현재의 생각
Lombok과는 무관한 내용이지만 자기반성의 의미로 작성해보았습니다.
처음 스프링에 대해 학습할때는 객체의 캡슐화, JSP페이지 에서의 활용 표준을 준수하기 위해 사용하는 일종의 필수요건 정도로 생각하고 사용했었고 일단 편했다. 손쉽게 데이터를 가져오고, 변경할 수 있기 때문인데 이게 문제점이었다.
Getter는 데이터변경이 없으니까 그렇다고 하지만 무분별한 Setter사용으로 데이터가 이곳저곳에서 변경되면 유지보수에
치명적이다.
- 필요하면 사용해야 하지만 최대한 Setter사용을 지양한다.
- 생성자를 사용한 데이터 주입을 우선으로 하고 setter사용 시 의미 있는 이름을 부여하여 사용한다. ex) xxxChange()
생성자 생성
@NoArgsConstructor
매개변수를 가지지 않는 기본생성자(default constructor)를 생성한다.
@NoArgsConstructor
public class Movie {
private Long id;
private String director;
private String movieName;
private int attendance;
//어노테이션으로 인해 생성되는 생성자는 아래와 같다.
public Movie() {}
}
@RequiredArgsConstructor
final 키워드가 붙은 필드에 대한 생성자를 생성한다.
@RequiredArgsConstructor
public class Movie {
private Long id;
private final String director;
private final String movieName;
private int attendance;
// 어노테이션으로 인해 생성되는 생성자는 다음과 같다.
public Movie(String director, String movieName) {
this.director = director;
this.movieName = movieName;
}
}
@AllArgsConstructor
클래스의 모든 필드에 대한 생성자를 생성한다.
@AllArgsConstructor
public class Movie {
private Long id;
private String director;
private String movieName;
private int attendance;
// 어노테이션으로 인해 생성되는 생성자는 다음과 같다.
public Movie(Long id, String director, String movieName, int attendance) {
this.id = id;
this.director = director;
this.movieName = movieName;
this.attendance = attendance;
}
}
@AllArgsConstructor, @RequiredArgsConstructor의 주의점!
만약 여러 로직에서 생성자가 사용된 상황에서 같은 타입의 dirctor, movieName의 순서가 변경된다면 어떨까
타입이 달랐다면 컴파일 오류가 났겠지만 타입이 같기 때문에 IDE도 모르고 입력값이 서로 바뀌어 들어가는 문제가 발생한다.
이러한 문제를 해결하는 여러 방법 중 필드명으로 데이터를 설정, 생성하여 변경에 영향이 없는 방식이 빌더 패턴이고
Lombok은 아래의 어노테이션으로 패턴 생성을 자동화해줍니다.
@Builder
빌더 패턴을 사용하고자 할 때 @Builder를 사용하면 빌더를 대신 생성한다.
결국 생성자가 필요하기 때문에 기본적으로 @AllArgsConstructor를 내포하여 private 한 생성자를 만들어 외부에서 호출하진 못하지만 내부에서 사용할 수 도 있기 때문에 직접 생성한 생성자 혹은 static 생성 메서드에서 사용하면 위험이 덜하다.
생성자 별로 멤버 변수를 정의하고 생성자마다 붙이면 해당 생성자들을 사용하는 Builder를 생성하므로 의미 있는 객체를 생성할 수 있습니다.
@Getter
public class Movie {
private String director;
private String movieName;
private int attendance;
@Builder
public Movie(String director, String movieName) {
this.director = director;
this.movieName = movieName;
this.attendance = 0;
}
@Builder
public Movie(String director, String movieName, int attendance) {
this.director = director;
this.movieName = movieName;
this.attendance = attendance;
}
}
@Data
@RequiredArgsConstructor + @Getter + @Setter + @ToString + @EqualsAndHashCode를 모두 생성한다.
- ToString의 경우 JPA를 사용한다면 연관관계에 따라 호출 시 무한루프가 돌 수 있기 때문에 잘 판단하여 사용하자!
- @EqualsAndHashCode는 equals, hashcode 메서드를 생성하는데 해당 메서드의 경우 IDE가 제공하는 방식으로 직접 생성 후 사용이 필드 간 정확한 기능 구현이 가능하다.
결론적으로 사용을 자제하는 것이 좋다고 생각된다. @RequiredArgsConstructor의 같은 경우도
위에서 작성한 문제가 있기 때문에 정말 특별하게 사용해야 하는 경우가 아닐 경우에는 되도록 이면 사용을 자제하자.
참고
- https://kwonnam.pe.kr/wiki/java/lombok
- https://projectlombok.org/features
'언어 > JAVA' 카테고리의 다른 글
[JAVA] emptyMap 사용 시 UnsupportedOperationException (0) | 2023.03.22 |
---|---|
[JAVA] 상수의 여러 관리법 (0) | 2022.12.11 |
[JAVA] Optional 사용법 - 어떻게 사용해야할까 (2/2) (0) | 2022.07.28 |
[JAVA] Optional의 사용법 (1/2) (0) | 2022.07.25 |
[JAVA] Builder 패턴 (0) | 2022.06.18 |
댓글