2026년 11월 13일 금요일

나만의 아침 대시보드 만들기 (2) 키 없이 쓰는 데이터 소스와 공공 API 함정

대시보드-따라하기 시리즈 2편. 카드에 넣을 데이터를 어디서 가져왔는지, 그리고 문서와 실제가 달랐던 곳들을 적는다. 모두 2026년 가을 기준으로 직접 확인한 내용이라 이후에 바뀌었을 수 있다.

가입 없이 시작할 수 있는 것

  • 날씨: Open-Meteo. 키가 없고 시간별 예보, 대기질까지 준다. 처음엔 이것 하나로 충분하다.
  • 뉴스: Google News RSS. 주제 섹션 피드와 검색어 피드가 있어서 설정 파일의 검색어만 바꾸면 탭이 늘어난다.
  • 일정: 캘린더의 비공개 iCal(ICS) 주소. OAuth 없이 URL 하나로 읽을 수 있다. 다만 반복 일정(RRULE)은 직접 펼쳐야 한다. 공휴일도 공개 ICS 로 받아서 "오늘이 쉬는 날인가"를 판단하는 데 쓴다.
  • 교통 소통 지도: 국가교통정보센터의 실시간 소통 타일이 지도 타일(WMTS) 형태로 제공된다. 지도 라이브러리의 베이스맵 위에 레이어로 겹치면 된다. 해당 기관 페이지는 iframe 으로 넣을 수 없게 막혀 있어서 타일을 직접 쓰는 방식이어야 했다.
  • 개발 뉴스: Hacker News 는 검색 API 로 프런트 페이지를, 국내 커뮤니티는 Atom 피드를 읽는다.
  • 역사 속 오늘: 위키백과의 날짜 문서를 API 로 받아 섹션을 파싱한다.

공공 API 에서 밟은 것들

  • 공공데이터포털 키 하나로 다 되지 않는다. 인증키는 계정에 하나지만 API 마다 활용신청을 해야 한다. 신청하지 않은 API 를 부르면 "등록되지 않은 서비스" 계열 오류(코드 30)가 오는데, 키가 틀렸다는 뜻으로 읽기 쉽다.
  • 버전이 조용히 바뀐다. 기상청 생활기상지수는 경로에 버전이 들어 있는데, 검색해서 나오는 예제의 구버전 경로는 "서비스 없음"(코드 12)을 돌려줬다. 포털의 현재 명세에서 경로를 다시 확인해야 한다.
  • 연산 이름 철자. 에어코리아의 측정소별 실시간 조회는 연산 이름 중간이 Accto 다. 한 글자 다르게 쓴 예제가 돌아다니는데 그대로 쓰면 코드 12 가 온다. 측정소 이름도 공식 명칭 그대로여야 하고, 줄여 쓰면 오류 없이 0건이 온다.
  • 응답이 문서와 다르다. 고속도로 돌발 정보 API 는 실제 응답의 키 이름과 날짜 형식이 문서와 달랐고, 몇 해 전 홍보성 항목이 계속 내려왔다. 최근 24시간으로 걸러서 쓴다.
  • 키가 없으면 5행. 교육 정보 공개 API 는 키 없이 부르면 5행만 주는데, 페이지 번호를 바꿔도 같은 5행이 온다. 기간을 반으로 쪼개 가며 조회하는 식으로 우회했다. 키를 받는 편이 속 편하다.
  • 좌표계. 주유소 가격 API 는 좌표를 위경도가 아닌 국내 좌표계(KATEC)로 준다. 지도에 찍으려면 변환이 필요하다. 변환식을 직접 구현했고 실측 오차는 수십 미터 안이었다.

비공식·무료 소스에서 밟은 것들

  • 전일 대비 계산. 널리 쓰이는 주가 차트 API 의 메타 정보에 "이전 종가"처럼 보이는 필드가 있는데, 이것은 요청한 차트 범위가 시작되기 전의 종가다. 전일 대비 등락률에 쓰면 틀린다. 일봉의 마지막 두 봉을 비교해야 한다.
  • 호출 제한은 생각보다 빡빡하다. 어떤 엔드포인트는 연속 7번째 호출에서 429 를 줬고(간격을 2.5초로 벌려 해결), 어떤 경제 일정 JSON 은 5분에 두세 번만 불러도 막혔다.
  • 개발 PC 와 서버가 같은 공인 IP 를 쓰면 로컬에서 시험한 호출이 서버 몫의 한도를 깎아 먹는다. 배포 직후 서버 쪽 카드가 비어서 알았다. 이런 소스는 응답을 디스크에 캐시하고, 429 를 받으면 한 시간 쉬게 했다.
  • 주소가 바뀐다. 음악 차트 RSS 는 호스트가 옮겨 가며 리다이렉트가 생겼고, 다른 차트 사이트는 어느 날 유료벽 뒤로 들어가 HTML 에서 순위가 사라졌다. 비공식 소스에 기대는 카드는 "없으면 조용히 빠지는" 구조여야 한다.
  • 검색 API 의 언어 옵션은 결과를 걸러 주지 않는다. 한국어 영상만 원하면 제목에 한글이 있는지 직접 봐야 했다. 제목은 HTML 엔티티로 이스케이프돼 오므로 디코드도 필요하다.

컨테이너에서만 타임아웃이 날 때

로컬에서는 잘 되던 호출이 컨테이너에서만 타임아웃이 났다. 대상 호스트가 IPv6 주소를 함께 내주는데 컨테이너 네트워크에는 IPv6 경로가 없어서, Node 가 IPv6 를 먼저 시도하다 멈춘 것이다. Dockerfile 에 한 줄을 넣어 해결했다.

ENV NODE_OPTIONS="--dns-result-order=ipv4first"

로그에 키를 남기지 않기

공공 API 는 인증키를 URL 쿼리에 넣는다. 오류가 날 때 URL 을 통째로 로그에 찍으면 키가 로그에 남는다. HTTP 래퍼에서 오류 메시지를 만들 때 쿼리 문자열을 떼어 낸다.

const safe = (url) => String(url).split('?')[0];
throw new Error(`HTTP ${res.status} ${safe(url)}`);

다음 편에서는 이렇게 모은 데이터를 LLM 으로 번역·요약하고, 그 비용을 관리하는 이야기를 한다. 시리즈 전체 목록은 여기.

댓글 없음:

댓글 쓰기

반도체 주식을 보기 전에 그려 두는 지도 — 설계, 파운드리, 메모리, 장비, 소재, 후공정

"반도체주"라고 한 묶음으로 부르지만, 그 안의 회사들은 하는 일도 돈 버는 방식도 전혀 다르다. 같은 뉴스에 어떤 회사는 오르고 어떤 회사는 내리는 이유가 여기에 있다. 종목을 들여다보기 전에 머릿속에 그려 두면 좋은 지도를 정리한...