Skip to content

Latest commit

 

History

History
295 lines (234 loc) · 30.8 KB

File metadata and controls

295 lines (234 loc) · 30.8 KB

OffWay 외부 데이터 인벤토리 · 발급 체크리스트

  • 조사일: 2026-07-18
  • 목적: OffWay가 끌어올 모든 외부 데이터의 발급처·인증·엔드포인트·가용 데이터를 한곳에. 이 문서가 곧 (1) 회원가입/키 발급 체크리스트, (2) 우리가 조합할 데이터 전체 목록.
  • 전략: 미리 전부 확보·적재(라이브 API + 정적 시딩) 해두고 조합해 서비스를 제공한다.

⚠️ 신뢰도 표기: 아래 상당수는 조사 기반이며 일부 오퍼레이션명·파라미터 철자는 활용신청 후 각 상세페이지의 활용가이드/Swagger로 최종 확정 필요. "추정" 표시된 항목 주의.


0. 회원가입은 딱 3곳 (대부분 data.go.kr 하나로 커버)

# 포털 URL 커버하는 데이터 인증 방식
1 공공데이터포털 data.go.kr https://www.data.go.kr 특일정보 · TourAPI · 관광빅데이터 · TAGO(버스/열차) · 코레일 · 생활인구(파일) 계정 1개 + API별 활용신청serviceKey
2 SK openapi.sk.com https://openapi.sk.com TMAP 경로/경유지 최적화 앱 등록 → appKey(헤더)
3 (선택) 통계청 SGIS https://sgis.kostat.go.kr/developer 센서스 인구·통계(생활인구 보강용) key+secret → accessToken

data.go.kr 서비스키 핵심 함정: 발급 화면에 Encoding 키 / Decoding 키 두 종류가 나온다. HTTP 클라이언트가 파라미터를 자동 인코딩하면 Decoding 키, 아니면 Encoding 키를 쓴다. 잘못 쓰면 SERVICE_KEY_IS_NOT_REGISTERED_ERROR. → application secret으로 두 키 다 보관하고, 한쪽 실패 시 반대로 시도.


1. 라이브 REST API (클라이언트 구현 대상 → external/ port)

1-1. 특일 정보 (공휴일·대체공휴일) — 한국천문연구원

  • 발급: data.go.kr 데이터셋 15012690 한국천문연구원_특일 정보활용신청 (자동승인)
  • Base: https://apis.data.go.kr/B090041/openapi/service/SpcdeInfoService
  • 오퍼레이션: getRestDeInfo(공휴일+대체공휴일 — 이걸 사용), getHoliDeInfo(국경일), getAnniversaryInfo, get24DivisionsInfo
  • 파라미터: serviceKey, solYear(필수), solMonth(권장, 월별 반복 호출 안전), _type=json, numOfRows, pageNo
  • 응답 필드: locdate(YYYYMMDD), dateName(예 "대체공휴일"), isHoliday(Y/N), dateKind
  • 한도: 무료, 개발계정 일 10,000건(추정)
  • 함정: 대체공휴일은 별도 플래그 없이 dateName="대체공휴일"로 판별. 미래 연도는 지정 전 누락 가능.
  • OffWay 용도: LNT 산출 · 샌드위치 연휴 탐지의 기반.

1-2. 국문 관광정보 서비스 (TourAPI) — 한국관광공사

  • 발급: data.go.kr 데이터셋 15101578 한국관광공사_국문 관광정보 서비스_GW활용신청 (자동승인)
  • Base(권장 v2, HTTPS): https://apis.data.go.kr/B551011/KorService2 (레거시 KorService1은 단계적 폐지)
  • 오퍼레이션: areaBasedList2(지역기반 목록 — 핵심), locationBasedList2(위경도+반경), searchKeyword2, detailCommon2(주소·좌표·개요), detailIntro2(운영시간·휴무일), detailImage2, areaCode2(지역코드 조회)
  • 파라미터: serviceKey, MobileOS(ETC), MobileApp(offway), _type=json, numOfRows, pageNo, arrange, areaCode, sigunguCode, contentTypeId, cat1/2/3
  • contentTypeId: 12=관광지 · 14=문화시설 · 15=축제공연행사 · 25=여행코스 · 28=레포츠 · 32=숙박 · 38=쇼핑 · 39=음식점
  • 응답 필드: contentid, title, addr1, mapx(경도)/mapy(위도), areacode, sigungucode, firstimage, tel; detailIntro는 usetime/restdate(운영·휴무, 자유텍스트)
  • 한도: 무료, 개발계정 일 1,000건 (운영 전환 시 증량)
  • ⚠️ 최대 함정 — 지역코드: sigunguCode는 KTO 전용 순번(법정 시군구 코드 아님)이고 areaCode함께만 유효. → 먼저 areaCode2로 (areaCode,sigunguCode)↔지명 매핑 테이블을 확보한 뒤 인구감소지역 89곳 지명과 매칭. 지명 기준 조인.
  • OffWay 용도: 인구감소지역 관광지·숙박·음식점 표출, 운영시간/휴무 기반 일정 생성.

1-3. 관광빅데이터(방문자수) — 한국관광공사 · 실호출 확인(#20)

  • 발급: data.go.kr 데이터셋 15101972 한국관광공사_관광빅데이터 정보서비스_GW활용신청 (15101578과 별개 신청)
  • Base: https://apis.data.go.kr/B551011/DataLabService ✅ 확인
  • 오퍼레이션: metcoRegnVisitrDDList(광역별 일별 방문자수) · locgoRegnVisitrDDList(기초 시군구별 — OffWay 89에 사용). 둘 다 실호출 성공(resultCode 0000).
  • 파라미터: serviceKey·MobileOS(ETC)·MobileApp(offway)·_type=json·startYmd/endYmd(YYYYMMDD)·pageNo·numOfRows. (지역 필터 param 없이 기간 전체 반환 → 클라가 시군구로 매칭)
  • 응답 필드(locgo): signguCode(11110)·signguNm(종로구)·daywkDivCd/daywkDivNm(요일)·touDivCd/touDivNm(1=현지인·2=외지인·3=외국인touNum(방문자수, 문자열)·baseYmd
  • 한도: 무료, 개발계정 일 1,000건
  • 함정 ①(매칭 키): signguCode법정 시군구코드(행정표준코드)라 TourAPI KTO 코드와 다름 → region 에 legal_code 컬럼을 따로 두고 코드로 매칭한다(#65).
    • signguNm(지명)으로 매칭 은 폐기했다. 지명은 전국에서 겹친다 — 동구 6곳·중구 6곳·서구 5곳·남구 4곳·북구 4곳·고성군 2곳(2026-06 실호출, 268개 시군구 기준). 우리 89곳 중 부산 동구·부산 서구·대구 남구·대구 서구·강원 고성군(51820)·경남 고성군(48820) 6곳이 걸려, 서로 다른 지역의 방문자가 한 버킷에 합산됐다(부산 동구 = 전국 동구 6곳의 합).
    • region.legal_code 의 정본은 이 응답의 signguCode 자체다. 매칭 상대에서 그대로 따와야 89곳 전부 매칭이 보장된다.
  • 함정 ②(발행 주기): 완결된 달만 월 단위로 발행된다. "N일 지연"이 아니다 — 2026-07-30 기준 6월(24,120건)까지 있고 7월은 0건. 고정 일수 지연을 가정하면 관측 창이 미발행 구간에 걸려 조회가 resultCode=0000 + 빈 결과로 조용히 성공하고, 전 지역 방문자가 0이 돼 랭킹이 무의미해진다(경고 로그도 안 남음). → 지난달부터 시작해 비면 이전 달로 물러선다.
  • 함정 ③(응답 크기): 지역 필터가 없어 기간 전체가 내려온다. 268 시군구 × 3 구분 × 일수 → 7일 약 1MB / 한 달 약 4MB. 운영 externalWebClientmaxInMemorySize 가 2MB 라 한 달치는 버퍼를 넘긴다. 관측 창을 발행된 달의 마지막 한 주로 잡는 이유.
  • 함정 ④: "방문자≠관광객" → 랭킹엔 외지인+외국인만.
  • OffWay 용도: "평일에 한산한 시점" 한산도 뱃지·지역 랭킹 — 차별화 핵심 데이터.
  • 미확인(후속): 관광지별 집중률·향후 방문자 예측은 별도 오퍼레이션(#21+ 필요 시 확인).

1-3-1. 기초지자체 중심 관광지 — 한국관광공사 · 실호출 확인(#185)

  • 발급: 관광빅데이터와 같은 계정(15101972)으로 호출된다 — 별도 신청 없이 serviceKey 를 그대로 쓴다.

  • Base: https://apis.data.go.kr/B551011/LocgoHubTarService1 ✅ 확인 (1-3 의 DataLabService다른 base)

  • 오퍼레이션: areaBasedList1 — 한 지자체의 중심 관광지를 순위로. 실호출 성공(resultCode=0000).

  • 파라미터: serviceKey·MobileOS(ETC)·MobileApp(offway)·_type=json·areaCd(시도 2자리)·signguCd(시군구 5자리)·baseYm(YYYYMM)·numOfRows·pageNo(필수)

  • 응답 필드: hubRank(순위)·hubTatsCd(식별자)·hubTatsNm(관광지명)·hubCtgryLclsNm(대분류: 관광지·음식·숙박)·hubCtgryMclsNm(중분류)·mapX(경도)/mapY(위도signguNm·baseYm

  • 실측(2026-08-09, 공주시 44150 · baseYm=202606)

    항목
    응답시간 n=20 · min 0.106s · p50 0.123s · p90 0.135s · p95 0.137s · max 0.139s
    응답 크기 numOfRows=309.5KB · numOfRows=10031KB
    totalCount 지자체당 51~100건(표본 5곳: 공주 100·완도 51·강원고성 100·경남고성 100·양구 82)
    페이지 상한이 100건이라 numOfRows=100 이면 1페이지로 끝난다 — 페이지 순회가 필요 없다
  • timeout 근거: 어댑터는 6초를 쓴다. 정상 p95(0.14초)의 40배로 크게 잡은 값인데, 표본이 20회라 p99 를 낼 수 없어 꼬리를 보수적으로 뒀다. 이 경로는 하루 한 번 도는 배경 배치라 지연이 사용자에게 닿지 않는다 — 89곳 순차 최악이 534초여도 아무도 기다리지 않는다. 요청 경로에 붙일 일이 생기면 이 값을 다시 재야 한다.

  • 한도: 1-3 과 같은 계정이라 일 1,000건을 공유한다. 갱신 1회가 89건(+발행월 탐색 최대 9건)이므로 하루 한 번이면 여유가 있다. 요청 경로에서 부르면 안 되는 이유가 이것이다(#193).

  • 함정 ①(코드 체계): areaCd/signguCd법정동 코드다 — 공주시는 44/44150. TourAPI 의 KTO 코드(34/1)를 넣으면 resultCode=0000totalCount=0 이 온다(실측). 성공 코드라 조용히 빈 결과가 되므로 특히 위험하다.

  • 함정 ②(pageNo 필수): 빠뜨리면 resultCode=11 NO_MANDATORY_REQUEST_PARAMETERS_ERROR1(pageNo) 인데, 그 응답만 response 래퍼 없이 최상위에 코드를 담아 온다(실측 원문: {"responseTime":"...","resultCode":"11","resultMsg":"..."}). 래퍼만 보고 파싱하면 코드가 빈 문자열이 돼 "결과 없음" 과 구분되지 않는다 — 조사 중 실제로 이걸로 "최신 월이 없다" 고 잘못 읽었다.

  • 함정 ③(1건이면 단일 객체): items.item 이 배열이 아니라 객체로 온다. 결과가 없으면 items빈 문자열이다. 둘 다 1-2·1-3 과 같은 data.go.kr 공통 함정.

  • 함정 ④(1위가 대표 사진감은 아님): 대분류가 숙박·음식인 경우가 있다 — 정선군 1위는 콘도, 2위는 카지노다. 데이터는 맞지만 지역 카드에 걸 그림이 아니라 대분류로 걸러야 한다.

  • 발행 주기: 1-3 과 같은 월 단위. 2026-08-09 기준 202607 까지 발행됨(확인). 이번 달은 아직이므로 지난달부터 시작해 비면 물러선다.

  • OffWay 용도: 지역 대표를 "제목순 첫 POI"(#182)가 아니라 실제 이동 데이터의 중심성으로 정한다. 공주시 1위 = 공산성 — TourAPI 에는 등록조차 없어 기존 구조로는 찾을 수 없던 곳이다.

1-3-2. 관광사진 갤러리 — 한국관광공사 · 실호출 확인(#196)

  • 발급: 관광빅데이터와 같은 계정(15101972). 별도 신청 없이 serviceKey 를 그대로 쓴다.

  • Base: https://apis.data.go.kr/B551011/PhotoGalleryService1 ✅ 확인

  • 오퍼레이션: galleryList1 — 전량 목록. 실호출 성공(resultCode=0000).

    • galleryKeywordList1 은 호출이 실패했다. 전량을 DB 로 내리면 키워드 검색이 필요 없어 더 파지 않았다.
  • 파라미터: serviceKey·MobileOS(ETC)·MobileApp(offway)·_type=json·arrange·numOfRows·pageNo

  • 응답 필드: galContentId·galTitle·galWebImageUrl·galPhotographyMonth(YYYYMM)·galPhotographyLocation·galPhotographer·galSearchKeyword

  • 실측(2026-08-09)

    항목
    전량 6,118건
    페이지 numOfRows=1000 이 그대로 받아들여져 7페이지로 끝난다
    응답 크기 1,000건 페이지 554KB (3건 1.9KB)
    응답시간 0.18~0.35초
  • timeout 근거: 어댑터는 10초. 실측 0.35초의 30배로, 표본이 적어 꼬리를 보수적으로 뒀다. 부팅 후 도는 배경 적재라 지연이 사용자에게 닿지 않는다.

  • maxInMemorySize 주의: 페이지당 554KB 라 운영 externalWebClient 상한(2MB) 안에 든다. 페이지 크기를 더 키우면 여기에 걸린다.

  • 한도: 1-3 과 같은 계정이라 일 1,000건을 공유한다. 전량 적재가 7회뿐이라 주 1회 갱신으로 충분하다.

  • ⚠️ 함정 ①(촬영 위치가 자유 텍스트): galPhotographyLocation 은 정제된 코드가 아니다. 실측 분포에서 이런 값이 나온다.

    전남광주통합특별시 711 · 강원도 581 / 강원특별자치도 198 · 전라북도 402 / 전북특별자치도 98
    서울 231 / 서울시 18 / 서울특별시 277 · 인청광역시 · 산광역시 · 전북특별자치도도 (오타)
    신승반점 · FNC · 전주식당 · 민가다헌 (시도 자리에 상호명)
    

    시도를 함께 정규화하지 않으면 조용히 틀린다. 시군구명만으로 세면 대구 남구가 104건으로 부풀었다(전국 남구의 합). 정규화 후 6건. 1-3 의 함정 ①과 같은 계열이다.

  • 함정 ②(제목이 장소명이 아닐 수 있다): galTitle 이 "봄의 약속" 같은 작품명인 경우가 있다. 장소명은 galSearchKeyword 에만 있을 수 있어 둘 다 봐야 한다 — 제목 "금강철교" 사진의 키워드에 "공산성" 이 들어 있다.

  • 함정 ③(1건이면 단일 객체·결과 없으면 빈 문자열): 1-2·1-3 과 같은 data.go.kr 공통 함정.

  • ⚠️ 함정 ④(죽은 이미지 URL): galWebImageUrl 의 상당수가 404 다 — 우리 89곳에 붙은 1,790장 중 345장(19.3%). 경로로는 못 가른다(같은 cms2/website/ 에 산 것과 죽은 것이 섞여 있다). 확인하지 않고 쓰면 지역 카드 15곳에 깨진 이미지가 나간다.

    • 생존 확인에 HEAD 를 쓰면 안 된다. 이 호스트는 HEAD 에 405 를 돌려줘 살아 있는 URL 도 죽은 것으로 판정된다(처음 잰 83개가 전부 405 였다). GET 으로 확인하고 본문을 버린다.
  • OffWay 용도: 지역 대표 사진(#196). 중심 관광지(1-3-1) 순위와 이어 "그 지역의 대표 명소 사진"을 고른다.

  • 커버리지 실측(죽은 URL 제외 후): 6,118건 중 1,790건이 우리 89곳에 붙고, 그중 살아 있는 것은 1,445건이다. 사진이 한 장도 없는 곳은 장수군 1곳.

    사다리 단계 지역 수
    ① 중심 관광지(1-3-1) × 갤러리 82곳
    ② 그 지역 갤러리 사진(5장 이상 보유) 4곳 — 부산 동구·인천 옹진군·전남 영암군·경남 의령군
    ③ TourAPI 폴백 3곳 — 전북 장수군·경북 영양군·경북 의성군

    ②를 둔 이유: 중심 관광지 이름과 갤러리 제목이 안 맞아도 그 지역에 쓸 사진이 없는 것은 아니다. 영암군은 중심 관광지 3위가 도갑사인데 정작 영암을 대표하는 월출산 사진이 13장 있었다. 다만 한두 장뿐인 곳(영양군의 유일한 사진은 '가마')은 우연히 찍힌 쪽에 가까워 TourAPI 로 내려보낸다.

1-4. TAGO 대중교통 — 국토교통부 (여러 서비스, 동일 계정)

  • Base 공통: https://apis.data.go.kr/1613000/... (serviceKey 가 URL 에 실리므로 HTTPS 필수 — 평문 전송 금지) · 응답 래퍼 resultCode/items>item[]
  • 한도: 무료, 개발계정 일 10,000건

⚠️ 경로 명명 — 서비스마다 다르다: data.go.kr TAGO 는 서비스마다 base·op casing 이 제각각이다. 버스류는 ...InqireService + 소문자 op(getCtyCodeList)다. 열차는 실측 확정: 짧은 base(TrainInfo) + 대문자 G op(GetStrtpntAlocFndTrainInfo). 고속버스·시외버스·지하철은 아직 추정(열차와 같은 규칙일 것으로 보이나 실호출 미확인). 틀린 조합은 게이트웨이가 404 "API not found" — 404 의 태반이 미구독이 아니라 경로·casing 오타였다.

서비스 데이터셋 base 핵심 op / 필드 비고
버스도착정보(시내) 15098530 ArvlInfoInqireService getSttnAcctoArvlPrearngeInfoList(소문자) → arrtime nodeId 선조회, 실시간
버스정류소정보 15098534 BusSttnInfoInqireService getCtyCodeList 등(소문자) 200
버스노선정보 15098529 BusRouteInfoInqireService 노선·경유정류소(소문자) 200
버스위치정보 15098531 BusLcInfoInqireService 실시간 차량 위치(소문자) 200
열차정보 15098552 TrainInfo GetStrtpntAlocFndTrainInfo(대문자 G) · GetCtyCodeList · GetCtyAcctoTrainSttnList 200 실호출·KTX 확인. SRT 미포함
고속버스정보 15098522 ExpBusInfo(추정) GetExpBusTrminlList(대문자 추정) 열차와 같은 규칙 예상
시외버스정보 15098541 SuburbsBusInfo(추정) (대문자 추정) ⚠️ 당일 배차만
지하철정보 SubwayInfo(추정) (대문자 추정) 도시 내
  • 응답 필드(열차): items.item[] (단건이면 item 객체 하나) · traingradename(KTX·ITX-새마을·무궁화) · depplandtime/arrplandtime(yyyyMMddHHmmss) · trainno. 미운행이면 items:""(빈 문자열).
  • 역/정류소/터미널 ID는 각 목록 op(GetCtyCodeListGetCtyAcctoTrainSttnList 등)으로 선조회. 예: 서울 NAT010000 · 부산 NAT014445.
  • OffWay 용도: 반차·퇴근후 모드 도착시각, 교통수단별 동선.

⚠️ 시내버스 커버리지 — 전국이 아니다 (실호출 확인 2026-07-31)

BusSttnInfoInqireService/getCtyCodeList 실호출 결과 138개 지자체만 담는다. 서울조차 없다(별도 TOPIS). 미커버 지역은 오류가 아니라 resultCode=00 + 빈 결과로 오므로, 그대로 두면 "주변에 정류소 없음"과 구분되지 않는다.

도시코드 앞 두 자리가 시도다(32010 춘천 → 32 강원). 이 구분이 있어야 동명 시군구를 갈라낸다 — 고성군은 강원(미커버)·경남(커버) 양쪽에 있어 지명만 맞추면 강원 고성군까지 커버로 오판한다. 광역시는 구 단위 없이 시 전체가 한 코드(21 부산)이고, 버스권역이 묶인 곳은 "원주시/횡성군" 합본으로 온다.

우리 89곳 중 미커버 13곳 (89 × 138 대조):

시도 미커버 시군구
강원특별자치도 고성군 · 삼척시 · 양구군 · 영월군 · 정선군 · 평창군 · 화천군
충청남도 예산군
전라남도 강진군 · 담양군 · 보성군 · 영광군 · 화순군

하필 이 서비스가 겨냥하는 강원 산간·전남 오지다. 공공데이터 폴백 없음전국 버스정류장 위치정보(15067528)도 "TAGO 연계 지자체" 스냅샷이라 같은 모집단이다. 상용 API(ODsay·카카오, 유료)만 남는다. 실시간 도착은 지자체 BIS 구축이 전제라 구조적으로 불가.

→ 메울 수 없으므로 구분해서 드러낸다: BusStopAccess.NotCovered("데이터 없음") ≠ NoStopNearby("정류소 없음"). 판별은 BusAccessService 가 도시목록(24h 캐시)으로 한다. 목록을 못 얻으면 판별 불가라 Unavailable 로 폴백한다 — 커버 여부를 모르는 채 "버스 없음"이라 안내하면 틀린 말이 될 수 있어서다.

1-5. 코레일 열차운행정보 — 한국철도공사

  • 발급: data.go.kr 15125762 한국철도공사_열차운행정보활용신청
  • 제공: 여객열차 운행계획/운행정보(실시간·지연). 출발역/도착역/운행일자 기반.
  • 함정: 요금·예매·좌석 미제공(운행 트래킹용). 시간표는 1-4 TAGO 열차정보가 더 적합.
  • OffWay 용도: KTX 지연/실제운행 보조 (선택).

1-6. TMAP 경로·경유지 최적화 — SK(티맵모빌리티) 별도 포털

  • 발급: https://openapi.sk.com 회원가입 → 앱 등록 → TMAP 상품 구독 → appKey(UUID) 발급
  • 인증: 요청 헤더 appKey: <키>
  • Base: https://apis.openapi.sk.com/tmap/...
    • 자동차 경로: POST /tmap/routes?version=1
    • 경유지 최적화(10곳): POST /tmap/routes/routeOptimization10 (20/30곳은 엔드포인트 별도)
  • 파라미터: startX/startY, endX/endY(경도X/위도Y, WGS84GEO), searchOption; 최적화는 viaPoints[](viaX/viaY/viaTime)
  • 응답: GeoJSON, totalTime(초)·totalDistance(m)·totalFare
  • 한도(무료): 경로 1,000/일, 경유지 최적화(10곳) 50/일 (초과 시 유료)
  • ⚠️ 함정: 결과 데이터 24시간 이상 저장 금지(약관) → 경로 결과 영구 캐싱 불가. 좌표 X=경도/Y=위도 순서.
  • OffWay 용도: 자가용 기준 실시간 소요시간, 관광지 경유지 순서 최적화(일정 자동 생성).

2. 정적 데이터셋 (런타임 호출 아님 → DB 시딩/임포트)

# 데이터 출처 형식 방식
2-1 인구감소지역 89곳 행안부 고시 (mois.go.kr / nabis.go.kr) 고시문/표 상수 시드(거의 불변, "고시 기준일" 기록)
2-2 생활인구(체류) 행안부 data.go.kr 15130539 (파일데이터) XLSX(분기) 분기마다 다운로드→임포트
2-3 로컬100 문체부 mcst.go.kr / culture.go.kr PDF/리스트 시드 + 좌표는 지오코딩 보강
2-4 관광두레 tourdure.mcst.go.kr 웹/발간물 시드 + 좌표는 TourAPI/지오코딩
2-5 7대 여행 지원 혜택 전용 API 없음(제안서 명시) 수동 수동 적재(정책명·기간·대상지·할인)
  • 생활인구 주의: 정책적 "생활인구(체류인구)"는 행안부 XLSX가 정본. SGIS는 센서스 인구라 개념이 다름. 서울시 생활인구 API는 2026-06 현행화 중지.

3. 데이터 조합 → 제공 가능한 기능 (전부 확보 시)

기능 필요한 데이터 조합
LNT 가용시간·샌드위치 연휴 특일정보
인구감소지역 여행지 추천 인구감소지역89(seed) + TourAPI + 관광빅데이터(집중률→한산시점) + 생활인구(가중치)
정책 혜택 매칭·뱃지 7대혜택(seed) + 인구감소지역 + 로컬100/관광두레(seed)
교통·도착시각 (반차/퇴근후) TAGO 버스/열차 + 코레일 + TMAP(자가용)
일정 자동 생성 TourAPI(운영시간/휴무) + TMAP(경유지 최적화) + 위 조합
연차 컨설팅 특일정보 (+ 위 전체)

4. "모든 걸 미리 준비" 실행 제약 (설계에 반영)

  • SRT 공공API 없음 → SRT 시간표는 제외하거나 별도 처리. KTX는 TAGO로.
  • 시외버스 미래날짜 조회 불가(당일만) → 미래 일정은 "예상 소요시간"으로 근사, 실시간은 당일에.
  • TMAP 24h 저장 제한 → 경로 결과는 단기 캐시(≤24h)만. 영구 저장 금지.
  • 개발계정 한도(TourAPI/빅데이터 1,000/일, TMAP 최적화 50/일) → 대량 사전적재는 배치·페이징·운영계정 전환 고려.
  • 지역코드 불일치(TourAPI sigunguCode ↔ 빅데이터 코드 ↔ 인구감소지역 지명) → 지명 기준 매핑 테이블을 먼저 구축(마스터 데이터).
  • Encoding/Decoding 서비스키 두 개 다 보관.

5. 발급 체크리스트 (본인 액션)

  • data.go.kr 회원가입 (휴대폰 본인인증)
  • 활용신청: 특일정보(15012690) · 국문관광정보(15101578) · 관광빅데이터(15101972) · TAGO 버스도착(15098530)·고속(15098522)·시외(15098541)·열차(15098552) · 코레일(15125762) · 생활인구 파일(15130539)
  • 발급된 serviceKey(Encoding+Decoding) 확보
  • openapi.sk.com 회원가입 → 앱 등록 → TMAP appKey 발급
  • (선택) SGIS 개발지원센터 key/secret
  • 정적 데이터 다운로드: 인구감소지역 89곳 · 생활인구 XLSX · 로컬100 리스트 · 관광두레 목록
  • 7대 혜택 정보 수동 정리(정책명·운영기간·대상지·할인율)

6. 볼거리 보강 후보 (미연동)

2026-07-21 조사. TourAPI만으론 볼거리가 부족한 소도시(영양 10개급) 보강용 추가 소스. 아래는 후보이며 아직 클라이언트 미구현. 이미 우리가 쓰는 소스(특일정보·TourAPI·관광빅데이터·TAGO·코레일·TMAP)는 그대로 유지한다. 관련 이슈 #44.

6-1. 국가유산 정보 (문화재) — 국가유산청 ⭐ 키 불필요, 즉시 사용 가능

  • 인증: 없음 (API key·로그인·프록시 불필요). GET · XML 응답 · User-Agent 헤더 필요 · timeout ~20s
  • 목록: https://www.khs.go.kr/cha/SearchKindOpenapiList.do
    • params: ccbaMnm1(유산명 검색어) · ccbaCtcd(시도코드 2자리) · pageUnit(1~100) · pageIndex · ccbaCncl=N(지정해제 제외)
    • item 필드: ccbaMnm1(명) · ccbaMnm2(한자) · ccbaCtcdNm(시도명) · ccbaAdmin(관리기관) · latitude · longitude · ccbaKdcd(종목코드) · ccbaAsno(관리번호) · ccbaCtcd(시도코드)
  • 상세: https://www.khs.go.kr/cha/SearchKindOpenapiDt.do — params ccbaKdcd+ccbaAsno+ccbaCtcd → 설명(content)·주소·좌표·이미지
  • 행사: https://www.khs.go.kr/cha/openapi/selectEventListOpenapi.do — params 연도(YYYY)·월(1~12) → 행사명·기간·지역·본문(subContent)·링크(subPath)
  • ⭐ 좌표 제공 → 지명·좌표로 우리 region/POI에 매핑. TourAPI contentTypeId=14(문화시설) 계열 볼거리 보강.
  • 함정: 공식 페이지 명시 한도 확인 필요. 지명↔시도코드 매핑 테이블 선구축(우리 89 지명 기준).
  • OffWay 용도: 콘텐츠 충분성(#21)에서 인접 50km 확장 전 자체 볼거리 확대 · 지역 상세에 문화재·이달의 행사.

6-2. 날씨 (기상청) — 채택. 남은 일수로 세 API 를 갈아탄다

여행까지 남은 일수에 따라 담당이 갈린다. 실호출 확인(2026-08-03), 전부 기존 DATA_GO_KR 키로 동작.

남은 일수 API base 주는 것
0~3일 단기예보 VilageFcstInfoService_2.0 기온·하늘상태·강수확률
4~10일 중기 육상예보 MidFcstInfoService 하늘상태·강수확률 (기온 없음)
1~9일 관광기후지수 TourStnInfoService1 관광 적합도 지수·등급
11일 이상 없음 예보가 존재하지 않는 구간(#133 평년값으로)

⚠️ VilageFcstInfoService (구버전)는 폐기됐다. NO_OPENAPI_SERVICE_ERROR(해당 오픈API 서비스가 없거나 폐기됨)가 온다. _2.0 을 써야 한다. 스키마·파라미터는 같아 base 만 다르다. 날씨는 부가 정보라 실패해도 코스가 200 으로 나가는 탓에 경로가 죽은 줄 모르고 지냈다(#128) — E2E 로 접점을 고정했다.

단기예보 VilageFcstInfoService_2.0/getVilageFcst

  • 입력: 격자 nx/ny(위경도 변환 필요) · base_date/base_time(발표 02·05·08·11·14·17·20·23시)
  • 실측: 907건 · 121KB · 1.15초. 예보는 오늘D+4 가 오되 **최저기온(TMN)까지 완전한 날은 D+1D+3**

중기 육상예보 MidFcstInfoService/getMidLandFcst

  • 입력: regId(광역 10개 구역) · tmFc(발표 06·18시, yyyyMMddHHmm)
  • 응답이 한 행에 D+4~D+10 이 컬럼으로 들어온다(wf4Am···wf10). D+7 까지만 오전/오후가 나뉘고 D+8 부터는 하루 하나
  • 구역 코드 10종 전부 응답 확인: 11B00000(서울·인천·경기) 11D10000(강원영서) 11D20000(강원영동) 11C10000(충북) 11C20000(대전·세종·충남) 11F10000(전북) 11F20000(광주·전남) 11H10000(대구·경북) 11H20000(부산·울산·경남) 11G00000(제주)
  • ⚠️ 기온(getMidTa)은 다른 코드 체계다. 시군 단위 지점 코드를 쓰는데, 광역 구역 코드를 넣으면 오류가 아니라 resultCode 00taMin4=0 이 온다. 응답에 지점명이 없어 코드를 열거해 찾을 수도 없다(찾아도 어느 시군인지 모른다). 지점 코드 확보 전까지 중기 기온은 비워 둔다

관광기후지수 TourStnInfoService1/getCityTourClmIdx1

  • 입력: CURRENT_DATE(yyyyMMddHH) · HOUR(산출 범위, 24) · DAY
  • ⚠️ 포털이 base 를 TourStnInfoService11 로 표기하나 실제로는 TourStnInfoService1(1 이 하나). 11 은 404
  • ⚠️ DAY 는 며칠 뒤가 아니라 며칠치다. DAY=9 면 D+9 하루가 아니라 D+1~D+9 아홉 날이 한꺼번에 온다(totalCount 가 236 × DAY 로 증가). 오프셋으로 착각해 날짜마다 부르면 같은 데이터를 아홉 번 받는다
  • ⚠️ 상한을 넘겨도 오류가 없다. DAY=10·DAY=12 모두 D+9 값을 그대로 준다. 요청 날짜로 라벨을 붙이면 조용히 틀리므로 응답 tm 으로 검증한다
  • DAY=0(오늘)은 NO_DATA조회 가능 범위는 D+1~D+9
  • 실측: DAY=9 기준 2,124건(9일 × 236 시군구) · 347KB · 2.5초. WebClient maxInMemorySize(2MB) 안에 들어온다
  • ⚠️ cityAreaId 는 법정동코드가 아니다. 우리 region.legal_code 로 조인하면 89곳 중 51곳만 맞는다 — 강원은 42xxx(특별자치도 전환 전), 전북은 45xxx, 광주+전남은 비표준 12xxx 로 묶여 있다. 시군구명(시도+시군구)으로 맞추면 89/89
  • 응답 필드: tm · totalCityName · doName(축약 시도명 17종) · cityName · cityAreaId · kmaTci · TCI_GRADE

6-3. 미세먼지 (에어코리아) — 후보, 우리 키로 직접 호출

  • upstream: 에어코리아(한국환경공단) 대기오염정보. 측정소명(행정구역) 기반 조회.
  • 용도: 지역 카드에 대기질 뱃지. Nice-to-have.

6-4. (검토) 공연/전시·자연휴양림 — 추가 키/스크래핑 필요

  • KOPIS 공연예술통합전산망: 공연·전시(체험거리). 별도 KOPIS 키 발급 필요 → 우선순위 낮음.
  • 숲나들e(자연휴양림, foresttrip.go.kr): 7대 혜택 농촌체험/치유관광과 매핑되나 공식 API 없이 스크래핑 → 백엔드 안정성 낮아 보류.

참고: KTX/SRT 예매 — 채택 안 함

  • 시중에 도는 ktx/srt 연동은 비공식 라이브러리(korail2-ncard/SRTrain) + 개인 로그인 계정 + anti-bot 토큰 기반이라 공개 서비스 백엔드에 부적합. 열차는 §1-4 TAGO(KTX 포함)·§1-5 코레일 공식 API를 유지한다. (§4의 "SRT 공공API 없음" 재확인.)