๐น ๊ฐ์
๋๋์ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๊ฒ์ ๋ฐฑ์๋ ๊ฐ๋ฐ์์ ์ค์ํ ๊ณผ์ ์ค ํ๋์ ๋๋ค.
Spring Batch๋ ์ด๋ฌํ ์๊ตฌ๋ฅผ ์ถฉ์กฑ์ํค๊ธฐ ์ํด ์ค๊ณ๋ ํ๋ ์์ํฌ๋ก, ๋ฐฐ์น ์์ ์ ์์ ์ ์ด๊ณ ํ์ฅ ๊ฐ๋ฅํ๊ฒ ์คํํ ์ ์๋๋ก ๋์์ค๋๋ค.
๋ณธ ํฌ์คํ ์์๋ Spring Batch์ ๊ธฐ๋ณธ ๊ฐ๋ ๋ถํฐ ์ค์ ์์ , ์ฑ๋ฅ ์ต์ ํ ๊ธฐ๋ฒ๊น์ง ์์ธํ ๋ค๋ค๋ณด๊ฒ ์ต๋๋ค.
๐น Spring Batch๋?
Spring Batch๋ ๋๋์ ๋ฐ์ดํฐ๋ฅผ ์ผ์ ํ ์ฃผ๊ธฐ๋ก ์ฒ๋ฆฌํ๋ ๋ฐ ์ต์ ํ๋ ํ๋ ์์ํฌ์ ๋๋ค. ์ฃผ๋ก ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์ ์ฌ์ฉ๋ฉ๋๋ค.
- ์ ๊ธฐ์ ์ธ ๋ฐ์ดํฐ ์ฒ๋ฆฌ: ์๋ฅผ ๋ค์ด, ๋งค์ผ ์๋ฒฝ ํน์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํ๋ ๊ฒฝ์ฐ
- ETL(Extract, Transform, Load) ์์ : ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ๋ณํ ํ ์ ์ฅํ๋ ๊ณผ์
- ๋๋์ ํธ๋์ญ์ ์ฒ๋ฆฌ: ๊ธ์ต, ๋ฌผ๋ฅ ์์คํ ๋ฑ์์ ๋๋์ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ์ฒ๋ฆฌํ ๋
โ Spring Batch ์ฃผ์ ํน์ง
- ์ฒญํฌ(Chunk) ๊ธฐ๋ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ: ๋ฐ์ดํฐ๋ฅผ ์ผ์ ๋จ์(์ฒญํฌ)๋ก ๋๋์ด ์ฒ๋ฆฌํ์ฌ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ์ ๊ทน๋ํ
- ํธ๋์ญ์ ๊ด๋ฆฌ: ์ฒ๋ฆฌ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ๋กค๋ฐฑ ์ง์
- ์ฌ์์ ๊ฐ๋ฅ์ฑ: ์คํจํ ๋ฐฐ์น ์์ ์ ์ค๋จ๋ ์ง์ ๋ถํฐ ๋ค์ ์คํ ๊ฐ๋ฅ
- ๋ณ๋ ฌ ์ฒ๋ฆฌ ์ง์: ๋ฉํฐ ์ค๋ ๋, ํํฐ์ ๋(Partitioning) ๋ฑ ๊ณ ์ฑ๋ฅ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ์ํ ๊ธฐ๋ฅ ์ ๊ณต
๐น Spring Batch ์ํคํ ์ฒ ๋ฐ ์ฃผ์ ์ปดํฌ๋ํธ
Spring Batch๋ Job์ ์ค์ฌ์ผ๋ก ๋์ํ๋ฉฐ, ๊ทธ ๋ด๋ถ์์ Step์ ํตํด ์์ ์ด ์ํ๋ฉ๋๋ค. ์ฃผ์ ์ปดํฌ๋ํธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- Job: ๋ฐฐ์น ์์ ์ ์คํ ๋จ์
- Step: Job ๋ด๋ถ์์ ๊ฐ๋ณ์ ์ผ๋ก ์คํ๋๋ ๋จ์
- ItemReader: ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ์ญํ (์: DB, CSV, API ๋ฑ์์ ๋ฐ์ดํฐ ๋ก๋)
- ItemProcessor: ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํ๋ ์ญํ (์: ๋ณํ, ํํฐ๋ง ๋ฑ)
- ItemWriter: ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ์ญํ (์: DB, ํ์ผ ๋ฑ)
๐น ๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ์ํ ์ฑ๋ฅ ์ต์ ํ ๊ธฐ๋ฒ
๋์ฉ๋ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ๋ ์ฑ๋ฅ์ ๊ทน๋ํํ๋ ๋ฐฉ๋ฒ์ ์์๋ด ๋๋ค.
โ 1. ์ฒญํฌ ๊ธฐ๋ฐ ์ฒ๋ฆฌ (Chunk-Oriented Processing)
- ๋ฐ์ดํฐ๋ฅผ ์ผ์ ํฌ๊ธฐ๋ก ๋๋์ด ํ ๋ฒ์ ์ฒ๋ฆฌํ๋ ๋ฐฉ์
- ์ฒญํฌ ๋จ์๋ก ํธ๋์ญ์ ์ด ์ ์ฉ๋๋ฏ๋ก, ์ฅ์ ๋ฐ์ ์ ์ผ๋ถ ๋ฐ์ดํฐ๋ง ๋กค๋ฐฑ ๊ฐ๋ฅ
@Bean
public Step chunkStep() {
return stepBuilderFactory.get("chunkStep")
.<InputData, ProcessedData>chunk(1000) // ํ ๋ฒ์ 1000๊ฐ์ฉ ์ฒ๋ฆฌ
.reader(itemReader())
.processor(itemProcessor())
.writer(itemWriter())
.build();
}
โ 2. Cursor ๊ธฐ๋ฐ vs ํ์ด์ง ๊ธฐ๋ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
- Cursor ๊ธฐ๋ฐ: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ปค์๋ฅผ ์ด์ฉํด ๋ฐ์ดํฐ๋ฅผ ์์ฐจ์ ์ผ๋ก ์ฝ์ → ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ ๊ฐ๋ฅ
- ํ์ด์ง ๊ธฐ๋ฐ: ๋ฐ์ดํฐ๋ฅผ ํ์ด์ง ๋จ์๋ก ๊ฐ์ ธ์ด → ๋๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ ์ฑ๋ฅ ์ด์ ์ด ์์
โ 3. ๋ฉํฐ ์ค๋ ๋ & ๋ณ๋ ฌ ์ฒ๋ฆฌ
- ๋ฉํฐ ์ค๋ ๋ ์คํ : Step์ ์ฌ๋ฌ ๊ฐ์ ์ค๋ ๋๋ก ์คํํ์ฌ ์ฑ๋ฅ ํฅ์
- Partitioning: ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฌ ๊ฐ์ ์ฒญํฌ๋ก ๋๋์ด ๋ถ์ฐ ์ฒ๋ฆฌ
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.initialize();
return executor;
}
๐น Spring Batch ์ค์ ์์ : CSV → DB ์ ์ฅ
๋ค์์ CSV ํ์ผ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ , ๋ณํํ ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ๋ ์์ ์ ๋๋ค.
โ 1. ItemReader (CSV ํ์ผ ์ฝ๊ธฐ)
@Bean
public FlatFileItemReader<MyData> itemReader() {
return new FlatFileItemReaderBuilder<MyData>()
.name("csvReader")
.resource(new ClassPathResource("data.csv"))
.delimited()
.names("id", "name", "age")
.targetType(MyData.class)
.build();
}
โ 2. ItemProcessor (๋ฐ์ดํฐ ๋ณํ)
@Bean
public ItemProcessor<MyData, MyData> itemProcessor() {
return item -> {
item.setName(item.getName().toUpperCase());
return item;
};
}
โ 3. ItemWriter (DB ์ ์ฅ)
@Bean
public JdbcBatchItemWriter<MyData> itemWriter(DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<MyData>()
.dataSource(dataSource)
.sql("INSERT INTO my_table (id, name, age) VALUES (:id, :name, :age)")
.beanMapped()
.build();
}
๐น Spring Boot์์ Batch ์คํ ๋ฐ ๋ฐฐํฌ
- CommandLineRunner๋ฅผ ์ฌ์ฉํ ์คํ
- Spring Scheduler์ ์ฐ๋ํ์ฌ ์ฃผ๊ธฐ์ ์คํ
- ๋ฐฐํฌ ์ ๊ณ ๋ คํด์ผ ํ ์ (DB Lock, ๋ฐฐ์น ์คํ ์ด๋ ฅ ๊ด๋ฆฌ ๋ฑ)
๐น ๊ฒฐ๋ก
Spring Batch๋ฅผ ํ์ฉํ๋ฉด ๋์ฉ๋ ๋ฐ์ดํฐ๋ ์์ ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
'BackEND > Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
JPA์ ๊ธฐ๋ณธ ์กฐํ ์ฑ๋ฅ ์ต์ ํ ๊ธฐ๋ฒ (0) | 2025.04.02 |
---|---|
JPA์ QueryDSL ์๊ฐ ๋ฐ ๋น๊ต (0) | 2025.04.01 |
ํ๋ก์ ํธ์์ Redis ์บ์ ์ต์ ํ ๋ฐฉ๋ฒ (0) | 2025.03.30 |
Spring Boot์์ Redis ์บ์ ์ฌ์ฉ ๋ฐฉ๋ฒ (1) | 2025.03.29 |
Spring Boot์์ @Cacheable์ ํ์ฉํ์ฌ ์บ์๋ฅผ ์ ์ฉํ๋ ๋ฐฉ๋ฒ (0) | 2025.03.28 |