@AllArgsConstructor와 @NoArgsConstructor

김지원·2025년 4월 20일

spring

목록 보기
3/3
post-thumbnail

개념

@AllArgsConstructor는 모든 필드를 파라미터로 받는 생성자를 자동으로 생성해주는 lombok 어노테이션이다.

@NoArgsConstructor는 기본 생성자를 만들기 위한 lombok 어노테이션이다.

import lombok.AllArgsConstructor;

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

를 하면

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

자동으로 생성되는 것이다.

하지만 기본 생성자는 생성되지 않는다.
그건 @NoArgsConstructor가 필요하다.

근데 이렇게 @AllArgsConstructor를 하게 되면
다른 곳에서 new 생성자를 이용해 아무 곳에서나 생성을 할 수 있게 된다. = 캡슐화가 전혀 되지 않는다.

그렇다면 어떻게 접근을 제어할 수 있을까?

access라는 옵션이 있다.
이 옵션은 NoArgsConstructor와 AllArgsConstructor 둘 다 해당한다.

@AllArgsConstructor(access = AccessLevel.PROTECTED)

로 쓸 수 있고

  • PUBLIC: 기본값
  • PROTECTED: 외부에서 new 불가하며 서브 클래스만 생성 가능
  • PACKAGE: 패키지 레벨에서 사용 가능
  • PRIVATE: 정적 팩토리 메서드 패턴 등에 사용 가능

사용하는 예시로는 PRIVATE같은 경우

정적 팩토리를 사용해 객체를 생성할 때 주로 사용한다.

@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class User {
    private String id;
    private String name;

    public static User of(String id, String name) {
        return new User(id, name);
    }
}

entity에서 사용할 때 주의할 점

spring에서 보통 사용하는 orm인 JPA에서는 프록시/리플렉션을 사용해서 객체를 생성하기 때문에 기본 생성자가 반드시 필요하다.

그럼으로 @AllArgsConstructor(access = PRIVATE)만 사용할 경우 에러가 날텐데 그럴땐

@Entity
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class User {
    @Id
    private String id;
    private String name;

    public static User create(String id, String name) {
       return User.builder()
          .id(id)
          .name(name)
          .build();
    }
}

이런 식으로
@NoArgsConstructor(access = AccessLevel.PROTECTED)
기본 생성자를 PROTECTED로 만들어줌으로써 에러를 방지 시킬 수 있다.

어떤 상황에서 사용해야 될까?

사실 이 두 어노테이션은 Entity나 DTO에서 무분별하게 사용하는 경우가 많다. (물론 기본값인 PUBLIC이다)

필자는 두가지 방법을 선호한다.

@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class UserDto {
    private String name;
    private int age;

    public static UserDto of(String name, int age) {
        return new UserDto(name, age);
    }
}

정적 팩토리 메서드 패턴을 강제시켜 생성은 의도 있는 메서드를 통해서만 가능하게 한다.

두 번째로 순서때문에 오류가 나지 않도록 builder 패턴을 사용한다.

of와 to, create, from 등의 메서드를 자주 사용하는데

  • of: 필드를 받아서 객체를 생성한다.
  • create: 비즈니스 로직이 포함되어 있는 객체 생성이다.
  • from: 기존 객체에서 다른 객체로부터의 변환이 있을 때 사용한다
    ex) DTO -> Entity
  • to: 객체를 다른 형태로 변환할 때 사용한다
    ex) toDto(), toCommand()

여기서 to와 from의 경계가 모호한데
to는 내부에서 변환할 때 from은 다른 객체를 받아서 본인의 객체를 만들 때라고 생각하면 편하다. (of와 from은 섞어 쓸 때도 있다)

profile
backend-developer

0개의 댓글