해당 글에서는 이전에 작성한 Lombok 환경 설정 및 이해 글에 이어서 Lombok을 활용하여 심화 활용 기능에 대해 확인합니다.
![](https://t1.daumcdn.net/keditor/emoticon/face/large/073.png)
💡 Lombok 설정 및 기초에 대해서 이해하고 싶은 경우 하단의 이전에 작성한 글을 이용하시면 됩니다.
[Java/Library] Lombok 이해하고 적용하기 -1 : 설정 및 기초
해당 글은 Spring Boot 내에 Lombok을 구성하는 방법에 대해서 작성하였습니다. 1) 적용 개발환경 개발 환경 버전 java 1.8 Spring Boot 2.7.4 빌드관리도구 Gradle 7.5 개발 툴 IntelliJ IDEA 2022.3 2) Lombok 💡 Lombok
adjh54.tistory.com
1) 적용 개발환경
개발 환경 | 버전 |
java | 1.8 |
Spring Boot | 2.7.4 |
빌드관리도구 | Gradle 7.5 |
개발 툴 | IntelliJ IDEA 2022.3 |
Lombok | 1.18.24 |
dependencies {
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
}
2) Lombok Annotation
💡 Lombok 이란?
- Java 라이브러리로 반복되는 getter, setter, toString 등의 메서드 작성 코드를 줄여주는 코드 다이어트 라이브러리입니다. 이는 코드 자체가 반복되는 메서드로 인한 복잡함을 줄여주는 역할을 수행합니다.
어노테이션 | 설명 |
@Getter | 클래스의 모든 필드에 대한 getter 메서드를 생성합니다. |
@Setter | 클래스의 모든 필드에 대한 setter 메서드를 생성합니다. |
@ToString | 클래스의 toString() 메서드를 생성합니다. |
@EqualsAndHashCode | 클래스에 대한 equals() 및 hashCode() 메서드를 생성합니다. |
@NoArgsConstructor | 클래스에 대한 인자가 없는 생성자를 생성합니다. |
@AllArgsConstructor | 클래스의 각 필드에 대해 하나의 매개변수가 있는 생성자를 생성합니다. |
@RequiredArgsConstructor | 클래스의 각 final 필드와 null이 아닌 필드에 대해 하나의 매개변수가 있는 생성자를 생성합니다. |
@Data | 클래스의 모든 필드에 대한 getter 및 setter 메서드, toString() 및 equals() 및 hashCode() 메서드를 생성합니다. |
@Builder | 클래스에 대한 빌더 패턴을 생성합니다. |
@Value | 최종 필드, getter 메서드, toString() 및 equals() 및 hashCode() 메서드가 있는 불변 클래스를 생성합니다. |
@Slf4j | SLF4J 로깅 프레임워크를 사용하여 클래스에 대한 로거 인스턴스를 생성합니다. |
@Log4j | Log4j 로깅 프레임워크를 사용하여 클래스에 대한 로거 인스턴스를 생성합니다. |
@Log | 내장 Java 로깅 프레임워크를 사용하여 클래스에 대한 로거 인스턴스를 생성합니다. |
3) 심화 Annotation 활용하기
💡 해당 부분에서는 기존에 일반적으로 사용되는 Lombok을 확장하여 심화로 활용할 수 있는 방법에 대해서 설명합니다.
1. @NoArgsConstructor Annotation 활용하기
1.1. 문제점 발생
💡 Lombok은 DTO, VO 내에서 생성된 객체에서 데이터를 넣고 빼는 목적으로 @Setter, @Data Annotation을 사용합니다. 해당 Annotation을 이용하여 객체의 '요소 값을 변형하는 기능(Setter)'을 사용합니다.
💡그러나, 해당 Setter의 기능을 사용하면 문제점이 발생합니다.
💡 @Setter 어노테이션을 사용하면 무분별한 객체의 생성과 변형이 발생하여 개발자가 실수로 클래스의 필드 중 하나의 필드에 대한 값 설정을 누락하였을 경우 객체는 불완정한 상태가 되어 버리는 문제가 발생합니다.
💡 [문제점 확인 -1 ]
- 아래와 같이 객체를 생성하고 값을 setter로 지정하였으나 ‘지정된 값을 다시 대입’ 하는 오류를 범할 수도 있으며 개발자의 실수로 ‘값의 누락’이 발생할 수 있는 객체 불완정 상태가 발생할 수 있습니다.
package com.adjh.multiflexapi.model;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestDto {
// 사용자 시퀀스
private int userSq;
// 사용자 아이디
private String userId;
// 사용자 패스워드
private String userPw;
// 사용자 이름
private String userNm;
// 사용자 상태
private String userSt = "S";
}
[문제점 확인 -2 : 생성자를 통한 객체 생성]
- 필요에 따라서 ‘매번 생성자를 구성’해야하는 점과 IDE 툴에서 각각의 ‘파라미터명을 지원해주지 않는다면 잘못된 값’을 넣을 수 있다는 오류를 범할 수 있습니다.
package com.adjh.multiflexapi.model;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestDto {
// 사용자 시퀀스
private int userSq;
// 사용자 아이디
private String userId;
// 사용자 패스워드
private String userPw;
// 사용자 이름
private String userNm;
// 사용자 상태
private String userSt = "S";
public TestDto(int userSq, String userId, String userPw, String userNm, String userSt) {
this.userSq = userSq;
this.userId = userId;
this.userPw = userPw;
this.userNm = userNm;
this.userSt = userSt;
}
}
1.2. 해결 방안
💡 Lombok의 @NoArgsConstructor(access = AccessLevel.PROTECTED)를 이용하여 이를 해결합니다.
💡 @NoArgsConstructor(access = AccessLevel.PROTECTED) 란?
- ‘파라미터가 없는 생성자’를 생성해주는 어노테이션이며 무분별한 객체 생성에 대해서 한번 더 체크할 수 있는 수단입니다.
- @NoArgsConstructor 어노테이션을 통해 파라미터가 없는 생성자를 생성을 제한합니다.
- AccessLevel.PROTECTED 속성으로 생성자를 같은 패키지 내에서, 또는 해당 클래스를 상속받은 하위 클래스에서만 접근 가능하도록 제한합니다.
- 즉, 결론적으로 생성자 사용을 금지하며 패키지내에서만 접근이 가능하도록 구성하는것입니다.
Access 속성 | 설명 |
AccessLevel.PUBLIC | 생성자를 모든 클래스에서 접근 가능하도록 설정합니다. (기본값) |
AccessLevel.PROTECTED | 생성자를 같은 패키지 내에서, 또는 해당 클래스를 상속받은 하위 클래스에서만 접근 가능하도록 설정합니다. |
AccessLevel.PRIVATE | 생성자를 해당 클래스 내에서만 접근 가능하도록 설정합니다. |
💡 아래와 같이 지정을 하면 객체 생성 및 객체 요소들의 값의 대입이 불가능합니다.
💡 이에 대해 해결 방안으로 아래의 @Builder Annotation을 사용하여 구성하여 무분별한 객체 생성에 대해서 한번 더 체크할 수 있습니다.
💡 해당 해결은 하단의 2번에서 이어집니다.
package com.adjh.multiflexapi.model;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class TestDto {
// 사용자 시퀀스
private int userSq;
// 사용자 아이디
private String userId;
// 사용자 패스워드
private String userPw;
// 사용자 이름
private String userNm;
// 사용자 상태
private String userSt = "S";
}
2. @Builder Annotation 활용하기
2.1. 문제점 발생
💡 위에서 언급한 점층적 생성자 패턴이나 자바 빈즈 패턴을 이용하여서 생성자를 구성하는 경우 무분별한 객체를 생성하여 값이 누락이 될 수 있는 문제점을 가지고 있습니다.
💡 이에 따라서 ‘빌더 패턴’을 이용하여서 객체의 생성자를 생성하는 방법을 이용합니다.
[참고] 이전에 작성한 글에서 각각에 대한 이해를 도울 수 있습니다.
[Java] 생성자 패턴 이해하기 : 점층적 생성자, 자바 빈즈, Builder 패턴)
해당 글에서는 생성자 패턴에 대해서 이해하고, 어떤 패턴으로 생성자를 구성하는 것이 좋을지에 대해서 공유합니다. 1) 생성자 패턴의 종류 1. 점층적 생성자 패턴 (Telescoping Constructor Pattern) 💡
adjh54.tistory.com
2.2. 해결 방안
💡 빌더 패턴을 이용하면 하나의 객체의 값들을 구성하고자 할 때 각각의 생성자를 구성하는 것이 아니라 @Builder만 구성하여 객체를 생성할 때 필요한 값만 넣어주고 객체를 구성합니다. 이를 통해 객체 내의 요소값들을 한눈에 확인이 가능하며, 매번 필요에 따라 생성자를 만들어 줄 필요도 없습니다.
[ 다시 알아보기 ]
💡 빌더 패턴(Builder Pattern)이란?
- 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴을 의미합니다.
- 다시 말해, Lombok에서 제공해 주는 Annotation으로 별도의 Bulider Pattern을 구성할 필요 없이 생성자에 @Bulider를 선언하면 이를 자동으로 구성하는 것을 의미합니다.
package com.adjh.multiflexapi.model;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class TestDto {
// 사용자 시퀀스
private int userSq;
// 사용자 아이디
private String userId;
// 사용자 패스워드
private String userPw;
// 사용자 이름
private String userNm;
// 사용자 상태
private String userSt = "S";
@Builder
TestDto(int userSq, String userId, String userPw, String userNm, String userSt) {
this.userSq = userSq;
this.userId = userId;
this.userPw = userPw;
this.userNm = userNm;
this.userSt = userSt;
}
}
💡 [참고] @Builder의 속성
어노테이션 속성 | 설명 |
builderClassName | 빌더 클래스의 이름을 지정합니다. |
builderMethodName | 빌더 인스턴스를 얻는 데 사용할 메서드 이름을 지정합니다. |
buildMethodName | 클래스의 인스턴스를 빌드하는 데 사용할 메서드 이름을 지정합니다. |
toBuilder | 기존 클래스 인스턴스를 기반으로 빌더 인스턴스를 얻는 빌더 메서드를 생성합니다. |
access | 빌더 클래스 및 생성자의 가시성을 지정합니다. |
setterPrefix | 생성된 설정기 메서드에 사용되는 접두사를 변경합니다. |
fluent | 빌더 메서드에 대해 유창한 API 스타일을 활성화합니다. |
generateBuilderPackage | 생성된 빌더 클래스에 사용할 패키지 이름을 지정합니다. |
generateBuilderClassName | 생성된 빌더 클래스에 사용할 이름을 지정합니다. |
useConstructorProperties | 도구 지원에 도움이 되는 @ConstructorProperties 어노테이션 사용을 활성화합니다. |
onConstructor | 생성된 생성자의 접근 수준을 지정합니다. |
onMethod | 생성된 빌더 메서드의 접근 수준을 지정합니다. |
onParam | 생성된 빌더 메서드 매개변수의 접근 수준을 지정합니다. |
anyConstructor | 특정 생성자 대신 빌더가 어떤 생성자를 사용할지 지정합니다. |
disableBuilder | 빌더 클래스의 생성을 비활성화합니다. |
toBuilderMethodName | 기존 클래스 인스턴스를 기반으로 빌더 인스턴스를 얻는 데 사용할 메서드 이름을 지정합니다. |
[참고] 추가 Builder 패턴에 대한 심화 속성 사용에 대해서 궁금하시면 아래의 링크를 이용하시면 됩니다.
[Java] 생성자 패턴 - Builder() 심화 속성 이해하기 : Lombok Annotation
해당 글에서는 생성자 패턴 중 Builder() 패턴을 기반으로 상세 속성을 이용하여 심화 내용의 이해를 돕기 위한 목적으로 작성한 글입니다. 💡 해당 글은 이전에 작성한 Builder() 생성자 패턴에 대
adjh54.tistory.com
3. @Slf4J / @Log4J Annotation 활용하기
3.1. 문제점 발생
💡 구성한 로깅 라이브러리를 사용하는 모든 페이지마다 Logger를 선언해주어야 하는 번거로움이 발생합니다.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Slf4jLogginSample {
private static final Logger log = LoggerFactory.getLogger(Slf4jLogginSample.class);
public static void main(String[] args) {
log.info("Slf4jLogginSample");
}
}
3.2. 해결 방안
💡 설정된 로깅 라이브러리를 기준으로 매번 선언의 필요 없이 @Slf4j, @Log4j을 통해 선언을 하면 매번 로깅 라이브러리의 선언 필요 없이 쉽게 어노테이션 설정만으로 사용이 가능합니다.
어노테이션 | 설명 |
@Slf4j | SLF4J 로깅 프레임워크를 사용하여 클래스에 대한 로거 인스턴스를 생성합니다. |
@Log4j | Log4j 로깅 프레임워크를 사용하여 클래스에 대한 로거 인스턴스를 생성합니다. |
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Slf4jforLombok {
public static void main(String[] args) {
log.info("Slf4j 테스트");
}
}
[ 더 알아보기 ]
💡 spring-boot-starter-log4j2의 로깅 라이브러리 설정 없이 @Slf4j, @Log4j를 사용할 수 있는가?
- 서버의 콘솔 내에 출력만 사용을 한다면 해당 Annotation을 사용하면 되지만 실제 ‘로그의 기록’을 하려면 해당 로깅 프레임워크의 설정이 필요합니다.
💡 @Slf4j, @Log4j 어노테이션과 spring-boot-starter-log4j2의 관계는 무슨 관계인가?
- @Slf4j, @Log4j는 로깅 프레임워크를 사용하여 클래스에 대한 로거 인스턴스를 자동으로 생성합니다.
- spring-boot-starter-log4j2 는 Log4j2를 사용하기 위한 라이브러리입니다.
- 로그를 기록하기 위해서는 @Slf4j, @Log4j와 spring-boot-starter-log4j2 라이브러리를 함께 사용해야 기록을 할 수 있습니다.
[참고] 로깅 라이브러리 Log4j2 설정 방법 + Slf4j 인터페이스 이용방법
[Java/Library] Slf4j - Log4j2 이해하고 설정하기
해당 글에서는 로깅 라이브러리에 대해 이해를 하고 개발환경을 구성하는 것을 목적으로 작성하였습니다 1) 개발 환경 💡 해당 글은 Spring Boot 내에 로깅 라이브러리를 적용한 개발 환경입니다.
adjh54.tistory.com
오늘도 감사합니다. 😀
'Java > Spring Boot' 카테고리의 다른 글
[Java] Spring Boot Cache 이해하고 설정하기 -2 : 사용 및 활용 예시 (0) | 2023.04.16 |
---|---|
[Java] Spring Boot Cache 이해하고 설정하기 -1 : 정의, 환경 설정 (2) | 2023.04.16 |
[Java] Spring Boot AOP(Aspect-Oriented Programming) 이해하고 설정하기 (2) | 2023.03.01 |
[Java] Business Exception 이해하고 구성하기 : Service Exception (0) | 2022.12.10 |
[Java] Global Exception 이해하고 구성하기 : Controller Exception (5) | 2022.11.13 |