롬복(Lombok)
자주 사용하는 롬복 애노테이션
롬복에서는 다양한 애노테이션을 제공해 코딩의 편의성을 높인다.
- @Getter, @Setter : 프로퍼티의 값을 흭득하거나 설정하는 Getter와 Setter를 만들어 준다. 프로퍼티에 사용하면 해당 프로퍼티에 대한
- Getter와 Setter를 생성하며, 클래스에 사용하면 해당 클래스에 정의된 모든 프로퍼티에 Getter와 Setter가 생성된다.
- @ToString : 클래스에 사용하며, 클래스 이름과 클래스에 포함된 모든 프로퍼티의 이름과 값을 String 객체로 작성해 반환하는 toString() 메서드를 만들어 준다. 객체를 로그로 출력할 때 유용하다.
- @Data : 클래스에 사용하며 @Getter, @Setter, @ToString 3개의 애노테이션을 @Data 하나의 애노테이션으로 대체할 수 있다.
- @AllArgsConstructor : 클래스에 사용되며, 모든 프로퍼티를 매개변수로 받는 생성자를 만들어 준다.
- @NoArgsConstructor : 클래스에 사용하며, 아무런 매개변수도 갖지 않는 생성자를 만들어 준다.
- @RequiredArgsConstructor : 클래스에 사용하며, final로 선언된 프로퍼티들을 매개변수로 받는 생성자를 만들어 준다. 스프링 부트 애플리케이션을 개발할 때는 의존성을 주입받기 위해 @Autowired를 사용하는 대신, 해당 프로퍼티를 final로 선언하고 @RequiredArgsConstructor를 사용하는 것을 권장한다.
@Service
@RequiredArgsConstructor
public class ArticleService {
private final MemberRepository memberRepository;
private final MemberRepository memberRepository;
// ...
}
- @Builder : 클래스에 사용하며, 객체 생성을 위해 빌더 패턴을 사용할 수 있도록 해준다. 빌더 패턴은 복잡한 객체를 생성하는 방법을 제공하는 디자인 패턴으로 객체 생성 과정을 단계별로 분리해 가독성을 높이고 불필요한 생성자 작성을 피할 수 있도록 도와준다. 특히 선택적 배개변수가 많을 때 유용하다. 예를 들어 멤버 객체를 생성하는 방법은 new Member()를 통해 객체를 생성한 후 Setter를 통해 필요한 프로퍼티의 값을 설정하거나 초기값을 설정하려는 프로퍼티를 매개변수로 하는 생성자를 만들어 사용하는 것이다. 하지만 @Builder 애노테이션이 사용된 객체의 경우 builder() 정적 메서드를 사용해 빌더 객체를 생성하고, 이 객체가 제공하는 프로퍼티와 동일한 프로퍼티를 계속 설정할 수 있고, 끝난 후에는 build() 메서드를 호출해 객체를 생성할 수 있다.
Member member = Member.builder().name("윤서준").age(10).build()
- @Slf4j : 클래스에 사용하며, 자동으로 클래스에 log라는 로깅 객체를 생성해 준다.
- @EqualsAndHashCode(of={"name", "email"}) : 필드 값을 비교하는 equals()를 만들어 준다. 원래 equals는 객체 자체가 동일한 객체일 때 TRUE이지만, @EqualsAndHashCode를 사용하면 해당 필드의 값이 같아야 TRUE로 반환한다.(참고로, ==는 여전히 동일 객체인지를 비교한다.)
@Builder
@EqualsAndHashCode(of = {"name", "email"})
public class Product {
private String name;
private String description;
private int price;
}
Product p1 = Product.builder().name("바나나").description("맛있는 상품").price(1000).build();
Product p2 = Product.builder().name("바나나").description("신선한 상품").price(1000).build();
System.out.println("p1.equals(p2) " + p1.equals(p2)) // name과 price는 같으므로 TRUE를 반환
@Slf4j로 로그 출력하기
private static final Logger log = LoggerFactory.getLogger(CoffeeMaker.class);
개발 단게에서 디버깅을 위해 로그를 출력하기도 하고, 운영 단계에서 정상적으로 운영되고 있는지 또는 특별한 오류가 발생하고 있는지를 확인하기 위해 로그를 사용한다. 스프링 부트에는 기본으로 로거가 포함되어 있어 위와 같이 클래스 내에 log 객체를 만들어 사용하거나, 또는 롬복을 사용해 클래스에 @Slf4j 애노테이션을 사용함으로써 log 객체를 만들 수 있다.
로그 출력을 위해 System.out.println() 대신 로거의 log 객체를 사용하면, 로그의 심각도에 따라 로그의 레벨을 단리하고 간단하게 애플리케이션 설정에서 로그를 레벨에 따라 필터링할 수 있다는 장점이 있다. 또한 출력하는 로그의 패턴을 바꾸거나 출력하는 대산을 콘솔, 파일 등 원하는 대로 설정할 수 있다는 장점이 있다.
로그 레벨의 심각도
TRACE < DEBUG < INFO < WARN < ERROR 순서로, 왼쪽에서 오른쪽으로 갈수록 심각도가 높은 단계이다.
@Component
@Slf4j
public class LogApplication implements ApplcationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
log.trace("application started");
log.debug("application started");
log.info("application started");
log.warn("application started");
log.error("application started");
}
}
로그 필터링은 애플리케이션 설정 파일에서 클래스 경로와 필터링할 로그 레벨을 정의하면 된다.
그러면 클래스 경로 하위의 모든 클래스에서 출력하는 로그는 설정된 로그 레벨이상의 것들만 필터링되어 출력된다.
logging.level.root = warn
loggin.level.com.example.demo.CoffeeMaker = debug
com.example.demo.CoffeeMaker 클래스에서 debug 레벨 이상의 모든 로그를 출력하고 그 밖의 클래스에서는 warn 레벨 이상의 로그만 출력한다.
애플리케이션에서 직접 log를 관리하고 로그 로테이션을 하려면 다음과 같이 설정하면 된다.
# 출력할 로그 파일 경로
logging.file.name = ./log/app.log
#로그 백업 시 파일 이름의 패턴(%d는 백업 날짜, %i는 동일한 날짜에 여러 개의 백업 파일이 생성될 경우 1부터 시작하는 일련번호, 확장자 gz라면 gzip으로 백업 파일 압축)
logging.logback.rollingpolicy.file-name-patter = ./log/app.backup.%d{yyyy-MM-dd}.%i.gz
# 백업 파일의 보관 일수
logging.logback.rollingpolicy.max-history = 7
#로그 파일의 크기가 10KB를 넘으면 백업
logging.logback.rollingpolicy.max-file-size=10KB
# 백업 전체 크기가 1GB를 넘으면 오래된 백업부터 삭제
logging.logback.rollingpolicy.total-size-cap = 1GB