본문 바로가기
JAVA

[Java] Lombok 이란?

by wook99 2024. 11. 8.

Spring이나 Spring boot Web 개발을 하다보면, 자주 사용하는 메서드나, 생성자들이 있다.

이는 가독성을 떨어뜨리고, 중복적으로 자주 적다보니 일의 효율이 떨어질 수 있다.

이를 해결해주는 아름다운 라이브러리가 바로 Lombok이다.


Lombok이란?

Lombok은 Java의 주석 기반 라이브러리로, 자주 사용하는 메서드나 생성자 등을 자동으로 생성해 주어 코드의 양을 크게 줄여주는 도구이다. 주로 boilerplate 코드(반복적인 코드)를 제거하는 데 유용하며, 코드의 가독성과 유지 보수성을 높이는 데 도움을 준다.

 

아래는 Lombok에서 제공하는 어노테이션들이다.

어노테이션 설명
@Getter 필드에 대해 Getter 메서드를 자동 생성합니다.
@Setter 필드에 대해 Setter 메서드를 자동 생성합니다.
@ToString toString() 메서드를 자동 생성합니다.
@EqualsAndHashCode equals()와 hashCode() 메서드를 자동 생성합니다.
@NoArgsConstructor 매개변수가 없는 기본 생성자를 자동 생성합니다.
@AllArgsConstructor 모든 필드를 매개변수로 받는 생성자를 자동 생성합니다.
@RequiredArgsConstructor final 또는 @NonNull이 붙은 필드만 매개변수로 받는 생성자를 자동 생성합니다.
@Data @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor를 모두 포함하는 어노테이션입니다.
@Value @Data와 유사하지만 모든 필드를 final로 만들며 불변 객체를 생성합니다.
어노테이션 설명
@Builder 빌더 패턴을 자동 생성하여 객체 생성 시 필드값을 명시적으로 설정할 수 있게 합니다.
@Slf4j org.slf4j.Logger를 이용한 log 객체를 자동 생성하여 로깅 기능을 제공합니다.
@Log4j2 org.apache.logging.log4j.Logger의 log 객체를 자동 생성합니다.
@NonNull 필드나 매개변수의 값이 null이 되지 않도록 체크합니다.
@Synchronized 동기화된 메서드를 생성하여 멀티스레드 환경에서 안전하게 만듭니다.
@With 불변 객체에서 필드를 변경한 새 객체를 반환합니다. (주로 @Value와 함께 사용)
@Cleanup 리소스를 자동으로 해제하여 try-finally 블록을 대체합니다.

 


Lombok 사용 시 장점

그렇다면 이 Lombok이라는 라이브러리를 사용했을 때 우리가 얻을 수 있는 장점이 무엇일까?

 

 

  • 코드 간결화: 반복적인 코드(예: Getter/Setter, toString 등)를 줄여준다.
  • 자동화: 개발자가 일일이 작성해야 하는 메서드를 자동으로 생성해준다.
  • 유지보수 용이: 코드를 간결하게 만들어서 유지보수가 용이하다.
  • 성능: 런타임에 코드가 동적으로 생성되는 것이 아니라 컴파일 타임에 코드가 생성되므로 성능에 미치는 영향이 거의 없다.

 


Lombok 사용 시 유의사항

사용하기 전, 몇가지 적용 사항이 있다.

 

1. 롬복을 사용하려면, 빌드 도구에 Lombok을 의존성으로 추가해야 한다.

Maven

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
    <scope>provided</scope>
</dependency>

 

Gradle

dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.24'
    annotationProcessor 'org.projectlombok:lombok:1.18.24'
}

 

 

2. 개발 툴에서 플러그인 설치 (Intellij)

 

File - Settings - Plugins 에서 Lombok 검색

 

이제 롬복에서 제공하는 어노테이션을 사용할 수 있다!


Lombok 사용법

이 포스팅에서는 자주 쓰이는 어노테이션들만 코드 예시로 다룰 예정이다.

 

 

@Getter, @Setter

 

적용전

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

 

적용후

@Getter
@Setter
public class Person {
    private String name;
    private int age;
}

 


@ToString

 

적용전

public class Person {
    private String name;
    private int age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

 

적용후

@ToString
public class Person {
    private String name;
    private int age;
}

@EqualsAndHashCode

 

적용전

public class Person {
    private String name;
    private int age;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

 

적용후

@EqualsAndHashCode
public class Person {
    private String name;
    private int age;
}

@NoArgsConstructor, @AllArgsConstructor

 

적용전

public class Person {
    private String name;
    private int age;

    public Person(){

    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

 

적용후

@NoArgsConstructor
@AllArgsConstructor
public class Person {
    private String name;
    private int age;
}

 

 

@RequiredArgsConstructor 는 final 필드나 @NonNull 필드를 받는 생성자를 생성한다.

Spring에서 생성자 주입을 할 때, Class레벨에 붙여 사용하기도 한다.


@Data

 

적용전

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

 

적용후

@Data
public class Person {
    private String name;
    private int age;
}

 


@Builder

 

적용전

public class Person {
    private String name;
    private int age;

    private Person(PersonBuilder builder) {
        this.name = builder.name;
        this.age = builder.age;
    }

    //Nested Builder Class
    public static class PersonBuilder {
        private String name;
        private Integer age;

        public PersonBuilder setName(String name) {
            this.name = name;
            return this;
        }

        public PersonBuilder setAge(Integer age) {
            this.age = age;
            return this;
        }

        public Person build() {
            return new Person(this);
        }

    }
}

 

적용후

@Builder
public class Person {
    private String name;
    private int age;
}

 


@Slf4j

@Slf4j
public class MyClass {
    public void logMessage() {
        log.info("This is a log message");
    }
}

 

 


 

예시 코드에는 필드가 2개뿐이라 드라마틱한 변화는 안보였지만, 만약 필드가 10개 20개 늘어난다면,

Lombok을 사용했을 때와 사용하지 않았을 때의 클래스 코드의 길이는 엄청난 차이가 날 것이다.

이처럼 프로젝트 상황에 맞는 알맞은 라이브러리를 사용하면 개발이나 성능에서도 이점을 가져갈 수 있으니,

적극 활용해도 좋을 것 같다.