외부 API 호출이 실패하면? - jinkshower/galmanhae GitHub Wiki
Place 장소 목록 최신화
(서비스의 운영 모습)
필요성: 서울시 공공 인구데이터를 사용하고 있고, 서비스에서 제공하는 장소는 인구데이터가 제공되는 100여 곳의 장소. 이 장소들의 목록은 추가될 가능성이 있기 때문에 주기적으로 목록을 다운로드 받아 DB에 sync를 해줄 필요가 있음.
개선 전: 일정 기간마다 장소 테이블을 삭제, 재 다운로드 후 파싱, 적재
배포가 자주 일어나고 있는 상황이었기에 애플리케이션 시작시에 최신의 장소 목록을 다운받아 파싱한 후 DB에 적재시킴.
문제점
삭제, 다운로드-파싱, 적재 세 단계 중 어느 하나라도 DB커넥션, 외부 API호출에 실패하거나 트랜잭션 처리 중 예외가 발생하면 서비스가 제대로 동작하지 않을 가능성이 있음(삭제 했는데 다운로드 실패, 삭제가 실패했는데 새로운 장소 저장은 성공 등)
장소 목록을 읽고 장소에 대한 날씨, 혼잡도 데이터를 fetch하기에 장소 목록은 언제나 온전한 상태가 되어야 함.
- 1차 개선
delete하는 로직을 삭제하고 장소 테이블에 version 컬럼을 추가, save 로직을 Spring @Transactional 사용. DB 트랜잭션의 범위를 batch insert하는 save 쿼리 하나로 잡고 가장 최신의 버전을 미리 쿼리하여 batch insert문에 +1한 version을 기록.
- 1차 개선 문제점
DB 트랜잭션을 사용하기에 insert의 원자성을 지켰으나 시간이 지날수록 장소 테이블에 쓰지 않는 데이터가 계속 쌓일 수 있음.
- 2차 개선
Pk나 Unique key 중복시 insert가 아닌 update를 실행하는 MySQL Upsert문법(on duplicate key update)사용.
장소의 코드를 Unique컬럼으로 삼고 서울시가 새로운 장소를 추가하거나 장소에 대한 변경사항이 있을 시에만 insert가 되게 하여 테이블이 필요 없이 비대해지는 것을 예방함.