데이터 연동작업을 배치작업으로 만들기
나는 회사에서 외부데이터 연동 API를 만들었다. 이 API는 현재 외부로부터 한번에 약 1만건 정도의 데이터를 가져와서 본 서비스에 저장한다. 이 API는 다음과 같은 과정을 거친다.
- API요청으로부터 작업 수행에 필요한 파라미터를 제공받는다.
- 해당 파라미터로 외부 API를 요청한다.
- 응답을 받고 사전에 정의된 DTO로 파싱된다.
- DTO 중 쓰레기값을 가지는 DTO를 제거한다.
- DTO의 Unique ID를 서비스 DB에서 조회해 결번으로 추가할 DTO를 선별한다.
- 선별된 DTO에 저장된 외부 파일 경로로 S3 GET를 수행한다.
- 받아온 외부파일을 변환하여 Thumbnail을 생성한다.
- 생성된 Thumbnail 파일을 서비스의 S3스토리지에 저장한다.
- DTO를 서비스의 Entity로 변환시킨다.
- 저장된 경로와 정보를 앞서 변환된 Entity에 저장한다.
- 최종적으로 Entity를 DB에 저장한다.
- 1의 API요청에 대한 응답으로 void 200 OK를 회신한다.
이 워크플로우에 따라서 나는 적절히 역할과 책임에 따라서 클래스를 분리했다.
- 우선 외부 API를 요청하는 기능을 클래스로 분리했다.
- DB에 접근하고 엔티티를 다루는 서비스의 메인 서비스 로직을 분리했다.
- S3에 접근하는 기능을 클래스로 분리했다.
- 파일의 변환을 담당하는 기능을 다른 클래스로 분리했다.
하지만 부족한 점이 많았다.
- 이전 과정에서 한번의 RuntimeException이 발생하면 모든 작업이 취소되고 외부 API도 요청해야한다.
- 응답데이터 중 어떤 데이터가 선별되는지에 대한 로깅이 이뤄지지 않고 개발자나 사용자가 인지할 수 없다. 즉 작업의 자세한 모니터링이 불가능하다.
- Thumbnail 파일 변환은 오래 걸려서 전체 작업 시간의 80%정도의 해당했다. 나중에 추가적으로 작업해도 무방한 작업이었다.
따라서 나는 워크플로우를 개선함과 다음과 같은 목적으로 동시에 스프링배치를 도입하고자했다.
- 도중 step이 실패해도 해당 스텝만 이어서 재시작이 가능하다.
- 실행, 수행의 결과들이 기록된다.
- 분리 가능한 작업은 신규로 job을 구성하여 분리 가능하다.