DS log

외부 API 연동 환경에서 안정적인 통계 집계 배치 개발하기 본문

트러블 슈팅

외부 API 연동 환경에서 안정적인 통계 집계 배치 개발하기

DS log 2026. 4. 8. 18:46
728x90

 

작년에 '외부 서비스 데이터를 연동해서 자사 서비스에 최적화된 통계 화면을 제공해!' 라는 요구사항을 받았습니다.

이번 포스팅에서는 해당 요구사항을 해결하면서 고민했던 부분을 정리해보려고 합니다.

요구사항 분석

구체적인 요구사항은 아래와 같습니다.

  • 2시간 주기로 최신화된 데이터를 제공하라.
  • 기간별로 통계 데이터를 조회가 가능해야한다.

또, 개발자로서 고려해야하는 상황은 아래와 같습니다.

  • 외부 API 응답 속도는 통제할 수 없다.

1차 설계

요구사항을 받고 대략적으로 설계를 해봤을 때 처음 든 생각은 내부 서비스에 API 요청을 하면 요청 시점에 외부 API를 호출해 응답을 가공한 뒤 반환하는 동기 처리 방식이었습니다. 

 

'당장 오늘 점심까지 해라' 와 같이 시간 제한이 타이트하지 않기도 하고, 자사 서비스의 스레드가 외부 API의 응답을 기다리면서 블라킹되어 스레드 고갈 문제가 발생할 수도 있기 때문에 바로 기각했습니다.

응답 시간, 기획 변경에 따른 영향 등을 고려할 때 '배치 기반 수집/적재 구조'로 설계하기로 결정했습니다.

-> 외부 데이터를 미리 수집하고 가공해 저장한 뒤, 서비스 조회는 적재된 데이터를 기준으로 처리하는 방법.

 

 

 

상세 설계를 하며 고민한 것들

대략적인 설계 방향을 정한 뒤 상세 설계를 진행하였습니다. 아래는 설계를 진행하면서 고민한 내용입니다.

1. 데이터 저장 모델 선택

가장 먼저 고민한 것은 데이터 저장 방식이었습니다.

가공된 데이터를 DB에 저장 할 지 vs 준원본 데이터를 저장할 지

전자의 경우에는 통계 API에서 추가적인 가공 없이 바로 사용할 수 있어 응답 속도가 빠르다는 장점이 있습니다. 그러나, 기획 변경에 유연하게 대응하기가 힘듭니다.

후자의 경우에는 추가적인 가공이 필요하지만 기획 변경에는 유연하게 대응이 가능합니다.

저는 후자 방식을 선택을 했는데 그 이유는 기획이 변경될 가능성이 크다고 생각을 했고, API 응답 속도가 문제가 있을 경우에는 기존에 저장된 원본 데이터를 사용해서 테이블을 하나 만들어서 데이터를 미리 가공하여 적재해놓으면 된다고 생각했습니다.

 

2. 적절한 청크 사이즈 설정

외부 API는 원하는 정보를 1번부터 N번까지 원하는 것을 한 번에 호출할 수 있는 구조입니다.

 

덕분에 자사 서비스에 맞게 청크 사이즈를 조절할 수 있었고, 테스트를 통해서 대략적인 값을 설정해놓고, 이후 운영을 하면서 조금씩 조절해나가기로 하였습니다.

3. 병렬 처리

병렬 처리를 수행해야할까? 수행한다면 어떻게 해야할까? 에 대해서 고민하였습니다.

사용자 규모가 작기 때문에 처리 시간이 오래 걸리지도 않았기 때문에 굳이 병렬 처리는 하지 않았습니다. 추후에 배치 수행 시간이 오래 걸리면 그때 병렬 처리를 도입하기로 결정하였습니다.

 

4. 트랜잭션 및 DB 커넥션 관리

청크 단위를 정한 다음에는 저장 구간의 트랜잭션 경계를 어디에 둘지 결정해야 했습니다. 외부 API 호출과 DB 저장을 같은 트랜잭션으로 묶으면 커넥션 점유 시간이 길어집니다. 외부 응답 지연이 DB 자원 문제로 번질 수 있다는 점이 가장 큰 리스크였습니다.

 

그래서 외부 호출과 가공은 트랜잭션 밖에서 처리하고, 저장 시점에만 짧은 트랜잭션을 열도록 분리했습니다. 또한 배치 대상 단위로 저장 경계를 나눠 실패 영향을 최소화했습니다.

 

5. 분산 환경 대응

다중 인스턴스 환경에서는 같은 배치가 동시에 실행될 수 있습니다. 이 경우 중복 수집과 저장 충돌이 발생할 수 있어 별도 제어가 필요했습니다.  그래서 ShedLock을 선택해 동시 실행을 제어했습니다. 핵심 이유는 두 가지였습니다.

 

첫째, 별도 인프라 없이 기존 DB 기반으로 분산 락을 운영할 수 있었습니다.

둘째, lockAtMostFor와 lockAtLeastFor를 통해 비정상 종료나 중복 실행 상황에서 좀비 커넥션 문제가 길어지는 것을 방지할 수 있었습니다.

 

6. 재시도/복구 전략

외부 API 호출 실패를 단순 로그로 끝내면 운영 복구가 어렵습니다. 그래서 집계 대상 정보를 먼저 DB에 저장하고, 상태 기반으로 처리 흐름을 추적하는 방식을 고민했습니다.

 

핵심은 각각의 통계 데이터에 대한 상태 관리입니다.

외부 API 호출 전에 저장될 통계에 대해서 대기 상태를 부여하고, 집계가 완료되어 데이터가 성공적으로 저장되면 성공 상태로 변경하는 것입니다. 그리고, 모종의 이유로 집계가 실패하였으면 실패 상태로 변경했습니다.

 

이 구조로 진행하게 되면, 실패 대상을 식별해 재처리할 수 있고, 운영자가 진행 상태를 확인할 수 있으며, 장애가 발생해도 필요한 대상만 선택적으로 복구할 수 있습니다.

 

회고

이번 요구사항을 개발하면서 외부 API 응답 결과를 기반으로 어떻게 하면 안정적으로 배치 처리를 수행할 수 있을까에 대해서 고민할 수 있었습니다.

728x90