2025. 2. 18. 17:57ใSpring/[2025] Spring Boot
๐ ๋ชฉ์ฐจ
Spring Batch
- ๊ธฐ๋ณธ ๊ฐ๋ & ํน์ง, ์ฃผ์ ๊ตฌ์ฑ ์์, ๋ฉํ๋ฐ์ดํฐ ํ ์ด๋ธ
Spring Scheduler
- ๊ธฐ๋ณธ ๊ฐ๋ , ์ฌ์ฉ ๋ฐฉ๋ฒ
๊ฐ๋จํ ์์ ๊ตฌํ
- CSV ํ์ผ ์ฝ์ด์ DB์ ์ ์ฅํด๋ณด๊ธฐ
Spring Batch
Spring Batch ์คํ๋ง ๋ฐฐ์น : ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์์ ์ ์๋ฐ ๊ธฐ๋ฐ์ ๋ฐฐ์น ์ฒ๋ฆฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค๊ธฐ ์ํ ํ๋ ์์ํฌ ๋๋์ ๋ฐ์ดํฐ๋ฅผ ์ผ๊ด์ ์ผ๋ก ์ฒ๋ฆฌํ๊ฑฐ๋ ๋ฐ๋ณต์ ์ธ ์์ ์ ์๋ํํ๋ ๋ฐ ์ฌ์ฉ๋จ
Spring Batch ํน์ง
- ๋์ฉ๋ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋๋ก ์ค๊ณ
- ๋๋์ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด chunk (์ฒญํฌ) ๊ธฐ๋ฐ ์ฒ๋ฆฌ์ paging (ํ์ด์ง) ๋ฑ์ ๊ธฐ์ ์ ๊ณต
- ๋ถ์ฐ ์ฒ๋ฆฌ ๋ฐ ๋ณ๋ ฌ ์ฒ๋ฆฌ ์ง์ํด ํ์ฅ์ฑ๊ณผ ์ฑ๋ฅ ๊ทน๋ํ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค, ํ์ผ, API ๋ฑ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ๋ณํํ์ฌ ์ ์ฅํ๋ ๊ณผ์ ์๋ํ
- ํธ๋์ญ์ ๊ด๋ฆฌ, ์์ ์ฌ์์ ๊ธฐ๋ฅ ๋ฑ ์ง์ → ์คํ๋ง ๋ฐฐ์น๋ ๋ฐฐ์น ์์ ์ ํธ๋์ญ์ ์ฒ๋ฆฌ์ ํจ๊ป ๊ด๋ฆฌํ๊ณ , ์คํจํ ์์ ์ ๋ณต๊ตฌํ๊ณ ์ฌ์์ํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํจ
Spring Batch ๋ฅผ ์ฌ์ฉํ๋ฉด ์ข์ ์์
- ๋๋์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
- ์ ๊ธฐ์ ์ธ ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ (ex. ๋งค์ผ ์๋ฒฝ 1์์ ์ ์ฐ ์์ ์คํ)
- ETL(Extract, Transform, Load) ์์
- ์๋ํ๋ ๋ณด๊ณ ์ ์์ฑ
- ์ด๋ฒคํธ ๊ธฐ๋ฐ ๋๋๋ฐ์ดํฐ ์ฒ๋ฆฌ
- ๋ฐ์ดํฐ ๋ง์ด๊ทธ๋ ์ด์
→ ๋๋์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ค์ผ ํ๋ ๊ฒฝ์ฐ, Spring Batch๋ฅผ ์ฌ์ฉํ๋ฉด ์ข์ !
Spring Batch ์ฃผ์ ๊ตฌ์ฑ ์์
Job → Step → (Reader → Processor → Writer) ๊ตฌ์กฐ๋ก ๋์
Job | ํ๋ ์ด์์ Step ์ ํฌํจํ๋ ๋ฐฐ์น ์์ |
Step | Job์ ๊ตฌ์ฑํ๋ ํ๋์ ์คํ ๋จ์ |
ItemReader | ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ค๋ ์ญํ (DB, CSV, API ๋ฑ) |
ItemProcessor | ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํ๋ ์ญํ (๋ณํ, ํํฐ๋ง ๋ฑ) |
ItemWriter | ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ์ญํ (DB, ํ์ผ ๋ฑ) |
JobRepository | Job ์คํ ์ด๋ ฅ์ ์ ์ฅํ๋ ์ ์ฅ์ |
JobLauncher | Job์ ์คํํ๋ ์์ง |
Job
Spring Batch์์ ๊ฐ์ฅ ํฐ ์คํ ๋จ์, ๋ฐฐ์น ์์ ์ ์ ์ฒด ํ๋ฆ์ ์ ์ํจ
- ํ๋ ์ด์์ Step ์ผ๋ก ์ด๋ฃจ์ด์ง๊ณ , ๊ฐ Step ์ ์์ฐจ์ /๋ณ๋ ฌ์ ์ผ๋ก ์คํํ ์ ์์
- Job ์ ์ฌ์คํ ๊ฐ๋ฅํ๊ณ , ์คํจํ ์์ ์ ์ฌ์์ํ ์ ์๋๋ก ์ํ ๊ด๋ฆฌ๋ฅผ ํจ
- JobBuilder๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑํ๊ณ , JobLancher๋ฅผ ํตํด ์คํ๋จ
JobInstance
ํนJob์ด ์คํ๋ ๋ ์์ฑ๋๋ ๊ณ ์ ํ ์คํ ๋จ์ Job ์ด ์คํ๋ ๋ ๋ง๋ค ์์ฑ๋จ (ํ๋์ Job์ด ์ฌ๋ฌ ๊ฐ์ JobInstance๋ฅผ ๊ฐ์ง ์ ์์)
- JobInstance๋ ๋ด๋ถ์ ์ผ๋ก Job ์ ์ด๋ฆ์ด๋ JobParameter ์ ํด์๊ฐ(JobKey)์ ์ฌ์ฉํ์ฌ ๊ณ ์ ํ๊ฒ ์๋ณ๋จ → ๋์ผํ JobParameter ๋ก ์คํํ๋ฉด ๊ธฐ์กด์ JobInstance ์ฌ์ฌ์ฉํ๊ณ , ์๋ก์ด JobParamter ๋ก ์คํํ๋ฉด ์๋ก์ด JobInstance๊ฐ ์์ฑ๋จ
- Spring Batch๋ JobInstance ์ ๋ณด๋ฅผ BATCH_JOB_INSTANCE ํ ์ด๋ธ์ ์ ์ฅํ์ฌ ๊ด๋ฆฌํจ → ๋์ผํ Job ์ด๋ฆ์ด๋ ๋์ผํ JobParamter์ ํด์๊ฐ์ ๊ฐ์ง ๋ฐ์ดํฐ๋ ์ค๋ณต ์ ์ฅ๋์ง ์์
JobExecution
Spring Batch์์ JobInstance ์ ์คํ ๋จ์, Job ์ด ์คํ๋ ๋๋ง๋ค ์์ฑ๋จ
- ์คํ ์ํ, ์์ ๋ฐ ์ข
๋ฃ ์๊ฐ, ์คํจ ์์ธ ๋ฑ ์คํ ์ค ๋ฐ์ํ ์ ๋ณด๋ค์ ์ ์ฅํ๊ณ ๊ด๋ฆฌํจ
- ์คํ ์ํ (BatchStatus) : STARTING, STARTED, COMPLETED, FAILED, STOPPED
- ์ข ๋ฃ ์ํ (ExitStatus) : ์ฑ๊ณต ๋๋ ์คํจ ์ด์ , ๊ธฐ๋ณธ ๊ฐ UNKNOWN
- JobInstance๊ฐ ์คํ ๋ ๋ ๋ง๋ค ์์ฑ๋๊ธฐ ๋๋ฌธ์ JobInstance๋ ์ฌ๋ฌ ๊ฐ์ JobExecution ์ ๊ฐ์ง ์ ์์
JobParamter
Spring Batch์์ ๋ฐฐ์น ์์ ์คํ ์ ์ธ๋ถ ๋๋ ๋ด๋ถ์์ ์ ๋ฌ๋ฐ์ ์ฌ์ฉํ ์ ์๋ ํ๋ผ๋ฏธํฐ ํน์ Job ์คํ์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๊ฑฐ๋ ์คํ ์กฐ๊ฑด์ ๋์ ์ผ๋ก ์ค์ ํ๊ธฐ ์ํด ์ฌ์ฉ
- JobInstance ๋ฅผ ์์ฑํ๊ณ ๊ตฌ๋ณํ๋ ๋ฐ ์ฌ์ฉ๋๋ ํ๋ผ๋ฏธํฐ
- Key-Value ํํ
- ์ง์๋๋ ๋ฐ์ดํฐ ํ์ : String, Long, Double, Date
Step
Job ์ ๊ตฌ์ฑํ๋ ํ๋์ ์คํ ๋จ์, ํน์ ์์ ์ ์ฒ๋ฆฌํ๋ ๋ก์ง์ ์บก์ํ ํจ
๊ตฌ์ฑ ์์
- Tasklet ๊ธฐ๋ฐ : ๋จ์ผ ์์ ์ ์ํํ๋ ๋ฐฉ์
- Chunk ๊ธฐ๋ฐ : ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฌ ์กฐ๊ฐ์ผ๋ก ๋๋์ด ์ฒ๋ฆฌํ๋ ๋ฐฉ์ → ItemReader, ItemProcessor, ItemWriter ๋ก ๊ตฌ์ฑ๋จ
StepExecution
Spring Batch์์ Step ์ ์คํ ๋จ์๋ฅผ ๋ํ๋ด๋ ๊ฐ์ฒด ํน์ Step ์คํ ์ ์์ฑ๋์ด ์คํ ์ํ์ ๊ด๋ จ๋ ์ ๋ณด๋ฅผ ๊ด๋ฆฌํจ
- Step์ ์์ ์๊ฐ, ์ข ๋ฃ ์๊ฐ, ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ ์, ์คํจ ์ฌ๋ถ ๋ฑ ์คํ ์ค ๋ฐ์ํ ๋ชจ๋ ์ ๋ณด๋ฅผ ์ ์ฅํจ
- StepExecution๋ ํน์ Step์ ํ ๋ฒ์ ์คํ์ ๋ํ๋, Step ์ด ์คํ๋ ๋ ๋ง๋ค ์๋ก์ด StepExecution ๊ฐ์ฒด๊ฐ ์์ฑ๋จ
- StepExecution ๋ฐ์ดํฐ๋ BATCH_STEP_EXECUTION ํ ์ด๋ธ์ ์ ์ฅํ์ฌ ์คํ ์ด๋ ฅ์ ๊ด๋ฆฌํจ
- Job์ด ์คํ๋๋ฉด JobInstacne, JobExecution ์์ฑ, ๊ทธ ์์์ Step์ด ์คํ๋ ๋ ๋ง๋ค, ์๋ก์ด StepExcecution ๊ฐ์ฒด ์์ฑ
ItemReader
๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ค๋ ์ญํ (DB, CSV ๋ฑ์ ํ์ผ ..)
ItemProcessor
Reader์์ ์ฝ์ด์จ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํ๊ฑฐ๋ ๋ณํํ๋ ์ญํ
- ์ ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ํํฐ๋งํ๊ฑฐ๋ ๋ณํํ ์ ์์
- ํ์๋ ์๋๊ณ , ํ์์ ๋ฐ๋ผ ์ถ๊ฐํ๋ฉด ๋จ
ItemWriter
Reader ๋๋ Processor ๋ฅผ ํตํด ์ป์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ฑฐ๋ ์ถ๋ ฅํ๋ ์ญํ
- ๋ฐ์ดํฐ๋ฅผ ์ผ๊ด์ ์ผ๋ก ์ฒ๋ฆฌํ์ฌ ์ฑ๋ฅ ์ต์ ํ
JobRepository
Job๊ณผ Step ์ ์คํ ์ํ๋ฅผ ๊ด๋ฆฌํ๊ณ ๋ฉํ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ์ญํ
- ๋ฐฐ์น ์์ ์ ๋ฉํ๋ฐ์ดํฐ (ex. ์คํ ์ํ, ์์/์ข ๋ฃ ์๊ฐ, ์คํจ ์ฌ๋ถ ๋ฑ)๋ฅผ ์ ์ฅํจ
- ํธ๋์ญ์ ๊ด๋ฆฌ์ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅ, ์คํจ ์ ๋ณต๊ตฌ ์ง์
JobLauncher
Job ์ ์คํํ๋ ์ญํ
- ๋๊ธฐ/๋น๋๊ธฐ ๋ฐฉ์์ผ๋ก Job ์ ์คํํ ์ ์์
- JobRepository์ ์ํธ์์ฉํ์ฌ JobInstance ๋ฐ JobExcution ์ ๋ณด๋ฅผ ๊ด๋ฆฌํจ
๋ฉํ๋ฐ์ดํฐ ํ ์ด๋ธ
Spring Batch ๋ ๋ฐฐ์น ์์ ์ ์คํ ์ํ์ ์ด๋ ฅ์ ๊ด๋ฆฌํ๊ธฐ ์ํด ๋ฉํ๋ฐ์ดํฐ ํ ์ด๋ธ์ ์ฌ์ฉ Spring Batch๊ฐ ์ ๊ณตํ๋ SQL ์คํฌ๋ฆฝํธ๋ฅผ ํตํด ์์ฑ๋จ
BATCH_JOB_INSTANCE | JobInstance(๋ฐฐ์น ์์ ์ ๋ ผ๋ฆฌ์ ๋จ์)์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅ. |
BATCH_JOB_EXECUTION | JobExecution(ํน์ JobInstance์ ์คํ)์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅ. |
BATCH_JOB_EXECUTION_PARAMS | Job ์คํ ์ ์ ๋ฌ๋ JobParameter์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅ. |
BATCH_JOB_EXECUTION_CONTEXT | JobExecution ์ค ์์ฑ๋ ExecutionContext(๊ณต์ ๋ฐ์ดํฐ)์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅ. |
BATCH_STEP_EXECUTION | StepExecution(๊ฐ Step์ ์คํ)์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅ. |
BATCH_STEP_EXECUTION_CONTEXT | StepExecution ์ค ์์ฑ๋ ExecutionContext์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅ. |
BATCH_JOB_INSTANCE
: JobInstance์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅ
- JOB_INSTANCE_ID : JobInstance๋ฅผ ๊ณ ์ ํ๊ฒ ์๋ณํ๋ ID
- JOB_NAME : Job์ ์ด๋ฆ (์คํ๋ Job์ ์ด๋ฆ)
- JOB_KEY : JobParameter ๋ฅผ ์ง๋ ฌํํ์ฌ ์์ฑ๋ ๊ณ ์ ํค
BATCH_JOB_EXECUTION
: JobInstance์ ์คํ(JobExecution) ์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅ
- Job ์ด ์คํ๋ ๋ ๋ง๋ค ์๋ก์ด JobExecution์ด ์์ฑ๋จ
- ์คํ ์ํ, ์์/์ข ๋ฃ ์๊ฐ, ์ข ๋ฃ ์ฝ๋ ๋ฑ์ ๊ธฐ๋กํจ
- JOB_EXECUTION_ID : JobExecution์ ๊ณ ์ ํ๊ฒ ์๋ณํ๋ ID
- JOB_INSTANCE_ID : ์ฐ๊ฒฐ๋ JobInstance์ ID
- STATUS : ์คํ ์ํ (STARTED, COMPLETED, FAILED)
- EXIT_CODE : ์ข ๋ฃ ์ฝ๋ (์ฑ๊ณต/์คํจ ์ฌ๋ถ)
- EXIT_MESSAGE : EXIT_CODE๊ฐ ‘FAILED’ ์ผ ๋, ์๋ฌ ๋ฉ์์ง
- START_TIME, END_TIME : ์คํ ์์ ๋ฐ ์ข ๋ฃ ์๊ฐ
BATCH_JOB_EXECUTION_PARAMS
: ํน์ JobExecution ์ ์ ๋ฌ๋ JobParamter
- ๊ฐ ํ๋ผ๋ฏธํฐ์ ์ด๋ฆ, ๊ฐ, ๋ฐ์ดํฐ ํ์ ์ ๊ธฐ๋กํจ
BATCH_JOB_EXECUTION_CONTEXT
: JobExecution ์ค ๊ณต์ ๋ฐ์ดํฐ(ExecutionContext) ๋ฅผ ์ ์ฅ
- ์ง๋ ฌํ๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ , ์์ ์ค ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ๊ฑฐ๋ ๋ณต๊ตฌํ ๋ ์ฌ์ฉํจ
BATCH_STEP_EXECUTION
: StepExecution, ๊ฐ Step์ ์คํ์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅ
- ๊ฐ Step์ด ์คํ๋ ๋๋ง๋ค ์๋ก์ด StepExecution ์ด ์์ฑ๋จ
- ์ฝ๊ธฐ/์ฐ๊ธฐ/์ปค๋ฐ/์คํต๋ ๋ฐ์ดํฐ ์ ๋ฑ์ ์ธ๋ถ ํต๊ณ ๊ธฐ๋ก
- STEP_EXECUTION_ID : StepExecution ์ ๊ณ ์ ํ๊ฒ ์๋ณํ๋ ID
- STEP_NAME : Step ์ด๋ฆ
- JOB_EXECUTION_ID : ์ฐ๊ฒฐ๋ JobExecution ์ ID
- STATUS : ์คํ ์ํ (STARTED, COMPLETED, FAILED)
- READ_COUNT, WRITE_COUNT, COMMIT_COUNT, SKIP_COUNT : ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ ์์ ํธ๋์ญ์ ํต๊ณ
BATCH_STEP_EXECUTION_CONTEXT
: StepExecution ์ค ๊ณต์ ๋ฐ์ดํฐ(StepExecutionContext) ์ ์ฅ
- BATCH_JOB_EXECUTION_CONTEXT์ ์ ์ฌํ์ง๋ง, Step ๋จ์๋ก ๋ฐ์ดํฐ ๊ด๋ฆฌ
ํ ์ด๋ธ ์๋ ์์ฑ
Spring Batch ์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฉํ๋ฐ์ดํฐ ํ ์ด๋ธ์ ์๋์ผ๋ก ์์ฑํ ์ ์์
* ์ง์ ํ ์ด๋ธ ์ ์ํ๋ ค๋ฉด Spring Batch์์ ์ ๊ณตํ๋ SQL ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํด ์๋์ผ๋ก ์์ฑํ ์๋ ์์
โ Spring Batch์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ฐฉ์
: Tasklet, Chunk
Tasklet
- ํ๋์ ์์ ์ ์ํํ๋ ๋ฐฉ์, ๋จ์ํ ํน์ ์์ ์ ์คํํ๊ณ ์ข ๋ฃํจ
- ๋์ฒด๋ก ๋จ์ํ๊ฑฐ๋ ๋ณต์กํ์ง ์์ ์์ ์ ์ํํ๋๋ฐ ์ ํฉํ๋ฉฐ, ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์๋๋ผ ์ผ๋ถ ๋ฐ์ดํฐ๋ ๋จ์ผ ์์ ์ ์ฒ๋ฆฌํ๋ ๋ฐ ์ฃผ๋ก ์ฌ์ฉ๋จ
- Tasklet ์ธํฐํ์ด์ค์ execute() ๋ฉ์๋๋ฅผ ๊ตฌํํ์ฌ ์ฌ์ฉํ๊ณ , ์ด ๋ฉ์๋๋ ํ๋์ ํธ๋์ญ์ ๋ฒ์์์ ์คํ๋จ
- ๋ฐํ ๊ฐ์ผ๋ก RepeatStatus.FINISHED ๋ฅผ ๋ฐํํ๋ฉด Step ์ข ๋ฃ๋จ
- ๋ฐํ ๊ฐ์ผ๋ก RepeatStatus.CONTINUABLE ๋ฅผ ๋ฐํํ๋ฉด Tasklet์ด ๊ณ์ ์คํ๋์ด์ผ ํจ
- ex) ํ์ผ ์ญ์ , ๋ฐ์ดํฐ ์ด๊ธฐํ, ๋ก๊ทธ ๊ธฐ๋ก ๋ฑ ๋ฐ๋ณต๋์ง ์๋ ์์
Chunk
- ๋ฐ์ดํฐ๋ฅผ ์ผ์ ํฌ๊ธฐ๋ก ๋๋์ด์ ์ฒ๋ฆฌํ๋ ๋ฐฉ์, ๋์ฉ๋ ๋ฐ์ดํฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉ
- ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ , ๊ฐ๊ณตํ๋ฉฐ, ์ ์ฅํ๋ ์์ ์ ์ฒญํฌ ๋จ์๋ก ๋ฐ๋ณต์ ์ผ๋ก ์ํํจ
- ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ๋ชจ๋ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์๋, ์ฒญํฌ ํฌ๊ธฐ๋งํผ ๋๋์ด ํธ๋์ญ์
๋จ์๋ก ์ฒ๋ฆฌํจ
- ํ๋์ ์ฒญํฌ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์ฒ๋ฆฌ๋๋ฉด ์ปค๋ฐ๋๊ณ , ์คํจํ๋ฉด ํด๋น ์ฒญํฌ๋ง ๋กค๋ฐฑ๋จ
์ฒ๋ฆฌ ๋ฐฉ์ | ๋จ์ผ ์์ ์ ์ํ | ๋ฐ์ดํฐ๋ฅผ ์ฒญํฌ ๋จ์๋ก ๋๋์ด ์ฒ๋ฆฌ |
ํธ๋์ญ์ ๊ด๋ฆฌ | ํธ๋์ญ์ ํ์ ์ ์๋ ์ค์ | ์ฒญํฌ ๋จ์๋ก ์๋ ๊ด๋ฆฌ |
๊ตฌ์ฑ ์์ | Tasklet ์ธํฐํ์ด์ค | Reader → Processor → Writer |
์ ํฉํ ์์ ์ ํ | ๊ฐ๋จํ ๋ฐ๋ณต ์๋ ์์ (์: ๋ก๊ทธ ๊ธฐ๋ก) | ๋๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ (์: ETL ํ๋ก์ธ์ค) |
์คํจ ์ ๋กค๋ฐฑ ๋ฒ์ | ์ ์ฒด ์์ | ์คํจํ ์ฒญํฌ๋ง ๋กค๋ฐฑ |
๋ณต์ก๋ | ๋ฎ์ | ์๋์ ์ผ๋ก ๋์ |
์ฌ์ฉ ์ฌ๋ก | ํ์ผ ์ญ์ , ์ด๊ธฐํ ์์ | ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋๋ ๋ฐ์ดํฐ ์ฝ๊ธฐ ๋ฐ ์ ์ฅ |
Spring Scheduler
Spring Scheduler ์คํ๋ง ์ค์ผ์ฅด๋ฌ : Spring Framework์์ ์ ๊ณตํ๋ ์์ ์ค์ผ์ค๋ง ๊ธฐ๋ฅ, ํน์ ์๊ฐ ๊ฐ๊ฒฉ์ด๋ ํน์ ์์ ์ ์์ ์ ์๋์ผ๋ก ์คํํ ์ ์๋๋ก ์ง์ํจ
Spring Scheduler ํน์ง
- ํน์ ์๊ฐ ๊ฐ๊ฒฉ/ํน์ ์์ ์ ์์ ์ ์คํํจ
- ๋ณ๋์ ์ค๋ ๋์์ ๋น๋๊ธฐ ์คํ
- ๊ธฐ๋ณธ์ ์ผ๋ก๋ ๋จ์ผ ์ค๋ ๋๋ฅผ ์ฌ์ฉํ์ฌ ์์ฐจ์ ์ผ๋ก ์คํ์ง๋ง, ์ค๋ ๋ ํ์ ์ค์ ํ์ฌ ๋ณ๋ ฌ ์คํ๋ ๊ฐ๋ฅํจ
- @EnableScheduling, @Scheduled ์ด๋ ธํ ์ด์ ์ผ๋ก ์์ ๊ตฌํ ๊ฐ๋ฅ
์ค์ ๋ฐฉ๋ฒ
0๏ธโฃ Spring Scheduler ๋ Spring Framework์ ๊ธฐ๋ณธ์ ์ผ๋ก ํฌํจ๋ ๊ธฐ๋ฅ์ด๊ธฐ ๋๋ฌธ์ ์์กด์ฑ ์ถ๊ฐ ์์ด ์ฌ์ฉํ ์ ์์
1๏ธโฃ ์ค์ผ์ค๋ฌ ํ์ฑํ
@EnableScheduling // SpringBoot Schedule ์ฌ์ฉ
@SpringBootApplication
public class BatchApplication {
public static void main(String[] args) {
SpringApplication.run(BatchApplication.class, args);
}
}
@EnableScheduling ์ด๋ ธํ ์ด์ ์ ์ถ๊ฐํ์ฌ ์ค์ผ์ค๋ง ๊ธฐ๋ฅ ํ์ฑํํ๋ค.
2๏ธโฃ ์ค์ผ์ค๋ง ์์ ์ ์
@Slf4j
@Component
public class TestScheduler
{
@Scheduled(fixedRate = 5000) // 5์ด ๋ง๋ค ์์
์คํ
public void fixedRateTask()
{
log.info("Fixed Rate Task Executed !!");
}
@Scheduled(fixedDelay = 5000) // ์ด์ ์์
์ข
๋ฃ ํ 5์ด ๋ค ์คํ
public void fixedDelayTask()
{
log.info("Fixed Delay Task Executed !! ");
}
@Scheduled(cron = "0 0 12 * * ?") // ๋งค์ผ ์ ์ค 12์์ ์คํ
public void cronTask()
{
log.info("Cron Task Executed !! ");
}
}
- fixedRateTask : ์ด์ ์์ ์ ์์ ์์ ๋ถํฐ ์ง์ ๋ ์๊ฐ ๊ฐ๊ฒฉ(ms) ๋ง๋ค ์์ ์ ์คํ
- fixedDelayTask : ์ด์ ์์ ์ด ์ข ๋ฃ๋ ์์ ๋ถํฐ ์ง์ ๋ ์๊ฐ ๊ฐ๊ฒฉ(ms) ๋ง๋ค ์์ ์ ์คํ
- cron : Cron ํํ์ ์ฌ์ฉํด์ ์ค์ผ์ค๋ง
- “0 0 12 * * ?”→ ๋งค์ผ ์ ์ค์ ์คํ
- “0 0/15 * * * ?”→ ๋งค 15๋ถ ๋ง๋ค ์คํ
- “0 0 9-17 * * MON-FRI”→ ์ ~ ๊ธ ์ค์ 9์๋ถํฐ 17์๊น์ง ๋งค์๊ฐ ์ ๊ฐ์ ์คํ
โ @Scheduled ์ด๋ ธํ ์ด์ ์ ๋ฐํ ํ์ ์ ๋ฐ๋์ void์ฌ์ผ ํ๊ณ , ๋งค๊ฐ๋ณ์ ์ฌ์ฉํ ์ ์์
๊ฐ๋จํ ์์ ๊ตฌํ
Spring Batch + Spring Scheduler๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ์์ ๊ตฌํํ๊ธฐ
- ํ์ผ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ , ๊ฐ๋จํ ๋ณํ(๊ฐ๊ณต) ์์ ํ DB์ ์ ์ฅํด๋ณด๊ธฐ !
1๏ธโฃ ์์กด์ฑ ์ถ๊ฐ
build.gradle
implementation 'org.springframework.boot:spring-boot-starter-batch'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
2๏ธโฃ CSV ๋ฐ์ดํฐ
batch/src/main/resources/people.csv
name,age,phoneNo
Hyejin,28,010-1234-5678
JungHa,28,010-0000-0000
Name1,29,010-1111-1111
Name2,29,010-2222-2222
Name3,30,010-3333-3333
Name4,30,010-4444-4444
3๏ธโฃ application.yml ์ค์
spring:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: sa
password:
jpa:
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: create
show-sql: true
batch:
jdbc:
initialize-schema: always # DB ์คํค๋ง ์ด๊ธฐํ.
job:
enabled: false # ์์๊ณผ ๋์์ ์คํ ๋ฐฉ์ง.
h2:
console:
enabled: true
path: /h2-console
4๏ธโฃ์คํ๋ง ๋ฐฐ์น ์ค์
BatchConfig
: Job, Step ์ค์
@Configuration
//@EnableBatchProcessing // Spring Batch 5.x ๋ ์ค์ ํ์ง ๋ง๊ธฐ
@RequiredArgsConstructor
public class BatchConfig
{
private final JobRepository jobRepository;
private final PlatformTransactionManager transactionManager; // ํธ๋์ญ์
๊ด๋ฆฌ ๋ด๋น
private final PersonRepository personRepository;
/**
* csv ํ์ผ ๋ฐ์ดํฐ ์ฝ์ด์ค๋ Reader
* @return
*/
@Bean
public FlatFileItemReader<Person> reader()
{
return new FlatFileItemReaderBuilder<Person>()
.name("personItemReader")
.resource(new ClassPathResource("people.csv"))
.delimited() // CSV ํ์ผ์ ๊ตฌ๋ถ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฐ์ดํฐ ์ฝ๋๋ก ์ค์
.names("name", "age", "phoneNo") // CSV ํ์ผ์ ๊ฐ ์ด ์ด๋ฆ ์ง์
.linesToSkip(1) // ์ฒซ๋ฒ์งธ ์ค ํค๋ ๋ฌด์
.fieldSetMapper(new BeanWrapperFieldSetMapper<>(){
{
setTargetType(Person.class); // CSV ํ์ผ์์ ์ฝ์ ๋ฐ์ดํฐ๋ฅผ Person ๊ฐ์ฒด๋ก ๋งคํ
}
})
// .fieldSetMapper(fieldSet -> new Person(fieldSet.readString("name"), fieldSet.readInt("age"), fieldSet.readString("phoneNo")))
.build();
}
/**
* Person phoneNo ๋ฐ์ดํฐ ๋ณํ processor
* @return
*/
@Bean
public ItemProcessor<Person, Person> processor()
{
return person -> {
person.setPhoneNo(person.getPhoneNo().replaceAll("-", ""));
return person;
};
}
/**
* ๋ณํํ ๋ฐ์ดํฐ DB์ ์ ์ฅ
* @return
*/
@Bean
public ItemWriter<Person> writer()
{
return personRepository::saveAll;
}
/**
* Step ์ค์ : Reader -> Processor -> Writer
* @return
*/
@Bean
public Step step()
{
return new StepBuilder("step1", jobRepository)
.<Person, Person>chunk(10, transactionManager) // ํ ๋ฒ์ 10๊ฐ์ ๋ฐ์ดํฐ ์ฝ๊ณ , ์ฒ๋ฆฌํ ๋ค ์ปค๋ฐ
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
/**
* Job ์ค์ : Step ์คํ ์ค์
* @return
*/
@Bean
public Job importPersonJob()
{
return new JobBuilder("importPersonJob", jobRepository)
.start(step())
.build();
}
}
- @EnableBatchProcessing : Spring Boot 3.0 ์ด์๋ถํฐ๋ ์ด ์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ์ง ์์ ! → ์ฌ์ฉํ๋ฉด Spring Batch ๊ธฐ๋ณธ ์ค์ ์ด ๋ฐฑ์คํ ๋จ
- @EnableBatchProcessing ์ด ์ด๋ ธํ ์ด์ ์ ์ฒ์์๋ ๋ถ์ฌ์ ํ ์คํธ ํ๋๋, ์ด ์ค์ ์ด ์ ์ฉ๋์ง ์์์ ๋ฐฐ์น ๊ด๋ จ ํ ์ด๋ธ๋ค์ด ์๋ ์์ฑ๋์ง ์์์!!
- Chunk ๊ธฐ๋ฐ : ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฌ ์กฐ๊ฐ์ผ๋ก ๋๋์ด ์ฒ๋ฆฌํ๋ ๋ฐฉ์ → ItemReader, ItemProcessor, ItemWriter ๋ก ๊ตฌ์ฑ
6๏ธโฃ ๋ฐฐ์น Job ์คํ
- BatchRunner ๋ก ์คํํด๋ณด๊ธฐ
: CommandLineRunner๋ฅผ ์ฌ์ฉํด์ Spring Boot ์คํํ ๋ ๋ฐฐ์น Job ์๋์ผ๋ก ์คํํ๋๋ก !
BatchRunner
@Component
@RequiredArgsConstructor
public class BatchRunner implements CommandLineRunner
{
private final JobLauncher jobLauncher;
private final Job importPersonJob;
@Override
public void run(String... args) throws Exception
{
JobParameters jobParameters = new JobParametersBuilder()
.addLong("time", System.currentTimeMillis())
.toJobParameters();
jobLauncher.run(importPersonJob, jobParameters);
}
}
- Spring Scheduler ์ด์ฉํด์ ํน์ ๊ฐ๊ฒฉ์ผ๋ก ์คํํด๋ณด๊ธฐ
PersonSchedule
@Slf4j
@Component
@RequiredArgsConstructor
public class PersonSchedule
{
private final JobLauncher jobLauncher;
private final Job importPersonJob;
@Scheduled(cron = "0 */3 15-16 * * ?")
public void startJob()
{
JobParameters jobParameters = new JobParametersBuilder()
.addLong("time", System.currentTimeMillis())
.toJobParameters();
try
{
jobLauncher.run(importPersonJob, jobParameters);
}
catch (JobExecutionAlreadyRunningException
| JobRestartException
| JobInstanceAlreadyCompleteException
| JobParametersInvalidException
e)
{
log.error("startJob run error :{}", e.getMessage(), e);
}
}
}
- @Scheduled(cron = "0 */3 15-16 * * ?")
- 0 : (ํ ๋ฒ) → ๋ง์ฝ 3
- */3 : 3๋ถ๋ง๋ค ์คํ
- 15-16 : ์คํ 15์๋ถํฐ 16์ ๋์๋ง ์คํ
- * : ๋งค์ผ ์คํ
- * : ๋งค์ ์คํ
- ? : ํน์ ์์ผ ๋ฌด๊ด