slick-address-kr 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API-KEY-GUIDE.md +428 -0
- package/AUTOCOMPLETE-GUIDE.md +399 -0
- package/HOW-TO-USE.md +416 -0
- package/LICENSE +21 -0
- package/README.ko.md +88 -0
- package/README.md +434 -0
- package/config.example.js +16 -0
- package/dist/address-finder.d.ts +68 -0
- package/dist/address-finder.js +262 -0
- package/dist/api-client.d.ts +25 -0
- package/dist/api-client.js +79 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/styles.css +279 -0
- package/dist/types.d.ts +83 -0
- package/dist/types.js +1 -0
- package/index.html +85 -0
- package/korean-address-finder.js +360 -0
- package/package.json +58 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 주소 검색 결과 인터페이스
|
|
3
|
+
*/
|
|
4
|
+
export interface AddressResult {
|
|
5
|
+
/** 도로명 주소 */
|
|
6
|
+
roadAddress: string;
|
|
7
|
+
/** 지번 주소 */
|
|
8
|
+
jibunAddress: string;
|
|
9
|
+
/** 우편번호 */
|
|
10
|
+
zipCode: string;
|
|
11
|
+
/** 건물명 */
|
|
12
|
+
buildingName?: string;
|
|
13
|
+
/** 상세 주소 입력용 */
|
|
14
|
+
detailAddress?: string;
|
|
15
|
+
/** 참고 항목 */
|
|
16
|
+
extraAddress?: string;
|
|
17
|
+
/** 시도명 */
|
|
18
|
+
sido?: string;
|
|
19
|
+
/** 시군구명 */
|
|
20
|
+
sigungu?: string;
|
|
21
|
+
/** 읍면동명 */
|
|
22
|
+
bname?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 주소 검색 설정 옵션
|
|
26
|
+
*/
|
|
27
|
+
export interface AddressFinderOptions {
|
|
28
|
+
/** 행정안전부 API 키 (선택사항 - 공개 API 사용 가능) */
|
|
29
|
+
apiKey?: string;
|
|
30
|
+
/** 한 페이지에 표시할 결과 수 (기본값: 10) */
|
|
31
|
+
countPerPage?: number;
|
|
32
|
+
/** 현재 페이지 번호 (기본값: 1) */
|
|
33
|
+
currentPage?: number;
|
|
34
|
+
/** 검색 결과를 표시할 컨테이너 ID */
|
|
35
|
+
containerId?: string;
|
|
36
|
+
/** 주소 선택 시 콜백 함수 */
|
|
37
|
+
onSelect?: (address: AddressResult) => void;
|
|
38
|
+
/** 상세주소 입력 필드 표시 여부 (기본값: true) */
|
|
39
|
+
showDetailInput?: boolean;
|
|
40
|
+
/** 커스텀 스타일 클래스 */
|
|
41
|
+
customClass?: string;
|
|
42
|
+
/** 자동완성 모드 사용 여부 (기본값: false) */
|
|
43
|
+
autocompleteMode?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* API 응답 인터페이스 (행정안전부 주소 API)
|
|
47
|
+
*/
|
|
48
|
+
export interface JusoApiResponse {
|
|
49
|
+
results: {
|
|
50
|
+
common: {
|
|
51
|
+
totalCount: string;
|
|
52
|
+
currentPage: string;
|
|
53
|
+
countPerPage: string;
|
|
54
|
+
errorCode: string;
|
|
55
|
+
errorMessage: string;
|
|
56
|
+
};
|
|
57
|
+
juso: Array<{
|
|
58
|
+
roadAddr: string;
|
|
59
|
+
roadAddrPart1: string;
|
|
60
|
+
roadAddrPart2: string;
|
|
61
|
+
jibunAddr: string;
|
|
62
|
+
zipNo: string;
|
|
63
|
+
bdNm: string;
|
|
64
|
+
admCd: string;
|
|
65
|
+
rnMgtSn: string;
|
|
66
|
+
bdMgtSn: string;
|
|
67
|
+
detBdNmList?: string;
|
|
68
|
+
bdKdcd: string;
|
|
69
|
+
siNm: string;
|
|
70
|
+
sggNm: string;
|
|
71
|
+
emdNm: string;
|
|
72
|
+
liNm: string;
|
|
73
|
+
rn: string;
|
|
74
|
+
udrtYn: string;
|
|
75
|
+
buldMnnm: string;
|
|
76
|
+
buldSlno: string;
|
|
77
|
+
mtYn: string;
|
|
78
|
+
lnbrMnnm: string;
|
|
79
|
+
lnbrSlno: string;
|
|
80
|
+
emdNo: string;
|
|
81
|
+
}>;
|
|
82
|
+
};
|
|
83
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/index.html
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="ko">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>한국 주소 검색</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: 'Malgun Gothic', -apple-system, sans-serif;
|
|
10
|
+
max-width: 800px;
|
|
11
|
+
margin: 50px auto;
|
|
12
|
+
padding: 20px;
|
|
13
|
+
background-color: #f5f5f5;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
h1 {
|
|
17
|
+
text-align: center;
|
|
18
|
+
color: #333;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.container {
|
|
22
|
+
background: white;
|
|
23
|
+
padding: 30px;
|
|
24
|
+
border-radius: 10px;
|
|
25
|
+
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.info-box {
|
|
29
|
+
background-color: #e3f2fd;
|
|
30
|
+
padding: 15px;
|
|
31
|
+
border-radius: 5px;
|
|
32
|
+
margin-bottom: 20px;
|
|
33
|
+
font-size: 14px;
|
|
34
|
+
line-height: 1.6;
|
|
35
|
+
}
|
|
36
|
+
</style>
|
|
37
|
+
</head>
|
|
38
|
+
<body>
|
|
39
|
+
<h1>🏠 한국 주소 검색</h1>
|
|
40
|
+
|
|
41
|
+
<div class="container">
|
|
42
|
+
<div class="info-box">
|
|
43
|
+
<strong>💡 사용 방법:</strong><br>
|
|
44
|
+
1. 아래 검색창에 주소를 입력하세요 (예: 판교역로)<br>
|
|
45
|
+
2. <strong>자동으로 검색 결과가 나타납니다!</strong> (2글자 이상 입력 시)<br>
|
|
46
|
+
3. 목록에서 원하는 주소를 클릭하세요<br>
|
|
47
|
+
<br>
|
|
48
|
+
<strong>✨ 자동완성 기능:</strong> 타이핑하는 즉시 결과가 표시됩니다!
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<!-- 주소 검색 컴포넌트가 여기에 렌더링됩니다 -->
|
|
52
|
+
<div id="address-finder"></div>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<!-- 1. config.js 파일 로드 (API 키 포함) -->
|
|
56
|
+
<script src="config.js"></script>
|
|
57
|
+
|
|
58
|
+
<!-- 2. 주소 검색 라이브러리 로드 -->
|
|
59
|
+
<script src="korean-address-finder.js"></script>
|
|
60
|
+
|
|
61
|
+
<!-- 3. 초기화 -->
|
|
62
|
+
<script>
|
|
63
|
+
// config.js에서 API 키 가져오기
|
|
64
|
+
const apiKey = window.CONFIG && window.CONFIG.jusoApiKey
|
|
65
|
+
? window.CONFIG.jusoApiKey
|
|
66
|
+
: 'devU01TX0FVVEgyMDI1MDExMDE1MTY0MTExNTM2MjY='; // 기본 테스트 키
|
|
67
|
+
|
|
68
|
+
// 주소 검색 초기화
|
|
69
|
+
const addressFinder = new KoreanAddressFinder({
|
|
70
|
+
containerId: 'address-finder',
|
|
71
|
+
apiKey: apiKey,
|
|
72
|
+
onSelect: function(address) {
|
|
73
|
+
console.log('선택된 주소:', address);
|
|
74
|
+
|
|
75
|
+
// 여기서 폼에 값을 채우거나 서버로 전송
|
|
76
|
+
// 예시:
|
|
77
|
+
// document.getElementById('zipcode').value = address.zipCode;
|
|
78
|
+
// document.getElementById('address1').value = address.roadAddress;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
addressFinder.init();
|
|
83
|
+
</script>
|
|
84
|
+
</body>
|
|
85
|
+
</html>
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Korean Address Finder - 실제 적용용
|
|
3
|
+
*
|
|
4
|
+
* 사용 방법:
|
|
5
|
+
* 1. 이 파일을 프로젝트에 복사
|
|
6
|
+
* 2. HTML에 포함: <script src="korean-address-finder.js"></script>
|
|
7
|
+
* 3. config.js 파일에 API 키 입력
|
|
8
|
+
* 4. 초기화 코드 실행
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
(function(window) {
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
// API 설정
|
|
15
|
+
const API_URL = 'https://business.juso.go.kr/addrlink/addrLinkApi.do';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 주소 검색 클래스
|
|
19
|
+
*/
|
|
20
|
+
class KoreanAddressFinder {
|
|
21
|
+
constructor(options = {}) {
|
|
22
|
+
this.apiKey = options.apiKey || '';
|
|
23
|
+
this.containerId = options.containerId || 'address-finder';
|
|
24
|
+
this.onSelect = options.onSelect || function() {};
|
|
25
|
+
this.countPerPage = options.countPerPage || 10;
|
|
26
|
+
this.autocomplete = options.autocomplete !== false; // 기본값: true (자동완성 켜짐)
|
|
27
|
+
this.minLength = options.minLength || 2; // 최소 검색 글자 수
|
|
28
|
+
this.debounceTimer = null; // 디바운스 타이머
|
|
29
|
+
|
|
30
|
+
if (!this.apiKey) {
|
|
31
|
+
console.warn('⚠️ API 키가 설정되지 않았습니다. config.js 파일을 확인하세요.');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* UI 초기화
|
|
37
|
+
*/
|
|
38
|
+
init() {
|
|
39
|
+
const container = document.getElementById(this.containerId);
|
|
40
|
+
if (!container) {
|
|
41
|
+
console.error(`❌ 컨테이너를 찾을 수 없습니다: #${this.containerId}`);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// HTML 구조 생성
|
|
46
|
+
container.innerHTML = `
|
|
47
|
+
<div class="kaf-wrapper">
|
|
48
|
+
<div class="kaf-search-box">
|
|
49
|
+
<input type="text" class="kaf-search-input" placeholder="주소를 입력하세요 (예: 판교역로 235)">
|
|
50
|
+
<button type="button" class="kaf-search-btn">검색</button>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="kaf-results" style="display: none;"></div>
|
|
53
|
+
<div class="kaf-selected-address" style="display: none;"></div>
|
|
54
|
+
</div>
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
// CSS 적용
|
|
58
|
+
this.injectStyles();
|
|
59
|
+
|
|
60
|
+
// 이벤트 리스너 등록
|
|
61
|
+
this.attachEvents(container);
|
|
62
|
+
|
|
63
|
+
console.log('✅ Korean Address Finder 초기화 완료');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 스타일 주입
|
|
68
|
+
*/
|
|
69
|
+
injectStyles() {
|
|
70
|
+
if (document.getElementById('kaf-styles')) return;
|
|
71
|
+
|
|
72
|
+
const style = document.createElement('style');
|
|
73
|
+
style.id = 'kaf-styles';
|
|
74
|
+
style.textContent = `
|
|
75
|
+
.kaf-wrapper {
|
|
76
|
+
width: 100%;
|
|
77
|
+
max-width: 600px;
|
|
78
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Malgun Gothic', sans-serif;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.kaf-search-box {
|
|
82
|
+
display: flex;
|
|
83
|
+
gap: 8px;
|
|
84
|
+
margin-bottom: 12px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.kaf-search-input {
|
|
88
|
+
flex: 1;
|
|
89
|
+
padding: 12px 16px;
|
|
90
|
+
font-size: 14px;
|
|
91
|
+
border: 2px solid #e0e0e0;
|
|
92
|
+
border-radius: 8px;
|
|
93
|
+
outline: none;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.kaf-search-input:focus {
|
|
97
|
+
border-color: #4a90e2;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.kaf-search-btn {
|
|
101
|
+
padding: 12px 24px;
|
|
102
|
+
font-size: 14px;
|
|
103
|
+
font-weight: 600;
|
|
104
|
+
color: white;
|
|
105
|
+
background-color: #4a90e2;
|
|
106
|
+
border: none;
|
|
107
|
+
border-radius: 8px;
|
|
108
|
+
cursor: pointer;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.kaf-search-btn:hover {
|
|
112
|
+
background-color: #357abd;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.kaf-results {
|
|
116
|
+
border: 1px solid #e0e0e0;
|
|
117
|
+
border-radius: 8px;
|
|
118
|
+
max-height: 400px;
|
|
119
|
+
overflow-y: auto;
|
|
120
|
+
background: white;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.kaf-result-item {
|
|
124
|
+
padding: 16px;
|
|
125
|
+
border-bottom: 1px solid #f0f0f0;
|
|
126
|
+
cursor: pointer;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.kaf-result-item:hover {
|
|
130
|
+
background-color: #f8f9fa;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.kaf-result-item:last-child {
|
|
134
|
+
border-bottom: none;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.kaf-result-type {
|
|
138
|
+
display: inline-block;
|
|
139
|
+
padding: 2px 8px;
|
|
140
|
+
font-size: 11px;
|
|
141
|
+
font-weight: 600;
|
|
142
|
+
color: white;
|
|
143
|
+
background-color: #4a90e2;
|
|
144
|
+
border-radius: 4px;
|
|
145
|
+
margin-right: 8px;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.kaf-result-address {
|
|
149
|
+
font-size: 14px;
|
|
150
|
+
color: #333;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.kaf-result-zipcode {
|
|
154
|
+
font-size: 12px;
|
|
155
|
+
color: #666;
|
|
156
|
+
margin-top: 4px;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.kaf-selected-address {
|
|
160
|
+
margin-top: 16px;
|
|
161
|
+
padding: 16px;
|
|
162
|
+
background-color: #f0f8ff;
|
|
163
|
+
border: 1px solid #4a90e2;
|
|
164
|
+
border-radius: 8px;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.kaf-selected-address h3 {
|
|
168
|
+
color: #4a90e2;
|
|
169
|
+
margin: 0 0 10px 0;
|
|
170
|
+
font-size: 16px;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.kaf-selected-address p {
|
|
174
|
+
margin: 5px 0;
|
|
175
|
+
font-size: 14px;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.kaf-loading, .kaf-error {
|
|
179
|
+
text-align: center;
|
|
180
|
+
padding: 20px;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.kaf-loading {
|
|
184
|
+
color: #666;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.kaf-error {
|
|
188
|
+
color: #e74c3c;
|
|
189
|
+
}
|
|
190
|
+
`;
|
|
191
|
+
document.head.appendChild(style);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* 이벤트 리스너 등록
|
|
196
|
+
*/
|
|
197
|
+
attachEvents(container) {
|
|
198
|
+
const input = container.querySelector('.kaf-search-input');
|
|
199
|
+
const button = container.querySelector('.kaf-search-btn');
|
|
200
|
+
const resultsDiv = container.querySelector('.kaf-results');
|
|
201
|
+
|
|
202
|
+
// 검색 버튼 클릭
|
|
203
|
+
button.addEventListener('click', () => this.search(input.value));
|
|
204
|
+
|
|
205
|
+
// 엔터키 검색
|
|
206
|
+
input.addEventListener('keypress', (e) => {
|
|
207
|
+
if (e.key === 'Enter') {
|
|
208
|
+
this.search(input.value);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// 자동완성 기능
|
|
213
|
+
if (this.autocomplete) {
|
|
214
|
+
input.addEventListener('input', (e) => {
|
|
215
|
+
const keyword = e.target.value.trim();
|
|
216
|
+
|
|
217
|
+
// 최소 길이 체크
|
|
218
|
+
if (keyword.length < this.minLength) {
|
|
219
|
+
resultsDiv.style.display = 'none';
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// 디바운스 적용 (300ms 대기)
|
|
224
|
+
clearTimeout(this.debounceTimer);
|
|
225
|
+
this.debounceTimer = setTimeout(() => {
|
|
226
|
+
this.search(keyword);
|
|
227
|
+
}, 300);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// 포커스 시 결과 다시 표시
|
|
231
|
+
input.addEventListener('focus', () => {
|
|
232
|
+
if (resultsDiv.innerHTML && resultsDiv.innerHTML !== '<div class="kaf-loading">검색 중...</div>') {
|
|
233
|
+
resultsDiv.style.display = 'block';
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// 외부 클릭 시 결과 닫기
|
|
238
|
+
document.addEventListener('click', (e) => {
|
|
239
|
+
if (!container.contains(e.target)) {
|
|
240
|
+
resultsDiv.style.display = 'none';
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* 주소 검색
|
|
248
|
+
*/
|
|
249
|
+
async search(keyword) {
|
|
250
|
+
if (!keyword || keyword.trim().length === 0) {
|
|
251
|
+
alert('검색어를 입력하세요');
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const container = document.getElementById(this.containerId);
|
|
256
|
+
const resultsDiv = container.querySelector('.kaf-results');
|
|
257
|
+
|
|
258
|
+
resultsDiv.style.display = 'block';
|
|
259
|
+
resultsDiv.innerHTML = '<div class="kaf-loading">검색 중...</div>';
|
|
260
|
+
|
|
261
|
+
try {
|
|
262
|
+
const params = new URLSearchParams({
|
|
263
|
+
confmKey: this.apiKey,
|
|
264
|
+
currentPage: '1',
|
|
265
|
+
countPerPage: this.countPerPage.toString(),
|
|
266
|
+
keyword: keyword.trim(),
|
|
267
|
+
resultType: 'json'
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
const response = await fetch(`${API_URL}?${params.toString()}`);
|
|
271
|
+
const data = await response.json();
|
|
272
|
+
|
|
273
|
+
if (data.results.common.errorCode !== '0') {
|
|
274
|
+
resultsDiv.innerHTML = `
|
|
275
|
+
<div class="kaf-error">
|
|
276
|
+
<strong>검색 오류:</strong><br>
|
|
277
|
+
${data.results.common.errorMessage}<br><br>
|
|
278
|
+
<small>API 키를 확인하세요.</small>
|
|
279
|
+
</div>
|
|
280
|
+
`;
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
this.displayResults(data.results.juso, resultsDiv);
|
|
285
|
+
|
|
286
|
+
} catch (error) {
|
|
287
|
+
console.error('검색 오류:', error);
|
|
288
|
+
resultsDiv.innerHTML = '<div class="kaf-error">검색 중 오류가 발생했습니다.</div>';
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* 결과 표시
|
|
294
|
+
*/
|
|
295
|
+
displayResults(addresses, resultsDiv) {
|
|
296
|
+
if (!addresses || addresses.length === 0) {
|
|
297
|
+
resultsDiv.innerHTML = '<div class="kaf-error">검색 결과가 없습니다.</div>';
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
let html = '';
|
|
302
|
+
addresses.forEach(addr => {
|
|
303
|
+
html += `
|
|
304
|
+
<div class="kaf-result-item" data-zipno="${addr.zipNo}" data-road="${addr.roadAddr}" data-jibun="${addr.jibunAddr}">
|
|
305
|
+
<div>
|
|
306
|
+
<span class="kaf-result-type">도로명</span>
|
|
307
|
+
<span class="kaf-result-address">${addr.roadAddr}</span>
|
|
308
|
+
</div>
|
|
309
|
+
<div style="margin-top: 4px;">
|
|
310
|
+
<span class="kaf-result-type" style="background-color: #999;">지번</span>
|
|
311
|
+
<span class="kaf-result-address">${addr.jibunAddr}</span>
|
|
312
|
+
</div>
|
|
313
|
+
<div class="kaf-result-zipcode">우편번호: ${addr.zipNo}</div>
|
|
314
|
+
</div>
|
|
315
|
+
`;
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
resultsDiv.innerHTML = html;
|
|
319
|
+
|
|
320
|
+
// 클릭 이벤트
|
|
321
|
+
resultsDiv.querySelectorAll('.kaf-result-item').forEach(item => {
|
|
322
|
+
item.addEventListener('click', () => {
|
|
323
|
+
this.selectAddress({
|
|
324
|
+
zipCode: item.dataset.zipno,
|
|
325
|
+
roadAddress: item.dataset.road,
|
|
326
|
+
jibunAddress: item.dataset.jibun
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* 주소 선택
|
|
334
|
+
*/
|
|
335
|
+
selectAddress(address) {
|
|
336
|
+
const container = document.getElementById(this.containerId);
|
|
337
|
+
const selectedDiv = container.querySelector('.kaf-selected-address');
|
|
338
|
+
const resultsDiv = container.querySelector('.kaf-results');
|
|
339
|
+
|
|
340
|
+
selectedDiv.innerHTML = `
|
|
341
|
+
<h3>✅ 선택된 주소</h3>
|
|
342
|
+
<p><strong>우편번호:</strong> ${address.zipCode}</p>
|
|
343
|
+
<p><strong>도로명 주소:</strong> ${address.roadAddress}</p>
|
|
344
|
+
<p><strong>지번 주소:</strong> ${address.jibunAddress}</p>
|
|
345
|
+
`;
|
|
346
|
+
|
|
347
|
+
selectedDiv.style.display = 'block';
|
|
348
|
+
resultsDiv.style.display = 'none';
|
|
349
|
+
|
|
350
|
+
// 콜백 실행
|
|
351
|
+
this.onSelect(address);
|
|
352
|
+
|
|
353
|
+
console.log('선택된 주소:', address);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// 전역으로 노출
|
|
358
|
+
window.KoreanAddressFinder = KoreanAddressFinder;
|
|
359
|
+
|
|
360
|
+
})(window);
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "slick-address-kr",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "행정안전부 도로명주소 API 기반 팝업 없는 한국 주소 검색 컴포넌트 (자동완성 지원) - Korean address search with autocomplete using official road address API",
|
|
5
|
+
"main": "korean-address-finder.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc && npm run copy-css",
|
|
9
|
+
"copy-css": "cp src/styles.css dist/styles.css",
|
|
10
|
+
"dev": "tsc --watch",
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
12
|
+
"prepare": "npm run build"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"korean",
|
|
16
|
+
"address",
|
|
17
|
+
"autocomplete",
|
|
18
|
+
"도로명주소",
|
|
19
|
+
"주소검색",
|
|
20
|
+
"자동완성",
|
|
21
|
+
"address-search",
|
|
22
|
+
"juso",
|
|
23
|
+
"postcode",
|
|
24
|
+
"우편번호",
|
|
25
|
+
"korea",
|
|
26
|
+
"도로명주소API",
|
|
27
|
+
"행정안전부",
|
|
28
|
+
"daum-address",
|
|
29
|
+
"address-finder",
|
|
30
|
+
"road-address"
|
|
31
|
+
],
|
|
32
|
+
"author": "Devguru-J",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/Devguru-J/slick-address-kr.git"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/Devguru-J/slick-address-kr#readme",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/Devguru-J/slick-address-kr/issues"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"typescript": "^5.3.3"
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"dist",
|
|
48
|
+
"korean-address-finder.js",
|
|
49
|
+
"config.example.js",
|
|
50
|
+
"index.html",
|
|
51
|
+
"README.md",
|
|
52
|
+
"README-KR.md",
|
|
53
|
+
"HOW-TO-USE.md",
|
|
54
|
+
"API-KEY-GUIDE.md",
|
|
55
|
+
"AUTOCOMPLETE-GUIDE.md",
|
|
56
|
+
"LICENSE"
|
|
57
|
+
]
|
|
58
|
+
}
|