본문 바로가기
Java

Java - Lombok이란?

by 오늘부터개발시작 2022. 9. 15.

 

 

 

Boilerplate 코드들

Java를 사용하기 위해서는 엄청나게 많은 Boilerplate 코드들을 작성하게 된다. 가장 기본적인 변수에 접근하기 위해서도 getter를 선언해야 한다. 실제 코드는 몇 줄 안되는 것 같은데 이미 스크롤은 끝이 없이 늘어나있다. 필요한 class를 찾기 위해서 이리저리 스크롤을 엄청나게 움직여야하는데 불편함이 이만 저만이 아니다.

 

public static class Create {
        private String username;
        private String nickname;
        private User.SnsType snsType;
        private String description;
        private String sellerEnabledYN;
        private Integer workHourFromDt;
        private Integer workHourToDt;
        private String specialty;
        private Integer peoplePrice;
        private Integer backgroundPrice;
        private Integer officialPrice;
    }

 

위와 같이 멤버 변수가 10개가 넘는 클래스가 있을 때 Getter, Setter, 생성자까지 선언하면 코드가 금새 50줄이 넘어갈 것이다. 다행히도 지금은 IDE에서 Getter, Setter, 생성자를 자동으로 생성해주는 기능을 제공해줘서 일일히 적지 않아도 되지만 코드를 읽을 때 불편한 것은 여전하다. 

 

Lombok

 

이럴 때 사용할 수 있는 Java 라이브러리가 있으니 바로 Lombok이다. Lombok은 어노테이션으로 엄청나게 많은 boilerplate 코드들을 대체할 수 있다. 위에서 본 멤버 변수가 많은 클래스도 어노테이션을 사용하면 아주 간단하게 Boilerplate 코드를 생성할 수 있다. 지금부터 Lombok에서 제공하는 주로 쓰이는 어노테이션들에 대해서 하나씩 알아보도록하겠다.

@Getter와 @Setter

@Getter
@Setter
public static class Create {
    private String username;
    private String nickname;
    private User.SnsType snsType;
    ..
}

 

위와 같이 클래스의 상단에 @Getter, @Setter라는 Lombok에서 제공하는 어노테이션을 선언하면 컴파일 할 때 Getter와 Setter를 자동으로 생성해서 class 파일에 추가해준다. 아래 사진은 실제로 컴파일 된 class 파일인데 Getter와 Setter가 자동으로 생성된 것을 확인할 수 있다. 

 

 

@RequiredArgsConstructor 

@RequiredArgsConstructor는 의존성 주입을 하기 위한 생성자를 자동으로 생성해주는 역할을 한다. Lombok이 생성자에 포함하는 조건은 final로 선언된 멤버 변수이다. 아래 코드에서는 final로 선언된 UserRepository를 자동으로 생성자에 포함해서 생성해준다. 주의할 점은 final로 선언된 모든 멤버 변수를 생성자에 넣기 때문에 원치 않는 필드도 같이 포함될 수 있다는 것이다.

 

@RequiredArgsConstructor
public class AuthService {
	private final UserRepository userRepository;
	...
}

@AlllArgsConstructor 

@AlllArgsConstructor는 이름 대로 모든 멤버 변수를 포함하는 생성자를 자동으로 생성해주는 어노테이션이다. 생성자의 입력 순서는 필드가 선언된 순서대로 생성된다. 이 때문에 멤버 변수의 선언 순서가 바뀌면 심각한 오류가 생길 수 있으니 주의해야 한다.

@NoArgsConstructor 

@NoArgsConstructor는 이름 그대로 빈 생성자를 만들어주는 어노테이션이다. 빈 생성자는 생성자를 따로 선언하지 않으면 디폴트로 존재하는데 이 어노테이션은 추가적인 생성자를 선언했을 때 빈 생성자를 손쉽게 생성하기 위해 사용한다.

@ToString

@ToString은 toString 메소드를 커스터마이징해주는 어노테이션이다. 보통 toString은 객체를 프린트하기 위해 사용하는데 커스터마이징하기 전에는 단순히 클래스 이름을 반환한다. 아래처럼 @ToString 어노테이션을 쓰면 객체의 필드와 필드 값을 반환해준다.

@ToString
public static class Test {
    public String a = "1";
    public String b = "2";
}

@EqualsAndHashCode

@EqualsAndHashCode는 자동으로 hashCode()와 equals() 메소드를 생성해준다. 이 두개의 메소드는 객체들을 구분짓기 위해 사용하는 메소드이다. equals()는 객체를 어떻게 같다고 판단할 것인지 정의하고 hashCode()는 객체마다 가지고 있는 해시코드를 어떻게 생성할 것인지 정의하는 것이다. 해시코드가 사용되는 예시는 Map에서 key 값으로 사용되는 것이 있다.

 

아래처럼 어노테이션을 사용해서 a 필드를 exclude하면 equals()에서는 b의 값만 비교하고 해시코드도 b만 사용해서 생성하게 된다.

@EqualsAndHashCode(exclude = {"a"})
public static class Test {
    public String a = "1";
    public String b = "2";
}

 

 

@Data

@Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor를 하나의 어노테이션으로 선언하고 싶을 때 사용하면 된다. 

@Builder

@Builder는 말 그대로 빌더를 자동으로 생성해주는 어노테이션이다. class에 어노테이션을 선언해주면 모든 필드에 대한 빌더를 생성해준다. 특정 필드만 빌더로 설정해주고 싶다면 아래처럼 원하는 필드만 존재하는 생성자를 만들고 어노테이션을 선언해주면 된다. 아래 예시에서는 a만 빌더로 설정해줄 수 있다.

 

public class Main {
    public static void main(String[] args) {
        System.out.println(Test.builder().a("a"));
    }

    public static class Test {
        public String a = "1";
        public String b = "2";

        @Builder
        public Test(String a) {
            this.a = a;
        }
    }
}

 

위의 예시는 a도 필수값이 아니기 때문에 꼭 설정해주지 않아도 되는데 필수값을 설정해야할 필요가 있을 수 있다. 이럴 경우에는 아래와 같은 방법으로 처리도 가능하다. lombok으로 생성할 빌더 이름을 testBuilder로 정해주고 builder()라는 static 메소드를 만들어서 필수값을 받고 testBuilder를 리턴해주는 방법이다. 

 

public class Main {
    public static void main(String[] args) {
        System.out.println(Test.builder("a").b("b"));
    }

    @Builder()
    public static class Test {
        public String a = "1";
        public String b = "2";

        public static TestBuilder builder(String a) {
            if(a == null) {
                throw new IllegalArgumentException("필수 파라미터 누락");
            }
            return new TestBuilder().a(a);
        }
    }
}

 

다음 시간에는 Lombok을 사용할 때 주의해야할 점에 대해서 알아보도록하겠다.