나는 회사에서 외부데이터 연동 API를 만들었다. 이 API는 현재 외부로부터 한번에 약 1만건 정도의 데이터를 가져와서 본 서비스에 저장한다. 이 API는 다음과 같은 과정을 거친다.

  1. API요청으로부터 작업 수행에 필요한 파라미터를 제공받는다.
  2. 해당 파라미터로 외부 API를 요청한다.
  3. 응답을 받고 사전에 정의된 DTO로 파싱된다.
  4. DTO 중 쓰레기값을 가지는 DTO를 제거한다.
  5. DTO의 Unique ID를 서비스 DB에서 조회해 결번으로 추가할 DTO를 선별한다.
  6. 선별된 DTO에 저장된 외부 파일 경로로 S3 GET를 수행한다.
  7. 받아온 외부파일을 변환하여 Thumbnail을 생성한다.
  8. 생성된 Thumbnail 파일을 서비스의 S3스토리지에 저장한다.
  9. DTO를 서비스의 Entity로 변환시킨다.
  10. 저장된 경로와 정보를 앞서 변환된 Entity에 저장한다.
  11. 최종적으로 Entity를 DB에 저장한다.
  12. 1의 API요청에 대한 응답으로 void 200 OK를 회신한다.

이 워크플로우에 따라서 나는 적절히 역할과 책임에 따라서 클래스를 분리했다.

  • 우선 외부 API를 요청하는 기능을 클래스로 분리했다.
  • DB에 접근하고 엔티티를 다루는 서비스의 메인 서비스 로직을 분리했다.
  • S3에 접근하는 기능을 클래스로 분리했다.
  • 파일의 변환을 담당하는 기능을 다른 클래스로 분리했다.

하지만 부족한 점이 많았다.

  • 이전 과정에서 한번의 RuntimeException이 발생하면 모든 작업이 취소되고 외부 API도 요청해야한다.
  • 응답데이터 중 어떤 데이터가 선별되는지에 대한 로깅이 이뤄지지 않고 개발자나 사용자가 인지할 수 없다. 즉 작업의 자세한 모니터링이 불가능하다.
  • Thumbnail 파일 변환은 오래 걸려서 전체 작업 시간의 80%정도의 해당했다. 나중에 추가적으로 작업해도 무방한 작업이었다.

따라서 나는 워크플로우를 개선함과 다음과 같은 목적으로 동시에 스프링배치를 도입하고자했다.

  • 도중 step이 실패해도 해당 스텝만 이어서 재시작이 가능하다.
  • 실행, 수행의 결과들이 기록된다.
  • 분리 가능한 작업은 신규로 job을 구성하여 분리 가능하다.