Lombok
은 Java 라이브러리로 개발을 하면서 기계적으로 작성하게 되는 Getter, Setter, ToString 등의 메서드 작성 코드를 어노테이션으로 대신해 코드 다이어트를 도와준다.
개발자는 Lombok
을 사용하여 아래의 장점을 얻을 수 있다.
💡 어노테이션 기반의 코드 자동 생성을 통한 생산성 증가
💡 코드 다이어트를 통한 코드 가독성 및 유지보수성 증가
🔔 과거에는 Lombok을 사용하려면 모든 팀원이 Lombok을 설치해야하는 번거로움이 있었지만, 현재는 IntelliJ의 기본 플러그인으로 설정되어 있기 때문에 바로 사용이 가능하다.
기본 Java 코드와 Lombok을 사용한 코드의 차이를 직접 확인해보자.
public class Car {
private String seqNumber;
private String id;
private String name;
private String color;
private Integer serialNumber;
private boolean isOnSale;
public Car() {
}
public Car(String seqNumber, String id, String name, String color, Integer serialNumber, boolean isOnSale) {
this.seqNumber = seqNumber;
this.id = id;
this.name = name;
this.color = color;
this.serialNumber = serialNumber;
this.isOnSale = isOnSale;
}
public String getSeqNumber() {
return seqNumber;
}
public void setSeqNumber(String seqNumber) {
this.seqNumber = seqNumber;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Integer getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(Integer serialNumber) {
this.serialNumber = serialNumber;
}
public boolean isOnSale() {
return isOnSale;
}
public void setOnSale(boolean onSale) {
isOnSale = onSale;
}
@Override
public String toString() {
return "Car{" +
"seqNumber='" + seqNumber + '\'' +
", id='" + id + '\'' +
", name='" + name + '\'' +
", color='" + color + '\'' +
", serialNumber=" + serialNumber +
", isOnSale=" + isOnSale +
'}';
}
}
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Car {
private String seqNumber;
private String id;
private String name;
private String color;
private Integer serialNumber;
private boolean isOnSale;
}
위 클래스에서 작성된 지저분한 코드들을 Lombok 어노테이션으로 활용함으로써 개발자 업무량을 줄이고 코드 다이어트를 통한 가독성이 올라간 것을 확인할 수 있다.
실질적으로 가장 많이 활용되는 어노테이션이다.
@Getter
→** Getter 메서드를 생성해준다.
@Setter
→** Setter 메서드를 생성해준다.
어노테이션을 클래스 위에 작성하면 해당 클래스의 모든 변수에 적용이 가능하고, 변수 이름 위에
작성하면 해당 변수에만 적용이 된다.
@Getter
, @Setter
어노테이션을 활용한 예제는 아래와 같다.
@Getter
public class Car {
@Setter
private String seqNumber;
private String id;
private String name;
private String color;
private Integer serialNumber;
private boolean isOnSale;
}
/** 컴파일 완료 소스 **/
public class Car {
private String seqNumber;
private String id;
private String name;
private String color;
private Integer serialNumber;
private boolean isOnSale;
public Car() {
}
public String getSeqNumber() {
return this.seqNumber;
}
public String getId() {
return this.id;
}
public String getName() {
return this.name;
}
public String getColor() {
return this.color;
}
public Integer getSerialNumber() {
return this.serialNumber;
}
public boolean isOnSale() {
return this.isOnSale;
}
public void setSeqNumber(String seqNumber) {
this.seqNumber = seqNumber;
}
}
/**
@Getter 어노테이션을 클래스 상단에 적용함으로써 모든 변수에 대한 Getter 메서드가 작성됨.
@Setter 어노테이션을 seqNumber 변수에만 적용했기 때문에 해당 변수의 Setter 메서드가 작성됨
**/
@ToString
어노테이션은 해당 클래스의 ToString 메서드를 생성해준다.
출력을 원치 않는 변수 위에 @ToString.Exclude
어노테이션을 적용하면 출력을 제외한다.
부모 클래스에 대해서도 toString을 적용하고자 한다면 @ToString(callSuper = true)
어노테이션을 적용하면 된다.
@ToString
어노테이션을 활용한 예제는 아래와 같다.
@ToString
public class Car {
private String seqNumber;
private String id;
private String name;
private String color;
private Integer serialNumber;
@ToString.Exclude
private boolean isOnSale;
}
/** 컴파일 완료 소스 **/
public class Car {
private String seqNumber;
private String id;
private String name;
private String color;
private Integer serialNumber;
private boolean isOnSale;
@Override
public String toString() {
return "Car{" +
"seqNumber='" + seqNumber + '\'' +
", id='" + id + '\'' +
", name='" + name + '\'' +
", color='" + color + '\'' +
", serialNumber=" + serialNumber
'}';
}
}
@AllArgsConstructor
→ 모든 변수를 사용하는 생성자를 생성해준다.
@NoArgsContructor
→ 변수를 사용하지 않는 기본 생성자를 생성해준다.
@AllArgsConstructor
어노테이션을 활용한 예제는 아래와 같다.
@AllArgsConstructor
@NoArgsConstructor
public class Car {
private String seqNumber;
private String id;
private String name;
private String color;
private Integer serialNumber;
private boolean isOnSale;
}
/** 컴파일 완료 소스 **/
public class Car {
private String seqNumber;
private String id;
private String name;
private String color;
private Integer serialNumber;
private boolean isOnSale;
public Car () {}
public Car(String seqNumber, String id, String name, String color, Integer serialNumber, boolean isOnSale) {
this.seqNumber = seqNumber;
this.id = id;
this.name = name;
this.color = color;
this.serialNumber = serialNumber;
this.isOnSale = isOnSale;
}
}
/**
@NoArgsConstructor 적용함으로써 기본 생성자가 작성됨
@AllArgsConstructor 적용함으로써 모든 변수에 대한 생성자가 작성됨
**/
@RequiredArgsConstructor
어노테이션은 특정 변수에 대한 생성자를 생성해준다.
주로 의존성 주입, 즉 DI 의 편의를 위해 사용되곤 한다.
해당 어노테이션으로 생성될 생성자의 인자를 추가하는 조건은 아래와 같다.
@RequiredArgsConstructor
어노테이션을 활용한 예제는 아래와 같다.
@RequiredArgsConstructor
public class Car {
private final String seqNumber;
private final String id;
private String name;
private String color;
@NonNull
private Integer serialNumber;
private boolean isOnSale;
}
/** 컴파일 완료 소스 **/
public class Car {
private final String seqNumber;
private final String id;
private String name;
private String color;
@NonNull
private Integer serialNumber;
private boolean isOnSale;
public Car(String seqNumber, String id, @NonNull Integer serialNumber) {
if (serialNumber == null) {
throw new NullPointerException("serialNumber is marked non-null but is null");
} else {
this.seqNumber = seqNumber;
this.id = id;
this.serialNumber = serialNumber;
}
}
}
/**
final로 선언하거나 @NonNull 어노테이션이 적용된 변수들만을 인자로 받는 생성자가 작성됨.
**/
@NonNull
어노테이션은 생성자에서 변수에 대한 NPE(Null Pointer Exception)를 검증해준다.
@NonNull
어노테이션을 활용한 예제는 아래와 같다.
@RequiredArgsConstructor
public class Car {
private final String seqNumber;
@NonNull
private final String id;
private String name;
private String color;
@NonNull
private final Integer serialNumber;
private boolean isOnSale;
}
/** 컴파일 완료 소스 **/
public class Car {
private final String seqNumber;
@NonNull
private final String id;
private String name;
private String color;
@NonNull
private final Integer serialNumber;
private boolean isOnSale;
public Car(String seqNumber, @NonNull String id, @NonNull Integer serialNumber) {
if (id == null) {
throw new NullPointerException("id is marked non-null but is null");
} else if (serialNumber == null) {
throw new NullPointerException("serialNumber is marked non-null but is null");
} else {
this.seqNumber = seqNumber;
this.id = id;
this.serialNumber = serialNumber;
}
}
}
/**
생성자로 Object를 생성할 때, @NonNull이 적용된 변수에 대한 Null 체크를 진행한다.
**/
@Data
어노테이션은 @ToString
, @EqualsAndHashCode
, @Getter
, @Setter
, @RequiredArgsConstructor
를 자동완성 시켜준다.
실무에서는 너무 무겁고 객체의 안정성을 지키기 때문에 @Data
의 활용을 지양한다.
@Builder 어노테이션은 해당 클래스의 생성자에 Builder 패턴을 적용시켜준다.
모든 변수에 적용시키려면 클래스 상단에 @Builder 를 적용하고, 특정 변수에 대한 Build를 원한다면
생성자를 작성하고 해당 생성자 위에 @Builder 를 적용하면 된다.
각 인자가 어떤 의미인지 파악하기 쉽다.
setter 메서드가 없으므로 변경 불가 객체를 만들 수 있다.
한번에 객체를 생성함으로써 제공 상태에 대한 일관성을 얻는다.
객체 생성 최종 단계인 build() 내부에서 값을 검증한다던지의 추가적인 처리가 가능하다.
아래와 같은 스타일로 객체를 생성하고 있다면, 빌더 패턴을 사용했다고 볼 수 있다.
Car car = Car.builder()
.seqNumber(seqNumber)
.id(id)
.serialNumber(serialNumber)
.build();
@Builder 어노테이션을 활용한 예제는 아래와 같다.
public class Car {
private String seqNumber;
private String id;
private String name;
private String color;
private Integer serialNumber;
private boolean isOnSale;
@Builder
public Car(String seqNumber, String id, Integer serialNumber) {
this.seqNumber = seqNumber;
this.id = id;
this.serialNumber = serialNumber;
}
}
/** 사용 예제 **/
public class CarFactory {
public Car initCar(String seqNumber, String id, Integer serialNumber) {
Car car = Car.builder()
.seqNumber(seqNumber)
.id(id)
.serialNumber(serialNumber)
.build();
return car;
}
}
/**
@Builder 어노테이션을 통해 해당 Object에 대해 Builder 패턴이 적용된 것을 확인할 수 있다.
step-by-step으로 필요한 인자를 선택해서 add하여 한번에 객체를 생성할 수 있다.
**/
Lombok은 여러가지의 Log 어노테이션을 제공해준다.
로그 어노테이션을 적용하면 해당 클래스에 대한 로그 클래스를 자동으로 생성한다.
@Log4j
어노테이션을 활용한 예제는 아래와 같다.
@Log4j
public class Car {
private String seqNumber;
private String id;
private String name;
private String color;
private Integer serialNumber;
private boolean isOnSale;
}
/** 컴파일 완료 소스 **/
public class Car {
private static final Logger log = Logger.getLogger(Car.class);
private String seqNumber;
private String id;
private String name;
private String color;
private Integer serialNumber;
private boolean isOnSale;
}
/**
적용시킨 Log 어노테이션에 맞는 Log 클래스를 자동으로 생성해준다.
**/
Lombok을 적재적소에 활용하여 불필요한 코드를 줄이고 생산성을 높이자.