개발하다보면 여기저기 Lombok코드들이 많이 쓰인다.
어느순간부터 코드에 들어와있던 녀석들...을 알고써보면 좋을 것 같아서 글을 쓴다.
역시 개발은 공부하고 내가 아는걸 코드로 작성해야지 더 재미있는 것 같다.
▶시작하기 전, 생성자는 뭐지??
생성자는 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메소드 이다.
인스턴스 변수의 초기화 작업에 사용되며, 인스턴스 생성시에 실행되어야 할 작업을 위해서도 사용된다.
생성자는 클래스 내에 선언되며, 메소드와 달리 리턴값이 없다.
또한 생성자의 이름은 클래스의 이름과 같아야한다.
생성자에는 기본생성자와 파라미터가 있는 생성자 두개가 존재한다.
public class MemberDTO {
private Long id;
private String memberEmail;
private String memberPassword;
private String memberName;
//기본 생성자
public MemberDTO() {
}
//파라미터가 있는 생성자
public MemberDTO(Long id, String memberEmail, String memberPassword, String memberName) {
this.id = id;
this.memberEmail = memberEmail;
this.memberPassword = memberPassword;
this.memberName = memberName;
}
}
좋다. 이제 생성자가 뭔지 왜 사용하는지도 알았으니 바로 본론으로 넘어가겠다.
▶@AllArgsConstructor란?
이 어노테이션은 클래스의 모든 필드값을 파라미터로 받는 생성자를 자동으로 생성해준다!
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class MemberDTO {
private Long id;
private String memberEmail;
private String memberPassword;
private String memberName;
}
이러한 코드에서 @AllArgsConstructor을 Delombok해보면
@Getter
@Setter
@NoArgsConstructor
@ToString
public class MemberDTO {
private Long id;
private String memberEmail;
private String memberPassword;
private String memberName;
public MemberDTO(Long id, String memberEmail, String memberPassword, String memberName) {
this.id = id;
this.memberEmail = memberEmail;
this.memberPassword = memberPassword;
this.memberName = memberName;
}
}
이렇게 모든 필드값을 파라미터로 가진 생성자를 만들어준다!
이 어노테이션을 사용하면, 클래스의 모든 필드를 한 번에 초기화할 수 있다!!
▶@NoArgsConstructor란?
그렇다면 @NoArgsConstructor은 무엇일까
이름만 보고 직관적으로 맞출 수 있을것이다.
바로 아무런 파라미터가 없는 즉 기본생성자를 만들어준다.
위 코드에서 @NoArgsConstructor를 Delombok해주면
@Getter
@Setter
@ToString
public class MemberDTO {
private Long id;
private String memberEmail;
private String memberPassword;
private String memberName;
public MemberDTO(Long id, String memberEmail, String memberPassword, String memberName) {
this.id = id;
this.memberEmail = memberEmail;
this.memberPassword = memberPassword;
this.memberName = memberName;
}
public MemberDTO() {
}
}
이렇게 아래에 기본생성자가 생겼다!
이 어노테이션을 사용하면, 클래스에 명시적으로 선언된 생성자가 없더라도 인스턴스를 생성할 수 있다!!
▶@RequiredArgsConstructor란?
아마 이놈은 Controller단이나 Service단에서 많이 봤을것이다.
이놈은 final이나 @NonNull로 선언된 필드만 파라미터로 받는 생성자를 자동생성해준다.
@Controller
@RequiredArgsConstructor
public class MemberController {
//생성자 주입
private final MemberService memberService;
이런식으로!
여기서 @RequiredArgsConstructor을 Delombok해보면
@Controller
public class MemberController {
//생성자 주입
private final MemberService memberService;
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
이렇게 생성자를 만들어준다는것을 알 수 있다.
이 어노테이션을 사용하면, 클래스가 의존하는 필드를 간단하게 초기화할 수 있다!!
▶accsee 옵션
각 어노테이션에 access옵션을 붙일 수 있다!
@NoArgsConstructor(access = AccessLevel.PROTECTED)
이렇게!
- PUBLIC: 기본값이며, 모든 클래스에서 생성자에 접근 가능
- PROTECTED: 같은 패키지의 클래스와 상속받은 클래스에서 생성자에 접근 가능
- PACKAGE: 같은 패키지의 클래스에서 생성자에 접근 가능
- PRIVATE: 해당 클래스 내부에서만 생성자에 접근 가능
▶@AllArgsConstructor, @RequiredArgsConstructor 사용을 "지양"하라고?
아마 이런 블로그 글들을 많이 봤을것이다.
지양하라는 이유는 이러하다.
@AllArgsConstructor는 편리하게 모든 필드를 가진 생성자를 만들어 주지만, 필드의 순서가 변경되는 경우 치명적일 수 있다.
예를 들어 어떤 객체가 2개의 String 타입을 필드로 가지고 있고, 이에 대한 생성자를 외부에서 사용하고 있다고 가정해 보자.
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class Person {
private String firstName;
private String lastName;
}
Person person = new Person("John", "Doe");
만약, 해당 객체의 필드 순서가 실수로 변경되어도 컴파일 에러가 발생하지 않고, 추후 인지하지 못한 치명적인 버그가 발생할 수 있는 여지가 된다.
@RequiredArgsConstructor를 사용해도 final 키워드만 붙었지 마찬가지이다.
하지만 블로그 글들을 보다보면 @AllArgsConstructor은 사용하지 않지만, @RequiredArgsConstructor는 사용하고있는분들이 꽤 있다.
그 이유는
- 사용자가 final 키워드를 붙이면서 필수 파라미터에 대한 인지를 하고 필드를 선언한다는 점
- 스프링에서는 객체의 생성자만 만들어두면 스프링에서 알맞은 타입과 이름의 빈을 찾아서 주입해주기 때문에, 필드 순서가 바뀌거나 해도 타입+이름 기반으로 동작하니 @RequiredArgsConstructor 를 사용해도 큰 무리가 없음
이러한 이유때문이다.
▶ 내 개인적인 생각
만약, Builder를 사용하지 않고 @AllArgsConstructor만 사용한다면 나는 위에 의견에 동의하면서 사용하지 않을 것이다.
하지만 Builder를 사용한다면 필드의 순서가 실수로 변경 될 일이 있나?? 아직 많은 개발을 하지 않았기 때문에 자세히는 모르겠지만 지금까지는 없었던 것 같다. (만약 있다면 댓글로 알려주시면 정말정말 감사하겠습니다!)
따라서 @AllArgsConstructor는 @Builder와 함께 할때만 사용할 것 같다.
'BackEnd > Spring Boot🍃' 카테고리의 다른 글
[Spring] 클래스 선언부에 @Builder와 @NoArgsConstructor, @AllArgsConstructor을 같이 사용해야 하는 이유 (0) | 2024.04.13 |
---|---|
[Spring] Builder 패턴과 Lombok의 @Builder (0) | 2024.04.13 |
[Spring] 의존성주입(DI)이란? 의존성주입의 4가지 방법 (0) | 2024.04.07 |
[Spring] ApplicationContext란? ApplicationContext Interface를 구현하고 있는 대표적인 클래스들, Bean 등록 방식 (0) | 2024.04.06 |
[Spring]Spring MVC 요청에서 응답까지의 흐름, @Controller와 @RequestMapping 원리 (0) | 2024.03.24 |