스프링부트와 AWS로 혼자 구현하는 웹 서비스 3 - Lombok

2 minute read

2장 스프링 부트에서 테스트 코드를 작성하자

💜롬복(LomBok)이란?

  • Java 라이브러리
  • Getter, Setter, default Constructure, toString() 등을 어노테이션으로 자동 생성해준다.
  • 코드 자동생성을 통해 생산성 향상, 반복코드 다이어트를 통해 가독성 및 유지보수성 향상을 기대할 수 있다.
  • API설명과 내부동작을 숙지하지않고 마구 사용하면 예상치못한 여러가지 예외상황이 발생할 수 있어 주의가 필요하다.

💜인텔리제이에 롬복추가하기

intelliJ 2021.2 버전 기준

211009171822.png

[ctrl+shift+A] 를 통해서 Plugins Action을 검색하고 Market Place에서 Lombok을 검색하여 설치하면된다.

intelliJ 2021.2 버전은 디폴트로 설치되어있다.

하지만, 플러그인이 설치되어있더라도 .jar 라이브러리는 따로 설치해주어야한다.

build.gradle 파일에 아래와 같이 dependency를 추가해준다.

repositories {
    mavenCentral()
}

dependencies {
    ...
    implementation 'org.projectlombok:lombok:1.18.22'
    annotationProcessor 'org.projectlombok:lombok:1.18.22'
    ... 
}

annotationProcessor 을 사용하면 Gradle 8.0 과 호환되지 않는 deprecated gradle feature가 사용되었다는 메세지를 확인할 수 있다.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

하지만 annotationProcessor 을 사용하지 않으면, 다음과 같은 에러를 만날 수 있다.

error: variable name not initialized in the default constructor
    private final String name;
                         ^

어차피 Gradle 8.0 버전을 사용하는 것도 아니기 때문에 그냥 사용하겠다.

실습을 위해서는 Gradle 4.x 버전을 추천한다고 한다.

책에서는 File->Settings->Build,Execution,Deployment->Compiler->Annotation Processors 에서 Enable Annotation Processing 설정을 체크해주라고 하는데, 내 프로젝트에서는 설정을 해제해도 오류가 나지는 않는다.

lombok 설정은 프로젝트마다 필요하다.

211009174543.png

💜롬복 예제

intellij 에서는 [Alt + Insert] 단축키로 Getter, Setter, Constructor 등을 자동완성해주는 편리한 기능을 제공하지만, 그래도 여전히 귀찮다. 또한, 코드가 반복되고, 길어지고, 복잡해보인다.

아래 HelloReponseDto 클래스를 롬복으로 리팩토링하여 비교해보았다.

//롬복을 사용하지 않았을 때

public class HelloResponseDto {

    private String name;
    private int amount;

    public HelloResponseDto(String name, int amount) {
        this.name = name;
        this.amount = amount;
    }

    public String getName() {
        return name;
    }

    public int getAmount() {
        return amount;
    }

}
//롬복을 사용하여 리팩토링 했을 때

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class HelloResponseDto {

    private final String name;
    private final int amount;

}

💜Test

[ctrl+shift+T] 를 이용해서 HelloResponseDto class의 테스트 클래스를 만들어본다.

HelloResponseDto class에서 @Getter 어노테이션을 사용했기때문에, 선언된 필드에 대해 자동으로 생성된 Getter가 테스트 클래스를 만들때에 보여지는 것을 확인할 수 있다.

211009172757.png

테스트 클래스를 생성하면, 자동으로 junit의 Assert 클래스가 import 되어있다.

import static org.junit.Assert.*;

하지만, 책의 예제에서는 assertThat 함수를 사용하기 위해 junit의 기본 assertThat이 아니라 assertj 라이브러리를 사용하는 것을 권장한다.

import static org.assertj.core.api.Assertions.assertThat;

🥕 junit에서 제공하는 assertThat 함수 말고, assertj 라이브러리의 assertThat 함수 사용을 권장하는 이유 ?

  • junit에서 제공하는 assertThat 함수의 인자로 받는 Matchers 함수들은 junit에서 의존성을 갖고있는 org.hamcrest.Matcher 에 포함된 함수들인데, 자동완성 지원이 약해서 불편하다.

211010002213.png

  • assertj 라이브러리의 assertThat 함수를 사용하면 함수 인자로 Matchers 함수를 넘기는 대신에 AbstractAssert class를 상속한 객체를 다시 리턴해서 메소드 체이닝을 이용할 수 있고, AbstractAssert class의 함수들은 자동완성 지원이 잘되어서 편리하다.

211010002132.png

211010002148.png

💜Functions for Test

  • assertThat()
    • assertj 라이브러리의 검증 메소드
    • 검증하고 싶은 대상을 메소드 인자로 받는다.
    • 메소드 체이닝 지원
  • isEqualTo()
    • assertj 라이브러리의 동등 비교 메소드
    • assertThat의 인자값과 isEqualTo의 값을 비교해서 같으면 테스트 성공
  • get()
  • param()
  • andExpect()
  • status().isOk()
  • jsonPath()

💜Spring Boot Annotations

  • @RequestParam

💜Lombok Annotations

  • @Getter
  • @Setter
  • @Data == (@ToString, @EqualsAndHashCode, @Getter, @Setter, @RequiredArgsConstructor)
  • @RequiredArgsConstructor
    • 선언된 모든 final 필드가 포함된 생성자를 생성해준다.
    • final이 없는 필드는 생성자에 포함되지 않는다.


Reference