Post

@Builder

@Builder

πŸ“Œ @Builder λž€?

Lombok 의 @Builder λŠ” λΉŒλ” νŒ¨ν„΄μ„ μžλ™μœΌλ‘œ μƒμ„±ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜μ΄λ‹€.

1
2
3
4
5
6
7
8
@Getter
@Builder
public class User {
    private String name;
    private String email;
    private int age;
    private String address;
}
1
2
3
4
5
6
User user = User.builder()
    .name("κΉ€μ² μˆ˜")
    .email("kim@example.com")
    .age(30)
    .address("μ„œμšΈμ‹œ 강남ꡬ")
    .build();

@Builder λ₯Ό ν΄λž˜μŠ€μ— 뢙이면 Lombok이 컴파일 μ‹œμ μ— λΉŒλ” ν΄λž˜μŠ€μ™€ λ©”μ„œλ“œλ₯Ό μƒμ„±ν•œλ‹€.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
private User(String name, String email, int age, String address) {
    this.name = name;
    this.email = email;
    this.age = age;
    this.address = address;
}

public static UserBuilder builder() {
    return new UserBuilder();
}

public static class UserBuilder {
    private String name;
    private String email;
    private int age;
    private String address;

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

    public UserBuilder email(String email) {
        this.email = email;
        return this;
    }

    public UserBuilder age(int age) {
        this.age = age;
        return this;
    }

    public UserBuilder address(String address) {
        this.address = address;
        return this;
    }

    public User build() {
        return new User(name, email, age, address);
    }
}

Lombok이 μžλ™μœΌλ‘œ μƒμ„±ν•˜λŠ” μ½”λ“œλŠ” μ„Έ 가지이닀.

  1. 전체 ν•„λ“œλ₯Ό 인자둜 λ°›λŠ” private μƒμ„±μž
  2. λΉŒλ” 객체λ₯Ό λ¦¬ν„΄ν•˜λŠ” λ©”μ„œλ“œ
  3. λ‚΄λΆ€ λΉŒλ” 클래슀

ν•„λ“œμ˜ λͺ¨λ“  setter λ©”μ„œλ“œλŠ” return this; λ₯Ό ν¬ν•¨ν•˜κΈ°μ— λ©”μ„œλ“œ 체이닝이 κ°€λŠ₯ν•˜λ‹€.

πŸ“Œ μž₯점

  1. μƒμ„±μžλ‘œ 객체λ₯Ό μƒμ„±ν•˜λŠ” 방법보닀 가독성이 μ’‹λ‹€.
  2. λ©”μ„œλ“œ 체이닝을 톡해 ν•„μš”ν•œ ν•„λ“œλ§Œ μ„ νƒν•˜μ—¬ 객체λ₯Ό μœ μ—°ν•˜κ²Œ 생성할 수 μžˆλ‹€.
  3. λ§€κ°œλ³€μˆ˜ μˆœμ„œλ₯Ό μ‹ κ²½μ“°μ§€ μ•Šμ•„λ„ λœλ‹€.
  4. setter λ©”μ„œλ“œ 없이 λΆˆλ³€ 객체λ₯Ό 생성할 수 μžˆλ‹€.

πŸ“Œ 단점

  1. ν•„μˆ˜λ‘œ ν•„μš”ν•œ ν•„λ“œλ₯Ό λˆ„λ½ν•  κ°€λŠ₯성이 μžˆλ‹€.
  2. 객체 생성에 μ—¬λŸ¬ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ―€λ‘œ μ„±λŠ₯ 상 μ˜€λ²„ν—€λ“œκ°€ λ°œμƒν•œλ‹€.

πŸ“Œ @Builder κ΄€λ ¨ μ˜΅μ…˜

@Builder.Default

@Builder.Default λŠ” @Builder λ₯Ό μ‚¬μš©ν•  λ•Œ νŠΉμ • ν•„λ“œμ— 기본값을 μ„€μ •ν•˜κΈ° μœ„ν•œ μ˜΅μ…˜μ΄λ‹€.

1
2
3
4
5
6
7
8
9
@Builder
public class User {
    private String name;
    private int age = 20;
}

User user = User.builder()
    .name("홍길동")
    .build();

λΉŒλ”λŠ” ν•„λ“œμ˜ μ΄ˆκΈ°ν™” 값을 λ¬΄μ‹œν•˜κ³ , μ„€μ •λ˜μ§€ μ•ŠλŠ” ν•„λ“œμ—λŠ” null 을 ν• λ‹Ήν•œλ‹€. μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•œ 방법은 초기 값이 μ„€μ •λœ ν•„λ“œ μœ„μ— @Builder.Default λ₯Ό λͺ…μ‹œν•˜λŠ” 것이닀. 이λ₯Ό 톡해 λΉŒλ”κ°€ μ„€μ •λ˜μ§€ μ•Šμ•„λ„ κΈ°λ³Έ 값을 μ œλŒ€λ‘œ ν• λ‹Ήν•  수 μžˆλ‹€.

toBuilder

toBuilder μ˜΅μ…˜μ€ κΈ°μ‘΄ 객체의 ν•„λ“œ 값을 λ³΅μ‚¬ν•˜μ—¬ μƒˆλ‘œμš΄ 객체λ₯Ό 생성할 λ•Œ μ‚¬μš©ν•œλ‹€. λΆˆλ³€ 객체의 일뢀 κ°’λ§Œ λ³€κ²½ν•΄μ•Ό ν•  λ•Œ μœ μš©ν•˜λ‹€.

toBuilder μ˜΅μ…˜μ΄ ν™œμ„±ν™”λ˜λ©΄ Lombok은 컴파일 μ‹œμ μ— toBuilder λ©”μ„œλ“œλ₯Ό μƒμ„±ν•œλ‹€. 이 λ©”μ„œλ“œλŠ” κΈ°μ‘΄ 객체의 ν•„λ“œ κ°’μœΌλ‘œ μ΄ˆκΈ°ν™”λœ λΉŒλ”λ₯Ό λ¦¬ν„΄ν•œλ‹€.

1
2
3
4
5
6
7
8
9
Order firstOrder= Order.builder()
    .orderNumber("12345")
    .productName("λ…ΈνŠΈλΆ")
    .totalPrice(1500000L)
    .build();

Order secondOrder= firstOrder.toBuilder()
    .totalPrice(1450000L)
    .build();

단, toBuilder λ©”μ„œλ“œλŠ” κΈ°μ‘΄ 객체λ₯Ό μˆ˜μ •ν•˜λŠ” 것이 μ•„λ‹Œ μƒˆλ‘œμš΄ 객체λ₯Ό μƒμ„±ν•˜λŠ” κ²ƒμ΄λ―€λ‘œ 이λ₯Ό save ν•˜κ²Œ 되면 μ˜λ„μ™€ λ‹€λ₯Έ λ™μž‘μ΄ λ°œμƒν•  수 μžˆλ‹€. μœ„ μ˜ˆμ œμ—μ„œ secondOrder λŠ” firstOrder 와 λ³„κ°œμ˜ μΈμŠ€ν„΄μŠ€μ΄λ‹€. save(secondOrder) λ₯Ό ν˜ΈμΆœν•˜λ©΄ JPAλŠ” INSERT 쿼리λ₯Ό μ‹€ν–‰ν•˜μ—¬ μƒˆλ‘œμš΄ λ ˆμ½”λ“œκ°€ μΆ”κ°€λœλ‹€.

JPA μ—”ν‹°ν‹°λ₯Ό μ˜¬λ°”λ₯΄κ²Œ μˆ˜μ •ν•˜κΈ° μœ„ν•œ 방법은 toBuilder λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ•„λ‹ˆλΌ μ˜μ† μƒνƒœ μ—”ν‹°ν‹°λ₯Ό setter λ‚˜ λ©”μ„œλ“œλ₯Ό 톡해 값을 λ³€κ²½ν•΄μ•Ό ν•œλ‹€.

@SuperBuilder

@SuperBuilder λŠ” 상속 관계에 μžˆλŠ” ν΄λž˜μŠ€μ—μ„œ λΉŒλ”λ₯Ό μ˜¬λ°”λ₯΄κ²Œ μ‚¬μš©ν•  수 μžˆλ„λ‘ ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜μ΄λ‹€.

1
2
3
4
5
6
7
8
9
@Builder
public class Parent {
    private String parentName;
}

@Builder
public class Child extends Parent {
    private String childName;
}

상속 관계에 μžˆλŠ” ν΄λž˜μŠ€μ— @Builder λ₯Ό μ‚¬μš©ν•˜λ©΄ 컴파일 μ—λŸ¬κ°€ λ°œμƒν•˜κ²Œ λœλ‹€. μžμ‹ ν΄λž˜μŠ€λŠ” λΆ€λͺ¨ 클래슀의 정적 멀버λ₯Ό μƒμ†λ°›μœΌλ©°, λ”°λΌμ„œ μžμ‹ ν΄λž˜μŠ€μ—λŠ” μžμ‹μ˜ builder λ©”μ„œλ“œμ™€ λΆ€λͺ¨μ˜ builder λ©”μ„œλ“œκ°€ λ™μ‹œμ— μ‘΄μž¬ν•˜κ²Œ λœλ‹€. μžλ°”λŠ” 정적 λ©”μ„œλ“œμ˜ μ˜€λ²„λΌμ΄λ”©μ„ ν—ˆμš©ν•˜μ§€ μ•ŠμœΌλ©°, μžμ‹μ˜ λ©”μ„œλ“œκ°€ λΆ€λͺ¨μ˜ λ©”μ„œλ“œλ₯Ό μˆ¨κΉ€ μ²˜λ¦¬ν•œλ‹€. κ·ΈλŸ¬λ‚˜ @Builder λŠ” 각 ν΄λž˜μŠ€μ— λŒ€ν•΄ μ„œλ‘œ κ΄€λ ¨ μ—†λŠ” λ‚΄λΆ€ λΉŒλ” 클래슀λ₯Ό μƒμ„±ν•œλ‹€. λ”°λΌμ„œ μžμ‹ ν΄λž˜μŠ€λŠ” 이름은 κ°™μœΌλ„ˆ μ„œλ‘œ ν˜Έν™˜λ˜μ§€ μ•ŠλŠ” 리턴 νƒ€μž…μ„ κ°€μ§„ 두 개의 builder λ©”μ„œλ“œλ₯Ό κ°€μ§€κ²Œ λ˜μ–΄ 컴파일 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.

@SuperBuilder λ₯Ό μ‚¬μš©ν•˜λ©΄ μžμ‹ 클래슀의 λΉŒλ”μ—μ„œ λΆ€λͺ¨ 클래슀 ν•„λ“œκΉŒμ§€ μ„€μ •ν•  수 있게 λœλ‹€. κ·Έ μ΄μœ λŠ” @Builder 와 달리 상속 관계λ₯Ό μ§€μ›ν•˜κΈ° μœ„ν•΄ μ œλ„€λ¦­μ„ μ‚¬μš©ν•œ λΉŒλ” 클래슀 계측을 μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€. 즉, λ‚΄λΆ€μ μœΌλ‘œ μžμ‹ λΉŒλ”κ°€ λΆ€λͺ¨ λΉŒλ”λ₯Ό μƒμ†λ°›λŠ” ꡬ쑰λ₯Ό λ§Œλ“ λ‹€.

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