개인정보처리방침이 2026년 9월 20일부터 변경됩니다. 온라인 맞춤형 광고 도입에 따라 행태정보 수집·이용 및 국외 이전 관련 조항이 추가됩니다.
개정 내용 보기

부분 실패 처리

일부 소스가 실패했을 때 무엇이 반환되고 언제 예외가 던져지는지, required 소스의 의미.

여러 API를 묶어 부르면 일부만 실패하는 상황이 생깁니다. 하나가 죽었다고 화면 전체를 비우는 것과, 나오는 것만이라도 보여주는 것 중 무엇이 나은지는 데이터마다 다릅니다. ApiCook은 기본적으로 후자를 택하고, 필요하면 전자로 바꿀 수 있게 합니다.

이 문서는 소스가 2개 이상인 엔드포인트에만 해당합니다. 단일 소스는 실패하면 곧바로 예외가 납니다.

기본 동작: 실패한 소스만 null

{
    "weather": { "temperature": 23 },
    "air": null,
    "_meta": {
        "partial": true,
        "errors": [
            { "source": "air", "kind": "http", "message": "500 Internal Server Error", "status": 500 }
        ]
    }
}

예외가 나지 않습니다. await은 정상적으로 값을 돌려주고, 실패는 _meta에만 기록됩니다.

그래서 멀티소스를 쓸 때는 성공한 응답도 검사해야 합니다. try/catch만으로는 부분 실패를 절대 감지할 수 없습니다.

const data = await cook.fetch('dashboard', { weather: {...}, air: {...} });

if (data._meta?.partial) {
    for (const e of data._meta.errors) {
        logger.warn(`소스 실패: ${e.source} (${e.kind}) ${e.message}`);
    }
}

// 실패한 소스는 null이므로 반드시 확인하고 씁니다
if (data.air) {
    renderAirQuality(data.air.pm10);
} else {
    renderAirQualityUnavailable();
}

required — 실패를 예외로 만들기

콘솔에서 소스를 필수로 지정하면, 그 소스가 실패했을 때 다른 소스가 성공했더라도 전체가 예외로 끝납니다.

ApiCookError: 'dashboard' 필수 소스 호출 실패 — air: 503 Service Unavailable

모든 소스가 실패하면 필수 지정과 무관하게 예외가 납니다.

ApiCookError: 'dashboard' 모든 소스 호출 실패 — weather: 500 ...; air: 503 ...

기본값은 필수가 아닙니다. 소스를 추가하면 별도로 지정하지 않는 한 선택 소스가 됩니다.

어디에 필수를 켜야 하나

화면이 성립하기 위해 반드시 있어야 하는 데이터에만 켜세요.

  • 필수로 둘 것 — 목록의 뼈대가 되는 데이터. 이게 없으면 화면에 아무것도 그릴 수 없는 경우.
  • 선택으로 둘 것 — 부가 정보. 날씨 화면의 미세먼지, 정류장 화면의 혼잡도처럼 없어도 나머지가 의미 있는 경우.

전부 필수로 켜면 소스가 늘어날수록 전체 실패 확률이 곱해집니다. 소스 세 개가 각각 99% 성공해도 셋 다 필수면 전체 성공률은 97%입니다.

실패 종류 구분하기

_meta.errors[].kind로 원인을 나눌 수 있습니다.

kind 의미 재시도 가치
timeout 제한 시간 초과 있음
fetch 네트워크 실패, JSON 파싱 실패, 응답 형식 불일치 있음
http 원본이 4xx·5xx 반환 (status 참조) 5xx만
transform 가공 규칙 적용 중 오류 없음 — 설정 문제입니다

http인 경우에만 status가 채워집니다. 개별 소스의 상태 코드를 얻을 수 있는 곳은 여기뿐입니다.

const retryable = data._meta.errors.filter(
    (e) => e.kind === 'timeout' || e.kind === 'fetch' || (e.status ?? 0) >= 500,
);

제한 시간

소스마다 따로 걸립니다. 하나가 느려도 나머지는 각자의 시간 안에 끝납니다.

경로 기본값
direct 모드 소스당 5초
proxy 모드 소스당 15초

콘솔에서 소스별로 100ms~30초 사이로 조정할 수 있습니다. 느린 원본을 선택 소스로 두고 시간을 짧게 잡으면, 그 소스만 빠르게 포기하고 나머지를 살릴 수 있습니다.

부분 실패 응답은 캐시되지 않습니다

proxy 모드는 응답을 기본 60초 캐시하지만, 일부 소스가 실패한 결과는 저장하지 않습니다. 잠깐의 장애가 60초 동안 굳어 전파되는 것을 막기 위해서입니다. 다음 호출은 원본을 다시 시도합니다.

사용량 집계에서는 성공으로 잡힙니다

부분 실패는 예외가 아니므로 사용량 통계에 성공으로 기록됩니다. 대시보드가 초록색이어도 특정 소스가 계속 죽고 있을 수 있습니다.

소스별 실패를 추적하려면 애플리케이션에서 _meta.errors를 직접 로깅하세요. 이것이 조용한 부분 실패를 알아채는 유일한 방법입니다.

if (data._meta?.partial) {
    Sentry.captureMessage('멀티소스 부분 실패', {
        level: 'warning',
        extra: { slug: 'dashboard', errors: data._meta.errors },
    });
}

전체 구조는 병렬 멀티소스 호출에, 예외 처리 방법은 에러 처리에 있습니다.