Amazon EventBridge ์ค์ผ์ค๋ฌ๋ฅผ ์ด์ฉํด์ ์ฃผ๊ธฐ์ ์ผ๋ก ๋๋ฐ์ด์ค๋ฅผ ์คํ์์ผฐ๋ค.
์ค์ผ์ค ๋ฐ์ดํฐ๊ฐ ๊ณ์ ๋์ด๋๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ๋ฅผ update (๋๋ create)ํ์ง ํ ๋ฌ์ด ์ง๋๋ฉด ์๋์ผ๋ก ์ญ์ ๋๋ ๊ธฐ๋ฅ์ ๊ฐ๋ฐํด์ผํ๋ค.
Spring Batch ์ฌ์ฉ์ ์ฒ์์ด๋ผ ์ด๋ป๊ฒ ํ ์ง ๊ตฌ๊ธ๋งํ๋ ์ค์ ๋ค์ด๋ฒ ๊ฐ๋ฐ์ ๋ถ ์ค Spring Batch๋ฅผ ๋ ์ฐ์ํ๊ฒ ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ์ํ ๊ฒ์๊ธ์ ๋ณด๊ฒ ๋์๋ค. ์ฌ์ง์ด ์ฝํ๋ฆฐ์ผ๋ก ํ์ฉํ๋ ๋ฐฉ๋ฒ๊น์ง ์์ด์ ์ฐธ๊ณ ํ๊ธฐ ์ข์ ๊ธ์ด์๋ค๋ง..๐
๐ํ์ง๋ง ์ฌ์ฉํ๋ ค๊ณ ๋ฏ์ด๋ณด๋.. ๋ฌธ์ ๊ฐ ์์ด์ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ํํ๋ค๐ฅฒ (๋ฐ ๊ธ ์ฐธ๊ณ )
Spring Batch๋ฅผ ํ์ฉํด ๊ฐ๋ฐํ ๊ฒ์ ๊ธฐ๋กํด๋ณด๊ฒ ๋ค
(์ฐธ๊ณ ๋ก ํ๋ก์ ํธ์์ ํ์ฉํ Spring Batch๋ 4.X.X์ด๋ค.)
๐ช ๋ชฉํ : update(๋๋ create)๋์ง ํ ๋ฌ์ด ์ง๋ ๋ฐ์ดํฐ ์ญ์ ํ๊ธฐ !
Spring Batch๋?
"A lightweight, comprehensive batch framework designed to enable the development of robust batch applications vital for the daily operations of enterprise systems."
์ ํด์ง ์๊ฐ์ ์ผ๊ด์ ์ผ๋ก ๋์ฉ๋์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ์ํ batch ์ฒ๋ฆฌ ํ๋ ์์ํฌ๋ก, ์ค์ผ์ค๋ฌ๋ฅผ ๋์ฒดํ๊ธฐ๋ณด๋ค๋ ์ค์ผ์ค๋ฌ์ ํจ๊ป ์๋
- ๋ค์ํ batch ์ฒ๋ฆฌ ์ง์
- ๋๋์ ๋ฐ์ดํฐ ์ฝ๊ธฐ/์ฐ๊ธฐ
- ๋ฐ์ดํฐ ๋ณํ ๋ฐ ์ฒ๋ฆฌ
- ๋ณ๋ ฌ ์ฒ๋ฆฌ ๋ฐ ๋ค์ค ์ค๋ ๋ ์ง์
- ํธ๋์ญ์ ๊ด๋ฆฌ
- ๋ชจ๋ํฐ๋ง ๋ฐ ๊ด๋ฆฌ ๊ธฐ๋ฅ
๐ท ์ฃผ์ ๊ตฌ์ฑ ์์
- Job
- batch ์์ ์ ๋ ผ๋ฆฌ์ ๋จ์๋ก, ์ฌ๋ฌ step์ผ๋ก ๊ตฌ์ฑ๋จ ๐ ์ ์ฒด batch process ์ ์
- ๋ฐฐ์น ์์ ์ ๋ฉํ ๋ฐ์ดํฐ ๊ด๋ฆฌ
- Step ์์ ์ ์
- JobParameters ๋ฐ์
- Step
- ์ค์ Batch ์์ ์ ์ํํ๋ ์ญํ
- Job์ ์ธ๋ถ ์์ ๋จ์๋ก, ๊ฐ๋ณ์ ์ผ๋ก ์คํ๋จ
- chunk ๊ธฐ๋ฐ (chunk-oriented), tasklet ๊ธฐ๋ฐ์ผ๋ก ๋๋จ
- ItemReader, ItemProcessor, ItemWriter๋ก ๊ตฌ์ฑ
- ItemReader
- ๋ฐ์ดํฐ ์ฝ์ด์ค๋ ์ญํ
- ItemProcessor
- ์ฝ์ด์จ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
- ItemWriter
- ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ ์ ์ฅ
ItemReader, ItemProcessor, ItemWriter๋ฅผ ๋ฌถ์ด์ Tasklet์ผ๋ก ๋ถ๋ฅด๊ธฐ๋ ํ๋ค.
๐ ํ๋์ ํธ๋์ญ์ ์์ ์ฒ๋ฆฌํ๋ฏ๋ก ๋จ์ํ ์ฒ๋ฆฌ ์ ์ฃผ๋ก ์ฌ์ฉ
- JobRepository
- Job ์คํ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ๊ด๋ฆฌ
- Step ์ ์ฅ
๐น Spring Batch ์คํค๋ง ๊ตฌ์กฐ
๐ ๋ฐฐ์น ์คํํ๊ณ ๊ด๋ฆฌํ๊ธฐ ์ํ ๋ฉํ ๋ฐ์ดํฐ ์ ์ฅ
- ์ด๊ธฐ ์ค์ ํ์
- Spring Batch Framework์ ์ํ๋ ๋ถ๋ถ์ด๋ฏ๋ก ์์ ํ์ง ์๊ณ ์กฐํ๋ง ํจ
- Job ์ด๋ ฅ, ํ๋ผ๋ฏธํฐ ๋ฑ ์คํ ๊ฒฐ๊ณผ ์กฐํ
Spring Batch Plus
https://github.com/naver/spring-batch-plus
๐ Spring Batch๋ฅผ ์กฐ๊ธ ๋ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ์ ์ฉํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ํฌํผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
๐ท DeleteMetadataJob
- ๋ ์ง๋ฅผ ๊ธฐ์ค์ผ๋ก ํด๋น ๋ ์ง ์ด์ ์ ์ํ๋ ๋ชจ๋ Job, Step์ metadata๋ฅผ ์ญ์ ํ๋ Job
๐ ์ด๊ฑธ ์ฌ์ฉํ๋ ค๊ณ ํ์ผ๋ ...
ํ๋ผ๋ฏธํฐ๋ก dataSource๋ฅผ ๋๊ฒจ์ฃผ์ด์ผํ๋ค.
ํ์ง๋ง MongoDB๋ฅผ ์ฌ์ฉํ๋ ํ๋ก์ ํธ๋ผ์ JDBC API๋ฅผ ํตํด ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ์์ฉํ๋ DataSource๋ฅผ MongoDB์ ์ ์ฉ์ํฌ ์ ์์๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ํํด์ผํ๋ค..ใ
update๋์ง ํ ๋ฌ ์ง๋ ์ค์ผ์ค ์ญ์ ๋ฐฐ์น ์ฒ๋ฆฌ
- DB์ ์ ์ฅ๋ ๋ฐ์ดํฐ ์ค update๋์ง ํ ๋ฌ์ด ์ง๋ ์ค์ผ์ค ์ฐพ๋ ๋ก์ง ๊ตฌํ ๐ ItemReader
- ๋์ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ ํ๋ก์ธ์ค ๊ตฌํ ๐ ItemProcessor & ItemWriter
- ๋จ์ํ ์ญ์ ๋ง ํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ Tasklet์ ํ์ฉํด ํ๋ก์ธ์ค๋ฅผ ๊ตฌํํ๋ค.
๐ท Batch ์ฒ๋ฆฌ ์์
- ์ค์ผ์ค Job ์ค์
- ์ค์ผ์ค Step ์ค์
- ์ค์ผ์ค Reader, Processor, Writer ๐ tasklet ์ค์
๐ถJob ์ค์
@Configuration
class DeviceControlBatchConfiguration(
private val jobBuilderFactory: JobBuilderFactory,
private val stepBuilderFactory: StepBuilderFactory,
private val deviceControlTasklet: DeleteDeviceControlTasklet
){
val log = LoggerFactory.getLogger(this::class.simpleName)
@Bean
fun deleteJob(): Job {
return jobBuilderFactory.get("deleteDeviceControlJob")
.start(deleteStep())
.build()
}
}
- Job ๊ฐ์ฒด๋ฅผ ์ฝ๊ฒ ์์ฑํ๊ณ ๊ตฌ์ฑํ ์ ์๋๋ก ํ๋ JobBuilderFactory๋ฅผ ์ฃผ์ ๋ฐ์
- "deleteDeviceControlJob"์ ์ด๋ฆ์ ๊ฐ์ง JobBuilder ์์ฑ
- start(deleteStep())์ผ๋ก Job์ ์ฒซ๋ฒ์งธ Step ์ค์
๐ถ Step ์ค์
@Bean
fun deleteStep(): Step {
return stepBuilderFactory.get("deleteDeviceControlStep")
.tasklet(deviceControlTasklet)
.build()
}
- Step ๊ฐ์ฒด๋ฅผ ์ฝ๊ฒ ์์ฑํ๊ณ ๊ตฌ์ฑํ ์ ์๋๋ก ํ๋ StepBuilderFactory๋ฅผ ์ฃผ์ ๋ฐ์
- "deleteDeviceControlStep"์ ์ด๋ฆ์ ๊ฐ์ง StepBuilder ์์ฑ
- tasklet(deviceControlTasklet)์ผ๋ก ์ด Step์์ ์คํํ Tasklet ์ค์
โจ Tasklet์ด๋?
๐ Spring Batch์์ ๋ฐฐ์น ์์ ์ ๋จ๊ณ๋ฅผ ์ ์ํ๋ ์ธํฐํ์ด์ค๋ก, ๋จ์ผ ์์ ๋จ์๋ก ํ ๋ฒ์ ํ๋์ ์์ ์ ์ํํ๋ ๋ฐ ์ฌ์ฉ๋จ = Step ์์์ ์ํ๋ ๊ธฐ๋ฅ ๋ช ์- StepContribution : ํ์ฌ step์ ์คํ์ ๋ํ ๋ฉํ ๋ฐ์ดํฐ๋ฅผ ๋ํ๋ ๐๋ฐฐ์น ์ฒ๋ฆฌ ์ค์ ๋ฐ์ํ๋ ๋ค์ํ ์ ๋ณด ์ถ์
- ChunkContext : ์ฒญํฌ ์ฒ๋ฆฌ์ ๋ํ ์ปจํ ์คํธ ์ ๋ณด ์ ๊ณต
- RepeatStatus : ์์ ์ด ๊ณ์ ๋ฐ๋ณต๋ ์ง, ์๋ฃ๋์๋์ง ์ฌ๋ถ ๋ํ๋
๐ถ Tasklet ์ค์
@Component
class DeleteDeviceControlTasklet(
private val deviceControlScheduleRepository: DeviceControlScheduleRepository
) : Tasklet {
// ๋ฐฐ์น ์์
์์ ์ค์ ๋ก ์ํ๋ ์์
์ ์
override fun execute(contribution: StepContribution, chunkContext: ChunkContext): RepeatStatus {
val oneMonthAgo = LocalDateTime.now().minusMonths(1)
deviceControlScheduleRepository.findAllByUpdatedAtBefore(oneMonthAgo)
.flatMap{ deviceControlSchedule -> deviceControlScheduleRepository.deleteById(deviceControlSchedule.id!!)}
.then(Mono.empty<Void>())
.block()
return RepeatStatus.FINISHED
}
}
- findAllByUpdatedAtBefore(oneMonthAgo) : update๋์ง ํ๋ฌ์ด ์ง๋ ๋ฐ์ดํฐ ์ฐพ๊ธฐ
- deleteById() : ํด๋นํ๋ id๊ฐ์ ๊ฐ์ง ๊ฐ์ฒด ์ญ์ ํ๊ธฐ
- .block() : ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ ๊ธฐ๋ค๋ฆฌ๊ธฐ ์ํด ์ฌ์ฉ ๐ ํ์ฌ ์ค๋ ๋ ์ฐจ๋จํ๊ณ ๊ฒฐ๊ณผ ๋ฐํ๋ฐ์
- return RepeatStatus.FINISHED : ์์๋ฅผ ๋ฐํํ์ฌ Spring Batch๋ ํ์ฌ ๋จ๊ณ๊ฐ ์๋ฃ๋์์ผ๋ฉฐ ๋ค์ ๋จ๊ณ ์งํ ๋๋ ๋ฐฐ์น ์์ ์ข ๋ฃํ ์ค๋น๋์์์ ์๋ฏธ
๐ถ ์ค์ผ์ค๋ฌ ์ฌ์ฉํด์ ์ฃผ๊ธฐ์ ์ผ๋ก Batch ์คํ์ํค๊ธฐ
- JobParameters : Spring Batch์ Job ์คํ ์ ์ ๋ฌ๋๋ ๋งค๊ฐ๋ณ์๋ก ๋ฐฐ์น ์์ ์ ๋์ ์ ์ด ๐ ํ์ผ ๊ฒฝ๋ก, ๋ ์ง, ID ๋ฑ๊ณผ ๊ฐ์ ๋์ ๊ฐ์ ๋ฐฐ์น ์์ ์ ์ ๋ฌ
- JobParametersBuilder : JobParameters ๊ฐ์ฒด๋ฅผ ์ฝ๊ฒ ๊ตฌ์ฑํ ์ ์๋๋ก ๋์์ฃผ๋ ๋น๋ ํด๋์ค
- JobLauncher : Job ์คํ ๐ ๋ฐฐ์น ์์ ์์ํ๊ณ ์์ ์คํ์ ์ํ ๊ด๋ฆฌ ๋ฐ ์์ ํ๋ผ๋ฏธํฐ ์ ๋ฌ ๊ธฐ๋ฅ ์ ๊ณต
@Component
class DeviceControlBatchScheduler (
@Autowired private val jobLauncher: JobLauncher,
@Autowired private val deleteJob: Job,
){
private val log = LoggerFactory.getLogger(DeviceControlBatchScheduler::class.java)
@Scheduled(cron="0 40 * * * ?")
fun runJob(){
val jobParameters = JobParametersBuilder()
.addLong("startTime", System.currentTimeMillis())
.toJobParameters()
val jobExecution = jobLauncher.run(deleteJob, jobParameters)
log.info("Job Execution Status: ${jobExecution.status}")
}
}
๐ find using query๋ฅผ ๋ณด๋ฉด ํ ๋ฌ ์ ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค.
๊ฐ์ ธ์จ ํ remove using query๋ฅผ ํตํด ์ญ์ ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ค๋ฅ
๐ท Could not autowire. No beans of 'JobBuilderFactory' type found.
๐ cache ์ญ์ ํ ์ ์ ์๋
๐ท Bean ๋ฑ๋ก ๋ฐ datasource ์ค๋ฅ
์ฒ์์๋
implementation 'org.springframework.boot:spring-boot-starter-batch'
์ด๊ฑธ๋ก ์์กด์ฑ ์ถ๊ฐ๋ฅผ ํด์ฃผ์๋๋ฐ dataSource์ Bean ๊ด๋ จํด์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
implementation("org.springframework.batch:spring-batch-core:4.3.7")
๐ ์์ ์๋ ๊ฑธ๋ก ๋ณ๊ฒฝํ๋๋ ์ ์์ ์ผ๋ก ์คํ๋๋ค.
๐ฅ์์ ๋ ์ฐจ์ด์ ์ ..?
- spring-boot-starter-batch๋ ์๋ ๊ตฌ์ฑ์ ์ ๊ณตํ๊ณ ๊ธฐ๋ณธ์ ์ธ ๋ฐฐ์น ์์ ์ค์ ์ ๊ฐํธํ๊ฒ ํ ์ ์๋ค.
- spring-batch-core
- spring-boot-starter
- spring-boot-starter-jdbc
- spring-batch-core๋ Spring Batch์ ํต์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ง ํฌํจํ๋ ์์กด์ฑ์ผ๋ก, Spring Batch ๊ธฐ๋ณธ ๊ธฐ๋ฅ๋ง ์ ๊ณตํ๋ฉฐ Spring Boot์ ์๋ ๊ตฌ์ฑ ๊ธฐ๋ฅ์ ํฌํจ๋์ด์์ง ์์ผ๋ฏ๋ก Spring Boot์ ์๋ ๊ตฌ์ฑ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค์ ๋ฑ์ ๋ณ๋๋ก ์ค์ ํด์ผํ๋ค.
ํ์ฌ ํ๋ก์ ํธ๋ ์์ ๋งํ๋ฏ์ด mongoDB๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค.
ํ์ง๋ง spring-batch๋ ๊ธฐ๋ณธ์ ์ผ๋ก RDB๋ฅผ ์ฌ์ฉํด ๋ฐฐ์น์์ ์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ๊ด๋ฆฌํ๋ค.
๊ทธ๋ฌ๋ฏ๋ก spring-boot-starter-batch๋ก ์์กด์ฑ์ ์ถ๊ฐํ ๊ฒฝ์ฐ, spring-boot-starter-jdbc๋ก ์ธํด RDB๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฉํ ๊ฒ์ผ๋ก ์๊ฐ๋์ด DB๋ฅผ ํธํํ๋๋ฐ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค.
spring-batch-core๋ starter์ ๋ฌ๋ฆฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค์ ์ ๋ณ๋๋ก ํด์ผํ๊ธฐ ๋๋ฌธ์ ์๋ง ์ ์์ ์ผ๋ก ์คํ๋๋ ๊ฒ ๊ฐ๊ณ , ๋ฉํ๋ฐ์ดํฐ๋ฅผ RDB ์ธ์ ์ ์ฅ์์ ์ ์ฅํ๋ ค๋ฉด ์ปค์คํฐ๋ง์ด์งํด์ผํ ๊ฒ ๊ฐ๋ค.
MongoDB๋ก ์ปค์คํฐ๋ง์ด์งํ๋ ๋ฐฉ๋ฒ์ ์ถํ์ ์ ๋ฆฌํ ์์ ์ด๋ค...๐
์ฐธ๊ณ ์๋ฃ
https://d2.naver.com/helloworld/9879422
https://github.com/naver/spring-batch-plus/blob/main/doc/ko/job/delete-metadata-job.md
https://tech.kakaopay.com/post/spring-batch-performance/
'Spring > Spring & Spring Boot' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] Example<T> ์ธํฐํ์ด์ค (0) | 2025.03.11 |
---|---|
[Spring] Spring Batch 5 ์ฌ์ฉํด๋ณด๊ธฐ (0) | 2024.07.31 |
[Spring/Spring Boot] SSE (Server-Sent Events)์ EventSource ์ ์ฉํด๋ณด๊ธฐ (0) | 2024.05.14 |
[Spring] Spring Security @AuthenticationPrincipal (0) | 2024.04.10 |
[Spring] ํํฐ(Filter)์ ์ธํฐ์ ํฐ(Interceptor) (0) | 2024.03.18 |