2025.07.03 - [๐ชBackend/Spring] - Spring Batch ๋์ ๊ธฐ!! - @Scheduled๋ก๋ ๋ถ์กฑํ๋ค(#1)
๐ ๋ค์ด๊ฐ๋ฉฐ
Spring Batch๋ฅผ ๋์ ํ ํ, ์ฒ์ ๋ง์ฃผํ ์ค์ง์ ์ธ ๊ณ ๋ฏผ์ ๋ฐ๋ก ์ด๊ฒ์ด์์ต๋๋ค:
Tasklet์ ์จ์ผ ํ ๊น, Chunk๋ฅผ ์จ์ผ ํ ๊น?
๋ฌธ์์๋, ๋ธ๋ก๊ทธ์๋ ๋ง์ ์ค๋ช ์ด ์์ง๋ง, ์ง์ ์ ์ฉํ๋ ค ํ๋ ํท๊ฐ๋ฆฌ๋ ๋ถ๋ถ์ด ๋ง์์ต๋๋ค.
- ์ข ๋ชฉ๋ณ๋ก API๋ฅผ ํธ์ถํด 3๋ ์น ๋ฐ์ดํฐ๋ฅผ ์์งํ๊ณ ์ ์ฅํ๋ ์์
- ๋งค์ผ ์ฃผ์ ๋ง๊ฐ ํ ํ๋ฃจ์น ๋ฐ์ดํฐ๋ฅผ ๊ฐฑ์ ํ๋ ์์
์ ๋ ์์ ๊ฐ์ ์์ ๋ค์ ๋ฆฌํฉํ ๋ง ์ค์ด์์ต๋๋ค.
์ด ์์
๋ค์ ์ด๋ค ๋ฐฉ์์ ์ ํํ๋ ๊ฒ ๋ง์๊น์?
์ด๋ฒ ๊ธ์์๋ Tasklet๊ณผ Chunk์ ๊ตฌ์กฐ์ ์ฐจ์ด์ ์ ์ฉ ๊ธฐ์ค์ ์ ๋ฆฌํด๋ณด๋ ค ํฉ๋๋ค..!!
๐งฑ ๊ธฐ๋ณธ ๊ฐ๋
โ Tasklet ๊ธฐ๋ฐ
stepBuilderFactory.get("step")
.tasklet((contribution, chunkContext) -> {
// ํ ๋ฒ์ ์ ์ฒด ์์
์ํ
return RepeatStatus.FINISHED;
})
.build();
- ๋จ์ผ ๋ฉ์๋์์ ์ ์ฒด ์์ ์ํ
- ๋ฐ๋ณต๋ฌธ, API ํธ์ถ, ํ์ผ ์ญ์ ๋ฑ ๋ช ๋ นํ ๋ก์ง์ ์ ํฉ
- ์์ ํ๋ฆ์ด ๋จ์ํ๊ณ ๋ช ํํ ๋ ์ฌ์ฉ
โ Chunk ๊ธฐ๋ฐ
stepBuilderFactory.get("step")
.<Input, Output>chunk(100)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
- ๋๋ ๋ฐ์ดํฐ๋ฅผ ์์ ๋ฉ์ด๋ฆฌ(chunk)๋ก ๋๋ ์ ์ฒ๋ฆฌ
- Reader → Processor → Writer ๊ตฌ์กฐ๋ก ์ญํ ๋ถ๋ฆฌ
- ํธ๋์ญ์ ๋จ์๋ก ์ฒ๋ฆฌ ๊ฐ๋ฅ
- ์ํ ์ ์ฅ, ์คํจ ๋ณต๊ตฌ, ๋ณ๋ ฌ ์ฒ๋ฆฌ ๋ฑ์์ ๊ฐ๋ ฅํจ
๐ ์ธ์ ๋ฌด์์ ์ ํํด์ผ ํ ๊น?
Tasklet | Chunk | |
๊ตฌ์กฐ | ๋จ์ผ ๋ฉ์๋ | Reader-Processor-Writer |
์ ํฉํ ์์ | ๋ฐ๋ณต๋ฌธ, ๋จ๋ฐ์ฑ API ํธ์ถ | ๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ |
ํธ๋์ญ์ | ์ ์ฒด ์์ ๋จ์ | Chunk ๋จ์ ํธ๋์ญ์ |
์ํ ์ ์ฅ | ์์ | ๊ฐ๋ฅ (Restart ์ง์) |
๋ณ๋ ฌ ์ฒ๋ฆฌ | ์ด๋ ต๊ฑฐ๋ ์๋ ๊ตฌํ | ๋ด์ฅ ๊ธฐ๋ฅ ์์ |
๋ํ ์์ | ํ์ผ ์ญ์ , ๋๋ ํ ๋ฆฌ ์ ๋ฆฌ, for๋ฌธ ์ํ | DB → ๊ฐ๊ณต → DB ์ ์ฅ |
โ ์ ์ ๊ณ ๋ฏผ ์ฌ๋ก
Spring Batch๋ฅผ ๋์ ํ๋ฉด์, ์ ๋ ๋จผ์ 3๋ ์น ์ฃผ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ์ด๊ธฐํ ์์ ๊ณผ ์๊ฐ์ด์ก ๊ณ์ฐ, ์นํฐ๋ณ ์์ต๋ฅ ๊ณ์ฐ๊ณผ ๊ฐ์ ํ์ฒ๋ฆฌ ์์ ๋ค์ ๋ฆฌํฉํ ๋งํ๊ฒ ๋์์ต๋๋ค.
์ด ๊ณผ์ ์์ ๊ฐ์ฅ ๋จผ์ ๋ง์ฃผํ ๊ณ ๋ฏผ์ด ๊ธ์ ๋์ ๋ถ์๋.. ์ด๋ค ๋ฐฉ์์ ์ ์ฉํ ์ง!์ ๋ํ ๊ณ ๋ฏผ์ด์์ต๋๋ค.
์ฒ์์ “Chunk๊ฐ ๋ ์ ์์ ์ธ ๊ตฌ์กฐ๋๊น ๋ฌด์กฐ๊ฑด ์จ์ผ ํ์ง ์์๊น?”๋ผ๋ ์๊ฐ๋ ๋ค์์ง๋ง, ์ง์ ์ ์ฉํด๋ณด๋ฉฐ ๋๋ ๊ฑด ์์ ์ ํน์ฑ๊ณผ ์ฒ๋ฆฌ ๋์์ ๋ฐ๋ผ ๊ฐ ๋ฐฉ์์ ์ฅ๋จ์ ์ด ๋ถ๋ช ํ ์กด์ฌํ๋ค๋ ๊ฒ์ด์์ต๋๋ค.
โ ์ข ๋ชฉ ๋ฐ์ดํฐ ์ ์ฅ: Chunk ๊ธฐ๋ฐ
์ด ์์
์ 3๋
์น ์ฃผ์ ๋ฐ์ดํฐ๋ฅผ ์นํฐ๋ณ ์ข
๋ชฉ ๊ธฐ์ค์ผ๋ก API ํธ์ถ → ๊ฐ๊ณต → DB/Redis ์ ์ฅํ๋ ์ด๊ธฐํ ๊ณผ์ ์
๋๋ค.
์ฒ๋ฆฌ ๋์๋ ๋ง๊ณ , ๋์ผํ ์์
์ ๋ฐ๋ณต์ ์ผ๋ก ์ํํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์์ฐ์ค๋ฝ๊ฒ Chunk ๊ธฐ๋ฐ์ผ๋ก ์ค๊ณํ์ต๋๋ค.
- Reader: ์นํฐ๋ณ ์ข ๋ชฉ ๋ชฉ๋ก์ ํ๋์ฉ ๋ฐํ
- Processor: ๊ฐ ์ข ๋ชฉ๋ณ๋ก API๋ฅผ ํธ์ถํ๊ณ ์๋ต๊ฐ์ ๊ฐ๊ณต
- Writer: ๊ฒฐ๊ณผ ๋ฐ์ดํฐ๋ฅผ DB์ Redis์ ์ ์ฅ
์ด ๊ตฌ์กฐ๋ฅผ Chunk๋ก ๊ตฌํํ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ์นํฐ ๋จ์ ํธ๋์ญ์ ๋ถ๋ฆฌ → ํ๋์ ์นํฐ์์ ๋ฌธ์ ๊ฐ ์๊ฒจ๋ ๋ค๋ฅธ ์นํฐ์๋ ์ํฅ ์์
- faultTolerant() ์ค์ ์ ํตํด API ์คํจ ์ฌ์๋, ์ผ๋ถ ์ข ๋ชฉ Skip ์ฒ๋ฆฌ ๊ฐ๋ฅ์ฑ ํ๋ณด
- Reader/Writer ๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ถํ ๋ณ๋ ฌ ์ฒ๋ฆฌ ๋๋ ๋ถ์ฐ ์ฒ๋ฆฌ๋ก ์ ํํ๊ธฐ ์ฌ์
Chunk์ ๊ตฌ์กฐ์ ํ์ฅ์ฑ๊ณผ ํ๋ณต๋ ฅ ํ๋ณด!
โ ์๊ฐ์ด์ก ๊ณ์ฐ: Tasklet ๊ธฐ๋ฐ
์๊ฐ์ด์ก ๊ณ์ฐ์ ๊ฐ ์ข
๋ชฉ์ ์ข
๊ฐ × ์ ํต์ฃผ์์๋ฅผ ๊ณ์ฐํด ์ ์ฅํ๋ ์์
์
๋๋ค.
์ข
๋ชฉ ์๋ ๋ง์ง๋ง, ์ ์ฒด ํ๋ฆ์ ๋จ์ ๊ณ์ฐ ๋ฐ๋ณต์ ๊ฐ๊น๊ณ , ํธ๋์ญ์
์ ๋๋ ํ์๋, ์ํ๋ฅผ ์ถ์ ํ ํ์๋ ์์์ต๋๋ค.
๊ฒ๋ค๊ฐ ์ด ๋ก์ง์ ์ด๋ฏธ ์๋น์ค ๋ ์ด์ด์ ํ๋์ ๋ฉ์๋๋ก ๊ตฌํ๋์ด ์์๊ธฐ ๋๋ฌธ์ Tasklet ๋ด๋ถ์์ ํด๋น ์๋น์ค ๋ฉ์๋๋ฅผ ํ ๋ฒ ํธ์ถํ๋ ๋ฐฉ์์ผ๋ก ๊ฐ๋จํ๊ฒ ์ฒ๋ฆฌํ์ต๋๋ค.
๋ง์ฝ ์ฒ์๋ถํฐ ๋ฐฐ์น ์ ์ฉ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์๋ค๋ฉด Chunk๋ก ๊ตฌ์ฑํ ์๋ ์์๊ฒ ์ง๋ง, ๊ธฐ์กด ๊ฒ์ฆ๋ ๋ก์ง์ ์์ ์ ์ผ๋ก ์ฌ์ฌ์ฉํ๋ฉด์ ํ์ํ ๋งํผ๋ง ๋ฐฐ์นํํ ๊ฒ์ด ์ด๋ฒ ์ํฉ์์๋ ๋ ํจ์จ์ ์ผ ๊ฑฐ๋ผ๋ ํ๋จ์ ํ์ต๋๋ค.
๐ง Tasklet vs Chunk – ์๋? ๊ตฌ์กฐ? ๋ณต๊ตฌ?
์ฒ์์๋ "Tasklet์ด ๋ ๋น ๋ฅด์ง ์์๊น?"๋ผ๋ ์๊ฐ๋ ํ์ง๋ง, ์ค์ ๋ก ์ค์ํ ๊ฑด ์๋ ์์ฒด๋ณด๋ค๋ ์์ ์ ์ฑ๊ฒฉ์ ๋ง๋ ๊ตฌ์กฐ๋ฅผ ์ ํํ๋ ๊ฒ์ด์์ต๋๋ค.
Tasklet | Chunk | |
๊ตฌ์กฐ | ๋จ์ ๋ฉ์๋ → ๋น ๋ฅด๊ฒ ๊ตฌํ ๊ฐ๋ฅ | ๋ช ํํ ๋จ๊ณ ๋ถ๋ฆฌ (Reader-Processor-Writer) |
๋ณต๊ตฌ/์ฌ์๋ | ์ง์ try-catch ํ์ | retry(), skip() ๋ฑ ๋ด์ฅ ๊ธฐ๋ฅ |
ํธ๋์ญ์ | ์ ์ฒด ์์ 1ํธ๋์ญ์ | Chunk ๋จ์๋ก ๋ถํ ์ฒ๋ฆฌ |
์ ํฉํ ๊ฒฝ์ฐ | ๋จ์ ๋ฐ๋ณต, ๊ณ์ฐ, ๋ช ๋ นํ ๋ก์ง | ๋๋ ๋ฐ๋ณต, ์์ ์ฑ, ์ํ ์ถ์ ํ์ |
ํ์ฅ์ฑ | ์ ํ์ | ๋ณ๋ ฌ ์ฒ๋ฆฌ, ๋ถ์ฐ ์ฒ๋ฆฌ ๋ฑ ์ฉ์ด |
โ ๊ฒฐ๋ก
๊ฒฐ๊ณผ์ ์ผ๋ก,
- ๋๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ณต ์ฒ๋ฆฌํ๊ณ , ํฅํ ํ์ฅ ๊ฐ๋ฅ์ฑ์ด ์๋ ์์ ์๋ Chunk ๊ธฐ๋ฐ
- ์ฒ๋ฆฌ๋์ด ์ ๊ณ ๊ณ์ฐ ์ค์ฌ์ด๋ฉฐ, ์ด๋ฏธ ์์ฑ๋ ๋ก์ง์ ํ์ฉํ ์ ์๋ ์์ ์๋ Tasklet ๊ธฐ๋ฐ
์ ์ ์ฉํ๋ ๊ฒ์ด ์ ํ๋ก์ ํธ์์๋ ๊ฐ์ฅ ํจ์จ์ ์ธ ์ ํ์ด์์ต๋๋ค.
โ๏ธ ๋ค์ ๊ธ ์๊ณ
๋ค์ ๊ธ์์๋ ์ ๊ฐ ์ด๋ป๊ฒ ๊ธฐ์กด ์ค์ผ์ค๋ฌ ์ค์ฌ์ ๊ตฌ์กฐ๋ฅผ Job ๋จ์๋ก ๋๋๊ณ , ์ด๋ค ์์ ์ ์ด๋ค Step์ผ๋ก ๋ถ๋ฆฌํ๋์ง๋ฅผ ์ ๋ฆฌํด๋ณด๋ ค๊ณ ํฉ๋๋ค.
๊ตฟ๋ฐ์ด..~.~