🧠 이번 주에 새로 배운 것
- 배치 프로그램을 작성할때 Spring Batch를 쓰는 이유를 잘 몰랐습니다. 공부하면서 batch가 다양한 기능들을 추상화 하였습니다. 중간 실패시 해당 부분부터 재시작, 특정 에러 발생시 스킵, 재시도, 배치 실행 정보를 보관하는 메타 데이터 등 Spring Batch를 사용하면 batch 작업을 편리하게 할수있는 장점을 여실히 깨달았습니다.
- Spring batch의 chunk 방식화 tasklet 방식을 혼합해서 사용할 수 있는 점을 새로 알게 되었습니다. batch를 chunk 방식으로 돌리기 전후 데이터 검증, 외부 메신저 발송은 tasklet으로 작성하는게 적절함을 알았습니다.
💭 이런 고민이 있었어요
- chunk 방식의 writer에서 oom 발생 이슈가 있었습니다. 이는 조회한 product_metric 정보가 계속해서 누적해서 였는데요. TOP 100을 구할려면 모든 데이터를 집계한 뒤에 추려야 했습니다. 해결책으로 메모리가 아닌 임시 테이블에 데이터를 적재 후 TOP 랭킹을 산정, 완료 후 임시 테이블 삭제 방법을 채택하여 OOM 문제를 해결할 수 있었습니다.
- 배치 실행의 멱등성을 어떻게 보장할까 고민하였습니다. 멱등성이란 같은 파라미터로 언제든 실행해도 결과가 같은 것인데요. spring batch로 어느 시점까지 읽었는지는 알수 있지만 writer를 어디까지 했는지 알 수 없었습니다. 이를 보완하기 위해 table swap(rename), append-only 방식(upsert, unique key) 방법이 있음을 알 수 있었습니다.
- 이번 과제는 아니지만 batch 작업내에 외부 API를 트랜잭션 격리 시키는 방법을 고민해보았습니다. @Transactional(Propagation.NOT_SUPPORTED) + 예외처리를 사용하여 외부 API는 트랜잭션에 포함시키지 않고, 예외 발생시 try-catch로 batch 까지 전파되지 않아 batch가 실패하지 않고 계속 작업해 가는 방식으로 격리를 시킬 수 있었습니다.
💡 앞으로 실무에 써먹을 수 있을 것 같은 포인트
- spring batch 작업이 할당될때 공통적으로 고민해야할 포인트를 알게 되었습니다. OOM이 가장 많이 발생하는 이슈이며, 트랜잭션에 외부 AP I작업 혹은 긴 가공 로직이 있을 경우 롱 트랜잭션으로 커넥션 유휴 시간을 초과하여 타임아웃 에러가 발생할 수도 있습니다.
- 마이그레이션 작업시 옮겨야할 데이터를 redis에 set으로 적재하여 병렬 처리하면 좀더 빠르게 마이그레이션 할 수 있는 테크닉을 배웠습니다. 회사에서 firestore -> postgresql 마이그레이션 업무를 할당 받았는데 적용해볼 예정입니다.
🤔 아쉬웠던 점 & 다음 주에 해보고 싶은 것
- 대용량이라 가정하고 Spring batch의 파티셔닝 혹은 step별 병렬 스레드 작업을 적용해보지 못한게 아쉽습니다.