slick-address-kr
Slick Address KR
행정안전부 도로명주소 API 기반 팝업 없는 한국 주소 검색 라이브러리
Korean address search library using official road address API - No popup required
v1에서 올라오는 경우 docs/MIGRATION-v2.md를 먼저 읽으세요.
특징
- ✨ 팝업 없는 인라인 UI: 다음 주소 API처럼 새 창이 열리지 않습니다
- 🚀 가벼운 용량: 외부 의존성 없이 순수 TypeScript로 작성
- 📱 반응형 디자인: 모바일부터 데스크톱까지 완벽 지원
- 🎨 커스터마이징 가능: CSS 변수와 클래스로 쉽게 스타일 변경 가능
- 🌗 다크모드 지원:
--kaf-*CSS 변수와prefers-color-scheme대응 - ⚡ 자동완성 모드: 타이핑하는 즉시 검색 결과 표시
- ⌨️ 키보드 네비게이션: 화살표 키로 결과 선택, 엔터로 적용 - 마우스 없이 빠른 입력!
- ♿ 스크린리더 지원: ARIA combobox 패턴 적용
- 🔒 TypeScript 지원: 완전한 타입 정의 제공
- 🌐 프레임워크 무관: Vanilla JS는 물론, React/Vue 전용 어댑터 제공
- 🔌 자체 프록시 연동:
endpoint/fetchFn옵션으로 API 키를 서버에 숨길 수 있음 - 📦 모든 패키지 매니저 지원: npm, yarn, pnpm, bun, deno 모두 호환
설치
npm
npm install slick-address-kr
yarn
yarn add slick-address-kr
pnpm
pnpm add slick-address-kr
bun
bun add slick-address-kr
deno
import { KoreanAddressFinder } from "npm:slick-address-kr@2";
TypeScript 사용자 참고:
moduleResolution: "node"(node10) 설정은 지원하지 않습니다."bundler","node16","nodenext"중 하나를 쓰세요 — 이 패키지는exports필드 기반 타입 해석만 제공합니다.
빠른 시작
1. 기본 사용 (Vanilla JavaScript)
간단한 방법:
- 라이브러리를 빌드합니다 (
examples/는../dist/index.js를 직접 참조하며,dist/는 git에 커밋되지 않습니다):npm run build - 프로젝트 폴더의
examples/index.html파일을 참조하세요 - 로컬 서버 실행:
python -m http.server 8000 - 브라우저에서 열기:
http://localhost:8000/examples/
코드 예제: examples/index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>주소 검색</title>
<link rel="stylesheet" href="node_modules/slick-address-kr/dist/styles.css">
</head>
<body>
<div id="address-search"></div>
<script src="node_modules/slick-address-kr/dist/browser.global.js"></script>
<script>
// 전역 이름은 window.KoreanAddressFinder다
const finder = new KoreanAddressFinder({
apiKey: 'YOUR_API_KEY',
autocompleteMode: true,
onSelect: (address, meta) => {
console.log(meta.reason, address);
},
});
finder.init(document.getElementById('address-search'));
</script>
</body>
</html>
ESM 환경(모듈 번들러)에서는 다음처럼 씁니다.
import { KoreanAddressFinder } from 'slick-address-kr';
import 'slick-address-kr/styles.css';
const finder = new KoreanAddressFinder({
apiKey: 'YOUR_API_KEY',
onSelect: (address) => console.log(address),
});
finder.init(document.getElementById('address-search'));
CommonJS로 require하는 경우, require('slick-address-kr')는 이름공간 객체를
돌려주므로 .default나 이름이 붙은 export를 꺼내 써야 합니다.
const { KoreanAddressFinder } = require('slick-address-kr');
// 또는
const KoreanAddressFinder = require('slick-address-kr').default;
2. React에서 사용
전용 훅을 쓰는 것을 권장합니다.
import { useKoreanAddress } from 'slick-address-kr/react';
import 'slick-address-kr/styles.css';
function AddressForm() {
const { containerRef, address } = useKoreanAddress({
apiKey: import.meta.env.VITE_JUSO_API_KEY,
autocompleteMode: true,
});
return (
<>
<div ref={containerRef} />
{address && <p>{address.zipCode} {address.roadAddress}</p>}
</>
);
}
훅 없이 클래스를 직접 다루고 싶다면 examples/react-example.jsx를 참고하세요.
3. Vue에서 사용
<script setup>
import { useKoreanAddress } from 'slick-address-kr/vue';
import 'slick-address-kr/styles.css';
const { containerRef, address } = useKoreanAddress({
apiKey: import.meta.env.VITE_JUSO_API_KEY,
autocompleteMode: true,
});
</script>
<template>
<div ref="containerRef"></div>
<p v-if="address">{{ address.zipCode }} {{ address.roadAddress }}</p>
</template>
참고:
slick-address-kr/vue의 컴포저블은setup()시점의 옵션을 한 번만 캡처합니다. React 훅과 달리 이후onSelect등을 바꿔도 반영되지 않습니다. 콜백을 동적으로 바꿔야 한다면 반환된finder인스턴스를 직접 조작하세요.
API 문서
Options
interface AddressFinderOptions {
/** 행정안전부 API 키. endpoint를 자체 프록시로 지정한 경우 생략 가능 */
apiKey?: string;
/** 한 페이지에 표시할 결과 수 (기본값: 10) */
countPerPage?: number;
/** 현재 페이지 번호 (기본값: 1) */
currentPage?: number;
/** 검색 결과를 표시할 컨테이너 ID. init()에 엘리먼트를 직접 넘기면 무시됨 */
containerId?: string;
/** 주소 선택 시, 그리고 상세주소가 바뀔 때마다 호출된다 */
onSelect?: (address: AddressResult, meta: AddressSelectMeta) => void;
/** 상세주소 입력 필드 표시 여부 (기본값: true) */
showDetailInput?: boolean;
/** 커스텀 스타일 클래스 */
customClass?: string;
/** 자동완성 모드 사용 여부 (기본값: false) */
autocompleteMode?: boolean;
/** 호출할 주소. 자체 프록시 서버를 쓸 때 지정 */
endpoint?: string;
/** fetch 대체 구현. 인증 헤더 주입이나 테스트에 사용 */
fetchFn?: typeof fetch;
}
AddressResult
interface AddressResult {
/** 도로명 주소 */
roadAddress: string;
/** 지번 주소 */
jibunAddress: string;
/** 우편번호 */
zipCode: string;
/** 건물명 */
buildingName?: string;
/** 상세 주소 */
detailAddress?: string;
/** 참고 항목 */
extraAddress?: string;
/** 시도명 */
sido?: string;
/** 시군구명 */
sigungu?: string;
/** 읍면동명 */
bname?: string;
/** 상세주소·좌표 API 연동에 필요한 원본 코드 (행정구역코드, 도로명코드 등) */
codes?: AddressCodes;
}
AddressSelectMeta
interface AddressSelectMeta {
/**
* 'select' — 사용자가 검색 결과에서 주소를 고른 시점
* 'detail-change' — 상세주소 입력값이 바뀐 시점
*/
reason: 'select' | 'detail-change';
}
Methods
init(targetElement?: HTMLElement): void
주소 검색 UI를 초기화합니다.
const finder = new KoreanAddressFinder(options);
finder.init(); // containerId 사용
// 또는
finder.init(document.getElementById('my-container')); // 직접 엘리먼트 전달
destroy(): void
컴포넌트를 제거하고 이벤트 리스너를 정리합니다. 여러 번 호출해도 안전합니다.
finder.destroy();
getSelectedAddress(): AddressResult | null
현재 선택된 주소 정보를 반환합니다. 선택 전에는 null입니다.
const selected = finder.getSelectedAddress();
console.log(selected); // AddressResult | null
search(): Promise<void>
검색 입력란의 현재 값으로 주소를 검색합니다. 검색 버튼 클릭이나 Enter와 같은 동작을 코드에서 그대로 재현할 때 씁니다. 진행 중이던 이전 검색은 자동으로 취소됩니다.
await finder.search();
에러 처리
API 호출이 실패하면 JusoApiError가 던져집니다 (v1처럼 조용히 빈 결과로
처리되지 않습니다). AddressApiClient를 직접 쓰는 경우:
import { AddressApiClient, JusoApiError } from 'slick-address-kr';
const client = new AddressApiClient({ apiKey: 'YOUR_API_KEY' });
try {
const { results, totalCount } = await client.search('판교역로 235', {
currentPage: 1,
countPerPage: 10,
});
} catch (error) {
if (error instanceof JusoApiError) {
// error.code: 행안부 API 원본 에러 코드
// error.userMessage: 화면에 바로 보여줄 수 있는 한국어 안내
console.error(error.code, error.userMessage);
}
}
error.userMessage는 실제 API로 확인된 코드에만 따로 쓴 안내를 담습니다.
- 승인키 문제(
E0001): 키·도메인 확인 안내와 발급 링크 - 검색어 문제(
E0005빈 검색어,E0006시도명만 입력,E0008한 글자,E0009·E0012숫자·특수문자만,E0013금지 특수문자): 코드 번호 없는 부드러운 안내.error.isInputError가true이고, 컴포넌트는 빨간 오류 대신 결과 머리줄 한 줄로 보여줍니다.
그 외 코드는 API가 준 원본 메시지를 그대로 담습니다.
자동완성 모드는 검색어가 두 글자가 될 때까지 검색하지 않습니다.
사용 예제
자동완성 모드
입력하는 즉시 검색 결과를 표시합니다.
const finder = new KoreanAddressFinder({
apiKey: 'YOUR_API_KEY',
autocompleteMode: true,
onSelect: (address) => {
console.log(address);
}
});
finder.init();
키보드 네비게이션
마우스 없이 키보드만으로 주소를 빠르게 입력할 수 있습니다!
사용 방법:
- ⬇️ 화살표 아래 / ⬆️ 화살표 위: 검색 결과 사이를 순환 이동
- Enter: 활성화된 결과를 선택 (없으면 검색 실행)
- ESC: 검색 결과 닫기
// 검색 결과가 열려 있으면 키보드 네비게이션이 자동으로 활성화됩니다
const finder = new KoreanAddressFinder({
autocompleteMode: true, // 타이핑 시 자동 검색
onSelect: (address, meta) => {
console.log('선택된 주소:', address, meta.reason);
// 폼에 자동으로 입력됩니다
}
});
finder.init();
데모: examples/proxy-test.html에서 키보드 네비게이션을 체험할 수 있습니다.
상세주소 입력 없이 사용
const finder = new KoreanAddressFinder({
apiKey: 'YOUR_API_KEY',
showDetailInput: false,
onSelect: (address) => {
console.log(address);
}
});
finder.init();
자체 프록시 서버로 승인키 숨기기
API 키를 클라이언트 번들에 노출하고 싶지 않다면, 자체 서버가 승인키를
붙여 행안부 API를 대신 호출하게 하고 endpoint만 지정하세요.
new KoreanAddressFinder({
endpoint: 'https://your-server.example/api/address',
// apiKey는 서버가 붙이므로 전달하지 않습니다
});
동작하는 예제 서버는 examples/backend-proxy/에 있습니다.
테마 커스터마이징
색상은 CSS 변수로 바꿀 수 있습니다.
.kaf-wrapper {
--kaf-accent: #ff6b35;
--kaf-border: #ddd;
}
다크모드는 prefers-color-scheme: dark를 자동으로 따릅니다. 클래스 단위
커스터마이징이 필요하면 customClass 옵션을 쓰세요.
const finder = new KoreanAddressFinder({
apiKey: 'YOUR_API_KEY',
customClass: 'my-custom-class',
onSelect: (address) => {
console.log(address);
}
});
finder.init();
.my-custom-class .kaf-search-btn {
background-color: #ff6b6b;
}
.my-custom-class .kaf-search-input:focus {
border-color: #ff6b6b;
}
API 키 발급 및 관리
이 라이브러리는 행정안전부 주소기반산업지원서비스 API를 사용합니다.
1. API 키 발급
- 주소기반산업지원서비스 검색 API 신청 접속
- 승인키 신청
- ⚠️ 중요: "검색 API" 선택 (팝업 API가 아님!)
- 사용할 도메인을 등록하세요. 발급 시 등록한 도메인에서만 호출이
허용됩니다. localhost 개발에는 도메인에
localhost를 넣은 별도의 개발용 키가 필요합니다.
2. API 키 안전하게 사용하기
⚠️ 중요: API 키를 코드에 직접 넣으면 누구나 볼 수 있습니다!
프로젝트 규모에 맞는 방법을 선택하세요:
방법 A: 설정 파일 사용 (간단한 프로젝트)
// config.js (Git에 올리지 않음)
export const config = {
jusoApiKey: 'your_actual_api_key_here'
};
// main.js
import { config } from './config.js';
const finder = new KoreanAddressFinder({
apiKey: config.jusoApiKey,
onSelect: (address) => console.log(address)
});
방법 B: 환경 변수 사용 (React, Vue 등)
# .env
VITE_JUSO_API_KEY=your_key_here
const finder = new KoreanAddressFinder({
apiKey: import.meta.env.VITE_JUSO_API_KEY,
onSelect: (address) => console.log(address)
});
방법 C: 백엔드 프록시 서버 (상용 서비스 ⭐ 추천)
API 키를 서버에만 저장하고 클라이언트는 자체 서버를 통해 API 호출:
// 클라이언트에서는 apiKey 불필요
const finder = new KoreanAddressFinder({
endpoint: 'https://your-server.example/api/address',
onSelect: (address) => console.log(address)
});
자세한 내용은 docs/API-KEY-GUIDE.md 및
examples/backend-proxy/ 참조
다음 주소 API와의 비교
| 기능 | Slick Address KR | 다음 주소 API |
|---|---|---|
| 팝업 | ❌ 없음 | ✅ 있음 (새 창) |
| 인라인 UI | ✅ 지원 | ❌ 미지원 |
| 커스터마이징 | ✅ 자유롭게 가능 | ⚠️ 제한적 |
| 자동완성 | ✅ 지원 | ✅ 지원 |
| 데이터 소스 | 행정안전부 공공 API | 다음 자체 DB |
| 의존성 | ✅ 독립적 | ⚠️ 다음 의존 |
| 모바일 최적화 | ✅ 완벽 지원 | ✅ 지원 |
브라우저 지원
- Chrome (최신 2개 버전)
- Firefox (최신 2개 버전)
- Safari (최신 2개 버전)
- Edge (최신 2개 버전)
- iOS Safari (12+)
- Android Chrome (최신)
더 읽어보기
- docs/MIGRATION-v2.md — v1 → v2 마이그레이션 가이드
- docs/QUICK-START.md — 빠른 시작
- docs/HOW-TO-USE.md — 실제 웹사이트 적용 가이드
- docs/API-KEY-GUIDE.md — API 키 발급·관리 가이드
- docs/AUTOCOMPLETE-GUIDE.md — 자동완성 상세 가이드
- docs/TEST-GUIDE.md — 테스트 가이드
- docs/SELF-HOSTED-DATABASE.md — 자체 DB 구축
- CHANGELOG.md — 버전별 변경 이력
라이선스
MIT License - 자유롭게 사용하세요!
기여하기
이슈와 PR은 언제나 환영합니다! 자세한 개발 절차는 CONTRIBUTING.md를 참고하세요.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
문제 해결
"승인되지 않은 KEY 입니다" 오류가 나요
이 라이브러리는 API 키가 필수입니다. 키 없이 사용하면 동작하지 않습니다.
- 행정안전부 도로명주소 OpenAPI에서 "검색 API" 키를 직접 발급받으세요. (팝업 API 아님!)
- 발급받은 키를
apiKey옵션으로 전달하세요:new KoreanAddressFinder({ apiKey: '발급받은_본인_키', /* ... */ }); - 행정안전부 개발용(dev) 키는 발급 후 일정 기간이 지나면 만료됩니다. 만료 시 새로 발급받으세요.
CORS 에러가 발생해요
행정안전부 API는 CORS를 지원합니다. 만약 에러가 발생한다면:
- API 키가 올바른지 확인
- ⚠️ 중요: API 발급 시 "검색 API"로 발급받았는지 확인 (팝업 API가 아님!)
- 키 발급 시 등록한 도메인에서만 호출이 허용됩니다. 사용할 도메인(예:
localhost, 실제 서비스 도메인)을 juso.go.kr에 등록했는지 확인하세요. localhost 개발에는 별도의 개발용 키가 필요합니다. - HTTPS 사용 권장
검색 결과가 나오지 않아요
- 인터넷 연결 확인
- API 키가 올바른지 확인
- ⚠️ API 발급 시 "검색 API"로 선택했는지 확인
- 콘솔에서 에러 메시지 확인 (v2부터는
JusoApiError가 던져지므로 원인이 명확히 보입니다)
지원
- 이슈: GitHub Issues
- GitHub: @Devguru-J
Project tango down by Devguru-J
Related Packages
A comprehensive set of Vue 3 directives for building accessible web applications...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 2.0.1 | >=3 | MIT | |
| 2.0.0 | >=3 | MIT | |
| 1.0.4 | MIT | ||
| 1.0.3 | MIT | ||
| 1.0.2 | MIT | ||
| 1.0.1 | MIT | ||
| 1.0.0 | MIT |