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모듈을 추가했다.
/img_2025-12-17-13-58-28.png)
빌드 후 프로젝트에서 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();
}
}
/img_2025-12-17-17-32-23.png)
- 실행까지 잘 된다! 이걸로 기초적인 빌드와 설정은 완료되었다.
데이터베이스 연결
로컬 환경에서 빠른 테스트를 위해 docker 이미지를 사용해 postgreSql이 설치된 컨테이너를 띄우고 연결한다.
데이터베이스를 연결하면 Spring Batch 가 배치 실행 싸이클을 관리하기 위한 메타데이터 스키마를 추가해줘야 한다. Spring Batch 5.x.x 부터는 스키마를 자동 주입하는 건 안되는 것 같고, DB 연결 후 spring-batch-core 라이브러리에서 스키마 파일을 찾아 이를 직접 실행하면 되겠다. 해당 파일을 복사하여 init.sql 이라는 이름으로 프로젝트 루트 디렉터리에 생성하고 사용하자.
/pastedimage_sql.png)
/schema.png)
필요한 스키마는 spring-batch-core 모듈을 검색해서 패키지를 뒤지다보면 확인할 수 있다.
이제 배치 작업에 대한 메타데이터를 확인하여 모니터링할 수 있게 되었다.
기초적인 세팅 끝
잘 실행되는 걸 확인했고 처음 세팅은 대충 끝났으니 다음부터는 구현을 시작해보자!