롬복(lombok)에 대해 알아보자

힐링코더·2023년 8월 20일
0

주의: 분량이 좀 됩니다

<롬복이란?>

롬복(Project Lombok)은 Java 프로그래밍을 더 편리하게 만들어주는 오픈 소스 라이브러리다.
롬복은 자동화된 코드 생성을 통해 일반적으로 반복적이고 번거로운 작업들을 간소화하고 줄여준다.


롬복의 주요 기능

  1. Getter와 Setter 메서드 자동 생성:
    롬복 어노테이션을 사용하면 클래스의 필드에 대한 Getter와 Setter 메서드를 자동으로 생성할 수 있다. 이렇게 하면 코드의 중복을 줄이고 더 간결한 코드를 작성할 수 있다.
  2. 빌더 패턴 자동 생성:
    롬복을 사용하면 빌더 패턴을 자동으로 생성할 수 있다. 빌더 패턴은 객체 생성 시 매개변수를 선택적으로 지정할 수 있게 해주는 패턴으로, 복잡한 객체를 생성할 때 유용하다.
  3. ToString 메서드 자동 생성:
    롬복은 객체의 toString() 메서드를 자동으로 생성해준다. 이를 통해 객체의 내용을 보다 쉽게 확인할 수 있다.
  4. Equals와 HashCode 메서드 자동 생성:
    객체의 동등성 비교를 위한 equals()와 해시 코드 생성을 위한 hashCode() 메서드를 자동으로 생성해준다.
  5. NoArgsConstructor와 RequiredArgsConstructor 등의 생성자 자동 생성: 생성자 관련 어노테이션을 사용하여 기본 생성자나 필수 인자를 갖는 생성자 등을 자동으로 생성할 수 있다.
  6. Slf4j, Log4j 등과 연동한 로깅 자동화: 롬복은 로깅 라이브러리와 연동하여 로깅 코드를 간소화하는 기능도 제공한다.

요약:
롬복은 프로젝트의 코드를 더 읽기 쉽고 유지보수하기 쉽게 만들어주는 도구로, 반복적이고 표준적인 코드 작성을 최소화하여 개발자가 핵심 로직에 더 집중할 수 있도록 도와준다.


롬복 기능 더 자세하게

val
Finally! Hassle-free final local variables.

val은 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, Java에서 final 키워드를 사용하여 선언된 로컬 변수를 더 간편하게 생성하도록 도와주는 기능입니다.

Java에서 final 키워드를 사용하여 변수를 선언하면 해당 변수는 재할당될 수 없는 불변 변수가 됩니다. 그러나 final 키워드를 사용하면 변수의 값을 초기화할 때 반드시 값을 할당해야 하기 때문에, 코드가 길어지거나 반복적으로 사용되는 경우에 번거로울 수 있습니다.

롬복의 @val 어노테이션은 이러한 문제를 해결하기 위해 도입되었습니다. 이 어노테이션을 사용하면 변수를 선언하면서 동시에 초기화할 수 있습니다. 이로써 코드를 더 간결하게 유지하면서도 불변 변수를 편리하게 생성할 수 있습니다. 아래는 val 어노테이션을 사용한 예시입니다:

import lombok.val;

public class ValExample {
    public void exampleMethod() {
        val name = "John"; // 변수 name은 불변 변수로서 자동으로 final로 선언되고 값이 할당됩니다.
        val age = 30;      // 변수 age 역시 불변 변수로서 final로 선언되고 값이 할당됩니다.
        
        // name = "Jane";  // 이 줄은 컴파일 에러가 발생합니다. val로 선언된 변수는 재할당이 불가능합니다.
    }
}

val 어노테이션을 사용하면 자료형을 추론하여 변수의 자료형을 결정합니다. 이를 통해 개발자는 코드를 더 간결하게 작성할 수 있고, 변수의 타입 선언에 신경쓸 필요가 없습니다.


var
Mutably! Hassle-free local variables.

var는 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, Java에서 변수의 자료형을 명시적으로 선언하지 않고도 변수를 선언하고 초기화할 수 있게 해주는 기능입니다. 이를 통해 코드를 더 간결하게 작성할 수 있습니다.

Java에서는 변수를 선언할 때 반드시 변수의 자료형을 명시해야 합니다. 그러나 자료형을 정확히 알고 있는 경우에도 변수의 자료형을 반복해서 작성해야 하는 번거로움이 있을 수 있습니다. var 어노테이션은 이러한 불편함을 해소하고 코드를 더 간단하게 작성할 수 있도록 도와줍니다.

아래는 var 어노테이션을 사용한 예시입니다:

import lombok.var;

public class VarExample {
    public void exampleMethod() {
        var name = "John"; // 변수 name의 자료형은 컴파일러가 문자열로 추론합니다.
        var age = 30;      // 변수 age의 자료형은 컴파일러가 정수로 추론합니다.
        
        name = "Jane";     // 변수 name의 값을 변경하는 것은 가능합니다.
        age = 31;          // 변수 age의 값을 변경하는 것은 가능합니다.
        var로 선언된 변수는 초기 자료형에 맞게끔 고정됩니다.
    }
}

주의해야 할 점은 var로 선언된 변수는 초기화된 값의 자료형에 따라 추론되므로, 초기화되지 않은 변수에는 var를 사용할 수 없습니다. 또한 한 번 추론된 자료형은 해당 변수의 라이프타임 동안 변경되지 않습니다.

var 어노테이션을 사용하면 코드를 더 간결하게 작성할 수 있으며, 변수의 자료형을 반복해서 작성하는 번거로움을 줄일 수 있습니다.


@NonNull
or: How I learned to stop worrying and love the NullPointerException.

@NonNull은 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, Java 코드에서 발생할 수 있는 NullPointerException을 방지하고자 할 때 사용하는 기능입니다.

Java에서는 객체가 null인 상태에서 해당 객체의 메서드나 속성을 호출하려고 하면 NullPointerException이 발생합니다. 이는 프로그램의 예상치 못한 동작을 야기할 수 있는 위험한 상황입니다. @NonNull 어노테이션은 이러한 문제를 방지하기 위해 사용됩니다.

이 어노테이션은 변수나 매개변수, 메서드 반환값 등에 적용할 수 있습니다. 해당 어노테이션을 사용하면 해당 요소가 null이 될 수 없다는 것을 나타내며, 컴파일러나 런타임 체크를 통해 null이 될 가능성이 있는 부분을 사전에 검사합니다.

아래는 @NonNull 어노테이션을 사용한 예시입니다:

import lombok.NonNull;

public class NonNullExample {
    public String processName(@NonNull String name) {
        // The '@NonNull' annotation on the 'name' parameter ensures that the parameter cannot be null.
        // The compiler will generate a warning if a null value is passed as an argument to this method.
        return "Hello, " + name;
    }
}

위의 예시에서 @NonNull 어노테이션을 사용하여 name 매개변수가 null이 될 수 없다고 표시하였습니다. 이렇게 하면 메서드가 호출될 때 컴파일러가 null이 아님을 확인하고 경고를 발생시킵니다.

@NonNull 어노테이션은 코드의 안정성을 높이고 NullPointerException을 사전에 방지하는 데 도움을 줍니다.


@Cleanup
Automatic resource management: Call your close() methods safely with no hassle.

@Cleanup은 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, 자원 관리를 간편하게 해주는 기능입니다. 주로 자원을 사용한 후에 해당 자원을 안전하게 닫아줄 때 사용됩니다.

Java 프로그래밍에서는 파일, 네트워크 연결, 데이터베이스 연결과 같은 자원들을 사용한 후 반드시 닫아주어야 합니다. 그렇지 않을 경우, 자원 누수(resource leak)가 발생하여 프로그램의 성능 저하나 예상치 못한 동작을 유발할 수 있습니다. 이러한 자원 관리는 번거로운 작업이며, 롬복의 @Cleanup 어노테이션은 이를 편리하게 처리할 수 있도록 도와줍니다.

@Cleanup 어노테이션은 주로 AutoCloseable 인터페이스를 구현한 자원에 사용됩니다. 어노테이션을 사용하면 롬복이 자동으로 close() 메서드를 호출하여 자원을 닫아줍니다.

아래는 @Cleanup 어노테이션을 사용한 예시입니다:

import lombok.Cleanup;

public class CleanupExample {
    public void processFile(String filePath) {
        @Cleanup FileReader reader = new FileReader(filePath);
        // 'reader' 자원을 사용한 후, 'close()' 메서드를 호출하여 자원을 닫아줍니다.
        
        // 파일 내용을 읽는 작업 수행
    }
}

위의 예시에서 @Cleanup 어노테이션을 사용하여 FileReader를 생성하고, processFile 메서드가 종료될 때 close() 메서드를 자동으로 호출하여 리소스 누수를 방지합니다. 이를 통해 자원 관리 코드를 간소화하고 안전하게 처리할 수 있습니다.


@Getter/@Setter
Never write public int getFoo() {return foo;} again.

@Getter와 @Setter는 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, Java 클래스의 필드에 대한 Getter와 Setter 메서드를 자동으로 생성해주는 기능입니다. 이를 통해 반복적인 코드 작성을 줄이고 더 간결한 코드를 작성할 수 있습니다.

@Getter 어노테이션:

@Getter 어노테이션을 클래스의 필드에 적용하면 해당 필드에 대한 Getter 메서드를 자동으로 생성합니다.
Getter 메서드는 해당 필드의 값을 반환하는 역할을 합니다.
Getter 메서드의 이름은 필드의 이름을 기반으로 자동으로 생성됩니다.
@Setter 어노테이션:

@Setter 어노테이션을 클래스의 필드에 적용하면 해당 필드에 대한 Setter 메서드를 자동으로 생성합니다.
Setter 메서드는 해당 필드의 값을 설정하는 역할을 합니다.
Setter 메서드의 이름은 "set" 다음에 필드의 이름이 옵니다.
아래는 @Getter와 @Setter 어노테이션을 사용한 예시입니다:

import lombok.Getter;
import lombok.Setter;

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

public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("John");
        person.setAge(30);
        
        System.out.println("Name: " + person.getName());
        System.out.println("Age: " + person.getAge());
    }
}

위의 예시에서 @Getter와 @Setter 어노테이션을 사용하여 Person 클래스의 name 필드와 age 필드에 대한 Getter와 Setter 메서드가 자동으로 생성됩니다. 이를 통해 필드의 값을 간편하게 설정하고 가져올 수 있으며, 반복적인 Getter와 Setter 메서드 작성을 피할 수 있습니다.


@ToString
No need to start a debugger to see your fields: Just let lombok generate a toString for you!

@ToString은 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, Java 클래스의 객체를 문자열로 표현하기 위한 toString() 메서드를 자동으로 생성해주는 기능입니다. 이를 통해 객체의 필드 값을 간단하게 확인할 수 있습니다.

Java의 모든 클래스는 Object 클래스로부터 상속받는데, 이 때 기본적으로 toString() 메서드를 가지고 있습니다. 이 기본 toString() 메서드는 객체의 클래스 이름과 해시 코드를 출력하는 역할을 합니다. 그러나 실제로 객체의 필드 값들을 보기 위해서는 매번 디버거를 사용하거나 별도의 코드를 작성해야 하는 번거로움이 있습니다.

@ToString 어노테이션은 이런 번거로움을 해소하고, 객체의 필드 값을 간편하게 확인할 수 있도록 도와줍니다.

아래는 @ToString 어노테이션을 사용한 예시입니다:

import lombok.ToString;

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

public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("John");
        person.setAge(30);
        
        System.out.println(person); // 객체의 필드 값들이 출력됩니다.
    }
}

위의 예시에서 @ToString 어노테이션을 사용하여 Person 클래스에 toString() 메서드가 자동으로 생성됩니다. 이제 System.out.println(person)을 호출하면 객체의 필드 값들이 문자열로 출력됩니다. 이를 통해 디버거를 사용하지 않고도 객체의 상태를 확인할 수 있습니다.


@EqualsAndHashCode
Equality made easy: Generates hashCode and equals implementations from the fields of your object..

@EqualsAndHashCode은 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, Java 클래스의 객체 비교를 위한 hashCode()와 equals() 메서드를 자동으로 생성해주는 기능입니다. 이를 통해 객체의 동등성 비교를 간편하게 할 수 있습니다.

hashCode() 메서드:

hashCode() 메서드는 객체의 해시 코드를 반환합니다.
hashCode() 메서드는 equals() 메서드와 함께 사용되는데, 객체의 동등성 비교를 위해 필요한 역할을 합니다.
동일한 객체에 대해서는 항상 같은 해시 코드를 반환해야 하지만, 다른 객체에 대해서도 같은 해시 코드를 반환할 수 있습니다. 이 경우를 해시 충돌(hash collision)이라고 합니다.
equals() 메서드:

equals() 메서드는 두 객체가 동등한지를 비교하는 역할을 합니다.
객체의 필드 값을 비교하여 두 객체가 동일한지를 판단합니다.
@EqualsAndHashCode 어노테이션은 클래스의 필드를 기반으로 hashCode()와 equals() 메서드를 자동으로 생성해줍니다. 이를 통해 개발자는 동등성 비교와 해시 코드 생성과 같은 작업을 직접 구현하지 않아도 됩니다.

아래는 @EqualsAndHashCode 어노테이션을 사용한 예시입니다:

import lombok.EqualsAndHashCode;

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

public class Main {
    public static void main(String[] args) {
        Person person1 = new Person();
        person1.setName("John");
        person1.setAge(30);
        
        Person person2 = new Person();
        person2.setName("John");
        person2.setAge(30);
        
        System.out.println(person1.equals(person2)); // true, 객체의 동등성 비교
        System.out.println(person1.hashCode()); // 해시 코드 출력
        System.out.println(person2.hashCode()); // 해시 코드 출력
    }
}

위의 예시에서 @EqualsAndHashCode 어노테이션을 사용하여 Person 클래스에 hashCode()와 equals() 메서드가 자동으로 생성됩니다. 이를 통해 객체의 동등성 비교와 해시 코드 생성을 편리하게 수행할 수 있습니다.


@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
Constructors made to order: Generates constructors that take no arguments, one argument per final / non-nullfield, or one argument for every field.

@NoArgsConstructor, @RequiredArgsConstructor, 그리고 @AllArgsConstructor은 롬복 라이브러리에서 제공하는 어노테이션으로, 클래스의 생성자를 자동으로 생성해주는 기능을 제공합니다. 각 어노테이션마다 생성자의 형태를 다르게 조절할 수 있습니다.

@NoArgsConstructor 어노테이션:

@NoArgsConstructor 어노테이션을 사용하면 매개변수 없는 기본 생성자를 자동으로 생성합니다.
주로 JPA와 같이 매개변수 없는 기본 생성자가 필요한 경우에 사용됩니다.
@RequiredArgsConstructor 어노테이션:

@RequiredArgsConstructor 어노테이션을 사용하면 필드 중 final이거나 @NonNull 어노테이션이 적용된 필드에 대한 생성자를 자동으로 생성합니다.
이 생성자는 해당 필드의 값을 받아 객체를 초기화하는 역할을 합니다.
@AllArgsConstructor 어노테이션:

@AllArgsConstructor 어노테이션을 사용하면 클래스의 모든 필드에 대한 생성자를 자동으로 생성합니다.
이 생성자는 클래스의 모든 필드 값을 받아 객체를 초기화하는 역할을 합니다.
아래는 각 어노테이션을 사용한 예시입니다:

import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.NonNull;

@NoArgsConstructor
public class NoArgsConstructorExample {
    // No-argument constructor is automatically generated.
}

@RequiredArgsConstructor
public class RequiredArgsConstructorExample {
    private final String name;
    private int age;
    // Constructor that initializes 'name' field is automatically generated.
}

@AllArgsConstructor
public class AllArgsConstructorExample {
    private String name;
    private int age;
    // Constructor that initializes both 'name' and 'age' fields is automatically generated.
}

public class Main {
    public static void main(String[] args) {
        RequiredArgsConstructorExample example = new RequiredArgsConstructorExample("John");
    }
}

위의 예시에서는 @NoArgsConstructor, @RequiredArgsConstructor, 그리고 @AllArgsConstructor 어노테이션을 사용하여 생성자를 자동으로 생성하였습니다. 이를 통해 필요한 생성자를 간편하게 생성하고 객체 초기화를 편리하게 수행할 수 있습니다.


@Data
All together now: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, and @Setter on all non-final fields, and @RequiredArgsConstructor!

@Data는 롬복 라이브러리에서 제공하는 강력한 어노테이션으로, 클래스의 여러 기능을 한 번에 설정해주는 기능을 제공합니다. 이를 통해 @ToString, @EqualsAndHashCode, @Getter, @Setter, 그리고 @RequiredArgsConstructor 어노테이션을 모두 함께 사용하는 효과를 얻을 수 있습니다.

@ToString: 객체를 문자열로 표현하는 toString() 메서드를 생성합니다. 객체의 필드 값을 간단하게 확인할 수 있습니다.

@EqualsAndHashCode: 객체의 동등성 비교를 위한 hashCode()와 equals() 메서드를 생성합니다. 객체의 동일성 비교를 용이하게 합니다.

@Getter: 필드에 대한 Getter 메서드를 생성합니다. 필드의 값을 읽어오는 역할을 합니다.

@Setter: 필드에 대한 Setter 메서드를 생성합니다. 필드의 값을 설정하는 역할을 합니다.

@RequiredArgsConstructor: final이거나 @NonNull 어노테이션이 적용된 필드를 기반으로 생성자를 생성합니다.

이 모든 기능을 @Data 어노테이션 하나로 간편하게 적용할 수 있습니다. 다음은 @Data 어노테이션의 사용 예시입니다:

import lombok.Data;

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

public class Main {
    public static void main(String[] args) {
        Person person = new Person("John");
        person.setAge(30);
        
        System.out.println(person); // 객체의 필드 값 출력
    }
}

위의 예시에서 @Data 어노테이션을 사용하여 Person 클래스에 여러 어노테이션을 한 번에 적용하고 있습니다. 이를 통해 toString(), hashCode(), equals(), Getter, Setter, 그리고 @RequiredArgsConstructor 등이 모두 자동으로 생성됩니다. 이렇게 클래스를 간결하게 유지하면서도 여러 가지 기능을 활용할 수 있습니다.


@Value
Immutable classes made very easy.

@Value는 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, 불변(immutable) 클래스를 쉽게 생성할 수 있도록 도와주는 기능을 제공합니다. 불변 클래스란 객체가 생성된 후 그 상태를 변경할 수 없는 클래스를 의미합니다.

불변 클래스의 주요 특징은 다음과 같습니다:

한 번 생성된 객체의 상태는 변경되지 않습니다.
객체의 필드는 최초 생성 시 초기화되며 이후에는 변경할 수 없습니다.
객체의 상태가 변하지 않기 때문에 객체를 여러 곳에서 공유해도 안전합니다.
스레드 안전성을 보장하기 쉽습니다.
@Value 어노테이션을 사용하면 불변 클래스를 정의하는 데 필요한 메서드들을 자동으로 생성합니다. 이를 통해 불변성을 유지하며 객체를 효과적으로 구현할 수 있습니다.

아래는 @Value 어노테이션을 사용한 예시입니다:

import lombok.Value;

@Value
public class ImmutablePerson {
    private String name;
    private int age;
}

public class Main {
    public static void main(String[] args) {
        ImmutablePerson person = new ImmutablePerson("John", 30);
        // person.setAge(31); // This will result in a compilation error
    }
}

위의 예시에서 @Value 어노테이션을 사용하여 ImmutablePerson 클래스를 정의하고 있습니다. @Value 어노테이션을 사용하면 Getter 메서드, equals(), hashCode(), 그리고 toString() 메서드가 자동으로 생성됩니다. 또한, 해당 클래스의 필드는 final로 선언되어 값을 변경할 수 없습니다. 이를 통해 객체의 불변성을 보장하며 안전하게 활용할 수 있습니다.


@Builder
... and Bob's your uncle: No-hassle fancy-pants APIs for object creation!

@Builder는 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, 복잡한 객체 생성을 간편하게 만들어주는 기능을 제공합니다. 빌더 패턴(Builder Pattern)을 사용하여 객체를 생성하면서 가독성 있고 유연한 API를 제공할 수 있습니다.

빌더 패턴은 객체 생성 시 매개변수의 개수나 순서에 상관없이 사용자가 원하는 속성을 설정하여 객체를 생성할 수 있게 하는 패턴입니다. 이를 통해 객체 생성 코드를 보다 직관적이고 가독성 좋게 작성할 수 있습니다.

@Builder 어노테이션을 사용하면 해당 클래스에 빌더 패턴을 적용할 수 있습니다. 이를 통해 개발자는 객체의 속성을 체이닝 방식으로 설정하거나 선택적으로 원하는 속성만 설정할 수 있는 API를 제공할 수 있습니다.

아래는 @Builder 어노테이션을 사용한 예시입니다:

import lombok.Builder;

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

public class Main {
    public static void main(String[] args) {
        Person person = Person.builder()
            .name("John")
            .age(30)
            .address("123 Main St")
            .build();
            
        System.out.println(person); // 출력: Person(name=John, age=30, address=123 Main St)
    }
}

위의 예시에서 @Builder 어노테이션을 사용하여 Person 클래스에 빌더 패턴을 적용하고 있습니다. builder() 메서드를 통해 빌더 객체를 생성하고, 체이닝 방식으로 원하는 속성을 설정한 후 build() 메서드를 호출하여 최종적으로 객체를 생성합니다. 이를 통해 객체 생성 과정이 명확하고 가독성이 좋아집니다.


@SneakyThrows
To boldly throw checked exceptions where no one has thrown them before!

@SneakyThrows는 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, 검사 예외(checked exception)를 런타임 예외(unchecked exception)로 변환하여 처리할 수 있도록 도와주는 기능을 제공합니다. 검사 예외는 컴파일러가 확인하여 처리해야 하는 예외로, 예외 처리 코드를 강제하는 특징이 있습니다. 반면에 런타임 예외는 예외 처리가 선택 사항이며, 명시적인 예외 처리가 필요하지 않습니다.

@SneakyThrows 어노테이션을 사용하면 메서드 내에서 발생하는 검사 예외를 명시적인 예외 처리 없이 런타임 예외로 변환할 수 있습니다. 이를 통해 코드 중복을 줄이고 예외 처리를 더 간단하게 만들 수 있습니다. 그러나 이 어노테이션을 남용하면 예외 처리의 명확성을 잃을 수 있으므로 신중하게 사용해야 합니다.

아래는 @SneakyThrows 어노테이션을 사용한 예시입니다:

import lombok.SneakyThrows;

public class SneakyThrowsExample {
    @SneakyThrows
    public void doSomething() {
        throw new Exception("This is a checked exception");
    }
    
    public static void main(String[] args) {
        SneakyThrowsExample example = new SneakyThrowsExample();
        example.doSomething(); // 예외가 런타임 예외로 변환되어 던져집니다.
    }
}

위의 예시에서 @SneakyThrows 어노테이션을 사용하여 doSomething() 메서드 내에서 발생하는 검사 예외를 런타임 예외로 변환하고 있습니다. 이로 인해 예외 처리 코드를 추가하지 않고도 예외가 런타임 예외로 던져집니다. 이를 통해 코드의 가독성을 높이고 예외 처리를 간단하게 만들 수 있습니다.


@Synchronized
synchronized done right: Don't expose your locks.

@Synchronized는 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, 동기화(synchronization) 처리를 간편하게 할 수 있도록 도와주는 기능을 제공합니다. 동기화는 여러 스레드가 공유하는 자원에 접근할 때 정확한 순서와 시간에 접근하도록 보장하는 작업을 의미합니다. 일반적으로 자바에서는 synchronized 키워드를 사용하여 동기화를 구현하지만, 롬복의 @Synchronized 어노테이션은 더 편리하게 동기화를 처리할 수 있도록 도와줍니다.

@Synchronized 어노테이션을 메서드에 적용하면 해당 메서드의 코드 블록이 동기화되어 한 번에 하나의 스레드만 접근할 수 있게 됩니다. 이를 통해 공유 자원에 대한 안전한 접근을 보장하며, synchronized 키워드를 직접 사용하지 않아도 됩니다. 또한, 롬복이 내부적으로 잠금(lock) 객체를 관리하므로 개발자는 자물쇠(lock)를 직접 노출시키지 않아도 됩니다.

아래는 @Synchronized 어노테이션을 사용한 예시입니다:

import lombok.Synchronized;

public class SynchronizedExample {
    private int count = 0;

    @Synchronized
    public void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }

    public static void main(String[] args) {
        SynchronizedExample example = new SynchronizedExample();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                example.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                example.increment();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final count: " + example.getCount()); // 예상 결과: 2000
    }
}

위의 예시에서 @Synchronized 어노테이션을 사용하여 increment() 메서드에 동기화를 적용하고 있습니다. 이로 인해 두 개의 스레드가 동시에 increment() 메서드를 호출해도 동기화 처리로 인해 안전한 접근이 가능하며, 최종적으로 count 변수의 값은 예상 결과대로 2000이 될 것입니다.


@With
Immutable 'setters' - methods that create a clone but with one changed field.

@With는 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, 불변(immutable) 객체에서 특정 필드만 변경한 새로운 객체를 생성할 때 사용하는 기능을 제공합니다. 이를 통해 객체의 상태를 변경하지 않고 새로운 객체를 생성하여 원하는 필드 값을 변경할 수 있습니다.

불변 객체는 한 번 생성된 후에 내부 상태를 변경할 수 없는 객체를 의미합니다. 이는 객체의 안정성과 스레드 안전성을 보장할 수 있는 중요한 개념입니다. 하지만 때로는 기존 객체의 일부 속성을 변경하여 새로운 객체를 생성하고 싶은 경우가 있을 수 있습니다. @With 어노테이션은 이러한 상황에서 유용하게 사용될 수 있습니다.

아래는 @With 어노테이션을 사용한 예시입니다:

import lombok.With;

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

public class Main {
    public static void main(String[] args) {
        Person person1 = new Person().withName("John").withAge(30);
        Person person2 = person1.withAge(31);

        System.out.println(person1); // 출력: Person(name=John, age=30)
        System.out.println(person2); // 출력: Person(name=John, age=31)
    }
}

위의 예시에서 @With 어노테이션을 사용하여 Person 클래스에 불변성을 유지하며 특정 필드만 변경하는 기능을 추가하고 있습니다. withXxx() 메서드는 현재 객체를 복제하면서 변경된 필드 값을 적용한 새로운 객체를 생성합니다. 이렇게 함으로써 기존 객체의 불변성을 유지하면서도 필드 값을 변경할 수 있습니다.

@With 어노테이션을 사용하면 객체의 상태를 변경하지 않고도 새로운 객체를 생성하여 특정 필드 값을 변경할 수 있으므로, 불변 객체를 다룰 때 편리하게 사용할 수 있는 기능입니다.


@Getter(lazy=true)
Laziness is a virtue!

@Getter(lazy=true)는 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, 게으른(lazy) 초기화를 사용하여 필드의 값을 처음 접근하는 시점에 초기화하는 기능을 제공합니다. 이를 통해 필드의 초기화를 최대한 미룰 수 있으며, 필요한 경우에만 초기화를 수행합니다.

게으른 초기화는 필드의 값을 처음 사용하는 시점에 초기화하므로, 불필요한 초기화나 메모리 사용을 줄일 수 있습니다. 특히 객체 내의 필드 중에 복잡한 연산이나 초기화 과정이 있는 경우에 효과적으로 사용될 수 있습니다.

아래는 @Getter(lazy=true) 어노테이션을 사용한 예시입니다:

import lombok.Getter;

public class LazyInitializationExample {
    @Getter(lazy = true)
    private final ExpensiveResource expensiveResource = createExpensiveResource();

    private ExpensiveResource createExpensiveResource() {
        System.out.println("Creating expensive resource...");
        return new ExpensiveResource();
    }

    public static void main(String[] args) {
        LazyInitializationExample example = new LazyInitializationExample();

        // 필드를 처음 접근하는 시점에 초기화가 수행됩니다.
        ExpensiveResource resource = example.getExpensiveResource();
        // 이미 초기화된 필드는 더 이상 초기화되지 않습니다.
        ExpensiveResource cachedResource = example.getExpensiveResource();
    }
}

class ExpensiveResource {
    // 복잡한 초기화 과정이나 연산이 있다고 가정합니다.
}

위의 예시에서 @Getter(lazy = true) 어노테이션을 사용하여 expensiveResource 필드를 게으른 초기화로 설정하고 있습니다. getExpensiveResource() 메서드가 처음 호출될 때에만 createExpensiveResource() 메서드를 통해 초기화가 이루어집니다. 이후 같은 필드에 대한 접근은 이미 초기화된 값을 반환합니다.

이를 통해 필드의 초기화를 필요한 시점으로 미루면서, 성능 향상과 메모리 절약을 동시에 달성할 수 있습니다.


@Log
Captain's Log, stardate 24435.7: "What was that line again?"

@Log는 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, 로깅 코드를 간편하게 추가할 수 있도록 도와주는 기능을 제공합니다. 로깅은 프로그램 실행 중에 중요한 정보나 디버깅 메시지를 기록하는 것으로, 프로그램의 동작을 이해하고 문제를 진단하는 데 도움이 됩니다.

@Log 어노테이션을 클래스에 적용하면 롬복이 자동으로 로깅 코드를 생성하여 로그를 출력하는 메서드를 추가합니다. 이를 통해 개발자는 로깅 코드를 직접 작성하지 않아도 되며, 간단한 어노테이션만으로 로그를 출력할 수 있습니다.

@Log 어노테이션은 다음과 같이 두 가지 버전으로 제공됩니다:

@Log: 자바 표준 로깅 라이브러리인 java.util.logging을 사용합니다.
@CommonsLog: Apache Commons Logging 라이브러리를 사용합니다.
아래는 @Log 어노테이션을 사용한 예시입니다:

import lombok.extern.java.Log;

@Log
public class LoggingExample {
    public static void main(String[] args) {
        log.info("This is an info message.");
        log.warning("This is a warning message.");
    }
}

위의 예시에서 @Log 어노테이션을 사용하여 LoggingExample 클래스에 로깅 기능을 추가하고 있습니다. log 필드가 생성되며, log.info()와 log.warning() 메서드를 통해 각각 정보 메시지와 경고 메시지를 출력합니다.

이렇게 롬복의 @Log 어노테이션을 사용하면 로깅 코드를 간단하게 추가하고, 로그를 효율적으로 관리할 수 있습니다.


experimental
Head to the lab: The new stuff we're working on.

@experimental은 롬복 라이브러리에서 제공하는 어노테이션 중 하나로, 실험적인 기능을 나타내는 어노테이션입니다. 이 어노테이션은 해당 기능이 아직 실험 중이거나 변경될 수 있는 기능임을 나타냅니다. 즉, 해당 기능은 미래에 변경될 수 있으며 안정성을 보장하지 않을 수 있다는 의미입니다.

@experimental 어노테이션이 적용된 요소는 롬복 개발자가 앞으로 변경하거나 수정할 가능성이 있는 것으로 표시됩니다. 따라서 해당 기능을 사용할 때에는 문서를 주의 깊게 읽고, 테스트와 피드백을 통해 어떻게 동작하는지 이해하고 사용하는 것이 중요합니다.

예를 들어, 다음과 같이 @experimental 어노테이션이 적용된 코드를 볼 수 있습니다:

import lombok.experimental.experimental;

@experimental
public class ExperimentalFeatureExample {
    // ...
}

위의 예시에서 @experimental 어노테이션은 ExperimentalFeatureExample 클래스에 실험적인 기능이 있다는 것을 나타냅니다. 이 경우 해당 기능은 롬복 개발자가 나중에 변경할 수 있으므로, 사용할 때 주의가 필요합니다.


일단 여기까지.

profile
여기는 일상 블로그, 기술 블로그는 https://yourhealingcoder.tistory.com/

2개의 댓글

comment-user-thumbnail
2024년 8월 2일

안녕하세요! 글 정리가 잘 되어있어서 제 블로그에서도 정리해서 포스팅하고 싶은데.. 해도 괜찮을 까요..?

1개의 답글