尚未检测到更新。GitHub 发布版本后会显示在这里。
制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗세계사 수업에서 보여줄 수 있는 한글 세계 지도와 두 장소 사이의 직선거리 측정 웹앱입니다. 지도는 MapLibre GL JS + OpenFreeMap, 장소 검색은 기본 Photon을 사용합니다. Nominatim은 설정으로 선택할 수 있습니다. Redis, API 키, 환경변수 없이 Vercel에 배포할 수 있습니다.
name:ko 또는 name_ko를 우선 표시합니다. 한글 이름이 없는 장소는 원래 지명으로 표시합니다. 자동 번역이 아니며 모든 지명의 한글 표기를 보장하지 않습니다.현재 탭은 현재 국가·도시 지도를, 세기 탭은 역사 자료의 해당 대표 연도 영역을 표시합니다.현재, BCE 5c ~ BCE 1c, 1c ~ 21c 탭을 제공합니다. 26개의 실제 역사 국경·문화권 자료를 data/history/에 포함했으며 선택한 세기의 파일만 불러옵니다. 대표 연도를 세기 전체로 보간하거나 인접한 세기의 자료로 대체하지 않습니다.
| 탭 | 세기의 범위 | 지도에 표시하는 연도 |
|---|---|---|
| BCE 5c | 기원전 500–401년 | 기원전 500년 |
| BCE 3c | 기원전 300–201년 | 기원전 300년 |
| BCE 1c | 기원전 100–1년 | 기원전 100년 |
| 1c | 서기 1–100년 | 서기 100년 |
| 20c | 서기 1901–2000년 | 서기 2000년 |
| 21c | 서기 2001–2100년 | 서기 2010년 |
기원전 세기는 시작 연도, 서기 1~20세기는 끝 연도의 실제 제공 자료를 사용합니다. 21세기는 자료가 있는 2010년을 표시하며 현재와 다릅니다. 연도 0은 사용하지 않습니다. 지도 위에 세기 범위와 표시 연도를 항상 명시합니다. 현재 탭에 돌아오면 현재 국가명과 도로 등이 복원됩니다.
역사 모드에서는 현재 국경·국가명·도시명·도로·건물을 숨기고 당시 정치체·문화권의 영역을 표시합니다. 주요 역사명은 별도 한글 사전으로 표시하고, 사전에 없는 이름은 원명을 유지합니다. 영역을 누르면 원래 이름, 자료에 기록된 지배 관계, 대표 연도가 나옵니다. 지명 숨기기·글자 크기 조절·지역 바로가기·수업 화면을 함께 사용할 수 있습니다. 장소 검색과 거리 계산은 계속 현재 지명과 좌표를 사용하며 역사상의 도시 존재 여부를 판단하지 않습니다.
출처는 Historical Basemaps · A. Ourednik 및 기여자이며, 원본 GeoJSON은 수정하지 않고 GPL-3.0 라이선스·출처와 함께 별도로 포함했습니다. 사용한 소스 커밋과 파일별 실제 연도는 data/history/manifest.json, 원자료 설명은 UPSTREAM-README.md, 배포 고지는 NOTICE.md, 라이선스는 LICENSE.txt에 있습니다. 이 자료의 라이선스 고지를 삭제하지 마세요.
수업용 개략적 복원 자료입니다. 시대별 자료의 정밀도·표기·누락이 다르며 정치체와 문화권의 구분도 균일하지 않습니다. 현재의 강·호수·해안선을 참고 바탕으로 사용하며 고대 지형을 복원하지 않습니다. 흰색 또는 이름 없는 영역이 무인 지대나 국가 부재를 뜻하지 않습니다. 정확한 사건·국경·명칭 설명은 다른 역사 자료와 대조해야 합니다.
파일 요청에 실패하면 기존 연도와 지도를 유지하고 다시 불러오기 버튼을 제공합니다. 현재 탭으로 돌아가거나 다른 세기를 선택하면 이전 요청은 취소되므로 늦은 응답이 선택한 시대를 바꾸지 않습니다. 역사 파일 약 31MB가 저장소에 포함되지만 페이지를 처음 열 때 모두 내려받지는 않습니다. 서버·API 키·환경변수 추가는 필요하지 않습니다. 인터넷 없이 실행되는 완전한 오프라인 지도는 아닙니다.
OpenStreetMap 기본 래스터 지도는 지도 이미지에 지명이 들어가 있어 한국어로 바꾸기 어렵습니다. 반면 벡터 지도는 브라우저에서 표시 언어를 선택할 수 있습니다. OpenFreeMap 공식 사용 안내의 MapLibre 통합과 공식 프로젝트의 지명 현지화 안내를 확인해 OpenFreeMap Positron 스타일을 한글 우선 표현식으로 조정했습니다. 별도 가입·API 키 없이 사용할 수 있어 기존 배포 조건에 맞습니다. OpenFreeMap의 이용약관을 준수하고 지도 출처 표시를 유지합니다.
지도 타일·스타일·글리프·스프라이트는 외부 지도 제공 서버에서 불러오므로 인터넷 연결이 필요합니다. 오프라인 세계 지도는 제공하지 않습니다. 지도 로딩 실패 시 다시 불러오기 버튼을 표시하며 장소 검색/거리 계산 화면은 독립적으로 사용할 수 있습니다. 지도 엔진 JS/CSS는 vendor/에 포함해 라이브러리 CDN 장애 의존성을 줄였습니다.
vercel.json에 빌드·설치 생략과 Output Directory .가 설정되어 있어 별도 빌드 설정은 필요하지 않습니다.화면은 HTML/CSS/JavaScript이며 검색에는 api/search.mjs Vercel Node.js 함수를 사용합니다. 패키지 설치, Redis, API 키, 환경변수가 필요하지 않습니다. Vercel이 API 함수를 자동 배포합니다. Sites 호스팅이나 GitHub 등록은 자동으로 수행하지 않았습니다.
장소 입력을 수정하면 기존 선택과 거리 결과가 초기화됩니다. ⇅ 버튼으로 출발지와 도착지를 바꿀 수 있습니다. 검색 결과는 최대 5개이며, 등록되지 않은 장소는 조회되지 않을 수 있습니다. 자동완성은 제공하지 않습니다.
기존 공개 Nominatim 서버에서 지속적으로 429가 발생하는 환경을 확인해, 기본 제공자를 Photon으로 변경했습니다. Photon도 OpenStreetMap 데이터를 사용하고 API 키가 필요하지 않습니다. 한국어 검색어를 UTF-8로 전달하며 GeoJSON의 [경도, 위도]를 앱의 좌표 형식으로 변환합니다. 실제 서울역 → 부산역, 삼각산중학교 → 남산타워 검색과 거리 표시를 확인했습니다. Photon 검색은 비슷한 이름의 후보도 반환하므로 주소를 확인하고 선택하세요.
Photon 공개 서버는 합리적인 요청량의 프로젝트 사용을 허용하지만 과도한 요청을 제한할 수 있고 가용성을 보장하지 않습니다. 기본값은 Photon에만 요청하며 Nominatim 제한 시 자동으로 제공자를 바꾸거나 재시도하지 않습니다. 검색어는 선택한 제공자에게 전송되므로 개인정보나 기밀정보를 입력하지 마세요.
config.json 설정:
{
"searchUrl": "/api/search",
"provider": "photon",
"photonUrl": "https://photon.komoot.io/api/",
"upstreamUrl": "https://nominatim.openstreetmap.org/search"
}
Nominatim을 사용하려면 provider를 nominatim으로 설정하고 아래 정책을 준수해야 합니다. upstreamUrl은 Nominatim jsonv2를 제공하는 서버 주소입니다. 브라우저가 제공 서버로 직접 요청하지 않으므로 제공 서버의 CORS 허용은 필요하지 않습니다.
Nominatim 이용정책을 읽고 준수해야 합니다. 공개 서버는 소규모 사용을 위한 서비스이며, 앱 전체의 모든 사용자 합계가 초당 1회 이하여야 합니다. 자동완성, 대량 수집, 주기적 자동 조회는 금지됩니다. 서버는 앱 식별 User-Agent를 전송하며 화면에 OpenStreetMap 저작자 표시와 이용정책 링크를 제공합니다. 검색어는 공개 서버로 전송되므로 개인정보나 기밀정보를 입력하지 마세요.
이 앱은 수동 검색만 수행하고, 동일 검색을 브라우저에 7일간 최대 80개 캐시합니다. 해당 브라우저의 요청 간격을 최소 1.1초로 제한하고, Web Locks를 지원하는 브라우저에서는 같은 사이트의 탭 사이에도 요청을 직렬화합니다.
서버 함수도 인스턴스 내 요청을 1.1초 간격으로 직렬화하고 7일간 최대 80개 결과를 캐시합니다. 선택한 제공자가 429를 반환하면 최소 60초와 제공 서버의 Retry-After 중 더 긴 기간 동안 추가 외부 요청을 차단합니다. 이 시간은 재시도까지의 최소 대기 시간이며, 그 후의 검색 성공을 보장하지 않습니다. 클라이언트에도 이 사실을 표시하며 자동 재시도하거나 다른 호스트로 우회하지 않습니다. CORS 헤더가 없는 오류 응답도 같은 출처 API를 통해 실제 오류로 전달됩니다.
중요한 운영 한계: Vercel 함수의 메모리는 인스턴스끼리 공유되지 않으므로 이 구현만으로 앱 전체 초당 1회 제한을 보장하지 않습니다. Redis나 환경변수 없이 실행되지만 다수 사용자의 동시 검색을 보장하는 구성은 아닙니다. 이용량이 증가하기 전에 정책에 맞는 별도 Nominatim 제공 서버 또는 전역 제한이 있는 프록시로 전환해야 합니다. 공개 서버가 요청을 제한하는 동안은 실제 검색이 불가능할 수 있으며, 앱 수정만으로 제공 서버의 제한을 해제할 수 없습니다.
설정을 변경한 뒤 로컬 서버를 재시작하거나 Vercel에 재배포하고 페이지를 새로고침하세요. 제공자별 서버 캐시·요청 제한 상태는 구분해 관리합니다.
以上为 README 的开头部分。其余内容请阅读原文。 查看完整 README ↗