비동기 리포트 API를 다루는 수집 패턴

데이터 · 크롤링4분 읽기

광고·통계 데이터를 주는 큰 플랫폼의 API는 요청을 넣으면 곧바로 데이터를 돌려주지 않는 경우가 많습니다. 데이터 양이 크고 집계에 시간이 걸리기 때문에, 리포트를 만들어 달라고 요청해 두고 완성되면 받아가라는 비동기 방식을 씁니다. 이 패턴을 처음 다루면 당황스럽지만 흐름을 네 단계로 나눠 두면 리포트 종류가 아무리 많아도 같은 틀을 재사용할 수 있습니다.

생성, 폴링, 다운로드, 변환

비동기 리포트 수집은 네 단계로 정리됩니다. 먼저 리포트 종류와 대상 날짜를 담아 생성을 요청하면 작업 번호가 돌아옵니다. 이 번호로 상태를 주기적으로 확인하는 것이 두 번째 폴링 단계입니다. 상태가 완료로 바뀌면 응답에 다운로드 링크가 담겨 오고 그 링크에서 실제 파일을 받아오는 것이 세 번째입니다. 마지막으로 받은 원본 파일을 우리가 쓸 형식으로 변환합니다.

이 네 단계를 하나의 함수로 감싸 두면, 리포트 종류만 바꿔 넣어 같은 흐름을 여러 번 돌릴 수 있습니다. 실제로 이 파이프라인은 열 종류가 넘는 리포트를 하나씩 이 흐름에 태워 순차 수집합니다. 각 리포트는 서로 독립적이라, 한 종류가 실패해도 나머지는 계속 돌도록 결과를 따로 담아 반환하게 했습니다.

폴링에는 두 개의 타이머가 필요하다

폴링 단계가 생각보다 까다롭습니다. 리포트가 언제 완성될지 모르니 상태를 반복해서 물어봐야 하는데, 여기에는 두 종류의 한계선이 필요합니다. 하나는 전체 폴링을 포기할 최대 대기 시간입니다. 리포트가 끝내 완성되지 않으면 무한정 기다릴 수 없으므로, 정해진 시간이 지나면 타임아웃으로 실패 처리합니다.

다른 하나는 폴링 요청 자체가 연속으로 실패할 때의 한계입니다. 상태를 물어보는 요청이 한두 번 네트워크 오류로 실패하는 것은 흔한 일이라 바로 포기하면 안 되지만 연속으로 여러 번 실패하면 무언가 근본적으로 잘못된 것이므로 그때는 멈춰야 합니다. 그래서 일시적 폴링 실패는 세어 두었다가 연속 실패가 한계에 닿으면 예외로 올리고 성공하면 그 카운터를 초기화합니다. 이 두 타이머가 없으면 폴링은 조용히 영원히 돌거나 너무 성급하게 포기합니다.

정리하는 습관: 만든 리포트는 지운다

비동기 리포트 API를 쓰다 보면 우리가 생성 요청을 넣을 때마다 상대 쪽에 리포트 작업이 하나씩 쌓입니다. 매일 수집을 돌리면 이 작업이 계속 누적되고 플랫폼에 따라서는 동시에 유지할 수 있는 리포트 수에 제한이 있어 언젠가 생성이 막힙니다. 그래서 다운로드까지 끝낸 리포트는 작업을 삭제해 정리하도록 했습니다.

이 정리는 성공 여부와 무관하게 항상 실행되어야 합니다. 수집이 중간에 실패하더라도 이미 만든 리포트는 남아 있으니까요. 그래서 삭제는 예외 처리의 마지막 정리 구간에 두어, 어떤 경로로 끝나든 생성한 리포트를 반드시 치우게 했습니다. 삭제 자체가 실패해도 다음 수집을 막을 이유는 없으므로 조용히 넘어갑니다.

헤더 없는 표를 JSON으로

받은 파일이 늘 친절한 형식은 아닙니다. 이 프로젝트에서 다룬 리포트는 컬럼 이름이 없는 표 형식이었습니다. 각 줄에 값만 구분자로 나열되어 있고 첫 줄에 컬럼 제목이 없어서 몇 번째 칸이 무엇인지 파일만 봐서는 알 수 없습니다. 그래서 리포트 종류별로 컬럼 순서를 미리 정의해 두고 각 줄의 값을 그 정의에 맞춰 이름 붙인 JSON으로 변환했습니다.

변환할 때 값의 타입도 함께 정리합니다. 원본은 전부 문자열이지만 노출 수나 금액 같은 값은 숫자로 바꿔 두어야 다운스트림에서 바로 계산할 수 있습니다. 숫자로 해석되면 정수나 실수로 바꾸고 아니면 문자열 그대로 두는 식입니다. 이렇게 이름과 타입까지 정리된 JSON은 원본 데이터 레이크 적재 설계에서 다루는 구조화 경로로 그대로 흘러갑니다. 전체 파이프라인은 멀티채널 광고·정산 데이터 수집 파이프라인 사례에서 볼 수 있습니다.

자주 묻는 질문

비동기 리포트 API는 왜 데이터를 바로 주지 않나요?

집계 대상이 크고 계산에 시간이 걸리기 때문입니다. 요청 즉시 응답하려면 대기 시간이 길어지고 연결이 끊길 위험도 큽니다. 그래서 리포트 생성을 예약해 두고 완성되면 링크로 받아가게 하는 편이 서버와 클라이언트 모두에게 안정적입니다.

폴링 간격은 얼마로 두는 게 좋나요?

리포트 완성에 걸리는 대략적인 시간에 맞춰 몇 초 단위로 두는 것이 일반적입니다. 너무 촘촘하면 불필요한 요청이 많아지고 너무 성기면 이미 끝난 리포트를 뒤늦게 받아 전체 수집이 느려집니다. 여기에 전체 대기 시간의 상한과 연속 폴링 실패의 상한을 함께 두어야 무한 대기나 성급한 포기를 막을 수 있습니다.

컬럼 이름이 없는 리포트는 어떻게 해석하나요?

리포트 종류마다 컬럼 순서를 미리 정의해 두고 각 줄의 값을 그 정의에 순서대로 대응시켜 이름을 붙입니다. 규격 문서에 명시된 컬럼 구성을 기준으로 삼으면 됩니다. 정의가 없는 리포트가 들어오면 위치 기반 임시 이름을 붙여 최소한 데이터가 유실되지 않게 처리합니다.

#API연동#데이터수집#비동기처리#데이터변환

업무자동화 구축이 필요하신가요?

무료 상담 신청