AllArgsConstructor, NoArgsConstructor, RequiredArgsConstructor

이기태·2023년 3월 21일
3

TIL

목록 보기
2/3
post-thumbnail

혼자 공부한 내용을 기록으로 남기고 있습니다. 만약에 내용이 틀렸을 경우에 댓글로 알려주시면 바로 수정하겠습니다! 도움이 되셨으면 댓글이나 좋아요 남겨주시면 감사하겠습니다:)

김영한 강사님 코드를 따라치면서 항상 궁금했던 것 중 하나가 @RequiredArgsConstructor 라는 어노테이션이었다.

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class UserService{
	// 생략
}

이렇게 Service 클래스 위에 붙거나

@RestController
@RequiredArgsConstructor
public class UserController{
	// 생략
}

이런식으로 Controller 클래스 위에 주로 붙는다는 것만 안다. 이런 식으로 대충 어디쯤에만 붙는지 알고 의미는 하나도 모른 채 쓰기만 했었는데 한번 알아보도록 하자.

🤔 @Lombok

우선 이런 어노테이션들은 모두 Java 라이브러리 중 Lombok으로부터 나온 어노테이션들이다. Lombok은 getter, setter, constructor 등 귀찮은 코드들을 자동화해주는 라이브러리라고 한다. 처음에 https://start.spring.io/ 에서 만들어줄 때 Dependencies에서 추가해준 기억이 있음. 그래서 내가 쓸 수 있었던 것이었다! 이때 추가를 안해줬더라도 build.gradle 파일에서 언제든 추가해줄 수 있으니 참고!

🤔 @NoArgsConstructor

그럼 Lombok에서 나온 거도 알았고 도대체 @RequiredArgsConstructor는 뭐냐! 이걸 공부하기 전에 먼저 @NoArgsConstructor를 알아보자. @NoArgsConstructor는 파라미터가 없는 기본 생성자를 생성한다. 밑의 코드를 보자.

public class User{
	private Long id;
	private String name;
	private String password;
	private Integer age;
}

이렇게 User 클래스가 있는 상황에서 밑의 코드를 보자.

User testUser = new User();

이렇게 User 객체 생성이 가능할까? Java를 조금이라도 아는 사람한테는 쉬운 문제이지만 나같은 초보한테는 상당히 헷갈리는 문제였다. 저렇게해서는 User 객체 생성이 불가능하다. 왜? 생성자가 없어서이다!!!

위의 코드가 가능해지려면 아래와 같이 코드를 바꿔야한다.

public class User{
	private Long id;
	private String name;
	private String password;
	private Integer age;

	public User(){
	}
}

이런 식으로, 파라미터가 없는 User 생성자를 만들어줘야 한다. 근데 객체마다 저렇게 만들어주기에 너무 귀찮지 않을까? 그래서 나온게 @NoArgsConstructor 이다!

@NoArgsConstructor
public class User{
	private Long id;
	private String name;
	private String password;
	private Integer age;
}

이렇게 어노테이션으로 한 줄만 적어주면 파라미터가 없는 생성자 역할을 해줌으로써 객체 생성이 가능해진다! 너무 편한 친구였다. 이 친구가 이해됐으면 나머지 @AllArgsConstructor, @RequiredArgsConstructor 두 친구는 훨씬 이해가 쉬울 것이다.

🤔 @AllArgsConstructor

그럼 이 친구는 뭘까? 문득 이름을 보고 유추해보면 ‘모든 파라미터를 갖는 생성자?’ 정확하다

클래스 내부에 선언된 모든 filed에 각 파라미터를 가진 생성자를 생성한다.

public class User{
	private Long id;
	private String name;
	private String password;
	private Integer age;

	public User(Long id, String name, String password, Integer age){
		this.id = id;
		this.name = name;
		this.password = password;
		this.age = age;
	}
}

위의 User 생성자를,

@AllArgsConstructor
public class User{
	private Long id;
	private String name;
	private String password;
	private Integer age;
}

로 대체가 가능하다. 정말 편한 친구다… 다만 종종 필요한 값만 넣어주는 생성자가 필요할 때도 있다. 항상 모든 필드값을 가져와야하는 경우보단 필요한 필드만 가져오는 경우가 많다. 이럴 때 만약 @AllArgsConstructor 이 친구를 쓰고

User testUser = new User(이기태, 25);

이렇게 쓰면 자동으로 @AllArgsConstructor가 Null Check를 해서 에러를 발생시킨다. 그럼 필요한 정보만 담은 생성자를 만들려면 어떻게 해야할까? 바로 @RequiredArgsConstructor 이다!

🤔 @RequiredArgsConstructor

@RequiredArgsConstructor는 final이나 @NonNull인 필드값만 파라미터로 받는 생성자를 만들어준다.

@RequiredArgsConstructor
public class User{
	@NonNull
	private Long id;
	private String name;
	private String password;
	@NonNull
	private Integer age;
}

위의 상황에서는 @RequiredArgsConstructor 는 어떤 생성자를 만들어낼까?

public User(Long id, Integer age){
	this.id = id;
	this.age = age;
}

이런 생성자를 만들어낸다! 그럼 처음으로 돌아와서 Service, Controller 위에 붙어있는 @RequiredArgsConstructor를 봐보자. 이를 이해하려면 Spring의 의존성 주입(Dependency Injection)을 알아야 한다. 뭔가 점점 더 어려워지지만 재밌긴 하다. 글이 너무 길어지는 관계로 의존성 주입 관련해서는 다음 글에서 공부해보도록 하겠다!

profile
사람들에게 도움이 되는 서비스를 만들기 위해 항상 노력하는 백엔드 개발자 이기태

3개의 댓글

comment-user-thumbnail
2023년 3월 21일

평소에 엄청 쓰지만 정확한 개념은 잊어버리고 살았는데 잘 배워갑니당 !

1개의 답글
comment-user-thumbnail
2024년 4월 1일

@NoArgsConstructor 부분 설명에서 매개변수가 있는 생성자를 만들지 않으면 기본 생성자 자동으로 생성되어서 User testUser = new User(); 이렇게 사용할 수 있지 않나요?

답글 달기