upload 기능 구현 전에 일단 커밋

This commit is contained in:
2026-08-20 16:00:15 +09:00
commit 2ed3c72b77
24 changed files with 4959 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
const VWORLD_ENDPOINT = 'https://api.vworld.kr/req/data';
function credentials() {
return {
key: process.env.VWORLD_API_KEY || process.env.VITE_VWORLD_API_KEY || '',
domain: process.env.VWORLD_DOMAIN || 'localhost',
};
}
async function fetchVworldFeatures(data, attrFilter) {
const { key, domain } = credentials();
if (!key) throw new Error('VWORLD_API_KEY 환경변수가 설정되지 않았습니다.');
const size = 1000;
const base = new URLSearchParams({
service: 'data',
request: 'GetFeature',
data,
format: 'json',
geometry: 'false',
size: String(size),
key,
});
if (attrFilter) base.set('attrFilter', attrFilter);
base.set('domain', domain);
const features = [];
let page = 1;
let total = Infinity;
while (features.length < total && page <= 20) {
const params = new URLSearchParams(base);
params.set('page', String(page));
const res = await fetch(`${VWORLD_ENDPOINT}?${params}`);
if (!res.ok) throw new Error(`VWorld 요청 실패 (HTTP ${res.status})`);
const json = await res.json();
const response = json.response;
if (response?.status !== 'OK') {
throw new Error(`VWorld 조회 실패: ${JSON.stringify(response ?? json)}`);
}
const result = response.result?.featureCollection?.features ?? [];
features.push(...result);
total = Number(response.record?.total ?? 0) || total;
if (result.length === 0) break;
page += 1;
}
return features;
}
export async function fetchGus() {
const features = await fetchVworldFeatures('LT_C_ADSIGG_INFO', 'full_nm:like:서울');
return features.map((f) => ({
code: f.properties.sig_cd,
name: f.properties.sig_kor_nm,
}));
}
export async function fetchDongs(guCode) {
const features = await fetchVworldFeatures('LT_C_ADEMD_INFO', `emd_cd:like:${guCode}`);
return features.map((f) => f.properties.emd_kor_nm).filter(Boolean);
}