Spring Batch 프로젝트 고도화 (2)

그럼 목표가 정해졌으니 기존 프로젝트를 fork 하고 필요한 것만 남겨보자.

프로젝트 기술 스택

기존 프로젝트에서 사용한, 리펙터링하는 부분과 직접적으로 관련있는 기술 스택은 다음과 같다.

  • 언어
    • Java17 LTS
  • 빌드
    • Gradle 8.13
  • 프레임워크
    • Spring Boot 3.4.4
    • Spring Batch 5.2.2
    • Spring Data JPA
    • Spring Cloud
  • 인프라
    • Docker
    • PostgreSQL (Docker Compose로 실행)

이를 바탕으로 프로젝트 초기설정을 완료해보자.

멀티 모듈 구조 생성

러닝 기록 통계 보고서(userrecap) 를 만드는 서비스와 러닝 기록 저장 서비스가 독립적인 마이크로서비스로 동작하는 MSA 구조를 간단하게 생성한다.

러닝 기록을 관리하는 서비스를 runningrecord-service, 러닝 기록 요약 보고서를 생성하는 서비스를 userrecap-service 라고 하자. 하나의 리포지토리(모노 레포) 에서 멀티 모듈 구조로 만든다.

루트 디렉터리의 settings.gradle 에 다음과 같이 작성한다.

// ./settings.gradle

rootProject.name = 'userrecap-refactoring'  
  
include 'userrecap-service'  
include 'runningrecord-service'

인텔리제이로 생성한 경우 루트 디렉터리의 src 디렉터리는 지워준 후, 서브 모듈을 생성한다. 서브 모듈에서는 src 디렉터리와 build.gradle 파일만 남긴다.

그 다음은 루트의 build.gradle 에서 하위 프로젝트를 관리할 설정을 작성해준다.

// file: "build.gradle"

plugins {  
    id 'java'  
    id 'org.springframework.boot' version '3.4.4' apply false  
    id 'io.spring.dependency-management' version '1.1.7' apply false  
}  
  
allprojects {  
    group = 'com.refactoring'  
    version = '0.0.1-SNAPSHOT'  
  
    java {  
        toolchain {  
            languageVersion = JavaLanguageVersion.of(17)  
        }  
    }  
  
    repositories {  
        mavenCentral()  
    }  
}  
  
subprojects {  
    apply plugin: 'java'  
    apply plugin: 'org.springframework.boot'  
    apply plugin: 'io.spring.dependency-management'  
  
    dependencies {  
        implementation 'org.springframework.boot:spring-boot-starter'  
        testImplementation 'org.springframework.boot:spring-boot-starter-test'  
        testRuntimeOnly 'org.junit.platform:junit-platform-launcher'  
  
        if (project.name != 'common'){implementation project(':common')}  
    }  
  
    tasks.named('test') {  
        useJUnitPlatform()  
    }  
}
  • 공통 설정을 적용하고 나중에 각 서비스마다 필요한 의존성을 따로 추가하면 된다.
  • 각 서비스에 필요한 공통 로직을 저장하기 위해 common 모듈을 추가했다.

빌드 후 프로젝트에서 gradle 의 계층 관계가 이렇게 된다!

Spring Batch 설정

기본적인 빌드가 끝났으니 이제 주로 작업할 userrecap-service 의 Spring Batch 관련 설정을 끝내보자.

// file: "./userrecap-service/build.gradle"

configurations {  
    compileOnly {  
        extendsFrom annotationProcessor  
    }  
}  
  
dependencies {  
    implementation 'org.projectlombok:lombok'  
    annotationProcessor 'org.projectlombok:lombok'  
    implementation 'org.springframework.boot:spring-boot-starter-batch'  
    runtimeOnly 'com.h2database:h2'  
  
}
  • 먼저 build.gradle 에 Spring Batch 같은 필요한 의존성을 추가한다.
// file: "UserrecapServiceApplication.java"

import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
  
@SpringBootApplication  
public class UserrecapServiceApplication {  
  
  public static void main(String[] args) {  
    System.exit(  
        SpringApplication.exit(SpringApplication.run(UserrecapServiceApplication.class, args)));  
  }  
}

  • 프로젝트를 생성했을 때 만들어주는 기본 생성 코드를 변경하였다.
  • 배치 프로그램은 모니터링과 제어가 중요하기 때문에 외부로 프로세스의 종료 코드를 전달할 수 있는 System.exit() 의 사용이 권장된다.

이제 hello world! 확인을 위한 간단한 Job 코드를 만들고 실행해보자.

// file: "RecapJobConfig.java"

@Configuration  
@RequiredArgsConstructor  
public class RecapJobConfig {  
  
  private final JobRepository jobRepository;  
  private final PlatformTransactionManager transactionManager;  
  
  @Bean  
  public Job recapJob() {  
    return new JobBuilder("recapJob", jobRepository)  
        .start(helloStep())  
        .build();  
  }  
  
  @Bean  
  public Step helloStep() {  
    return new StepBuilder("hellpStep", jobRepository)  
        .tasklet((contribution, chunkContext) -> {  
          System.out.println("Hello World!");  
          return RepeatStatus.FINISHED;  
        }, transactionManager)  
        .build();  
  }  
  
}

  • 실행까지 잘 된다! 이걸로 기초적인 빌드와 설정은 완료되었다.

데이터베이스 연결

로컬 환경에서 빠른 테스트를 위해 docker 이미지를 사용해 postgreSql이 설치된 컨테이너를 띄우고 연결한다.

데이터베이스를 연결하면 Spring Batch 가 배치 실행 싸이클을 관리하기 위한 메타데이터 스키마를 추가해줘야 한다. Spring Batch 5.x.x 부터는 스키마를 자동 주입하는 건 안되는 것 같고, DB 연결 후 spring-batch-core 라이브러리에서 스키마 파일을 찾아 이를 직접 실행하면 되겠다. 해당 파일을 복사하여 init.sql 이라는 이름으로 프로젝트 루트 디렉터리에 생성하고 사용하자.

필요한 스키마는 spring-batch-core 모듈을 검색해서 패키지를 뒤지다보면 확인할 수 있다.

이제 배치 작업에 대한 메타데이터를 확인하여 모니터링할 수 있게 되었다.

기초적인 세팅 끝

잘 실행되는 걸 확인했고 처음 세팅은 대충 끝났으니 다음부터는 구현을 시작해보자!