Java 언어를 사용해 개발을 하다 보면 DTO, VO 개발을 하다 보면 Lombok(롬복) 이란 라이브러리를 사용하여 개발을 하곤 한다.(물론 아직까지도 안 쓰는 회사도 있기도 하겠지만....)
이번 글에서는 자주 사용하는 Lombok 이란 라이브러리에 대해서 정리해보고자 한다.
1. Lombok 이란?
- Java 의 라이브러리로 반복되는 메소드를 Annotation(어노테이션) 기반으로 코드를 자동으로 완성해주는 라이브러리이다.
- Lombok 을 이용하면 Getter, Setter, ToString 등과 같은 다양한 코드를 자동 완성시킬 수 있다.
- Lombok 을 이용해서 작성한 코드는 컴파일 과정에서 Annotation 을 이용해서 코드를 생성하고 이런 결과물이 .class 에 담기게 된다.
- 생산성을 향상해 많은 개발자들이 선호하지만, 팀 프로젝트에 도입하는 경우에는 호불호가 갈릴 수 있기 때문에 주의해야 한다.(무분별한 @Data 사용을 통한 에러 발생, 속도 저하가 발생할 수 있다)
2. Lombok 의 장점 / 단점
2-1. 장점
- 어노테이션 기반의 코드 자동 생성을 통한 생산성 향상
- 반복되는 코드 다이어트를 통한 가독성 및 유지보수성 향상
- Getter, Setter 이외에 Builder(빌더) 패턴이나 로그 생성 등 다양하게 활용 가능
2-2. 단점
- 만약 Intelli J에서 개발 시에는 모든 팀원이 Lombok 플러그인을 설치하여야만 한다.(최근에는 Intelli j 기본 플러그인으로 제공)
- 무분별한 어노테이션을 사용하면, 순환 참조 또는 무한 재귀 호출로 인해 StackOverFlow 가 발생할 수 있다.
2-3. Lombok 의 필요성
- 기존의 VO 를 만들 때는 아래와 같이 개발하였다.
// AS-IS
public class Member {
private Long id;
private String memberId;
private String memberPw;
private String memberName;
private String memberPhone;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getMemberId() {
return memberId;
}
public void setMemberId(String memberId) {
this.memberId = memberId;
}
public String getMemberPw() {
return memberPw;
}
public void setMemberPw(String memberPw) {
this.memberPw = memberPw;
}
public String getMemberName() {
return memberName;
}
public void setMemberName(String memberName) {
this.memberName = memberName;
}
public String getMemberPhone() {
return memberPhone;
}
public void setMemberPhone(String memberPhone) {
this.memberPhone = memberPhone;
}
}
- 이렇게 긴 코드를 Lombok 을 사용하여 줄일 수 있다.
// TO-BE
@Getter
@Setter
public class Member {
private Long id;
private String memberId;
private String memberPw;
private String memberName;
private String memberPhone;
}
3. Lombok 사용법
3-1. @Getter, @Setter
- Lombok에서 가장 자주 활용하는 Annotation(어노테이션)이다.
- 필드에 대한 getter, setter 메소드를 자동으로 생성해주는 어노테이션이다.
- 클래스 이름 위에 적용시키면 모든 변수들에 적용이 되고, 변수 이름 위에 적용시키면 해당 변수들에게만 적용이 된다.
- 자동으로 생성되는 getter 와 setter 의 경우 기본은 public 이며, AccessLevel 을 명시한 경우에는 public. protected, package, private 등으로 생성할 수 있다.
- 이름이 같고 매개변수의 수가 같은 메소드가 이미 존재한다면 메소드가 생성되지 않는다.
예를 들어, getMemberName(String str)가 존재한다면 getter를 통한 getMemberName() 메소드는 기술적으로 가능하더라도 생성되지 않는다.(생성되지는 않지만, 이에 대한 경고 메시지를 알려준다.)
// 클래스 전체
@Getter
@Setter
public class Member {
private Long id;
private String memberId;
private String memberPw;
private String memberName;
private String memberPhone;
}
- 컴파일 시 Member.class 는 아래 이미지와 같고, get/set 메소드를 생성한 것을 확인할 수 있다.
// 필드
@Getter
public class Member {
private Long id;
private String memberId;
@Getter(AccessLevel.PROTECTED)
private String memberPw;
@Setter
private String memberName;
@Setter
private String memberPhone;
}
- @Setter 어노테이션을 필드에 선언하면 해당 필드에만 선언이 된다.
- @Getter 어노테이션에 AccessLevel 을 선언하면 해당 레벨에 맞게 메소드를 생성해준다.
3-2. @ToString
- 클래스 이름 위에 적용하며, 클래스의 변수들을 기반으로 ToString 메소드를 자동으로 완성시켜 준다.
- 출력을 원하지 않는 변수에 대해서는 @ToString.Exclude 어노테이션을 붙여주면 제외된다.
- 상위 클래스에 대해서도 ToString 을 적용시키고자 한다면, 상위 클래스에 @ToString(callSuper = true)를 적용시킨다.
- includeFieldNames 를 설정하면 각 필드의 이름과 함께 값을 확인할 수 있다.(Default = true)
@ToString
public class Member {
private Long Id;
private String memberId;
@ToString.Exclude
private String memberPw;
private String memberName;
private String memberPhone;
}
3-3. @AllArgsConstructor
- 모든 변수를 사용하는 생성자를 자동완성시켜준다.
@AllArgsConstructor
public class Member {
private Long Id;
private String memberId;
private String memberPw;
private String memberName;
private String memberPhone;
/* AllArgsConstructor를 통해 아래의 생성자를 자동 생성할 수 있다.
public Member(Long id, String memberId, String memberPw, String memberName, String memberPhone) {
this.id = id;
this.memberId = memberId;
this.memberPw = memberPw;
this.memberName = memberName;
this.memberPhone = memberPhone;
}
*/
}
3-4. @NoArgsConstructor
- 매개변수가 없는 기본 생성자를 자동완성시켜준다.
@NoArgsConstructor
public class Member {
private Long id;
private String memberId;
private String memberPw;
private String memberName;
private String memberPhone;
/* NoArgsConstructor를 통해 아래의 생성자를 자동 생성할 수 있다.
public Member () {
}
*/
}
3-5.RequiredArgsConstructor
- 특정 변수(초기화되지 않은 모든 final 필드, @NonNull 필드)만을 활용하는 생성자를 자동완성시켜준다.
- @NonNull 필드의 경우 null check 구몬 또한 생성해준다.
@RequiredArgsConstructor
public class Member {
@NonNull
private Long id;
private String memberId;
private String memberPw;
private String memberName;
private String memberPhone;
/* RequiredArgsConstructor를 통해 아래의 생성자를 자동 생성할 수 있다.
public Member (Long id, String memberId) {
this.id = id;
this.memberId = memberId;
}
*/
}
3-6. @NonNull
- 메소드나 생성자의 매개변수에 사용하면 lombok이 null check를 해준다.
@AllArgsConstructor
public class Member {
@NonNull
private Long Id;
private String memberId;
private String memberPw;
private String memberName;
private String memberPhone;
}
3-7. @EqualsAndHashCode
- 클래스에 대한 equals 메소드와 hashCode 메소드를 자동으로 생성해준다.
- 서로 다른 두 객체에서 특정 변수의 이름이 똑같은 경우에 같은 객체로 판단을 하고 싶다면 아래와 같이 가능하다.
@RequiredArgsConstructor
@EqualsAndHashCode(of = {"memberName", "memberPhone"})
public class Member {
private Long id;
private String memberId;
private String memberPw;
@NonNull
private String memberName;
@NonNull
private String memberPhone;
}
- Member 라는 클래스 위에 @EqualsAndHashCode 어노테이션을 선언하여, MemberName 과 MemberPhone 의 값이 동일하다면 같은 객체로 인식하도록 도와준다.
@RestController
@RequestMapping(value = "/member")
@Slf4j
public class MemberController {
@GetMapping(value = "/test")
private void test(){
Member member1 = new Member("개발자", "01011112222");
Member member2 = new Member("개발자", "01011112222");
Member member3 = new Member("개발자", "01088887777");
// MemberName 과 MemberPhone 이 같기 때문에 true가 나옴
log.info("결과 : " + member1.equals(member2));
// MemberName 과 MemberPhone 이 다르기 때문에 false가 나옴
log.info("결과 : " + member1.equals(member3));
}
}
3-8. @Data
- 해당 어노테이션은 @ToString, @EqualsAndHashCode, @Getter, @Setter, @RequiredArgsConstructor 를 자동 완성시켜준다.
- callSuper, includeFieldName, exclude 와 같은 파라미터와는 같이 사용될 수 없어, 필요시에는 개별 어노테이션으로 따로 명시가 필요하다.
- 실무에서는 해당 어노테이션을 무분별하게 사용하다 보면 프로그램이 무거워지고 객체의 안정성을 해치기 때문에 사용을 지양한다.
3-9. @Builder
- 클래스의 객체의 생성에 Builder 패턴을 적용시켜 준다.
- 모든 변수들에 대해 build 하기를 원한다면 클래스 위에 @Builder 어노테이션을 추가하고, 특정 변수만을 build 하기를 원한다면 생성자를 작성하고 그 위에 @Builder 어노테이션을 추가한다.
@Builder
public class Member {
private int Id;
private final String MemberId;
private String MemberPw;
private String MemberName;
private String MemberPhone;
}
@RestController
@RequestMapping(value = "/member")
@Slf4j
public class MemberController {
@GetMapping(value = "/test")
private void test(){
Member member = Member.builder()
.memberId("test")
.memberPw("1234")
.memberName("개발자")
.memberPhone("01011112222")
.build();
}
}
참고
'BackEnd > Java' 카테고리의 다른 글
[Java] MDC 를 사용한 로그(Log)추적하기 (0) | 2022.07.30 |
---|---|
[Java] Lambda 정리 (0) | 2022.07.16 |
[Java] String, StringBuffer, StringBuilder 차이 및 장단점 (0) | 2022.06.26 |
[Java] List 안에 있는 Map Value 찾기 (0) | 2022.01.15 |
[Java] 생성한 객체 배열 정렬하기(Comparator) (0) | 2022.01.09 |