인증 파라미터 관리
공개 API의 서비스 키를 setAuth()로 한 번만 설정하고 안전하게 관리하는 방법.
공개 API는 대부분 서비스 키를 요구합니다. 매 호출마다 키를 파라미터에 섞어 넘기는 대신, setAuth()로 한 번 설정해 두면 이후 호출에 자동으로 붙습니다.
기본 사용법
const cook = new ApiCook('proj_xxx', { apiKey: 'apk_xxx' });
cook.setAuth('air-quality', { serviceKey: process.env.DATA_GO_KR_KEY });
// 이후 호출에는 serviceKey를 쓰지 않아도 됩니다
const data = await cook.fetch('air-quality', { sidoName: '서울' });
첫 인자는 엔드포인트 slug입니다. 엔드포인트마다 따로 설정해야 하며, 한 번 설정한 값이 다른 slug에 적용되지는 않습니다.
여기서 apiKey와 서비스 키는 전혀 다른 것입니다. apiKey(apk_로 시작)는 ApiCook에 자신을 증명하는 키이고, setAuth()에 넣는 값은 원본 API 제공처가 발급한 키입니다. 전자는 설정 JSON을 받고 프록시를 호출할 때 X-ApiCook-Key 헤더로 나가고, 원본 API 쪽으로는 절대 전달되지 않습니다.
키는 설정 JSON에 들어 있지 않습니다
콘솔에서 엔드포인트를 배포하면 파라미터 정의는 설정 JSON에 실리지만 서비스 키 값은 포함되지 않습니다. 그래서 키는 항상 호출하는 쪽이 넣어야 합니다. proxy 모드에서도 마찬가지로 SDK가 매 요청에 실어 보냅니다 — 서버에 키가 보관되어 있지 않습니다.
값이 실제로 어디에 붙는가
설정에서 파라미터 위치가 path로 정의된 이름만 경로의 {name} 자리에 치환되고, 나머지는 전부 쿼리스트링으로 나갑니다.
cook.setAuth('air-quality', { serviceKey: 'ABC123' });
await cook.fetch('air-quality', { sidoName: '서울' });
// → https://apis.data.go.kr/.../getCtprvnRltmMesureDnsty?serviceKey=ABC123&sidoName=서울
헤더로 인증하는 API는 지원되지 않습니다. 파라미터 정의에
header위치가 있더라도 SDK는 그 값을 쿼리 파라미터로 보냅니다.Authorization헤더나 커스텀 헤더를 요구하는 API는 현재 SDK의 인증 경로로 처리할 수 없습니다.
멀티소스: 소스마다 다른 키
소스를 여러 개 붙인 엔드포인트는 가운데 인자로 소스 라벨을 지정합니다.
cook.setAuth('dashboard', 'weather', { serviceKey: 'WKEY' });
cook.setAuth('dashboard', 'news', { apiKey: 'NKEY' });
await cook.fetch('dashboard', {
weather: { city: '서울' },
news: { q: '날씨' },
});
weather 소스에는 serviceKey=WKEY만, news 소스에는 apiKey=NKEY만 붙습니다. 서로 섞이지 않습니다.
라벨을 생략한 2인자 형태는 모든 소스에 공통으로 적용됩니다.
cook.setAuth('dashboard', { common: 'C' });
// weather·news 양쪽 모두에 common=C가 붙습니다
함정 세 가지
1. 같은 대상에 다시 부르면 병합이 아니라 교체입니다.
cook.setAuth('air-quality', { serviceKey: 'ABC' });
cook.setAuth('air-quality', { returnType: 'json' });
// serviceKey는 사라지고 returnType만 남습니다
키를 나눠서 추가할 수 없습니다. 필요한 값을 한 객체에 모아 한 번에 넘기세요.
2. 라벨 전용 설정이 있으면 공통 설정은 그 소스에 합쳐지지 않습니다.
cook.setAuth('dashboard', { common: 'C' });
cook.setAuth('dashboard', 'weather', { serviceKey: 'WKEY' });
// weather 소스에는 serviceKey만 붙고 common은 붙지 않습니다
// news 소스에는 common이 붙습니다
라벨 전용 값이 있으면 그것만 쓰이고, 없을 때만 공통 값으로 넘어갑니다. 두 값이 합쳐지는 경우는 없습니다.
3. fetch()에 같은 이름을 넘기면 그쪽이 이깁니다.
cook.setAuth('air-quality', { serviceKey: 'ABC' });
await cook.fetch('air-quality', { serviceKey: 'XYZ' }); // XYZ로 나갑니다
의도한 동작이지만, 호출부에 남아 있는 오래된 키가 조용히 우선하는 상황도 같이 만들어집니다. 값이 예상과 다르면 호출부의 파라미터부터 확인하세요.
설정은 인스턴스에만 남습니다
setAuth()가 저장하는 값은 그 ApiCook 인스턴스의 메모리에만 있습니다. 파일이나 스토리지에 기록되지 않고, 새 인스턴스를 만들면 다시 설정해야 합니다. 서버에서는 인스턴스를 모듈 최상위에 한 번만 만들어 재사용하는 편이 좋습니다.
// lib/apicook.ts
export const cook = new ApiCook(process.env.APICOOK_PROJECT_ID!, {
apiKey: process.env.APICOOK_API_KEY!,
});
cook.setAuth('air-quality', { serviceKey: process.env.DATA_GO_KR_KEY! });
키를 어디에 두어야 하는가
브라우저에서 실행되는 코드에 서비스 키를 넣으면 누구나 개발자 도구에서 볼 수 있습니다. proxy 모드를 쓰더라도 키는 SDK가 요청 본문에 실어 보내므로 브라우저에 존재해야 합니다.
- 키가 노출돼도 괜찮은 공개 데이터(대부분의 공공데이터 무료 API)라면 브라우저에서 써도 실질적 위험은 트래픽 도용 정도입니다.
- 유료 API나 한도가 빠듯한 키라면 서버에서만 호출하세요. Next.js라면 서버 컴포넌트나 라우트 핸들러에서 SDK를 쓰고, 브라우저에는 결과만 내려보내는 구성이 안전합니다.
자세한 배치 기준은 보안에서 다룹니다.