mirror of
https://github.com/NomaDamas/k-skill.git
synced 2026-06-24 02:04:11 +00:00
The public-restroom lookup now keeps the official CSV as the authoritative first layer while enriching sparse areas with Kakao Local keyword and gas-station searches when a REST API key is configured. All returned POIs are normalized onto local haversine distance calculations so Kakao's unreliable distance field cannot affect ordering, and map links encode names before coordinates.\n\nThe CSV path can optionally use Kakao coord2address to correct display names and addresses for known source-data coordinate mismatches without changing the default no-key behavior.\n\nConstraint: Kakao REST API requires caller-provided REST API key via option or KAKAO_REST_API_KEY\nConstraint: Existing no-key CSV-only behavior must continue to work\nRejected: Replace CSV with Kakao-only search | loses official open-time metadata and source priority\nRejected: Trust Kakao distance field | issue evidence shows user-origin mismatch\nConfidence: high\nScope-risk: moderate\nDirective: Keep CSV sourceLayer priority ahead of Kakao dedupe unless official data is explicitly deprecated\nTested: npm test --workspace public-restroom-nearby\nTested: npm run lint --workspace public-restroom-nearby\nTested: npm run ci\nNot-tested: Live Kakao REST API call with a production key
6.6 KiB
6.6 KiB
근처 공중화장실 찾기 가이드
이 기능으로 할 수 있는 일
- 현재 위치 기준 근처 공중화장실 / 개방화장실 검색
- 동네/역명/랜드마크를 Kakao Map anchor 로 변환한 뒤 nearby 계산
- 공식
공중화장실정보표준데이터 기반 거리순 요약 - Kakao REST API 키가 있으면
공중화장실/개방화장실키워드와OL7주유소 레이어를 추가 병합 - 개방시간, 주소, 지도 링크까지 함께 정리
가장 먼저 할 일
이 기능은 반드시 현재 위치를 먼저 물어본 뒤 실행합니다.
권장 질문 예시:
현재 위치를 알려주세요. 동네/역명/랜드마크/위도·경도 중 편한 형식으로 보내주시면 근처 공중화장실을 찾아볼게요.
입력값
- 동네/상권:
광화문,성수동,해운대 - 역명/랜드마크:
서울역,강남역,코엑스 - 좌표:
37.57103, 126.97679
위치 문자열은 Kakao Map anchor 검색으로 WGS84 좌표를 잡고, anchor 주소에서 추론한 시도 코드가 있으면 해당 지역 CSV만 내려받습니다.
공식 표면
- 공공데이터포털 공중화장실 표준데이터 안내:
https://www.data.go.kr/data/15012892/standard.do - 파일 소개 페이지:
https://file.localdata.go.kr/file/public_restroom_info/info - 전국 CSV:
https://file.localdata.go.kr/file/download/public_restroom_info/info - 지역별 CSV:
https://file.localdata.go.kr/file/download/public_restroom_info/info?orgCode=<시도코드> - Kakao Map 모바일 검색:
https://m.map.kakao.com/actions/searchView - Kakao Map 장소 패널 JSON:
https://place-api.map.kakao.com/places/panel3/<confirmId> - Kakao Local 키워드 검색:
https://dapi.kakao.com/v2/local/search/keyword.json(공중화장실,개방화장실) - Kakao Local 카테고리 검색:
https://dapi.kakao.com/v2/local/search/category.json(category_group_code=OL7) - Kakao 좌표→주소 보정:
https://dapi.kakao.com/v2/local/geo/coord2address.json
공식 CSV에는 화장실명, 주소, 위·경도, 남녀/장애인 화장실 수, 개방시간, 기저귀교환대, 비상벨 등이 담겨 있습니다.
기본 흐름
- 유저에게 현재 위치를 먼저 묻습니다.
- 위치 문자열을 받으면 Kakao Map으로 anchor 후보를 고르고 좌표를 확보합니다.
- anchor 주소에서 서울/경기/부산 같은 시도 정보를 추론합니다.
- 공식
공중화장실정보CSV를 내려받고, Kakao REST API 키가 있으면공중화장실,개방화장실,OL7주유소 결과를 추가 조회합니다. - Kakao 응답의
distance값은 사용하지 않고 모든 결과를 WGS84 위·경도 haversine 거리로 다시 계산합니다. - CSV를 우선 보존하면서 50m 이내 중복 시설을 제거한 뒤, 가장 가까운 3~5개만 짧게 응답합니다.
Node.js 예시
const { searchNearbyPublicRestroomsByLocationQuery } = require("public-restroom-nearby");
async function main() {
const result = await searchNearbyPublicRestroomsByLocationQuery("광화문", {
limit: 3
});
for (const item of result.items) {
console.log(`${item.name}: ${Math.round(item.distanceMeters)}m, ${item.address}`);
}
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Kakao REST API 키가 있으면 기본 반경 1,000m에서 Kakao 레이어를 병합합니다. radiusMeters 로 Kakao 조회 반경을 조정할 수 있고, maxDistanceMeters 는 CSV와 Kakao 병합 후 전체 결과에 적용됩니다. Kakao 키가 없으면 기존처럼 CSV 단일 소스로 동작합니다.
반경 제한이 필요하면 maxDistanceMeters 옵션으로 100m 같은 거리 캡을 줄 수 있습니다.
const { searchNearbyPublicRestroomsByLocationQuery } = require("public-restroom-nearby");
async function main() {
const result = await searchNearbyPublicRestroomsByLocationQuery("광화문", {
limit: 3,
maxDistanceMeters: 100,
kakaoRestApiKey: process.env.KAKAO_REST_API_KEY
});
console.log(`100m 이내 결과 수: ${result.meta.total}`);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
CSV 좌표의 표시명/주소가 실제 건물과 어긋나는 경우에는 Kakao coord2address 보정을 명시적으로 켤 수 있습니다. 기본값은 꺼짐입니다.
const result = await searchNearbyPublicRestroomsByLocationQuery("양재천", {
kakaoRestApiKey: process.env.KAKAO_REST_API_KEY,
correctCsvWithKakao: true
});
Offline smoke example
fixture 기반 검증:
node --test packages/public-restroom-nearby/test/index.test.js
검증된 live smoke 예시
아래 값은 2026-04-16 에 광화문, limit=3 로 실제 호출해 확인한 결과 일부입니다.
{
"anchor": {
"name": "광화문",
"address": "서울 종로구 사직로 161 (세종로)"
},
"meta": {
"region": {
"name": "서울특별시"
}
},
"items": [
{
"name": "세종로공영주차장",
"type": "개방화장실",
"openTimeDetail": "00~24"
},
{
"name": "종로구청화장실",
"type": "개방화장실",
"openTimeDetail": "평일9시간(09:00~18:00)"
},
{
"name": "세종문화회관 화장실",
"type": "개방화장실",
"openTimeDetail": "08~22"
}
]
}
같은 날짜에 광화문, limit=3, maxDistanceMeters=100 으로 확인했을 때는 meta.total = 0 이었습니다.
운영 팁
- 좌표를 직접 받으면 anchor 검색을 생략해 더 빠르게 nearby 계산을 할 수 있습니다.
- 화장실이 너무 많이 잡히는 지역이면
maxDistanceMeters로 100m, 300m 같은 거리 캡을 먼저 걸어두세요. - CSV와 Kakao 검색 모두 실시간 잠금/점검 상태는 보장하지 않습니다. CSV 개방시간과 현장 안내를 보수적으로 안내하세요.
- 넓은 질의(예:
강남)는 기준점이 흔들릴 수 있으니 필요하면 역명/동 이름으로 한 번 더 좁히세요. - 지도 링크가 필요하면
item.mapUrl을 함께 전달하면 됩니다.
주의할 점
- 데이터는 공식 공개 CSV와 Kakao POI 검색을 병합하지만 실시간 availability API는 아닙니다.
- CSV 인코딩은 CP949 계열일 수 있어 직접 구현할 때 디코딩 처리가 필요합니다.
- Kakao Map anchor 검색은 기준점만 잡는 용도입니다. Kakao REST 결과를 병합하더라도 CSV가 1순위 데이터이며, 50m 이내 중복은 CSV 항목을 보존합니다.
- Kakao
distance필드는 사용하지 않습니다. 정렬과 필터링은 모두 로컬 haversine 계산값 기준입니다.