오픈 소스 프로젝트 - XE 개발 포럼
zbxe에 검색 서버를 입력하게는 되어있는데 막상 db서버가 없으니 사용할 방법이 없습니다.
데이터는 우정사업본부의 데이터(대략 6메가)를 가져와서 이용한다고 할 때 zbxe에 연결하여 사용할 수 있는 우편번호 검색서버 구축에 대해서 프로그램과 설명이 있었으면 좋겠습니다.
제로님이 소스를 올려주셨고 3980에서 수정이 되어 단독으로 우편번호 검색서버를 만들어 사용할 수 있게 되었습니다.
법정지번이 필요한 분들도 법정데이터만 올리면 사용이 가능하겠습니다.
사간이 나면 일본 우편번호를 시도 해봐야겠습니다.

개인적인 질문은 아래 링크로 해주십시오. 쪽지나 메일로 질문을 하시면 답변하지 않습니다.
http://hihsw.com/?mid=hpsfree
해당 사이트 자체가 뜨지 않으면 접속이 안되니 사용자가 회원가입 시도를 할 일이 없으므로 불만이 없으나 사이트가 정상으로 뜨는데 주소를 가져오는 서버는 따로 있으니 회원가입 진행이 되지않아 사용자는 답답한 실정입니다.
사용자로써는 홈페이지에 대하여 불만만 토로 할 뿐입니다.
특히나 구매신청이나 이벤트 신청시에는 대부분 회원가입을 전제로 하고 있는데 회원가입이 안될 때는 황당하게 됩니다.
예전에는 호스팅업체들이 DB용량을 적게는 10MB 많아도 100MB도 주지 않았을때 우편번호의 경우 제로보드에서 지원해주는 개념이였다면 이젠 바뀌긴 해야겠죠.
제가 알기로는 제로보드4에서는 팁을 통해서 스스로 dB를 사용할 수 있는 방법들이 공개된 것으로 압니다.
그리고 지금 와서 제로보드4의 DB 검색 부분을 수정해서 배포해봐야 소용이 없구요.
그래서 zbXE에서는 api server를 지정할 수 있게 해 놓았습니다.
황당한건 황당한거고 대안은 대안인거죠. :)
누군가 우편번호 검색서버를 제공하고 싶다면 언제든 환영이고 소스코드야 열몇줄도 안되니 제공 또한 가능하구요.
저는 어떤 일이든 문제점에 대한 불만토로보다는 대안을 제시하고 그 대안에 대한 논의를 환영합니다.
자신의 자산을 이용하지 않는 우편번호 검색서버는 장단점이 있고 단점에 대한 극복은 본인이 직접 하거나 혹은 답을 구해야 한다고 봅니다.
저도 1년 365일 끄덕없는 서버를 만들고야 싶지만 서버 다운은 늘 그렇듯 예상치 못하게 생기기에 어쩔 수 없죠. :)
제로보드의 우편번호 검색서버의 주소로 연결되는데(zip.zeroboard.com/server.php?addr3= )
"/server.php?addr3= " 이 소스를 유저가 자기 서버에 업로드하고 db를 입력해서 사용할 수 없느냐 하는 것입니다.
소스와 db의 내용을 모르니 설치에 관한 파일을 위젯스킨과 같이 따로 올려 놓으면 필요한 사람은 설치가 가능하지 않겠냐 하는 것입니다.
예로 설치방법은
server.php를 어느 폴더에 업로드하십시오.
*.dbf(혹은 *.sql)를 db에서 어떻게 설치하십시오.
이렇게 해주시면 좋을 것 같습니다.^^
그러면 저는 당장 설치 해보고 싶습니다.
사이트를 하나 만들어 mysql db에 아래와 같이 만들었습니다.
테이블zipcode
필드
SEQ(6)
ZIPCODE(7)
SIDO(15)
GUGUN(26)
DONG(26)
RI(45)
ST_BUNJI(11)
ED_BUNJI(9)
이렇게 하여 mysql db에 데이터는 넣어 봤는데 이것을 ZBXE 주소검색과 연계를 시킬려면 php는 어떻게 하는 것일까요?
저 역시 제 DB에서 검색을 해보려고 하는데요..(저는 행정동이 아닌 법정동을 써야해서 ㅡㅡ;)
잘되질 않네요..
$address[] = "주소1 주소2 주소3 주소4 우편번호"; 이게 정확히 .. ㅡㅡ;;;;;
서버 php 는 어떤식으로 구성되어야 하나요?
염치 불구하고 여쭤봅니다. ^^;
제로님이. 위에서 열몇줄 안되는 코드 제공 가능하다고 하셨는데요.. ㅡㅡㅎ..
그 열몇줄을 도통 모르겠네요...좀 알려주시면 안될까요? ㅎㅎ ㅡㅡa
<?php
$addr3 = trim($_REQUEST['addr3']);
if(!$addr3) exit();
if(get_magic_quotes_gpc()) $addr3 = stripslashes(str_replace("\\","\\\\",$addr3));
if(!is_numeric($addr3)) $addr3 = mysql_escape_string($addr3);
$connect = mysql_connect(IP, User, Password) or die(mysql_error());
mysql_select_db('zipcode_db', $connect) or die(mysql_error());
mysql_query("SET NAMES 'utf8'", $connect) or die(mysql_error());
$query = "select * from kr_zipcode where addr3 like '".$addr3."%'";
$result = mysql_query($query, $connect) or die(mysql_error());
while($tmp = mysql_fetch_object($result)) {
$address[] = sprintf("%s %s %s %s (%s)", $tmp->addr1, $tmp->addr2, $tmp->addr3, $tmp->addr4, $tmp->zip);
}
print base64_encode(serialize($address));
?>
위의 코드입니다.
addr3이라는 get parameter로 동네 이름을 받습니다.
그리고 결과를 serialize하고 base64_encode하여 출력하는 구조입니다. ^^
아, db에는 당연히 utf8로 데이터들이 입력되어 있어야 합니다.
ps. addr1, addr2, addr3, addr4, zip 의 column이 있습니다. :)
그런데 궁금한 점이 하나 있습니다.
zbxe에서 우편번호 검색 서버가 아닌 임의의 주소를 적어 넣었을 때 검색해서 없으면 디폴트로 제로보드 사이트를 찾아 가는 것인지요?
아무 주소나 넣어도 주소가 검색되기에 궁금해서 질문합니다.
제가 중국 우편번호 mdb파일을 가지고 있습니다.. 사용가능한지 모르겟지만...
디비 테이블 형태는 아래와 같습니다..
CREATE TABLE ZipCode(
ID int PRIMARY KEY , /*번호*/
address varchar(100) NOT NULL default '', /*상세주소*/
zip varchar(6) NOT NULL default '', /*우편번호*/
city varchar(50) NOT NULL default '', /*도시*/
province varchar(30) NOT NULL default '', /*성/직할시/자치구/자치주/*/
isCapital char(1) NOT NULL default 'n' /*각 성급/현급 수부*/
)
isCapital==y 이면
사용형태는 province address zip
isCapital==n 이면
사용형태는 province city address zip 순서로 되겟습니다..
사용가능하다면 파일을 올려드리도록 하겟습니다..
근데 거이 18만개 되더라구요... 무리가 된다면 지원 안하셔도 됩니다.ㅎㅎ
만약에 우편번호검색 서버에 여러 국가의 db가 있다면
국가별로 우편번호 db를 선택하려면 어떻게 해야 될까요?
국가별로 우편번호 db테이블이 다르므로 db를 합치는 것 보다
국가를 선택하게 하고 선택한 국가의 우편번호 db를 검색하게 하면 좋을 것 같습니다.
예로 주소입력에서
국가 선택 한국(), 일본(), 중국() 에서 선택하면 선택한 db를 검색.
이 부분 소스를 어떻게 만들면 되는지 궁금해서 또 글을 올렸습니다.
프로그램 잘 하시는 분들~
그렇게 간단한 소스도 못 만드냐고 질책하지 마시길...^^
이 글 읽어보다가 왠지...
불타버린... OTL
제로님의 코드를 기본으로 해서 조금(?) 변경해 봤습니다.
코드로 올릴려고 했는데 어떻게 해서 올리는건지 -_-;; 올라가진 않네요.
그래서 그냥 텍스트로 올립니다. (편집시 탭4칸으로 하면 알아보기 수월할 겁니다.)
기본 설정된 값들은 백성찬님하고 guny님이 적어주신 DB테이블을 모델로 했습니다.
적용시 자신이 가지고 있는 테이블에 맞게 설정해 주시면 됩니다.
실제 테스트나 한국,중국 외에 다른 국가는 모릅니다-_-;
아직은 테스트 용도로 써주세요.
코드의 수정은 자유롭게 하실수 있습니다.
<?php
/***
**
** National ZipCode
**
**
** 기본 설명:
** - 국가별 설정에 따라 각 테이블에서 우편번호 또는 주소로 검색합니다.
** - PHP에서 변수만 설정해 주면 프로그래밍 코드는 따로 손대지 않아도 적용가능합니다.
** - 단, 테스트 해보지 않은 다른 국가들 우편번호의 경우 제한적일 수 있습니다.
** - 쿼리시 옵션을 넣을 경우 소스 중간에 있는 $query 변수 뒷부분에 적어주세요.
** - 버그가 있을 수 있으니 충분히 테스트 후 적용해주세요.
**
****
주의!! 모든 폼의 필드명이나 DB의 필드명은 '대소문자 구분'하여 입력해야 합니다.
또한 사용되는 필드명들은 흔하지 않은 이름으로 변경하시기 바랍니다.
(흔한 이름 사용시 str_replace 함수에서 잘못된 결과가 나올 수 있음, 특히 영어권 주소 다룰때)
****
**
** 상세 설명:
**
HTML 폼 작성시 필드 설정
-필드- -필드명- -설명-
국가 Form_Contury : 검색하고자 하는 국가
검색대상 Form_SearchType : 검색하고자 하는 필드 (우편번호 또는 주소)
검색어 Form_SearchText : 검색대상에 따라 처리가 달라지지만 '우편번호'나 '주소'를 입력
추가 입력값 사용자 지정 : 각 국가마다 따로 입력해야 하는 값이 있는 경우
테이블 설정
- 테이블 구조는 특히 따로 변경해야할 부분은 없습니다.
- 필드명이 흔한 이름일 경우 머릿말을 붙인다던가 하는 식으로 고유 필드명으로 변경해 주십시오.
- 단, 테이블명은 하나의 형식으로 통일해야 합니다. (기본 머릿말: 'ZipCode_')
예) ZipCode_KR , ZipCode_CH , ZipCode_JP , ZipCode_EN
- 국가별 코드는 마음대로 정해도 상관없지만 아래에서 설정하는 배열의 '키'값과는 일치해야 합니다.
국가별 테이블 필드 설정
// 각 국가별 코드로 배열을 만드세요. 주의할점은 테이블명의 꼬릿말과 일치해야 합니다.
// 현재 설정된 테이블명의 머릿말은 'ZipCode_' 입니다.
'KR' => Array(
// [입력 받을 폼의 필드들]
// - HTML 폼 필드명 입력
// - 이콜('=')은 기본으로 적용되는 것이니 지우지 마세요. (맨앞에 위치)
'FORM_FIELDS' =>Array('=', 'Form_SearchText'),
// [우편번호로 검색시]
// - 기본형식: DB필드명 = 'HTML폼 필드명%'
// - 따옴표('')는 문자일 경우 넣고, 숫자일 경우는 뺍니다.
// - 또한 %는 SQL에서 *와 같은 역할의 특수문자로 넣거나 빼서 검색시 활용할 수 있습니다.
// - OR 는 둘중 하나만 맞을 경우에 검색되고, AND 는 둘다 모두 맞아야 검색 됩니다.
'ZIPCODE' =>"ZIPCODE = 'Form_SearchText%'",
// [주소로 검색시] - 설명은 위와 같습니다.
'ADDRESS' =>"DONG = 'Form_SearchText%' OR RI = 'Form_SearchText%'",
// [나라별로 특정값에 따라 출력이 다를 경우]
// - HTML 폼 필드명 입력
'OPTION_FIELD' =>'',
// [출력 양식]
// - DB 필드명 입력
// - XML 로 출력시 예: <tag>필드명1 필드명2 ...</tag>...
// - HTML 로 출력시 예: <option value="필드명1 필드명2 ...">필드명1 필드명2 ...</option>
// - 한국처럼 번지수에 '-' 가 들어가는 경우 없는 주소도 있으므로 ((, ))로 감싸줍니다.
'OUTPUT' =>"SIDO GUGUN DONG RI ((ST_BUNJI-ED_BUNJI))",
// [템플릿]
// - XML 이나 HTML 로 출력시 필요한 테그들이 있을 경우
// - [OUTPUT] 은 반드시 들어가야 합니다
// - 이 변수가 불필요할 경우 PHP 코드 끝 부분에 처리 루틴을 손봐주시면 됩니다.
// - 작성 예: <?xml>[OUTPUT]</xml> 또는 <select>[OUTPUT]</select>
'TEMPLATE' =>"[OUTPUT]"
**
****
*/
$DbTableDefine = Array(
'KR' => Array(
'FORM_FIELDS' =>Array('=', 'Form_SearchText'),
'ZIPCODE' =>"ZIPCODE = 'Form_SearchText%'",
'ADDRESS' =>"DONG = 'Form_SearchText%' OR RI = 'Form_SearchText%'",
'OPTION_FIELD' =>'',
'OUTPUT' =>"SIDO GUGUN DONG RI ((ST_BUNJI-ED_BUNJI))",
'TEMPLATE' =>"[OUTPUT]"
),
'CH' => Array(
'FORM_FIELDS' =>Array('=', 'Form_IsCapital', 'Form_SearchText'),
'ZIPCODE' =>"zip = 'Form_SearchText%'",
'ADDRESS' =>"isCapital = 'Form_IsCapital' AND city = 'Form_SearchText%'",
'OPTION_FIELD' =>'Form_IsCapital',
'OUTPUT' =>Array('y'=>"province address zip", 'n'=>"province city address zip"),
'TEMPLATE' =>"[OUTPUT]"
)
);
$country = trim($_REQUEST['Form_Country']); // 국가
$search_type = trim($_REQUEST['Form_SearchType']); // 검색 대상: 대소문자 정확히 입력해야합니다(모두 대문자로)
$_table_define = $DbTableDefine[$country]; // 각 국가에 따른 배열값
$_table_name = 'ZipCode_'. $country; // 각 국가에 따른 테이블명 + 국가코드 = ZipCode_KR
$_magic_quotes = get_magic_quotes_gpc();
if (empty($country) || empty($search_type)) {
echo '검색 대상이 선택되지 않았습니다.';
// exit; // 또는 뒤로 가기
} else {
$aFormValues = Array();
foreach ($_table_define['FORM_FIELDS'] as $_v) { // 선언된 필드값 검사
if ($_v === '=') { // = 를 LIKE 로 변경하기 위해
$aFormValues[] = ' LIKE ';
}
$aFormValues[$_v] = @trim($_REQUEST[$_v]);
if (!empty($aFormValues[$_v])) { // 값이 비어있는지 검사
if ($_magic_quotes) {
$aFormValues[$_v] = stripslashes(str_replace("\\", "\\\\", $aFormValues[$_v]));
}
if (!is_numeric($aFormValues[$_v])) {
$aFormValues[$_v] = mysql_escape_string($aFormValues[$_v]);
}
} else { // 값이 비어있으면 멈춤
break;
}
}
}
if (empty($aFormValues[count($aReplaces) -1])) { // 입력값 검사
echo '검색어를 입력해주세요.'; // 오류 메시지 확장은 안하겠습니다.
} else { // 입력이 정상적이라면 DB에서 검색 및 출력
//$dbconnect = @mysql_connect(IP, User, Password) or die(mysql_error());
//@mysql_select_db('데이터베이스 이름', $dbconnect) or die(mysql_error());
//@mysql_query("SET NAMES 'utf8'", $dbconnect) or die(mysql_error());
$aAddress = Array();
$query = "SELECT * FROM {$_table_name} WHERE "
.str_replace($_table_define['FORM_FIELDS'], $aFormValues, $_table_define[$search_type]) .' '
.";"; // 기타 옵션: LIMIT 이나, 정렬 등...
//$result = @mysql_query($query, $dbconnect) or die(mysql_error());
/* 특정 필드에 따라 결과 출력이 달라질 경우.
쿼리 결과값에 따라 출력이 달라지기 때문에 while 문 안에서 비교하지 않고,
약간의 성능을 위해(사실 그리 차이는...;) while 밖에서 비교하도록 while 문을 두개로 했습니다.
*/
if (is_array($_table_define['OUTPUT'])) {
while ($aResult = @mysql_fetch_assoc($result)) { // 쿼리 내용을 결과값으로 리턴
$_k =&$aResult[$_table_define['OPTION_FIELD']];
$aAddress[] = trim(str_replace(array_keys($aResult), $aResult, $_table_define['OUTPUT'][$_k]));
}
} else {
while ($aResult = @mysql_fetch_assoc($result)) { // 쿼리 내용을 결과값으로 리턴
$aAddress[] = trim(str_replace(array_keys($aResult), $aResult, $_table_define['OUTPUT']));
}
}
/* 출력 부분.
- XML 이나 HTLM 코드로 출력시 이대로 사용하면 되고, 이외에 따로 함수를 사용할경우는
따로 코드를 적어서 사용하시면 됩니다.
- DB에서 가져온 주소는 $aAddress 변수에 배열로 저장되어 있습니다.
- '((', '-))'는 번지가 없는 주소에서 번지수에 들어가는 '-'를 제거하기 위한 것입니다.
*/
$output = implode("\n", $aAddress);
echo str_replace(Array(' ((', '((', '-))', '[OUTPUT]'), Array('', '', '', $output), $_table_define['TEMPLATE']);
// print base64_encode(serialize($aAddress)); // 일반 함수로 출력시
exit;
}
?>
<form name="Form_ZipCode" method="GET">
국가: <select name="Form_Country">
<option value="KR">한국</option>
<option value="CH">중국</option>
<option value="JP">일본</option>
</select>
<!-- 국가별 필요한 설정은 레이어로 선택시 보여지고 감춰지고 하는게 좋겠죠 -->
- 기타설정(중국): <select name="Form_IsCapital">
<option value="y">Y</option>
<option value="n">N</option>
</select><br />
<!-- 검색 대상에서 사용된 옵션값은 PHP코드의 배열선언시 사용된 키값과 동일해야 합니다.(대소문자 포함) -->
검색 대상: <select name="Form_SearchType">
<option value="ZIPCODE">우편번호로 검색</option>
<option value="ADRRESS">주소로 검색</option>
<select><br />
검색어: <input type="text" name="Form_SearchText" value=""><br />
<input type="submit" value="찾기">
</form>
관리자에서 우편번호검색 서버 선택(지금은 하나)을 국가별로 다중으로 입력할 수 없을 까요?
여러 국가 주소를 원하는 경우 서버 선택을 여러 개 할 수 있게 하고
서버1. 명:한국(이것은 가입폼에서 나타나는 명칭) 서버주소:우편번호서버입력 디렉토리:
서버2.
서버3.
..
서버7
순서는 바꾸어도 서버명이 db종류를 나타내면 될 것 같음.
회원가입 시 서버정보가 입력되어 있으면 표시가되어 가입자가 자기의 국가주소를 선택하면 해당서버에서 데이터를 불러오면 좋을 것같습니다.




$address[] = "주소1 주소2 주소3 주소4 우편번호";
위와 같이 주소가 나열된 배열값을 serialize하고 base64_encode하여 출력하면 되는건데 차후 개발자 가이드라인에 추가해야겠네요. ㅎㅎ