BackEND/Java

Spring Batch๋ฅผ ํ™œ์šฉํ•œ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

mingmingIT 2025. 3. 31. 10:03

๐Ÿ”น ๊ฐœ์š”

๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์—์„œ ์ค‘์š”ํ•œ ๊ณผ์ œ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

Spring Batch๋Š” ์ด๋Ÿฌํ•œ ์š”๊ตฌ๋ฅผ ์ถฉ์กฑ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์„ค๊ณ„๋œ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, ๋ฐฐ์น˜ ์ž‘์—…์„ ์•ˆ์ •์ ์ด๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅํ•˜๊ฒŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

๋ณธ ํฌ์ŠคํŒ…์—์„œ๋Š” Spring Batch์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๋ถ€ํ„ฐ ์‹ค์ „ ์˜ˆ์ œ, ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ธฐ๋ฒ•๊นŒ์ง€ ์ƒ์„ธํžˆ ๋‹ค๋ค„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿ”น Spring Batch๋ž€?

Spring Batch๋Š” ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ผ์ •ํ•œ ์ฃผ๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์ตœ์ ํ™”๋œ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. ์ฃผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

  • ์ •๊ธฐ์ ์ธ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ: ์˜ˆ๋ฅผ ๋“ค์–ด, ๋งค์ผ ์ƒˆ๋ฒฝ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•˜๋Š” ๊ฒฝ์šฐ
  • ETL(Extract, Transform, Load) ์ž‘์—…: ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ  ๋ณ€ํ™˜ ํ›„ ์ €์žฅํ•˜๋Š” ๊ณผ์ •
  • ๋Œ€๋Ÿ‰์˜ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ: ๊ธˆ์œต, ๋ฌผ๋ฅ˜ ์‹œ์Šคํ…œ ๋“ฑ์—์„œ ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•  ๋•Œ

 

โœ… Spring Batch ์ฃผ์š” ํŠน์ง•

  • ์ฒญํฌ(Chunk) ๊ธฐ๋ฐ˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ: ๋ฐ์ดํ„ฐ๋ฅผ ์ผ์ • ๋‹จ์œ„(์ฒญํฌ)๋กœ ๋‚˜๋ˆ„์–ด ์ฒ˜๋ฆฌํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ์„ ๊ทน๋Œ€ํ™”
  • ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ: ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋กค๋ฐฑ ์ง€์›
  • ์žฌ์‹œ์ž‘ ๊ฐ€๋Šฅ์„ฑ: ์‹คํŒจํ•œ ๋ฐฐ์น˜ ์ž‘์—…์„ ์ค‘๋‹จ๋œ ์ง€์ ๋ถ€ํ„ฐ ๋‹ค์‹œ ์‹คํ–‰ ๊ฐ€๋Šฅ
  • ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ์ง€์›: ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ, ํŒŒํ‹ฐ์…”๋‹(Partitioning) ๋“ฑ ๊ณ ์„ฑ๋Šฅ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ๊ธฐ๋Šฅ ์ œ๊ณต

 

๐Ÿ”น Spring Batch ์•„ํ‚คํ…์ฒ˜ ๋ฐ ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ

Spring Batch๋Š” Job์„ ์ค‘์‹ฌ์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ, ๊ทธ ๋‚ด๋ถ€์—์„œ Step์„ ํ†ตํ•ด ์ž‘์—…์ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. Job: ๋ฐฐ์น˜ ์ž‘์—…์˜ ์‹คํ–‰ ๋‹จ์œ„
  2. Step: Job ๋‚ด๋ถ€์—์„œ ๊ฐœ๋ณ„์ ์œผ๋กœ ์‹คํ–‰๋˜๋Š” ๋‹จ์œ„
  3. ItemReader: ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์—ญํ•  (์˜ˆ: DB, CSV, API ๋“ฑ์—์„œ ๋ฐ์ดํ„ฐ ๋กœ๋“œ)
  4. ItemProcessor: ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•˜๋Š” ์—ญํ•  (์˜ˆ: ๋ณ€ํ™˜, ํ•„ํ„ฐ๋ง ๋“ฑ)
  5. 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๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋„ ์•ˆ์ •์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.