Lombok이란?

2021-02-13

프로젝트를 하면서 알게 되었던

Lombok에 대해 정리를 한 내용 입니다.


Lombok이란?

Lombok(롬복)Java 라이브러리 중 하나입니다.

자바에서 Model을 만들고자 할 때 반복되는 작업을 많이 줄여줍니다.

백문이 불여일견.

예전에 작성했던 예시를 통해서 살펴봅니다.

 public class Movie {
    private String title;
    private String director;
    private int grade;
    private String genre;
    private String summary;
    public Movie() {
    }
    public Movie(String title, String director, int grade, String genre) {
        this.title = title;
        this.director = director;
        this.grade = grade;
        this.genre = genre;
    }
    public Movie(String title, String director, int grade, String genre, String summary) {
        this.title = title;
        this.director = director;
        this.grade = grade;
        this.genre = genre;
        this.summary = summary;
    }
    
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getDirector() {
        return director;
    }
    public void setDirector(String director) {
        this.director = director;
    }
    public int getGrade() {
        return grade;
    }
    public void setGrade(int grade) {
        this.grade = grade;
    }
    public String getGenre() {
        return genre;
    }
    public void setGenre(String genre) {
        this.genre = genre;
    }
    public String getSummary() {
        return summary;
    }
    public void setSummary(String summary) {
        this.summary = summary;
    }
    @Override
    public String toString() {
        return "제목 : "+title+"\n"+"감독 : "+director+"\n"+"평가 : "+grade+"\n"+"장르 : "+genre+"\n"+"평가 : "+summary+"\n";
    }
}

이렇게 Model을 만들다 보면

Getter, Setter, toString 등 을 만들면 코드가 길어집니다.

물론 Generate를 사용하면 그나마 편하게 자동완성이 되기는 하지만

코드가 길다보니 한번에 보기에도 번거롭기도 합니다.

그 과정에서 Lombok을 사용하니 훨씬 간결해진 코드를 확인할 수 있습니다.

package backend.domain.review;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;

@Entity
@Getter @Setter
@NoArgsConstructor
public class ReviewImage {
    @Id
    @GeneratedValue
    private Long reviewImageId;

    @ManyToOne
    @JoinColumn(name = "REVIEW_ID")
    private Review reviewId;

    @Column(columnDefinition = "TEXT")
    private String reviewImage;

    public ReviewImage(Review review, String url) {
        this.reviewId = review;
        this.reviewImage = url;
    }
}

이건 현재 진행중인 프로젝트에서 예시를 가져왔습니다.

JPA를 사용하다보니 컬럼별로 어노테이션이 붙어서 길어보이지만

아무래도 GetterSetter같은 것이 없다보니

훨씬 간결해진다는 것을 알 수 있습니다.

처음 예시에서도 @Getter@Setter, @ToString 어노테이션 사용한다면

훨씬 간결해질 수 있습니다.

어노테이션 기반으로 하기 때문에 추가적으로 변수를 생성하고 싶다면

변수만 추가해줘도 자동으로 만들어줘서 생산성이 높아집니다.

의존성 주입

사용하기 위해서는 의존성을 주입해줘야 합니다.

Maven과 Gradle 두 가지에 대해서 정리해봤습니다.

버젼은 동일한 버젼, 최신중에서 다운로드 된 횟수가 가장 많은 것을 기준으로 헀습니다.

Maven을 사용하는 경우

  • pom.xml에 Dependency 추가
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
</dependency>

Gradle을 사용하는 경우

  • build.gradle에 Dependency 추가
// https://mvnrepository.com/artifact/org.projectlombok/lombok
providedCompile group: 'org.projectlombok', name: 'lombok', version: '1.18.12'

사용 예제.

[ @Getter @Setter ]

@Getter@Setter를 클래스 이름 위에 적용시키면

모든 변수들에 적용이 가능하고, 변수 이름 위에 적용시키면 해당 변수들만 적용 가능합니다.

예를 들기 위해 Project Lombok이라는 공식사이트에서 예시를 가져왔습니다.

첫 번째 예시는 클래스 위에 적용시킴으로써 모든 변수들에 적용하는 예시입니다.

import lombok.Getter;
import lombok.Setter;

@Getter @Setter 
public class GetterSetterExample {
  private int age = 10;
  private String name;
}

특정 변수에 대해서만 적용하고 싶다면 아래와 같이 적용하면 됩니다.


import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;

public class GetterSetterExample {
  @Getter @Setter private int age = 10;
  
  @Setter(AccessLevel.PROTECTED) private String name;
}

[ @NoArgsConstructor, @AllArgsConstructor ]

@NoArgsConstructor는 파라미터가 없는 기본 생성자를 자동완성 시켜줍니다.

@AllArgsConstructor는 모든 파라미터를 사용하는 생성자를 자동완성 시켜줍니다.

이번 예제는 공식사이트 내용이 보기 복잡해보여서

진행 중인 프로젝트에서 일부 수정해서 예를 만들었습니다.

@NoArgsConstructor
@AllArgsConstructor
public class ChallengeDto {
    private Long challengeID;
    private String challengeName;
    private String challengeDesc;
    private UserDto challengeOwner;
    private String categoryName;
    private HashtagDto hashtags;
    ...

이렇게 한다면 아래와 같은 생성자가 추가로 만들어집니다.

    public ChallengeDto() {

    }
    public ChallengeDto(Long challengeID, String challengeName, String challengeDesc...){
    this.challengeID = challengeID;
    this.challengeName = challengeName;
    this.challengeDesc = challengeDesc;
    ...(생략)
}

[ @RequiredArgsConstructor ]

@RequiredArgsConstructor

특정 변수만을 활용하는 생성자를 자동완성 시켜주는 어노테이션입니다.

생성자의 인자로 추가할 변수에 @NonNull 어노테이션을 붙여서

해당 변수를 생성자의 인자로 추가할 수 있습니다.

아니면 해당 변수를 final로 선언해도 의존성을 주입받을 수 있습니다.

위의 Dto를 예시로 했을 때

@RequiredArgsConstructor
public class ChallengeDto {
    private Long challengeID;
    @NonNull
    private String challengeName;
    @NonNull
    private String challengeDesc;
    private UserDto challengeOwner;
    private String categoryName;
    private HashtagDto hashtags;
    ...

이렇게 된다면 challengeNamechallengeDesc에 대한 인자를 받는 생성자가

자동으로 완성됩니다.

    public ChallengeDto(String challengeName, String challengeDesc){
    this.challengeName = challengeName;
    this.challengeDesc = challengeDesc;
}

[ @ToString ]

@ToString 어노테이션을 활용하면

클래스의 변수들을 기반으로 ToString 메소드를 자동으로 완성시켜 줍니다.

출력을 원하지 않는 변수에 exclude를 작성해 출력을 제외할 수 있습니다.


import lombok.ToString;

@ToString(exclude = "password")
public class User {
  private Long id;
  private String username;
  private String password;
  private int[] scores;
}

[ @EqualsAndHashCode ]

@EqualsAndHashCode 어노테이션을 활용하면

클래스에 대한 equals 함수와 hashCode 함수를 자동으로 생성해줍니다.

@EqualsAndHashCode(callSuper = true)
public class User extends Domain {
  private String username;
  private String password;
}

callSuper 속성을 통해 equalshashCode 메소드 자동 생성 시

부모 클래스의 필드까지 감안할지 안 할지에 대해서 설정할 수 있습니다.

즉, callSuper = true는 부모 클래스 필드 값들도 동일한지 체크하며,

callSuper = false는 자신 클래스의 필드 값들만 고려합니다.

[ @Data ]

@Data 어노테이션을 활용하면

@ToString, @EqualsAndHashCode, @Getter, @Setter,

@RequiredArgsConstructor를 자동완성 시켜줍니다.

그러나 실무에서는 이것을 지양한다고 합니다.

아무래도 Setter는 객체를 언제든지 변경할 수 있는 상태가 되어서

객체의 안전성이 보장받기 힘듭니다.

때문에 @Data의 활용을 지양한다고 합니다.