Gemini는 공개 API라고 했지만, Careerjet의 등록 포털은 동의하지 않았습니다.
요약
Gemini가 Careerjet API를 인증이 필요 없는 공개 API로 잘못 안내하여 발생한 개발 오류와 실제 구현 시 직면한 인증 및 필수 파라미터 문제를 다룹니다.
핵심 포인트
- AI의 '공개 API' 정의와 실제 인증 요구사항 간의 차이 주의
- Careerjet API 사용 시 HTTP Basic Auth 및 IP 화이트리스트 필요
- v4 API 호출 시 user_ip와 user_agent 파라미터 필수 포함
- AI 생성 코드의 기술적 정확성을 반드시 공식 문서로 검증할 것
저는 채용 공고 데이터가 필요한 무언가를 만들고 있었습니다. Gemini는 Careerjet를 확실한 옵션으로 지목했습니다.
"Careerjet는 공개 API (public API)를 보유하고 있습니다 — 구조화된 데이터, 스크래핑 불필요, 케냐 지원."
Gemini가 언급하지 않은 네 가지 요구사항이 있었습니다.
처음에 내가 만든 것
기존의 Careerjet 제휴 엔드포인트(public.api.careerjet.net/search)는 인증되지 않은 요청에도 응답합니다. affid 파라미터를 전달하는데, 이는 원래 Careerjet가 클릭을 추적하고 파트너 사이트와 수익을 나누기 위해 사용하던 것입니다. 저는 자리 표시자(placeholder)를 전달하고 다음 단계로 넘어갔습니다.
params = urlencode({
"keywords": "software engineer",
"location": "Kenya",
...
JSON이 반환되었습니다. 저는 이를 기반으로 파서 (parser)를 작성했습니다. 그리고 파일을 배포했습니다.
이 방식은 문제가 생기기 직전까지는 잘 작동했을 것입니다. Careerjet가 기존 엔드포인트를 폐기하거나, 인증 요구사항을 강화하거나, 혹은 (더 가능성이 높은 것은) 어떤 것도 제대로 귀속되지 않아 기존의 게시자 계약(publisher agreement)을 조용히 위반하게 되는 상황 말입니다. 하지만 응답이 깔끔하게 돌아왔기에 저는 그대로 진행했습니다.
그러다 실제로 등록을 해보니
호기심에 Careerjet의 게시자 포털 (publisher portal)에 접속해 보았습니다. 제가 발견한 것은 다음과 같습니다:
- 등록된 도메인에 연결된 API 키 (API key)
- 필수적인 IP 화이트리스트 (IP whitelist) — 무엇인가 작동하기 전에 어떤 서버 IP가 API를 호출할 수 있는지 선언해야 했습니다.
- 모든 요청에 대한 HTTP 기본 인증 (HTTP Basic auth): 사용자 이름(username)으로 API 키를 사용하고, 비밀번호(password)는 빈 문자열로 사용합니다.
실제 엔드포인트는 https://search.api.careerjet.net/v4/query입니다. v4, https, 다른 서브도메인(subdomain), 그리고 affid 파라미터의 완전한 부재에 주목하십시오.
Careerjet의 어휘 사전에서 "공개 (Public)"라는 의미는 _승인 절차 없이 등록하는 모든 게시자에게 사용 가능하다_는 뜻입니다. _인증이 필요 없다_는 뜻이 아닙니다. AI는 두 가지 서로 다른 의미를 하나의 확신에 찬 문장으로 뭉뚱그려 버린 것입니다.
수정된 구현
import base64
import urllib.request
import json
...
AI의 설명에서 완전히 누락된 세 가지 사항은 다음과 같습니다:
비밀번호가 없는 기본 인증 (Basic auth). 형식은 base64("your-api-key-here" + ":")입니다. 사용자 이름(Username)은 API 키이며, 비밀번호(Password)는 공란입니다. 표준 HTTP 기본 인증 (Basic auth) 방식이지만, 이는 실제 문서(docs)를 직접 확인해야만 알 수 있는 내용입니다.
user_ip와 user_agent는 필수 필드입니다. 이 부분이 가장 흥미롭습니다. v4 API는 게시자(publisher)가 자신의 웹사이트에 채용 검색 기능을 삽입하도록 설계되었습니다. 즉, 실제 사용자가 쿼리를 입력하고 버튼을 클릭하면 API가 호출되는 방식입니다. Careerjet은 분석을 위해 사용자의 IP와 브라우저 문자열 (browser string)을 요구합니다.
저의 사용 사례는 브라우저도, 사용자도 없이 UTC 23:00에 실행되는 크론 잡 (cron job)입니다. 전달할 사용자 IP가 없습니다. 명세서(spec)에는 "API 호출을 트리거한 사용자의 IP"라고 명시되어 있습니다. 야간 크론 잡이 트리거 역할을 합니다. 따라서 저는 서버의 아웃바운드 IP (이 예제에서는 203.0.113.1)를 전달합니다. API는 이를 허용합니다.
무엇이든 작동하기 전에 IP 화이트리스트 (IP whitelisting) 등록이 필수입니다. 게시자 대시보드(publisher dashboard)에 최대 8개의 IP 주소를 입력할 수 있는 텍스트 박스가 있습니다. 서버의 아웃바운드 IP가 여기에 등록되어 있지 않으면
실패 모드는 다음과 같습니다: AI가 특정 시점에, 특정 유스케이스 (use case)에 대해 정확한 동작을 설명했지만, 제가 그것이 어떤 유스케이스를 설명하고 있는 것인지 확인하지 않았습니다. "공개 API (Public API)"라는 문구는 문서를 작성한 개발자에게는 특정한 의미를 갖지만, 웹 전반에서 정보를 합성하는 모델에게는 더 느슨한 의미를 갖습니다.
해결하는 데는 20분이 걸렸습니다 — 등록하고, IP를 화이트리스트 (whitelist)에 추가하고, 엔드포인트 (endpoint)를 교체하고, 인증 헤더 (auth header)를 추가했습니다. 등록은 즉각적이며 승인이 필요하지 않습니다. 문서는 명확합니다.
확인하지 않았을 때의 대가: 개발 단계에서는 작동하지만, 트래픽을 조용히 잘못 할당하고, 결국 기존 엔드포인트가 사라질 때 작동이 중단되는 통합 (integration)입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기