Lombok이란?
프로젝트를 하면서 알게 되었던
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
를 사용하다보니 컬럼별로 어노테이션이 붙어서 길어보이지만
아무래도 Getter
와 Setter
같은 것이 없다보니
훨씬 간결해진다는 것을 알 수 있습니다.
처음 예시에서도 @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;
...
이렇게 된다면 challengeName
과 challengeDesc
에 대한 인자를 받는 생성자가
자동으로 완성됩니다.
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
속성을 통해 equals
와 hashCode
메소드 자동 생성 시
부모 클래스의 필드까지 감안할지 안 할지에 대해서 설정할 수 있습니다.
즉, callSuper = true
는 부모 클래스 필드 값들도 동일한지 체크하며,
callSuper = false
는 자신 클래스의 필드 값들만 고려합니다.
[ @Data ]
@Data
어노테이션을 활용하면
@ToString
, @EqualsAndHashCode
, @Getter
, @Setter
,
@RequiredArgsConstructor
를 자동완성 시켜줍니다.
그러나 실무에서는 이것을 지양한다고 합니다.
아무래도 Setter는 객체를 언제든지 변경할 수 있는 상태가 되어서
객체의 안전성이 보장받기 힘듭니다.
때문에 @Data의 활용을 지양한다고 합니다.