[lombok] @Builder와 @NoArgsConstructor를 같이 사용할 수 없는 이유

YJ KIM·2023년 12월 15일
2

코드를 작성하다 보면 객체에 멤버 변수가 많은 경우 생성자로 객체를 생성하기가 어려워진다. 그래서 Builder를 사용하여 객체를 생성하는 편이다.

그런데 가끔 @Builder와 @NoArgsConstructor 어노테이션을 같이 사용하면 컴파일 자체가 되지 않을 때가 있다. 구글링하면 대부분 @AllArgsConstructor도 같이 붙이면 해결된다는 결론만 나와있어서 나도 어노테이션을 덕지덕지 붙여 해결했다. 해당 이유를 알아보기 위해 글을 작성한다.

@Builder

Builder 어노테이션은 lombok 라이브러리 기능 중 하나로, 해당 어노테이션을 클래스 위에 기재하면 컴파일 시에 자동으로 해당 클래스에 Builder 관련 코드가 생긴다.

@Builder
public class TestDto {
    String test;
    String value;
}

이런 클래스가 있다고 가정했을 때,

        TestDto testDto = TestDto.builder()
                .test("test")
                .value("test")
                .build();

위와 같은 형태로 객체를 사용할 수 있다.

@Builder의 장점

만약 저 TestDto에 멤버 변수가 10개라고 했을 때, 생성자를 통해 객체를 생성하는 것은 너무 번거롭다. 데이터 순서가 헷갈릴 수 있고 코딩이 힘들어진다.

-> 이럴 때 Builder를 사용하면 멤버 변수를 확인해서 값을 넣어줄 수 있다.

@Builder 빌드시에

Builder 어노테이션을 적용한 클래스를 빌드하면

public class TestDto {
    String test;
    String value;

    TestDto(final String test, final String value) {
        this.test = test;
        this.value = value;
    }

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

    public String getTest() {
        return this.test;
    }

    public String getValue() {
        return this.value;
    }

    public static class TestDtoBuilder {
        private String test;
        private String value;

        TestDtoBuilder() {
        }

        public TestDtoBuilder test(final String test) {
            this.test = test;
            return this;
        }

        public TestDtoBuilder value(final String value) {
            this.value = value;
            return this;
        }

        public TestDto build() {
            return new TestDto(this.test, this.value);
        }

        public String toString() {
            return "TestDto.TestDtoBuilder(test=" + this.test + ", value=" + this.value + ")";
        }
    }
}

위와 같이 빌드된다.
이때 주의해서 봐야할 부분은

TestDto(final String test, final String value) {
        this.test = test;
        this.value = value;
    }

이 부분인데, 자동적으로 모든 멤버 변수에 해당하는 생성자가 생성된다는 것이다.
@AllArgsConstructor를 명시하지 않아도 이러한 생성자가 생성되고, Builder 패턴에서 사용된다.

근데 왜 @NoArgsConstructor를 같이 기재하면 안될까?

이유는 생각보다 간단하다. Builder.java 코드를 확인하면 주석에 설명되어 있다.

한마디로 해당 어노테이션을 통해 모든 인자에 대한 생성자가 자동적으로 생성되지만, @~ArgsConstructor 어노테이션을 같이 기재하면 자동적으로 생성되지 않는다는 것이다. 그래서 Builder 패턴 안에서 객체를 생성할 수 없다.

순서대로 설명하면
1. NoArgsConstructor를 선언함으로써 Builder가 자동적으로 생성한 모든 인자에 대한 생성자가 생성되지 않음.
2. Builder 패턴 내부적으로 클래스의 모든 인자에 대한 생성자를 사용하고 있음 -> 이 부분에서 해당 메소드가 없으니 에러가 컴파일 불가함

위와 같은 과정을 거쳐 결과적으로,
@NoArgsConstructor를 사용하면 모든 인자에 대한 생성자가 없기 때문에 @AllArgsConstrucotr를 추가적으로 명시해줘야 한다. 와 같은 결론이 도출되게 된다.


생각보다 매우 간단했다.
근데 알아보지 않고 그냥 해결하려고 하니까 맨날 검색했던 것 같다. 지금이라도 바로 잡아서 시원하다~!

참고
https://www.javadoc.io/doc/org.projectlombok/lombok/latest/lombok/Builder.html
https://projectlombok.org/features/Builder
https://stackoverflow.com/questions/74588981/why-the-lombok-builder-cant-be-used-with-noargsconstructor-togerther

profile
모르면 쓰지 말고 쓸 거면 알고 쓰자

0개의 댓글