본문 바로가기
개발

[Lombok] @Builder와 @SuperBuilder (2탄)

by angeloper 2023. 6. 28.
반응형

오늘은 바로 앞 글에서 @Builder와 @SuperBuilder의 차이점과 상속을 받았을 시에 오류가 나서 해결하는 것을 보셨을 거예요.

 

그럼 소스상에는 어떤 처리가 다를까? 라는 궁금증이 있으신 분들을 위해서 한번 분석을 해 보려고 합니다. (저 또한 지금까지 개발을 진행하면서 소스까지 분석해 본 적은.... 잘 없는 것 같아요... 글을 쓰면서 궁금증이 더 많아진 케이스 같아요.)

그럼 오류가 발생한 케이스 말고, 단일 클래서에서 @Builder와 @SuperBuilder가 어떤 차이점이 있는지 확인해 보죠.

 

우선, 기본클래스는 다음과 같습니다.

package com.example.builder.entity;

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

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

만약, 이 상태에서 @Builder를 붙였을 시와 @SuperBuilder를 붙였을 시에 차이점이 무엇인지 확인해 볼까요?

 

@Builder를 붙였을 시에 코드입니다.

엇!! 위에 @Builder만 붙이는게 아니었나요? 넵!!! 그냥 붙이면 글자의 차이이지 분석이 아니자나요. Java가 class로 컴파일되신다는 것은 아시죠? 저희는 컴파일된 소스 분석을 하는거예요~!! 물론, 내부에 어떻게 하는 것보다 편하게 쓰는게 중요할 수 있지만, 어떻게 작동하는지도 중요하니까요.

package com.example.builder.entity;

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

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

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

    public Person() {
    }

    public static class PersonBuilder {
        private Long id;
        private String name;
        private int age;

        PersonBuilder() {
        }

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

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

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

        public Person build() {
            return new Person(this.id, this.name, this.age);
        }

        public String toString() {
            return "Person.PersonBuilder(id=" + this.id + ", name=" + this.name + ", age=" + this.age + ")";
        }
    }
}

@SuperBuilder를 붙였을 시에 코드입니다.

package com.example.builder.entity;

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

    protected Person(final PersonBuilder<?, ?> b) {
        this.id = b.id;
        this.name = b.name;
        this.age = b.age;
    }

    public static PersonBuilder<?, ?> builder() {
        return new PersonBuilderImpl();
    }

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

    public Person() {
    }

    public abstract static class PersonBuilder<C extends Person, B extends PersonBuilder<C, B>> {
        private Long id;
        private String name;
        private int age;

        public PersonBuilder() {
        }

        public B id(final Long id) {
            this.id = id;
            return this.self();
        }

        public B name(final String name) {
            this.name = name;
            return this.self();
        }

        public B age(final int age) {
            this.age = age;
            return this.self();
        }

        protected abstract B self();

        public abstract C build();

        public String toString() {
            return "Person.PersonBuilder(id=" + this.id + ", name=" + this.name + ", age=" + this.age + ")";
        }
    }

    private static final class PersonBuilderImpl extends PersonBuilder<Person, PersonBuilderImpl> {
        private PersonBuilderImpl() {
        }

        protected PersonBuilderImpl self() {
            return this;
        }

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

 

위의 소스가 보이시나요? @Builderpublic static class PersonBuilder 클래스가 내부에 생성되었으며, @SuperBuilder에는, 1. public static PersonBuilder<?, ?> builder(), 2. public abstract static class PersonBuilder<C extends Person, B extends PersonBuilder<C, B>>, 3. private static final class PersonBuilderImpl extends PersonBuilder<Person, PersonBuilderImpl> 의 함수 및 클래스가 내부에 생성되었습니다. 즉, @SuperBuilder의 경우에는 다음과 같습니다.

@SuperBuilder를 붙였을 시에 Person class의 구조

    여기서 C, B는 제너릭 타입에 기본적으로 사용하는 내역에는 없는 것으로 저는 C를 Class, B를 Builder 라고 의미를 생각했습니다.

단순히 기존과 같이 Builder로 데이터를 생성하였을 시, 정상작동하여 다른 부분이 없구나 라고 생각을 하였습니다. 그러나, 제가 SuperBuilder를 사용한 이유가 분명히 존재하였고, 그 부분에 대해서는 추후 3탄으로 내용을 진행하도록 하겠습니다.

 

그럼 오늘도 즐거운 개발하세요~!!!!

반응형