πŸ—οΈ λΉŒλ”(Builder) νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λŠ” 이유

HanjmoΒ·2024λ…„ 2μ›” 8일
post-thumbnail

ν‰ν™”λ‘­κ²Œ ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜λ˜ 도쀑에 정말 어이 μ—†λŠ” μ‹€μˆ˜λ₯Ό ν•΄μ„œ 잠깐 μ‚½μ§ˆν•˜λŠ” μ‹œκ°„μ„ κ°€μ§€κ³  μ™”λ‹€.

@Data
@AllArgsConstructor
public class VoteRequest {
    private Long selectedOptionId;
    private Long memberId;

		...
}

// 문제의 μ½”λ“œ. νŒŒλΌλ―Έν„°μ˜ μˆœμ„œλ₯Ό μ„œλ‘œ λ°”κΏ”μ„œ 전달함...
VoteRequest voteRequest = new VoteRequest(**member.getId(), optionB.getId()**);

μœ„μ™€ 같이 μž‘μ„±λœ DTO 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ 인자λ₯Ό 잘λͺ» μ „λ‹¬ν•΄μ„œ μ΄μƒν•œ 였λ₯˜κ°€ λ°œμƒν–ˆλŠ”λ°, ν•˜ν•„ λ‘˜ λ‹€ Long νƒ€μž…μ΄λΌ ν•œμ°Έμ„ ν—€λ§Έλ‹€.

μ΄λŸ¬ν•œ μ‹€μˆ˜λ₯Ό λ‹€μŒμ— 또 μΌμ–΄λ‚˜μ§€ μ•Šλ„λ‘ ν•˜κ³ μž, μ–΄λ…Έν…Œμ΄μ…˜λ§Œ 달아놓고 뭔지도 λͺ¨λ₯΄κ³  μ“°λ˜ Builder νŒ¨ν„΄μ— λŒ€ν•΄ ν•™μŠ΅ν•΄λ΄€λ‹€.

λΉŒλ” νŒ¨ν„΄μ΄λž€?

λΉŒλ” νŒ¨ν„΄μ΄λž€ 객체의 생성 κ³Όμ •κ³Ό ν‘œν˜„ 방법을 λΆ„λ¦¬ν•˜μ—¬ λ‹€μ–‘ν•œ κ΅¬μ„±μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“œλŠ” 생성 νŒ¨ν„΄μ΄λ‹€.

예λ₯Ό λ“€μ–΄ 집을 μ§“λŠ”λ‹€κ³  ν•  λ•Œ, μ–΄λ–€ 집은 λͺ©μž¬λ₯Ό μ‚¬μš©ν•˜κ³  λ‹€λ₯Έ 집은 콘크리트λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€. μ΄λ ‡κ²Œ 집을 μ§“λŠ” κ³Όμ •(생성 κ³Όμ •)이 λ‹€λ₯΄λ”라도 μ™„μ„±λœ λͺ¨μŠ΅μ€ μ§‘μ΄λΌλŠ” 곡톡적인 ν˜•νƒœ(ν‘œν˜„ 방법)λ₯Ό λ„κ²Œ 될 것이닀.

이처럼 λΉŒλ” νŒ¨ν„΄μ€ 객체의 생성 κ³Όμ •κ³Ό ν‘œν˜„ λ°©λ²•μ΄λΌλŠ” 두 관심사λ₯Ό λΆ„λ¦¬ν•˜μ—¬ μœ μ§€ 보수λ₯Ό μš©μ΄ν•˜κ²Œ λ§Œλ“ λ‹€.

λΉŒλ” νŒ¨ν„΄μ€ μ–΄λ–»κ²Œ νƒ„μƒν–ˆμ„κΉŒ?

πŸ•‘ 점측적 μƒμ„±μž νŒ¨ν„΄(Telescoping Constructor Pattern)

점측적 μƒμ„±μž νŒ¨ν„΄μ€ ν•„μˆ˜ λ§€κ°œλ³€μˆ˜μ™€ ν•¨κ»˜ 0κ°œλΆ€ν„° 1개, 2κ°œμ”© 점차 μ¦κ°€ν•˜λŠ” 선택 λ§€κ°œλ³€μˆ˜λ₯Ό λ°›λŠ” ν˜•νƒœλ‹€.
즉, λ‹€μ–‘ν•œ λ§€κ°œλ³€μˆ˜λ₯Ό 전달 λ°›μ•„ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κ³  싢을 λ•Œ 기쑴에 μ‚¬μš©ν•˜λ˜ μƒμ„±μžλ₯Ό μ˜€λ²„λ‘œλ”©ν•˜λŠ” 방식이닀.

class Sandwich {
    // ν•„μˆ˜
    private String bread;
    private String bacon;

    // 선택
    private String source;
    private String cheese;
    private String tomato;
    private String lettuce;

    public Sandwich(String bread, String bacon) {
        this.bread = bread;
        this.bacon = bacon;
    }

    public Sandwich(String bread, String bacon, String tomato) {
        this.bread = bread;
        this.bacon = bacon;
        this.tomato = tomato;
    }

    public Sandwich(String bread, String bacon, String source, String cheese) {
        this.bread = bread;
        this.bacon = bacon;
        this.source = source;
        this.cheese = cheese;
    }
    
    ...
}

μ΄λŸ¬ν•œ 점측적 μƒμ„±μž νŒ¨ν„΄μ—λŠ” λͺ‡ κ°€μ§€ 단점이 μ‘΄μž¬ν•œλ‹€.

  1. 클래슀의 ν•„λ“œ κ°œμˆ˜κ°€ μ¦κ°€ν• μˆ˜λ‘ μƒμ„±μžμ— λ“€μ–΄κ°ˆ 수 μžˆλŠ” 인자 μˆ˜κ°€ μ¦κ°€ν•˜κ²Œ λ˜λŠ”λ°, μ΄λ ‡κ²Œ 되면 μƒμ„±μžμ˜ λͺ‡ 번째 μΈμžκ°€ μ–΄λ–€ ν•„λ“œμ˜€λŠ”μ§€ ν—·κ°ˆλ¦¬λŠ” λ¬Έμ œκ°€ λ°œμƒν•œλ‹€.
    (λ‚΄κ°€ μ΄λ²ˆμ— λΉŒλ” νŒ¨ν„΄μ„ ν•™μŠ΅ν•˜κ²Œ 된 근본적인 원인이닀…πŸ₯²)

  2. μœ„ μ˜ˆμ œμ—μ„œ μƒŒλ“œμœ„μΉ˜λ₯Ό λ§Œλ“€ λ•Œ λΉ΅κ³Ό ν† λ§ˆν† λ§Œ λ„£κ³  싢은 경우 μ•„λž˜ μƒμ„±μžμ—μ„œ bacon 뢀뢄은 μ–΄μ©” 수 없이 null을 전달해야 ν•œλ‹€.

    public Sandwich(String bread, String bacon) {
        this.bread = bread;
    		this.bacon = bacon;
    }
  3. β€˜μ μΈ΅μ  μƒμ„±μžβ€™λΌλŠ” μ΄λ¦„μ—μ„œ μ•Œ 수 μžˆλ“―, νƒ€μž…μ΄ λ‹€μ–‘ν• μˆ˜λ‘ μƒμ„±μžκ°€ κΈ°ν•˜κΈ‰μˆ˜μ μœΌλ‘œ μ¦κ°€ν•œλ‹€. μ΄λŠ” 가독성을 λ–¨μ–΄λœ¨λ¦¬λ©° μœ μ§€ 보수 μΈ‘λ©΄μ—μ„œλ„ ꡉμž₯히 μ’‹μ§€ μ•Šλ‹€.

πŸ•’ μžλ°” 빈(Java Beans) νŒ¨ν„΄

μœ„μ—μ„œ μ‚΄νŽ΄λ³Έ 점측적 μƒμ„±μž νŒ¨ν„΄μ˜ 단점을 λ³΄μ™„ν•˜κΈ° μœ„ν•΄ κ³ μ•ˆλœ νŒ¨ν„΄μœΌλ‘œ, λ§€κ°œλ³€μˆ˜κ°€ μ—†λŠ” μƒμ„±μžλ‘œ 객체λ₯Ό μƒμ„±ν•œ ν›„ setterλ₯Ό μ΄μš©ν•΄ ν•„λ“œλ₯Ό μ΄ˆκΈ°ν™”ν•˜λŠ” 방식이닀.

class Sandwich {
		...

    public Sandwich() {
    }

    public void setBread(String bread) {
        this.bread = bread;
    }

    public void setBacon(String bacon) {
        this.bacon = bacon;
    }

    // λ¬΄μˆ˜ν•œ setterλ“€...
}

μžλ°” 빈 νŒ¨ν„΄μ€ 점측적 μƒμ„±μž νŒ¨ν„΄μ˜ 단점을 μ–΄λ–»κ²Œ λ³΄μ™„ν–ˆμ„κΉŒ?

  1. μƒμ„±μžμ˜ λ§€κ°œλ³€μˆ˜κ°€ ν—·κ°ˆλ¦¬λŠ” 문제 β‡’ 클래슀의 각 ν•„λ“œλ§ˆλ‹€ setterκ°€ μ‘΄μž¬ν•˜κ³ , 이 setterλ₯Ό 톡해 값을 μ£Όμž…ν•˜κΈ° λ•Œλ¬Έμ— λ§€κ°œλ³€μˆ˜λ₯Ό ν—·κ°ˆλ¦΄ 일이 μ—†λ‹€.
  2. null 전달 β‡’ λ§€κ°œλ³€μˆ˜κ°€ μ—†λŠ” μƒμ„±μžλ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό λ¨Όμ € μƒμ„±ν•˜κΈ° λ•Œλ¬Έμ— μ–΅μ§€λ‘œ null을 전달할 ν•„μš”κ°€ μ—†λ‹€.
  3. 가독성 문제 β‡’ λ§Žμ€ μƒμ„±μžκ°€ ν•„μš”ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 가독성이 μ˜¬λΌκ°„λ‹€.

이처럼 setterλ₯Ό μ‚¬μš©ν•˜λ©΄ μœ μ—°ν•œ 객체λ₯Ό 생성할 수 μžˆμ§€λ§Œ, μžλ°” 빈 νŒ¨ν„΄λ„ 치λͺ…적인 단점이 μ‘΄μž¬ν•œλ‹€.

  1. 일관성(consistency)

    ν•„μˆ˜ λ§€κ°œλ³€μˆ˜λŠ” 객체가 μ΄ˆκΈ°ν™”λ  λ•Œ λ°˜λ“œμ‹œ μ„€μ •λ˜μ–΄μ•Ό ν•œλ‹€. ν•˜μ§€λ§Œ κ°œλ°œμžκ°€ μ‹€μˆ˜λ‘œ ν•„μˆ˜ λ§€κ°œλ³€μˆ˜μ˜ setterλ₯Ό μž‘μ„±ν•˜μ§€ μ•Šκ±°λ‚˜ ν˜ΈμΆœν•˜μ§€ μ•Šμ„ 경우 ν•΄λ‹Ή 객체의 일관성이 λ¬΄λ„ˆμ§€κ²Œ λœλ‹€.

    이처럼 일관성이 λ¬΄λ„ˆμ§„ 객체λ₯Ό λ§Œμ•½ λ‹€λ₯Έ κ³³μ—μ„œ μ‚¬μš©ν•˜κ²Œ 되면 λŸ°νƒ€μž„ μ˜ˆμ™Έκ°€ λ°œμƒν•  것이닀.

  2. λΆˆλ³€(immutable)

    μ™ΈλΆ€μ μœΌλ‘œ setterλ₯Ό λ…ΈμΆœν•˜κ²Œ 되면, λˆ„κ΅°κ°€ 고의둜 setterλ₯Ό ν˜ΈμΆœν•΄μ„œ 객체λ₯Ό μ‘°μž‘ν•  수 있게 λœλ‹€. 즉, 객체가 μ–Έμ œλ“ μ§€ λ³€ν•  수 μžˆλŠ” μœ„ν—˜μ΄ μžˆλ‹€.

πŸ•™ λΉŒλ”(Builder) νŒ¨ν„΄

점측적 μƒμ„±μž νŒ¨ν„΄κ³Ό μžλ°” 빈 νŒ¨ν„΄μ˜ λͺ¨λ“  λ¬Έμ œλ“€μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ λ“œλ””μ–΄ λΉŒλ” νŒ¨ν„΄μ΄ λ“±μž₯ν–ˆλ‹€.

λΉŒλ” νŒ¨ν„΄μ€ λ³„λ„μ˜ 클래슀(Builder)λ₯Ό λ§Œλ“€μ–΄ λ©”μ„œλ“œλ₯Ό 톡해 값을 ν•˜λ‚˜ν•˜λ‚˜ 전달 λ°›κ³ , μ΅œμ’…μ μœΌλ‘œ ν•˜λ‚˜μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ—¬ λ°˜ν™˜ν•˜λŠ” 방식이닀.

λΉŒλ” νŒ¨ν„΄ ꡬ쑰

예제λ₯Ό 톡해 λΉŒλ” νŒ¨ν„΄μ˜ ꡬ쑰λ₯Ό μ‚΄νŽ΄λ³΄μž.

Post 클래슀

κ²Œμ‹œκΈ€μ„ μ˜λ―Έν•˜λŠ” Post ν΄λž˜μŠ€λŠ” 멀버 λ³€μˆ˜λ‘œ 아이디, 제λͺ©, λ‚΄μš©, μž‘μ„±μž, μž‘μ„±μΌμ„ κ°€μ§€κ³  있으며, ν•˜λ‚˜μ˜ μƒμ„±μžλ„ μ‘΄μž¬ν•œλ‹€.

class Post {
    private Long id; // 아이디
    private String title; // 제λͺ©
    private String content; // λ‚΄μš©
    private String createdBy; // μž‘μ„±μž
    private LocalDate createdDate; // μž‘μ„±μΌ

    public Post(Long id, String title, String content, String createdBy, LocalDate createdDate) {
        this.id = id;
        this.title = title;
        this.content = content;
        this.createdBy = createdBy;
        this.createdDate = createdDate;
    }
}

λΉŒλ” 클래슀 κ΅¬ν˜„

λ‹€μŒμœΌλ‘œ Post 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ λΉŒλ” 클래슀λ₯Ό κ΅¬ν˜„ν•œλ‹€.

class PostBuilder {
    private Long id; // 아이디
    private String title; // 제λͺ©
    private String content; // λ‚΄μš©
    private String createdBy; // μž‘μ„±μž
    private LocalDate createdDate; // μž‘μ„±μΌ

    public PostBuilder id(Long id) {
        this.id = id;
        return this;
    }

    public PostBuilder title(String title) {
        this.title = title;
        return this;
    }

    public PostBuilder content(String content) {
        this.content = content;
        return this;
    }

    public PostBuilder createdBy(String createdBy) {
        this.createdBy = createdBy;
        return this;
    }

    public PostBuilder createdDate(LocalDate createdDate) {
        this.createdDate = createdDate;
        return this;
    }

    public Post build() {
        return new Post(id, title, content, createdBy, createdDate);
    }
}

PostBuilder 클래슀의 멀버 λ³€μˆ˜λŠ” λŒ€μƒ 클래슀인 Post의 멀버 λ³€μˆ˜μ™€ λ˜‘κ°™μ΄ κ΅¬μ„±λ˜μ–΄ 있으며, 각 멀버 λ³€μˆ˜μ— λŒ€ν•œ μ΄ˆκΈ°ν™” λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•˜κ³  μžˆλ‹€.

μ΄λ•Œ 각 μ΄ˆκΈ°ν™” λ©”μ„œλ“œλŠ” 가독성을 μœ„ν•΄, 그리고 κΈ°μ‘΄ setter와 μ°¨λ³„ν•˜κΈ° μœ„ν•΄ λ©”μ„œλ“œλͺ…을 κ°„λ‹¨ν•˜κ²Œ ν•„λ“œλͺ…μœΌλ‘œ μ§€μ–΄μ€€λ‹€. 그리고 λ©”μ„œλ“œμ—μ„œ μ€‘μš”ν•˜κ²Œ 봐야할 또 λ‹€λ₯Έ 점은 자기 μžμ‹ μ„ λ°˜ν™˜ν•œλ‹€λŠ” 것이닀. μ΄λŠ” 후에 μ„€λͺ…ν•  λ©”μ„œλ“œ 체이닝을 μœ„ν•œ 과정이닀.

λ§ˆμ§€λ§‰μœΌλ‘œ μ΅œμ’… 객체λ₯Ό λ§Œλ“€μ–΄μ£ΌλŠ” build λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•œλ‹€. 이 λ©”μ„œλ“œλŠ” μ΄ˆκΈ°ν™”ν•œ 멀버 λ³€μˆ˜λ“€μ„ κ°€μ§€κ³  Postλ₯Ό μƒμ„±ν•˜μ—¬ λ°˜ν™˜ν•œλ‹€.

μ‹€ν–‰ μ½”λ“œ

이제 PostBuilder 클래슀λ₯Ό μ΄μš©ν•΄ Post 객체λ₯Ό μƒμ„±ν•΄λ³΄μž.

public class Main {
    public static void main(String[] args) {
        Post post = new PostBuilder()
                .id(1L)
                .title("κ²Œμ‹œκΈ€ 제λͺ©")
                .content("κ²Œμ‹œκΈ€ λ‚΄μš©")
                .createdBy("홍길동")
                .createdDate(LocalDate.now())
                .build();

        System.out.println(post);
    }
}

PostBuilder 클래슀의 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ 값을 μ „λ‹¬ν•œ λ’€ μ΅œμ’…μ μœΌλ‘œ build λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ λ‹€μŒκ³Ό 같이 Post 객체가 μƒμ„±λœλ‹€.

λΉŒλ” νŒ¨ν„΄μ˜ μž₯단점

μž₯점

  • 객체 생성 과정을 μΌκ΄€λœ ν”„λ‘œμ„ΈμŠ€λ‘œ ν‘œν˜„ λΉŒλ” νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λ©΄ μ–΄λ–€ ν•„λ“œμ— μ–΄λ–€ 값이 μ„€μ •λ˜λŠ”μ§€ μ§κ΄€μ μœΌλ‘œ μ•Œ 수 μžˆλ‹€. λ”°λΌμ„œ 객체λ₯Ό μΌκ΄€μ μœΌλ‘œ 생성할 수 있게 λœλ‹€. 특히 μ—°μ†λœ 같은 νƒ€μž…μ˜ λ§€κ°œλ³€μˆ˜λ₯Ό 많이 μ„€μ •ν•΄μ•Ό ν•  λ•Œ λ°œμƒ κ°€λŠ₯ν•œ μ‹€μˆ˜λ₯Ό λ°©μ§€ν•  수 μžˆλ‹€.
  • λ””ν΄νŠΈ λ§€κ°œλ³€μˆ˜ μƒλž΅ κ°„μ ‘ 지원 인자λ₯Ό λ”°λ‘œ μ „λ‹¬ν•˜μ§€ μ•Šμ„ 경우 λ‹€μŒκ³Ό 같이 기본적으둜 μ„€μ •λ˜λŠ” λ§€κ°œλ³€μˆ˜λ₯Ό λ””ν΄νŠΈ λ§€κ°œλ³€μˆ˜λΌκ³  ν•œλ‹€.
    public Post(Long id, **String title = "제λͺ©"**, String content, ...) {
        this.id = id;
        this.title = title;
    	  this.content = content;
    		...
    }
    Python, JS, C++ λ“± λ‹€μˆ˜ μ–Έμ–΄μ—μ„œ λ””ν΄νŠΈ λ§€κ°œλ³€μˆ˜λ₯Ό μ§€μ›ν•˜μ§€λ§Œ, Javaμ—μ„œλŠ” μ§€μ›ν•˜μ§€ μ•ŠλŠ”λ‹€. λ”°λΌμ„œ λ””ν΄νŠΈ λ§€κ°œλ³€μˆ˜λ₯Ό κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄μ„œλŠ” 클래슀 ν•„λ“œ λ³€μˆ˜μ— μ΄ˆκΉƒκ°’μ„ 미리 μ„€μ •ν•˜κ³ , μ΄ˆκΈ°ν™”λœ ν•„λ“œλŠ” λ§€κ°œλ³€μˆ˜μ—μ„œ μ œμ™Έμ‹œν‚¨ μƒμ„±μžλ₯Ό λ”°λ‘œ λ§Œλ“€μ–΄μ•Ό ν•œλ‹€. ν•˜μ§€λ§Œ μ΄λŠ” κ²°κ΅­ μ§€λ‚˜μΉœ μƒμ„±μž μ˜€λ²„λ‘œλ”©μœΌλ‘œ 인해 본래의 문제둜 λ˜λŒμ•„κ°€λŠ” 것이닀.
    class PostBuilder {
        private Long id;
        private String title = "제λͺ©"; // default parameter μ—­ν•  μˆ˜ν–‰
        private String content;
        private String createdBy;
        private LocalDate createdDate;
    
    		...
    λΉŒλ” νŒ¨ν„΄μ—μ„œλ„ λ””ν΄νŠΈ λ§€κ°œλ³€μˆ˜λ₯Ό κ΅¬ν˜„ν•˜λŠ” 방법은 λ™μΌν•˜λ‹€. ν•˜μ§€λ§Œ λ””ν΄νŠΈ λ§€κ°œλ³€μˆ˜κ°€ μ„€μ •λœ ν•„λ“œμ— λŒ€ν•œ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ§€ μ•ŠλŠ” 방식을 μ‚¬μš©ν•˜λ©΄, λ””ν΄νŠΈ λ§€κ°œλ³€μˆ˜λ₯Ό μƒλž΅ν•˜κ³  ν˜ΈμΆœν•˜λŠ” 효과λ₯Ό κ°„μ ‘μ μœΌλ‘œ κ΅¬ν˜„ν•  수 μžˆλ‹€.
    Post post = new PostBuilder()
            .id(1L)
            .title("κ²Œμ‹œκΈ€ 제λͺ©")
            .content("κ²Œμ‹œκΈ€ λ‚΄μš©")
            .createdBy("홍길동")
            .createdDate(LocalDate.now())
    				.build();
    
    System.out.println(post);

  • ν•„μˆ˜ 멀버와 선택 멀버 뢄리 κ°€λŠ₯ μ΄ˆκΈ°ν™”κ°€ ν•„μˆ˜μΈ 멀버 λ³€μˆ˜λŠ” λΉŒλ” 클래슀의 μƒμ„±μžλ‘œ λ°›κ²Œ ν•¨μœΌλ‘œμ¨, ν•„μˆ˜ 멀버 λ³€μˆ˜λ₯Ό μ΄ˆκΈ°ν™” ν•΄μ•Όλ§Œ 객체가 μƒμ„±λ˜λ„λ‘ μœ λ„ν•  수 μžˆλ‹€.
    Post post = new PostBuilder(1L)
    				.content("κ²Œμ‹œκΈ€ λ‚΄μš©")
            .createdBy("κΉ€μ² μˆ˜")
            .createdDate(LocalDate.now())
    				.build();
  • 멀버별 μ΄ˆκΈ°ν™” 검증 κ°€λŠ₯ μƒμ„±μžλ₯Ό μ‚¬μš©ν•΄ 값을 전달 받을 경우 λ§€κ°œλ³€μˆ˜μ— λŒ€ν•œ 검증 λ‘œμ§μ„ 각 μƒμ„±μž μ•ˆμ—μ„œ λ³„λ„λ‘œ μ²˜λ¦¬ν•΄μ•Ό ν•œλ‹€. μ΄λŠ” μƒμ„±μžμ˜ 크기가 μ»€μ§€λŠ” 문제λ₯Ό μ•ΌκΈ°ν•œλ‹€. λ°˜λ©΄μ— λΉŒλ” νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λ©΄ 각각의 λ©”μ„œλ“œλ₯Ό 톡해 λ©€λ²„λ³„λ‘œ 검증 λ‘œμ§μ„ λ”°λ‘œ λ‘˜ 수 있기 λ•Œλ¬Έμ— μœ μ§€ λ³΄μˆ˜κ°€ μš©μ΄ν•΄μ§„λ‹€.

단점

μž₯점만 μžˆμ„ 것 같은 λΉŒλ” νŒ¨ν„΄μ—λ„ λͺ‡ κ°€μ§€ 단점이 μ‘΄μž¬ν•œλ‹€.

  • μ½”λ“œ λ³΅μž‘μ„± 증가 N개의 ν΄λž˜μŠ€μ— λŒ€ν•΄ N개의 λΉŒλ” 클래슀λ₯Ό λ§Œλ“€μ–΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— 관리해야 ν•  클래슀 κ°œμˆ˜κ°€ μ¦κ°€ν•΄μ§€λ©΄μ„œ ꡬ쑰가 λ³΅μž‘ν•΄μ§„λ‹€.
  • μ„±λŠ₯ 이슈 맀번 λΉŒλ” 클래슀의 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κΈ° λ•Œλ¬Έμ— μƒμ„±μžλ³΄λ‹€λŠ” μ„±λŠ₯이 μ•½κ°„ λ–¨μ–΄μ§„λ‹€. λ¬Όλ‘  객체 생성 λΉ„μš© μžμ²΄κ°€ κ·Έλ ‡κ²Œ 크지 μ•Šμ•„ μ‹¬κ°ν•œ λ¬Έμ œλŠ” μ•„λ‹ˆλ‹€.

μ•žμ—μ„œ λ΄μ„œ μ•Œ 수 μžˆλ“―μ΄ λΉŒλ” νŒ¨ν„΄μ˜ μ½”λ“œλŠ” λ‹€μ†Œ μž₯ν™©ν•˜λ‹€.
λ”°λΌμ„œ ν•„λ“œ μˆ˜κ°€ 적고 λ³€κ²½ κ°€λŠ₯성이 μ—†μœΌλ©΄ 차라리 정적 νŒ©ν† λ¦¬ λ©”μ„œλ“œλ₯Ό μ΄μš©ν•˜μž.
λ‹€λ§Œ APIλŠ” μ‹œκ°„μ΄ μ§€λ‚ μˆ˜λ‘ λ§€κ°œλ³€μˆ˜κ°€ μ¦κ°€ν•˜κΈ° λ•Œλ¬Έμ— μ• μ΄ˆμ— λΉŒλ” νŒ¨ν„΄μœΌλ‘œ μ‹œμž‘ν•˜λŠ”κ²Œ λ‚˜μ„ μˆ˜λ„ μžˆλ‹€.

λΉŒλ” ν΄λž˜μŠ€λŠ” κ΅¬ν˜„ν•  클래슀의 λ‚΄λΆ€ 정적 클래슀둜 κ΅¬ν˜„ν•œλ‹€

λΉŒλ” νŒ¨ν„΄ ꡬ쑰 λΆ€λΆ„μ—μ„œ 보여쀀 Post ν΄λž˜μŠ€λŠ” 사싀 λ‹€μŒκ³Ό 같이 κ΅¬ν˜„λ˜μ–΄μ•Ό ν•œλ‹€.

λΉŒλ” ν΄λž˜μŠ€κ°€ Post의 λ‚΄λΆ€ 정적 클래슀둜 κ΅¬ν˜„λ˜λ©°, Post의 μƒμ„±μžλŠ” private으둜 μ„€μ •ν•œλ‹€.

class Post {
    private Long id; // 아이디
    private String title; // 제λͺ©
    private String content; // λ‚΄μš©
    private String createdBy; // μž‘μ„±μž
    private LocalDate createdDate; // μž‘μ„±μΌ

    private Post(Builder builder) {
        this.id = id;
        this.title = title;
        this.content = content;
        this.createdBy = createdBy;
        this.createdDate = createdDate;
    }

    public static class Builder {
        private Long id; // 아이디
        private String title; // 제λͺ©
        private String content; // λ‚΄μš©
        private String createdBy; // μž‘μ„±μž
        private LocalDate createdDate; // μž‘μ„±μΌ

        public Builder id(Long id) {
            this.id = id;
            return this;
        }

        public Builder title(String title) {
            this.title = title;
            return this;
        }

        public Builder content(String content) {
            this.content = content;
            return this;
        }

        public Builder createdBy(String createdBy) {
            this.createdBy = createdBy;
            return this;
        }

        public Builder createdDate(LocalDate createdDate) {
            this.createdDate = createdDate;
            return this;
        }

        public Post build() {
            return new Post(id, title, content, createdBy, createdDate);
        }
    }
}

ν•˜λ‚˜μ˜ λΉŒλ” ν΄λž˜μŠ€λŠ” 였직 ν•˜λ‚˜μ˜ λŒ€μƒ 객체 μƒμ„±λ§Œμ„ μœ„ν•΄ μ‚¬μš©λœλ‹€. λ”°λΌμ„œ 두 클래슀λ₯Ό 물리적으둜 λ¬Άμ–΄λ²„λ¦ΌμœΌλ‘œμ¨ 두 클래슀 κ°„μ˜ 관계λ₯Ό μ‰½κ²Œ νŒŒμ•…ν•  수 있게 λœλ‹€.

λ˜ν•œ, λΉŒλ” 클래슀λ₯Ό 정적 클래슀둜 κ΅¬ν˜„ν•¨μœΌλ‘œμ¨ μ™ΈλΆ€ 클래슀의 μΈμŠ€ν„΄μŠ€ 없이도 생성할 수 있게 λœλ‹€.
λ§Œμ•½ λΉŒλ” ν΄λž˜μŠ€κ°€ 일반 λ‚΄λΆ€ 클래슀둜 κ΅¬ν˜„λœλ‹€λ©΄, λ‚΄λΆ€ 클래슀(Builder) 생성 전에 μ™ΈλΆ€ 클래슀(Post)의 μΈμŠ€ν„΄μŠ€λ₯Ό λ¨Όμ € 생성해야 ν•˜λŠ” λͺ¨μˆœμ— λΉ μ§„λ‹€.

Post 클래슀의 μƒμ„±μžλ₯Ό private으둜 μ„€μ •ν•œ μ΄μœ λŠ” λŒ€μƒ 객체가 였직 λΉŒλ”μ— μ˜ν•΄ μ΄ˆκΈ°ν™”λ˜κΈ° λ•Œλ¬Έμ΄λ‹€. 즉, μƒμ„±μžλ₯Ό 외뢀에 λ…ΈμΆœν•  ν•„μš”κ°€ μ—†κΈ° λ•Œλ¬Έμ— μƒμ„±μžλ₯Ό private으둜 μ„€μ •ν•˜λŠ” 것이닀.

Lombok의 @Builder

κ°œλ°œμžκ°€ λ”μš± νŽΈν•˜κ²Œ λΉŒλ” νŒ¨ν„΄μ„ μ‚¬μš©ν•  수 μžˆλ„λ‘ Lombokμ—μ„œλŠ” λ³„λ„μ˜ μ–΄λ…Έν…Œμ΄μ…˜μ„ μ§€μ›ν•˜λŠ”λ°, 그것이 λ°”λ‘œ @Builderλ‹€. λ‹€μŒκ³Ό 같이 ν΄λž˜μŠ€μ— λΆ™μ—¬μ£ΌκΈ°λ§Œ ν•˜λ©΄ 내뢀에 λΉŒλ” ν΄λž˜μŠ€μ™€ builder λ©”μ„œλ“œλ₯Ό μƒμ„±λœλ‹€.

@Builder
class Post {
    private Long id;
    private String title;
    private String content;
    private String createdBy;
    private LocalDate createdDate;

		private Post(Builder builder) {
        this.id = id;
        this.title = title;
        this.content = content;
        this.createdBy = createdBy;
        this.createdDate = createdDate;
    }
}

끝으둜

λ‹€μ‹œλŠ” 이와 같은 μ‹€μˆ˜λ₯Ό ν•˜μ§€ μ•Šκ² λ‹€λŠ” 의미둜 λΉŒλ” νŒ¨ν„΄μ˜ κ°œλ…κ³Ό 탄생 λ°°κ²½, 그리고 μž₯λ‹¨μ κΉŒμ§€ μ•Œμ•„λ΄€λ‹€.

μ§€κΈˆκΉŒμ§€λŠ” λ‹¨μˆœνžˆ μ–΄λ…Έν…Œμ΄μ…˜λ§Œ 뢙이고 μ–΄λ–»κ²Œ λŒμ•„κ°€λŠ”μ§€ λͺ°λžλŠ”λ°, μ΄λ ‡κ²Œ μ•Œμ•„λ³΄λ‹ˆ μ–΄λ–»κ²Œ μ‚¬μš©ν•΄μ•Όν• μ§€ 더 λͺ…ν™•ν•˜κ²Œ 와닿은 λ“― ν•˜λ‹€.

0개의 λŒ“κΈ€