ESS Data Reduction
ESS 기기용 데이터 축소
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기공항 체류전환 모니터 — 지방공항 외래객의 권역 체류·소비를 데이터랩 공개 데이터로 국적별·시군구별 산출 (2026 한국관광 데이터랩 활용 경진대회)
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
2026 한국관광 데이터랩 활용 경진대회 · 응모작 시제품(웹) 배포 → https://airport-stay-monitor.vercel.app 지방공항으로 들어온 외래객이 그 권역에 며칠 머물고 얼마를 쓰는지, 한국관광 데이터랩 공개 데이터로 매달 국적별·시군구별로 산출해 보여 주는 웹입니다. 청주·대구·김해 공항을 같은 산식으로 비교하고 제주는 기준선으로 둡니다. 청주공항 대만 입국자는 2026 상반기에 두 배(+105%) 늘었지만, 입국 1인당 충북 카드소비는 36,790원으로 제자리입니다. 김해공항 대만 입국자는 부산에서 440,089원을 씁니다. 공항 소재지 청원구는 방문이 가장 많은데 방문 1회당 소비는 1,975원으로 가장 적습니다. • 1차 사용자: 충북도·청주시 관광 담당, 청주공항 활성화 협의체, 충북문화재단(권역형 DMO), 심사위원 화면 — 첫 화면은 위성지도, 담당자가 매달 쓰는 네 탭README 전문 보기 ↗
2026 한국관광 데이터랩 활용 경진대회 · 응모작 시제품(웹) 배포 → https://airport-stay-monitor.vercel.app
지방공항으로 들어온 외래객이 그 권역에 며칠 머물고 얼마를 쓰는지, 한국관광 데이터랩 공개 데이터로 매달 국적별·시군구별로 산출해 보여 주는 웹입니다. 청주·대구·김해 공항을 같은 산식으로 비교하고 제주는 기준선으로 둡니다.
청주공항 대만 입국자는 2026 상반기에 두 배(+105%) 늘었지만, 입국 1인당 충북 카드소비는 36,790원으로 제자리입니다. 김해공항 대만 입국자는 부산에서 440,089원을 씁니다. 공항 소재지 청원구는 방문이 가장 많은데 방문 1회당 소비는 1,975원으로 가장 적습니다.
| 탭 | 주소 | 하는 일 |
|---|---|---|
| 지도 | #map | 전면 위성지도(V-World 위성 + 하이브리드 라벨). 공항 4곳 원(크기 = ② 체류 인·일, 채움 = ① 1인당 카드소비, 청주 노랑·제주 점선 참고값), 출발 안내판 패널, 월별 재생, 공항 반경 5·10km 숙박 공급. 「청주 권역 보기」 → 충북 14개 시군구 단계구분도(위성 위 투명도 0.55)·시군구 표·대만 타깃 콘텐츠 6곳. 「숙박·음식 건물」을 켜면 줌 14부터 숙박·음식·소매 업소가 든 건물 3,634동(청주 4구·충주·제천 시내·단양읍), 건물을 누르면 주용도·층수·사용승인연도·업소 목록·시군구 평균. 아래로 반기 핵심 지표·월별 추이·1인당 소비 변화 요인 |
| 효과 계산 | #effect | 대상 입국자·체류 증가일·상한 공항·사업비를 넣으면 추가 카드소비와 「추가 카드소비 ÷ 사업비(단순 배수)」, 예산 요구서용 산출 근거 |
| 보고 문안 | #report | 월간 동향 · 반기 분석 · 사업 효과 근거를 □○-※ 개조식으로 작성. 한글 파일(.hwpx) 저장, 복사, .txt 저장 |
| 자료·검증 | #data | 검증 6종, 데이터 점검 9항목, 산식, 출처, 한계, 연동 검정 전체 표 |
국적(대만·일본)은 어느 탭에서든 상단에서 바꿉니다. 문안과 요약 문장은 src/lib/report.ts·story.ts가 산출 JSON에서 만들므로 숫자가 화면 값과 어긋나지 않습니다. 예전 주소(#overview #sgg #summary #trend)는 #map으로, #method는 #data로 바뀝니다.
배경은 V-World 타일만(위성·하이브리드·midnight). 구글·네이버·카카오 타일 없음, 하단에 「국토교통부 브이월드」 출처
최대 줌 12(시군구 규모). 「숙박·음식 건물」을 켠 때만 17. 공항은 점 하나(소수 둘째 자리 좌표)이고 시설명·활주로 라벨·3D 없음. 청주·대구·김해는 공군과 활주로를 같이 쓰는 공항(military_shared)
공항 보호구역: 청주·대구·김해 중심 3km는 줌 13 이상이면 불투명 마스크(「공항 보호구역 · 확대 표시 안 함」)로 덮고, 그 안의 건물·업소 위치는 산출물에 넣지 않습니다(개수만, tests/test_buildings.py가 확인)
실행 중 외부 호출은 V-World 타일뿐(글꼴 파일 제외). 콘텐츠 지점 좌표·건물 윤곽은 빌드 때 한 번 V-World에서 받아 정적 파일로 고정(scripts/geocode_pins.py, scripts/build_buildings.py)
타일이 실패하면 위성 → 지도(midnight) → 배경 없음 순으로 물러나며 안내
기능명세: 공항_체류전환_모니터_기능명세서.xlsx v1.0 (기능ID·UI_id·규칙ID를 코드 주석과 data-ui 속성에 그대로 씁니다)
pip install -r requirements.txt
npm install
npm run build:data # 원천 CSV → public/data/*.json + 검증 리포트
npm test # pytest(지표 기대값) + Vitest(화면)
[C1] 행수 PASS 입국 8,528행 적재 · 데이터랩 37,793행 · 간편결제 2,772행
[C2] 월 연속성 PASS 빠진 달 없음 · 입국 202301~202607 · 데이터랩 202301~202608
[C4] 시도-시군구 정합성 PASS 대조 2건 중 불일치 0건 · 생략 3건(시군구 자료 없음)
[C7] 경계 코드 대응 PASS 충북 14개 시군구 전부 조인(SGIS → 행정표준)
[V1] 분모 재현 PASS 입국관광통계 합 30,030 / 62,891명, 공사 발표 30,117 / 62,971명(청주, 반기). 오차 0.3% 이내
[V3] 시도-시군구 정합성 PASS … 보정(충북 2026 상반기 59.4억 → 191.1억 원)
[V4] 결제수단·거주자 PASS 간편결제를 더해도 충북 대만 소비 +0.55%(간편결제 단위 천원 추정)
산식 로직은 표준 라이브러리만 씁니다(경계 좌표 변환에만 pyproj·pyshp). 참고 구현 reference/compute_indicators.py와 같은 값이 나오는지 tests/test_indicators.py가 고정합니다.
| 기대값(기능명세 ⑨) | 값 | 테스트 |
|---|---|---|
| 청주 대만 2026H1 ① · ② | 36,790원 · 2.55 | test_ind01_02_half |
| 청주 대만 2025H1 ① · ② | 36,316원 · 3.06 | 〃 |
| 청주 일본 2026H1 ① | 113,144원 | 〃 |
| 김해 / 대구 / 제주 대만 ① · ② | 440,089·5.43 / 129,664·4.71 / 377,357·5.80 | 〃 |
| V2 청주 대만 수준·차분(인천) | 0.75(0.40) · 0.83(0.49) 채택 | test_ind03_v2 |
| V2 제주 대만 차분(인천) | 0.30(0.41) 제외 | 〃 |
| Kitagawa 청주 | 74,702 → 66,903원(−7,798, −10.4%), 구성 +2,348, 대만 +294, 일본 −10,440 (표시값 반올림, 구성+국적별 = 합계) | test_ind04_kitagawa |
| 충북 카드 보정 2026H1 | 59.4억 → 191.1억 원, 대만 1,019,084,278원 | test_dat03_card_correction |
| 청주 전체 입국 | 2025H1 30,030 · 2026H1 62,891 | test_dat01_arrivals_total_excludes_subtotals |
| 청원구 대만 | 월평균 방문 8,388 · 방문 1회당 1,975원 | test_ind05_sgg |
| 체류 +0.5일(김해 비교) | +2.0억 ~ +11.2억 원(14,427원 ~ 81,048원) | test_ind06_scenario |
데이터를 갱신하면 숫자가 달라지므로 tests/expected.json만 교체합니다(OPS-04).
npm run dev # http://localhost:5173
npm run build # 검증 리포트 관문 → 타입 검사 → vite build (dist/)
npm run preview
.env.local에 국토교통부 브이월드 인증키(이 서비스 전용 개발키, 서비스 URL airport-stay-monitor.vercel.app, 2027-03-29 만료 — 만료 전 브이월드 마이포털에서 연장)를 넣으면 지도 배경에 「지도」(WMTS white, 어두운 화면에서는 midnight)와 「위성」(Satellite)을 쓸 수 있습니다. Vercel에서는 프로젝트 환경변수 VITE_VWORLD_KEY로 넣고, 브이월드에 배포 도메인을 서비스 URL로 등록합니다.
VITE_VWORLD_KEY=발급받은-키
data/raw/에 교체합니다(자동 수집 코드 금지, BR-C1). 파일명이 바뀌면 data/config/sources.json을 고칩니다.data/config/sources.json의 datalab_extract(화면 표기)와 card_extracted_on(카드 추출일)을 고칩니다. 추출일이 2026-08-11 재소급 이전이면 경고가 뜹니다(BR-D3).npm run build:data # 산출 + 검증 리포트 출력(FAIL이면 종료 코드 1)
git commit -am "데이터 2026.MM 갱신" && git push # CI 통과 후 Vercel 배포
data/config/settings.json의 halves·sgg.period를 바꾸고 tests/expected.json을 새 기대값으로 교체합니다.npm run build가 먼저 scripts/check_report.mjs를 돌려, 산출 JSON이 없거나 리포트에 FAIL이 있으면 빌드(=배포)를 멈춥니다. 시도-시군구 불일치 같은 경고는 빌드를 멈추지 않고 화면에 배지로 보입니다(DAT-06, ST-09)..github/workflows/ci.yml)는 원천에서 다시 산출해 커밋된 JSON과 같은지(npm run check:data), 테스트, 빌드를 확인합니다.사각119(scripts/fetch_buildings.py)와 같은 방식으로, 빌드 때 브이월드 WFS(lt_c_bldginfo, 국토교통부 GIS건물통합정보)에서 건물 윤곽·주용도·층수·사용승인일을 받아 소상공인시장진흥공단 상가(상권)정보와 잇습니다. 실행 중에는 public/data/buildings/*.json만 읽습니다.
소상공인시장진흥공단_상가(상권)정보_20260630.zip에서 충북 CSV를 data/external/상가정보_충북_202606.csv로 풉니다(52MB, 커밋하지 않음 — .gitignore).python scripts/build_buildings.py — .env.local의 VITE_VWORLD_KEY로 업소가 모인 약 1km 칸 384개를 묻고(요청 약 700건, 1,000건이 차면 4등분), 응답은 data/external/wfs_cache/에 남깁니다. 다시 만들 때는 --offline(캐시만).public/data/buildings/{시군구코드}.json(좌표 소수 5자리) + index.json(수집일·출처·보호구역 안 업소 수·잇기 통계).| 항목 | 규칙(data/config/buildings.json) |
|---|---|
| 범위 | 청주 4구 전체 · 충주·제천 동 지역 · 단양읍. 청주공항 3km 제외 |
| 업소 | 상권업종대분류 숙박·음식·소매 37,562곳(보호구역 108곳은 개수만) |
| 잇기 | 업소 좌표가 든 건물 31,762 → 같은 지번(50m 안) 1,441 → 15m 안 가장 가까운 건물 1,154 · 못 이음 3,205(8.5%, 대부분 업소가 드문 칸) |
| 남기는 건물 | 주용도 숙박시설(건축물대장 코드 15000) 또는 업소 3곳 이상 → 3,634동 |
| 색 | 숙박시설 노랑 · 근린생활·판매시설 청록 · 그 밖 회색 테두리 |
건물 패널의 외국인 값(월평균 방문·방문 1회당 카드소비)은 소속 시군구 값을 그대로 가져와 「시군구 평균」으로 표시합니다. 건물별 외국인 소비·방문 값은 없어서 만들지 않습니다.
data/raw/ 원천 CSV·경계(사용자가 교체). 받은 바이트 그대로 보관
data/config/ airports.json(공항-권역 쌍) · region_map.json(지역·국가명·코드 대응) · gu_cities.json(구 설치 시 보정)
settings.json(임계값·비교 반기) · sources.json(파일·추출일) · reference_values.json(공사 발표·원자료 결과값)
data/external/ 상가정보 CSV · 브이월드 WFS 캐시(커밋하지 않음)
scripts/ indicators.py(산식, 표준 라이브러리) · build_data.py(적재·경계 변환·리포트·JSON) · check_report.mjs(배포 관문)
build_buildings.py(건물 레이어) · geocode_pins.py(콘텐츠 지점 좌표)
tests/ test_indicators.py · test_buildings.py · expected.json(기대값)
public/data/ indicators.json · sgg.json · boundary_43.geojson(WGS84) · meta.json(기준 시점·검증 리포트) · buildings/(구역별 건물)
src/ React 화면(Vite + TypeScript, 지도 react-leaflet, 차트 SVG 직접 구현)
reference/ 시제품 airport_monitor.html · compute_indicators.py(정답 구현) · 재현 안내
공항을 늘리려면 airports.json에 한 줄을 넣고 npm run build:data 하면 카드·차트에 자동으로 붙습니다(UI-12). 해당 권역 데이터랩 자료가 없으면 「자료 없음」, V2 검정을 통과하기 전에는 「참고값」으로만 보입니다.
| 기능ID | 구현 |
|---|---|
| DAT-01~04 | scripts/indicators.py load_arrivals · load_datalab · corrected_card · corrected_industry · easypay_effect |
| DAT-05 | scripts/build_data.py build_boundary (EPSG:5179 → 4326, 단순화, SGIS → 행정표준 코드, 대응 실패 시 빌드 실패) |
| DAT-06 | build_report → meta.json report (C1 |
| IND-01~06 | half_values · v2_test · kitagawa · sgg_from_raw · per_person_day/scenario |
| UI-01~11 | src/components/* — 화면 요소마다 data-ui="CRD-01" 식으로 UI_id를 붙였습니다(CRD-01 출발 안내판, TBL-02 요인분해 막대, CRD-02·SLD-01 표지판, PNL-01·02 근거와 검증) |
| UI-12 | data/config/airports.json + test_ui12_extra_airport_without_region_data |
| ST-01~10 | 스켈레톤 · 새로고침 안내 · 자료 없음 카드 · 참고값 칩 · 소표본 툴팁 · 경계 실패 안내 · 배경 실패 토스트 · 불일치 배지 · 기준일 확인 필요 |
| OPS-01~04 | 위 갱신 절차 · vercel.json · 접근성(Lighthouse 접근성 100, 400px 가로 스크롤 0) · pytest/Vitest |
「보고 문안」과 「효과 계산」 탭의 한글 파일(.hwpx) 버튼은 브라우저에서 바로 한글 문서를 만듭니다(서버를 거치지 않음).
public/templates/report.hwpx — python scripts/make_hwpx_template.py(python-hwpx)로 만든 유효한 HWPX 골격. 제목 16pt 굵게, □ 소제목, ○·- 내어쓰기 본문, 머리글 음영·반복 표, ※ 주석src/lib/hwpx.ts가 Contents/section0.xml의 {{토큰}} 문단과 표 행을 줄 수만큼 복제해 넣고, mimetype을 맨 앞·비압축으로 다시 묶는다src/lib/report.ts의 ReportDoc)에서 나온다. 표는 셀 병합 없이 첫 행이 머리글이고 숫자 칸에는 단위가 없다(단위는 머리글에)src/lib/hwpx.test.ts, tests/test_hwpx_template.py%d)이면 구성 + 국적별 효과의 합이 −7,799원이 되어 합계 −7,798원과 어긋나기 때문입니다.충북_시군구_외국인_2026H1.csv(데이터랩 화면 시군구 값 정리표) 값을 씁니다. 원천 행이 있는 7곳은 정리표와 14/14 일치를 리포트에서 확인합니다.AL_D010_43)를 적었지만, 같은 GIS건물통합정보를 사각119처럼 브이월드 WFS로 빌드 때 받았습니다. WFS에 건물관리번호가 비어 있어 업소와는 좌표로 잇습니다(위 표)data/config/tw_pins.json의 verified_on에 날짜를 적어야 화면의 「좌표 확인 전」이 사라집니다main에 푸시하면 자동 배포.제작: 최현규(충북대학교 소프트웨어학부)