Post

[Java] Lombok

[Java] Lombok

πŸ“Œ Lombokμ΄λž€?

Lombok μ΄λž€ μ–΄λ…Έν…Œμ΄μ…˜ 기반으둜 μžλ°” μ½”λ“œλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•΄μ£ΌλŠ” λΌμ΄λΈŒλŸ¬λ¦¬μ΄λ‹€. 이λ₯Ό 톡해 μ½”λ“œκ°€ κ°„κ²°ν•΄μ§€λ©° 가독성을 ν–₯μƒμ‹œν‚¬ 수 μžˆλ‹€. λ˜ν•œ 반볡적으둜 μž‘μ„±λ˜λŠ” λ³΄μΌλŸ¬ν”Œλ ˆμ΄νŠΈ μ½”λ“œκ°€ κ°μ†Œν•˜κ²Œ λœλ‹€.

μ΄λŠ” κ°œλ°œμžκ°€ 핡심 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ— 더 집쀑할 수 μžˆλ„λ‘ ν•˜λŠ” 효과λ₯Ό κ°€μ Έμ˜€λ©°, μœ μ§€λ³΄μˆ˜κ°€ μ‰¬μ›Œμ§„λ‹€.


μ‹€μ œλ‘œ Lombok을 μ‚¬μš©ν•˜κΈ° μ „κ³Ό ν›„μ˜ 차이점을 μ‚΄νŽ΄λ³΄μž.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

ν˜„μž¬λŠ” ν•„λ“œκ°€ 두 개 밖에 μ—†μ§€λ§Œ, ν•„λ“œμ˜ μˆ˜κ°€ μ¦κ°€ν•˜λ©΄ 그만큼 μž‘μ„±ν•΄μ•Ό ν•˜λŠ” getter/setter λ©”μ„œλ“œμ˜ μˆ˜κ°€ μ¦κ°€ν•˜κ²Œ λœλ‹€. 반볡적인 μ½”λ“œμ˜ μž‘μ„±μ΄ μ¦κ°€ν•œλ‹€λŠ” λœ»μ΄λ‹€.

1
2
3
4
5
6
7
8
9
10
import lombok.Getter;
import lombok.Setter;

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

Lombok을 μ‚¬μš©ν•˜κ²Œ 되면 μ–΄λ–»κ²Œ μ½”λ“œκ°€ κ°„κ²°ν•΄μ§ˆκΉŒ? @Getter, @Setter μ–΄λ…Έν…Œμ΄μ…˜μ„ μΆ”κ°€ν•˜λ©΄ 컴파일 μ‹œμ μ— μžλ™μœΌλ‘œ getter/setter λ©”μ„œλ“œκ°€ μƒμ„±λœλ‹€.

πŸ“Œ μ„€μ • 방법

  • Gradle
1
2
3
4
5
6
dependencies {
    implementation 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.projectlombok:lombok'
    testAnnotationProcessor 'org.projectlombok:lombok'
}
  • Maven
1
2
3
4
5
6
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.16</version>
    <scope>provided</scope>
</dependency>

πŸ“Œ λ™μž‘ 원리

μ½”λ“œμ— μ–΄λ…Έν…Œμ΄μ…˜μ„ λΆ™μ΄κ²Œ 되면 컴파일 μ‹œμ μ— ν•΄λ‹Ή μ–΄λ…Έν…Œμ΄μ…˜μ„ κ°μ§€ν•˜μ—¬ ν•„μš”ν•œ μ½”λ“œλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•œλ‹€. javac(μžλ°” 컴파일러)μ—λŠ” Annotation Processing 단계가 μ‘΄μž¬ν•œλ‹€. 이 λ‹¨κ³„μ—μ„œ Lombok의 Annotation Processor κ°€ λ™μž‘ν•˜μ—¬ μ½”λ“œλ₯Ό νŒŒμ‹±ν•˜μ—¬ λ§Œλ“  AST(Abstract Syntax Tree) λ₯Ό λ™μ μœΌλ‘œ μˆ˜μ •ν•œλ‹€. μˆ˜μ •λœ ASTλ₯Ό 기반으둜 javacκ°€ μ΅œμ’… λ°”μ΄νŠΈμ½”λ“œ(.class)λ₯Ό μƒμ„±ν•œλ‹€.

πŸ“Œ μ£Όμš” Lombok μ–΄λ…Έν…Œμ΄μ…˜

@Getter/Setter

클래슀의 ν•„λ“œμ— λŒ€ν•œ getter/setter λ©”μ„œλ“œλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•œλ‹€.

1
2
3
4
5
6
7
8
// 클래슀 전체에 적용
@Getter
@Setter
public class Member {
    private String id;
    private String name;
}

@AllArgsConstructor

클래슀의 λͺ¨λ“  ν•„λ“œλ₯Ό νŒŒλΌλ―Έν„°λ‘œ λ°›λŠ” μƒμ„±μžλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•œλ‹€.

1
2
3
4
5
6
7
8
9
10
11
12
@AllArgsConstructor
public class Employee {
    private String name;
    private int salary;
}

// μƒμ„±λ˜λŠ” μƒμ„±μž
public Employee(String name, int salary) {
    this.name = name;
    this.salary = salary;
}

@NoArgsConstructor

νŒŒλΌλ―Έν„°κ°€ μ—†λŠ” κΈ°λ³Έ μƒμ„±μžλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•œλ‹€.

1
2
3
4
5
6
7
8
9
10
@NoArgsConstructor
public class Employee {
    private String name;
    private int salary;
}

// μƒμ„±λ˜λŠ” μƒμ„±μž
public Employee() {
}

@RequiredArgsConstuctor

클래슀 λ‚΄μ—μ„œ μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ final ν•„λ“œμ™€ @NonNull 이 뢙은 ν•„λ“œλ§Œμ„ νŒŒλΌλ―Έν„°λ‘œ λ°›λŠ” μƒμ„±μžλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•œλ‹€.

1
2
3
4
5
6
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;
    private String name;
}

μœ„ μ½”λ“œμ—μ„œ userRepository 만 μƒμ„±μžμ˜ νŒŒλΌλ―Έν„°λ‘œ ν¬ν•¨λœλ‹€.

@ToString

클래슀의 λͺ¨λ“  ν•„λ“œλ₯Ό 기반으둜 toString() λ©”μ„œλ“œλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•œλ‹€. toString()은 객체λ₯Ό 읽을 수 μžˆλŠ” λ¬Έμžμ—΄λ‘œ λ³€ν™˜ν•˜λŠ” λ©”μ„œλ“œμ΄λ‹€.

exclude 속성을 μ‚¬μš©ν•˜μ—¬ νŠΉμ • ν•„λ“œλ₯Ό toString() κ²°κ³Όμ—μ„œ μ œμ™Έν•  수 있으며, λ˜λŠ” @Tostring.Exclude μ–΄λ…Έν…Œμ΄μ…˜μ„ 직접 λΆ™μ—¬ μ œμ™Έν•  수 μžˆλ‹€.

@ToString(callSuper = true) λ₯Ό μ‚¬μš©ν•˜λ©΄ λΆ€λͺ¨ 클래슀의 toString() 결과도 ν•¨κ»˜ 포함할 수 μžˆλ‹€. κ·ΈλŸ¬λ‚˜ 객체 κ°„ μˆœν™˜ μ°Έμ‘°κ°€ μžˆμ„ 경우 λ¬΄ν•œ 루프가 λ°œμƒν•  수 μžˆλ‹€.

@EqualsAndHashCode

ν΄λž˜μŠ€μ— equals() 와 hashCode() λ©”μ„œλ“œλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•œλ‹€. equals()λŠ” 두 객체가 λ…Όλ¦¬μ μœΌλ‘œ λ™λ“±ν•œμ§€ λΉ„κ΅ν•˜λ©°, hashCode()λŠ” 객체λ₯Ό ν•΄μ‹œ 기반 μžλ£Œκ΅¬μ‘°μ—μ„œ μ‚¬μš©ν•  λ•Œ 객체의 ν•΄μ‹œκ°’μ„ λ¦¬ν„΄ν•œλ‹€.

두 객체λ₯Ό 비ꡐ할 λ•Œ, λ¨Όμ € hashcodeλ₯Ό λΉ„κ΅ν•œλ‹€. hashcodeκ°€ λ‹€λ₯΄λ‹€λ©΄ 두 κ°μ²΄λŠ” λͺ…λ°±ν•˜κ²Œ λ‹€λ₯΄λ‚˜, κ°™λ‹€λ©΄ equals()λ₯Ό 톡해 두 객체가 같은지 λΉ„κ΅ν•œλ‹€.

@Data

@Data μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λ©΄ @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor μ–΄λ…Έν…Œμ΄μ…˜μ„ ν•œ λ²ˆμ— μ μš©ν•  수 μžˆλ‹€. κ·ΈλŸ¬λ‚˜ 각각의 μ–΄λ…Έν…Œμ΄μ…˜μ— λŒ€ν•œ 세뢀적인 μ˜΅μ…˜μ„ μ μš©ν•  수 μ—†μœΌλ―€λ‘œ μ‹€λ¬΄μ—μ„œ 잘 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” νŽΈμ΄λ‹€.

@Builder

객체λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ λΉŒλ” νŒ¨ν„΄μ„ μžλ™μœΌλ‘œ κ΅¬ν˜„ν•΄μ€€λ‹€. λΉŒλ”λ₯Ό 톡해 객체λ₯Ό 생성할 λ•Œ 각 ν•„λ“œμ˜ 값을 λ©”μ„œλ“œ 체이닝 λ°©μ‹μœΌλ‘œ μ§€μ •ν•  수 μžˆλ‹€.

1
2
3
4
5
6
7
8
9
10
11
@Builder
public class Person {
    private final String name;
    private final int age;
}

Person person = Person.builder()
    .name("Alice")
    .age(25)
    .build();

πŸ“Œ μ£Όμ˜μ‚¬ν•­

  • λ¬΄λΆ„λ³„ν•œ Setter, Data, AllArgsConstructor λ“±κ³Ό 같은 μ–΄λ…Έν…Œμ΄μ…˜ μ‚¬μš©μ„ μ§€μ–‘ν•˜μž.
    • @Data λŠ” λΆˆν•„μš”ν•œ setter의 λ…ΈμΆœ, μˆœν™˜ μ°Έμ‘°, μ˜ˆμƒμΉ˜ λͺ»ν•œ λ™μž‘κ³Ό 같은 λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλ‹€.
    • @Setter λŠ” 객체의 λΆˆλ³€μ„±μ„ ν•΄μΉ  수 μžˆλ‹€.
    • @AllArgsConstructor λŠ” ν•„λ“œ μˆœμ„œκ°€ λ°”λ€Œκ±°λ‚˜ ν•„λ“œκ°€ μΆ”κ°€ λ˜λŠ” μ‚­μ œλ  λ•Œ 객체 생성 였λ₯˜κ°€ λ°œμƒν•  수 μžˆλ‹€. λ”°λΌμ„œ λͺ…ν™•ν•˜κ²Œ μƒμ„±μžλ₯Ό μž‘μ„±ν•˜λŠ” 것이 μ’‹λ‹€.
  • μˆœν™˜ μ°Έμ‘°κ°€ λ°œμƒν•˜λŠ” 상황을 μ‘°μ‹¬ν•˜μž. @ToString, @EqualsAndHashCode 와 같은 μ–΄λ…Έν…Œμ΄μ…˜μ„ μ–‘λ°©ν–₯ 연관관계가 μžˆλŠ” 엔티티에 μ‚¬μš©ν•˜λ©΄ μˆœν™˜ μ°Έμ‘°κ°€ λ°œμƒν•  수 μžˆλ‹€.
  • μ‚¬μš©ν•  μ–΄λ…Έν…Œμ΄μ…˜λ§Œ λͺ…μ‹œν•˜κ³ , ν•„μš”ν•œ λΆ€λΆ„μ—λ§Œ λͺ…μ‹œν•˜μž.

πŸ“Œ μ°Έκ³ 

https://lucas-owner.tistory.com/26#google_vignette

https://mangkyu.tistory.com/78

https://jake-seo-dev.tistory.com/70

This post is licensed under CC BY 4.0 by the author.