- 조사일: 2026-07-18
- 목적: OffWay가 끌어올 모든 외부 데이터의 발급처·인증·엔드포인트·가용 데이터를 한곳에. 이 문서가 곧 (1) 회원가입/키 발급 체크리스트, (2) 우리가 조합할 데이터 전체 목록.
- 전략: 미리 전부 확보·적재(라이브 API + 정적 시딩) 해두고 조합해 서비스를 제공한다.
⚠️ 신뢰도 표기: 아래 상당수는 조사 기반이며 일부 오퍼레이션명·파라미터 철자는 활용신청 후 각 상세페이지의 활용가이드/Swagger로 최종 확정 필요. "추정" 표시된 항목 주의.
| # | 포털 | 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으로 두 키 다 보관하고, 한쪽 실패 시 반대로 시도.
- 발급: 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 산출 · 샌드위치 연휴 탐지의 기반.
- 발급: 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 용도: 인구감소지역 관광지·숙박·음식점 표출, 운영시간/휴무 기반 일정 생성.
- 발급: data.go.kr 데이터셋 15101972
한국관광공사_관광빅데이터 정보서비스_GW→ 활용신청 (15101578과 별개 신청) - Base:
https://apis.data.go.kr/B551011/DataLabService✅ 확인 - 오퍼레이션:
metcoRegnVisitrDDList(광역별 일별 방문자수) ·locgoRegnVisitrDDList(기초 시군구별 — OffWay 89에 사용). 둘 다 실호출 성공(resultCode0000). - 파라미터:
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).은 폐기했다. 지명은 전국에서 겹친다 — 동구 6곳·중구 6곳·서구 5곳·남구 4곳·북구 4곳·고성군 2곳(2026-06 실호출, 268개 시군구 기준). 우리 89곳 중 부산 동구·부산 서구·대구 남구·대구 서구·강원 고성군(51820)·경남 고성군(48820) 6곳이 걸려, 서로 다른 지역의 방문자가 한 버킷에 합산됐다(부산 동구 = 전국 동구 6곳의 합).signguNm(지명)으로 매칭region.legal_code의 정본은 이 응답의signguCode자체다. 매칭 상대에서 그대로 따와야 89곳 전부 매칭이 보장된다.
- 함정 ②(발행 주기): 완결된 달만 월 단위로 발행된다. "N일 지연"이 아니다 — 2026-07-30 기준 6월(24,120건)까지 있고 7월은 0건. 고정 일수 지연을 가정하면 관측 창이 미발행 구간에 걸려 조회가
resultCode=0000+ 빈 결과로 조용히 성공하고, 전 지역 방문자가 0이 돼 랭킹이 무의미해진다(경고 로그도 안 남음). → 지난달부터 시작해 비면 이전 달로 물러선다. - 함정 ③(응답 크기): 지역 필터가 없어 기간 전체가 내려온다. 268 시군구 × 3 구분 × 일수 → 7일 약 1MB / 한 달 약 4MB. 운영
externalWebClient의maxInMemorySize가 2MB 라 한 달치는 버퍼를 넘긴다. 관측 창을 발행된 달의 마지막 한 주로 잡는 이유. - 함정 ④: "방문자≠관광객" → 랭킹엔 외지인+외국인만.
- OffWay 용도: "평일에 한산한 시점" 한산도 뱃지·지역 랭킹 — 차별화 핵심 데이터.
- 미확인(후속): 관광지별 집중률·향후 방문자 예측은 별도 오퍼레이션(#21+ 필요 시 확인).
-
발급: 관광빅데이터와 같은 계정(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=30→ 9.5KB ·numOfRows=100→ 31KBtotalCount 지자체당 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=0000에totalCount=0이 온다(실측). 성공 코드라 조용히 빈 결과가 되므로 특히 위험하다. -
함정 ②(
pageNo필수): 빠뜨리면resultCode=11NO_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 에는 등록조차 없어 기존 구조로는 찾을 수 없던 곳이다.
-
발급: 관광빅데이터와 같은 계정(15101972). 별도 신청 없이
serviceKey를 그대로 쓴다. -
Base:
https://apis.data.go.kr/B551011/PhotoGalleryService1✅ 확인 -
오퍼레이션:
galleryList1— 전량 목록. 실호출 성공(resultCode=0000).은 호출이 실패했다. 전량을 DB 로 내리면 키워드 검색이 필요 없어 더 파지 않았다.galleryKeywordList1
-
파라미터:
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 로 내려보낸다.
- 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(
GetCtyCodeList→GetCtyAcctoTrainSttnList등)으로 선조회. 예: 서울NAT010000· 부산NAT014445. - OffWay 용도: 반차·퇴근후 모드 도착시각, 교통수단별 동선.
BusSttnInfoInqireService/getCtyCodeList 실호출 결과 138개 지자체만 담는다. 서울조차 없다(별도 TOPIS). 미커버 지역은 오류가 아니라 resultCode=00 + 빈 결과로 오므로, 그대로 두면 "주변에 정류소 없음"과 구분되지 않는다.
도시코드 앞 두 자리가 시도다(32010 춘천 → 32 강원). 이 구분이 있어야 동명 시군구를 갈라낸다 — 고성군은 강원(미커버)·경남(커버) 양쪽에 있어 지명만 맞추면 강원 고성군까지 커버로 오판한다. 광역시는 구 단위 없이 시 전체가 한 코드(21 부산)이고, 버스권역이 묶인 곳은 "원주시/횡성군" 합본으로 온다.
우리 89곳 중 미커버 13곳 (89 × 138 대조):
| 시도 | 미커버 시군구 |
|---|---|
| 강원특별자치도 | 고성군 · 삼척시 · 양구군 · 영월군 · 정선군 · 평창군 · 화천군 |
| 충청남도 | 예산군 |
| 전라남도 | 강진군 · 담양군 · 보성군 · 영광군 · 화순군 |
하필 이 서비스가 겨냥하는 강원 산간·전남 오지다. 공공데이터 폴백 없음 — 전국 버스정류장 위치정보(15067528)도 "TAGO 연계 지자체" 스냅샷이라 같은 모집단이다. 상용 API(ODsay·카카오, 유료)만 남는다. 실시간 도착은 지자체 BIS 구축이 전제라 구조적으로 불가.
→ 메울 수 없으므로 구분해서 드러낸다: BusStopAccess.NotCovered("데이터 없음") ≠ NoStopNearby("정류소 없음"). 판별은 BusAccessService 가 도시목록(24h 캐시)으로 한다. 목록을 못 얻으면 판별 불가라 Unavailable 로 폴백한다 — 커버 여부를 모르는 채 "버스 없음"이라 안내하면 틀린 말이 될 수 있어서다.
- 발급: data.go.kr 15125762
한국철도공사_열차운행정보→ 활용신청 - 제공: 여객열차 운행계획/운행정보(실시간·지연). 출발역/도착역/운행일자 기반.
- 함정: 요금·예매·좌석 미제공(운행 트래킹용). 시간표는 1-4 TAGO 열차정보가 더 적합.
- OffWay 용도: KTX 지연/실제운행 보조 (선택).
- 발급: 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-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 현행화 중지.
| 기능 | 필요한 데이터 조합 |
|---|---|
| LNT 가용시간·샌드위치 연휴 | 특일정보 |
| 인구감소지역 여행지 추천 | 인구감소지역89(seed) + TourAPI + 관광빅데이터(집중률→한산시점) + 생활인구(가중치) |
| 정책 혜택 매칭·뱃지 | 7대혜택(seed) + 인구감소지역 + 로컬100/관광두레(seed) |
| 교통·도착시각 (반차/퇴근후) | TAGO 버스/열차 + 코레일 + TMAP(자가용) |
| 일정 자동 생성 | TourAPI(운영시간/휴무) + TMAP(경유지 최적화) + 위 조합 |
| 연차 컨설팅 | 특일정보 (+ 위 전체) |
- SRT 공공API 없음 → SRT 시간표는 제외하거나 별도 처리. KTX는 TAGO로.
- 시외버스 미래날짜 조회 불가(당일만) → 미래 일정은 "예상 소요시간"으로 근사, 실시간은 당일에.
- TMAP 24h 저장 제한 → 경로 결과는 단기 캐시(≤24h)만. 영구 저장 금지.
- 개발계정 한도(TourAPI/빅데이터 1,000/일, TMAP 최적화 50/일) → 대량 사전적재는 배치·페이징·운영계정 전환 고려.
- 지역코드 불일치(TourAPI sigunguCode ↔ 빅데이터 코드 ↔ 인구감소지역 지명) → 지명 기준 매핑 테이블을 먼저 구축(마스터 데이터).
- Encoding/Decoding 서비스키 두 개 다 보관.
- 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대 혜택 정보 수동 정리(정책명·운영기간·대상지·할인율)
2026-07-21 조사. TourAPI만으론 볼거리가 부족한 소도시(영양 10개급) 보강용 추가 소스. 아래는 후보이며 아직 클라이언트 미구현. 이미 우리가 쓰는 소스(특일정보·TourAPI·관광빅데이터·TAGO·코레일·TMAP)는 그대로 유지한다. 관련 이슈 #44.
- 인증: 없음 (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(시도코드)
- params:
- 상세:
https://www.khs.go.kr/cha/SearchKindOpenapiDt.do— paramsccbaKdcd+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 확장 전 자체 볼거리 확대 · 지역 상세에 문화재·이달의 행사.
여행까지 남은 일수에 따라 담당이 갈린다. 실호출 확인(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 00에taMin4=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초.WebClientmaxInMemorySize(2MB) 안에 들어온다 ⚠️ cityAreaId는 법정동코드가 아니다. 우리region.legal_code로 조인하면 89곳 중 51곳만 맞는다 — 강원은42xxx(특별자치도 전환 전), 전북은45xxx, 광주+전남은 비표준12xxx로 묶여 있다. 시군구명(시도+시군구)으로 맞추면 89/89- 응답 필드:
tm·totalCityName·doName(축약 시도명 17종) ·cityName·cityAreaId·kmaTci·TCI_GRADE
- upstream: 에어코리아(한국환경공단) 대기오염정보. 측정소명(행정구역) 기반 조회.
- 용도: 지역 카드에 대기질 뱃지. Nice-to-have.
- KOPIS 공연예술통합전산망: 공연·전시(체험거리). 별도 KOPIS 키 발급 필요 → 우선순위 낮음.
- 숲나들e(자연휴양림, foresttrip.go.kr): 7대 혜택 농촌체험/치유관광과 매핑되나 공식 API 없이 스크래핑 → 백엔드 안정성 낮아 보류.
- 시중에 도는 ktx/srt 연동은 비공식 라이브러리(
korail2-ncard/SRTrain) + 개인 로그인 계정 + anti-bot 토큰 기반이라 공개 서비스 백엔드에 부적합. 열차는 §1-4 TAGO(KTX 포함)·§1-5 코레일 공식 API를 유지한다. (§4의 "SRT 공공API 없음" 재확인.)