Lombok(롬복)은 여러 어노테이션을 제공하는 라이브러리입니다 Java로 개발할 때 반복되는 getter/setter 등의 반복을 줄여주는 코드 다이어트 라이브러리입니다.
이를 기반으로 어노테이션을 사용하면 작성하는 소스 상엔 안보이지만 컴파일러 과정에서 컴파일된 결과물(.class)에는 getter,setter 등 생성됩니다.
lombok사용 전과 후의 소스코드입니다.
import java.time.LocalDateTime;
import java.util.Objects;
public class ProductModel {
private String productNo;
private String productName;
private String productType;
private String deliveryType;
private int stock;
private LocalDateTime regDttm;
private LocalDateTime modiDttm;
public ProductModel(String productNo, String productName, String productType, String deliveryType, int stock, LocalDateTime regDttm, LocalDateTime modiDttm) {
this.productNo = productNo;
this.productName = productName;
this.productType = productType;
this.deliveryType = deliveryType;
this.stock = stock;
this.regDttm = regDttm;
this.modiDttm = modiDttm;
}
public String getProductNo() {
return productNo;
}
public void setProductNo(String productNo) {
this.productNo = productNo;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductType() {
return productType;
}
public void setProductType(String productType) {
this.productType = productType;
}
public String getDeliveryType() {
return deliveryType;
}
public void setDeliveryType(String deliveryType) {
this.deliveryType = deliveryType;
}
public int getStock() {
return stock;
}
public void setStock(int stock) {
this.stock = stock;
}
public LocalDateTime getRegDttm() {
return regDttm;
}
public void setRegDttm(LocalDateTime regDttm) {
this.regDttm = regDttm;
}
public LocalDateTime getModiDttm() {
return modiDttm;
}
public void setModiDttm(LocalDateTime modiDttm) {
this.modiDttm = modiDttm;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ProductModel that = (ProductModel) o;
return stock == that.stock &&
Objects.equals(productNo, that.productNo) &&
Objects.equals(productName, that.productName) &&
Objects.equals(productType, that.productType) &&
Objects.equals(deliveryType, that.deliveryType) &&
Objects.equals(regDttm, that.regDttm) &&
Objects.equals(modiDttm, that.modiDttm);
}
@Override
public int hashCode() {
return Objects.hash(productNo, productName, productType, deliveryType, stock, regDttm, modiDttm);
}
@Override
public String toString() {
return "ProductModel{" +
"productNo='" + productNo + '\'' +
", productName='" + productName + '\'' +
", productType='" + productType + '\'' +
", deliveryType='" + deliveryType + '\'' +
", stock=" + stock +
", regDttm=" + regDttm +
", modiDttm=" + modiDttm +
'}';
}
}
import lombok.*;
import java.time.LocalDateTime;
@Getter
@Setter
@ToString
@EqualsAndHashCode
@RequiredArgsConstructor
public class ProductModel {
private String productNo;
private String productName;
private String productType;
private String deliveryType;
private int stock;
private LocalDateTime regDttm;
private LocalDateTime modiDttm;
}
확연히 코드가 줄어든 것을 볼 수 있습니다. annotation 5개가 부담스럽다면 @Data로 한번에 처리할 수 있습니다. 자세한 건 아래에서 더 다룰 예정입니다.
장점
주의사항
1.lombok 다운&설치 -> 2.dependency추가 -> 3.lombok사용
#eclipse나 sts를 사용하는 경우
#intellij를 사용 하는 경우
Maven 사용 - pom.xml에 추가
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
Gradle 사용 - build.gradle에 추가
// https://mvnrepository.com/artifact/org.projectlombok/lombok
provided group: 'org.projectlombok', name: 'lombok', version: '1.18.4'
intellij의 경우 아래와 같이 추가 설정을 해줘야합니다.
[ @Getter @Setter ]
Lombok에서 가장 자주 활용하는 어노테이션입니다. @Getter와 @Setter를 클래스 이름 위에 적용시키면 모든 변수들에 적용이 가능하고, 변수 이름 위에 적용시키면 해당 변수들만 적용 가능합니다.
@Getter와 @Setter를 활용한 예제는 아래와 같습니다.
@Getter
public class ProductModel {
@Setter
private String productNo;
private String productName;
private String productType;
private String deliveryType;
private int stock;
private LocalDateTime regDttm;
private LocalDateTime modiDttm;
}
[ @AllArgsConstructor ]
@AllArgsConstructor는 모든 변수를 사용하는 생성자를 자동완성 시켜주는 어노테이션입니다.
@AllArgsConstructor를 활용한 예제는 아래와 같습니다.
@AllArgsConstructor
public class ProductModel {
private String productNo;
private String productName;
private String productType;
private String deliveryType;
private int stock;
private LocalDateTime regDttm;
private LocalDateTime modiDttm;
/* @AllArgsConstructor를 사용함으로써 아래 소스가 자동 생성됨
public ProductModel(String productNo, String productName, String productType, String deliveryType, int stock, LocalDateTime regDttm, LocalDateTime modiDttm) {
this.productNo = productNo;
this.productName = productName;
this.productType = productType;
this.deliveryType = deliveryType;
this.stock = stock;
this.regDttm = regDttm;
this.modiDttm = modiDttm;
}
*/
}
[ @NoArgsConstructor ]
@NoArgsConstructor는 어떠한 변수도 사용하지 않는 기본 생성자를 자동완성 시켜주는 어노테이션입니다.
@NoArgsConstructor를 활용한 예제는 아래와 같습니다.
@NoArgsConstructor
public class ProductModel {
private String productNo;
private String productName;
private String productType;
private String deliveryType;
private int stock;
private LocalDateTime regDttm;
private LocalDateTime modiDttm;
/* @NoArgsConstructor 사용함으로써 아래 소스가 자동 생성됨
public ProductModel(){
}
*/
}
[ @RequiredArgsConstructor ]
@RequiredArgsConstructor는 특정 변수만을 활용하는 생성자를 자동완성 시켜주는 어노테이션입니다. 생성자의 인자로 추가할 변수에 @NonNull 어노테이션을 붙여서 해당 변수를 생성자의 인자로 추가할 수 있습니다. 아니면 해당 변수를 final로 선언해도 의존성을 주입받을 수 있습니다.
@RequiredArgsConstructor를 활용한 예제는 아래와 같습니다
@RequiredArgsConstructor
public class ProductModel {
@NonNull
private String productNo;
private final String productName;
private String productType;
private String deliveryType;
private int stock;
private LocalDateTime regDttm;
private LocalDateTime modiDttm;
/* @RequiredArgsConstructor 사용함으로써 아래 소스가 자동 생성됨
public ProductModel(String productNo, String productName) {
this.productNo = productNo;
this.productName = productName;
}
}
[ @EqualsAndHashCode ]
@EqualsAndHashCode 어노테이션을 활용하면 클래스에 대한 equals 함수와 hashCode 함수를 자동으로 생성해줍니다. 만약 서로 다른 두 객체에서 특정 변수의 이름이 똑같은 경우 같은 객체로 판단을 하고 싶다면 아래와 같이 해줄 수 있습니다.
@EqualsAndHashCode를 활용한 예제는 아래와 같습니다
@RequiredArgsConstructor
@EqualsAndHashCode(of = {"productNo", "productName"}, callSuper = false)
public class ProductModel {
@NonNull
private String productNo;
@NonNull
private String productName;
private String productType;
private String deliveryType;
private int stock;
private LocalDateTime regDttm;
private LocalDateTime modiDttm;
}
public static void main(String[] args) {
ProductModel product1 = new ProductModel("a111", "바나나");
ProductModel product2 = new ProductModel("a111", "바나나");
ProductModel product3 = new ProductModel("a222", "바나나");
// productNo과 productName이 모두 같기 때문에 같다고 판단
System.out.println(product1.equals(product2)); //true
// productNo은 같지만 productName이 다르기 때문에 다르다고 판단
System.out.println(product1.equals(product3)); //false
}
[ @ToString ]
@ToString 어노테이션을 활용하면 클래스의 변수들을 기반으로 ToString 메소드를 자동으로 완성시켜 줍니다. 출력을 원하지 않는 변수에 @ToString.Exclude 어노테이션을 붙여주면 출력을 제외할 수 있습니다. 또한 상위 클래스에 대해도 toString을 적용시키고자 한다면 상위 클래스에 @ToString(callSuper = true) 를 적용시키면 됩니다.
@ToString를 활용한 예제는 아래와 같습니다
@ToString
@AllArgsConstructor
public class ProductModel {
private String productNo;
private String productName;
@ToString.Exclude
private String productType;
private String deliveryType;
private int stock;
private LocalDateTime regDttm;
private LocalDateTime modiDttm;
}
public static void main(String[] args) {
ProductModel product = new ProductModel("a111", "바나나", "일반상품", "일반택배", 10, LocalDateTime.now(), LocalDateTime.now());
System.out.println(product.toString());
//결과 : ProductModel(productNo=a111, productName=바나나, deliveryType=일반택배, stock=10, regDttm=2021-05-23T17:45:20.270, modiDttm=2021-05-23T17:45:20.271)
//@ToString.Exclude 된건 제외하고 출력
}
[ @Data ]
@Data 어노테이션을 활용하면 @ToString, @EqualsAndHashCode, @Getter, @Setter, @RequiredArgsConstructor를 자동완성 시켜줍니다. 실무에서는 너무 무겁고 객체의 안정성을 지키기 때문에 @Data의 활용을 지양합니다.
[ @Builder ]
@Builder 어노테이션을 활용하면 해당 클래스의 객체의 생성에 Builder패턴을 적용시켜줍니다. 모든 변수들에 대해 build하기를 원한다면 클래스 위에 @Builder를 붙이면 되지만, 특정 변수만을 build하기 원한다면 생성자를 작성하고 그 위에 @Builder 어노테이션을 붙여주면 됩니다.
@Builder를 활용한 예제는 아래와 같습니다
모든 변수에 적용예시
@Builder
public class ProductModel {
private String productNo;
private String productName;
private String productType;
private String deliveryType;
private int stock;
private LocalDateTime regDttm;
private LocalDateTime modiDttm;
}
public static void main(String[] args) {
//ProductModel product = new ProductModel("a111", "바나나", "일반상품", "일반택배", 10, LocalDateTime.now(), LocalDateTime.now());
ProductModel product = ProductModel.builder()
.productNo("a111")
.productName("바나나")
.productType("일반상품")
.deliveryType("일반택배")
.stock(10)
.regDttm(LocalDateTime.now())
.modiDttm(LocalDateTime.now())
.build();
}
특정 변수에만 적용예시
public class ProductModel {
private String productNo;
private String productName;
private String productType;
private String deliveryType;
private int stock;
private LocalDateTime regDttm;
private LocalDateTime modiDttm;
@Builder
public ProductModel(String productNo, String productName){
this.productNo = productNo;
this.productName = productName;
}
}
public static void main(String[] args) {
ProductModel product = ProductModel.builder()
.productNo("a111")
.productName("바나나")
.build();
}
[ @Log 관련 어노테이션 ]
@Log4j2와 같은 어노테이션을 활용하면 해당 클래스의 로그 클래스를 자동 완성 시켜줍니다 @Log 관련 어노테이션을 활용한 예제는 아래와 같습니다.
@RestController
@RequestMapping(value = "/product")
@Log4j2
public class ProductController {
@GetMapping(value = "/productList")
private ResponseEntity log(){
log.error("에러 발생");
return ResponseEntity.ok().build();
}
}
결론
Lombok은 많은 개발자들이 사용하고 시간 낭비를 줄여주는 정말 소중한 라이브러리이지만 그만큼 조심해야 될 부분도 많다. Lombok이 어떻게 이런 고민을 해결하는지 살펴보고 실제로 사용해보면 좋을 것 같다!