[우체국의 API는 구주소만 서비스한다. 도로명 주소를 검색하려면 공공데이터포털을 이용해야 한다. 우체국 API를 이용해 구주소를 검색하는 이 예제도 2014-01-10 현재 잘 돌아간다. 공공데이터포털을 이용할 사람은 내가 쓴 공공데이터포털의 우편번호 API 정리 글을 참고하라.]
예전에 우체국이 제공하는 우편번호 API에 대해 쓴 적이 있었다.
당시 나는 세 가지 문제에 봉착했다.
- ajax 호출이 되지 않는다.
- 테스트를 해 보려고 url로 적으면, IE에서는 보이는데 크롬과 파이어폭스에서는 보이지 않는다.
file_get_contents로 긁어도 안 된다.
그래서 포기했었다. 그냥 DB를 이용했다. 그렇게 하니 최신 우편번호를 적용하기 위해 DB를 매번 갱신해 줘야 했다.
시간이 지나고 많은 것을 알게 됐다. 일단 다른 domain에 있는 놈을 ajax 호출하는 것은 안 된다는 것을 알게 됐다. 그래서 1번 문제가 해결됐다.
2번 문제는, URL로 접근할 때나 문제지 호출할 때 그 자체로는 문제가 되지 않으며 POST로 값을 넘기면 된다는 사실을 알게 됐다. 그래서 해결.
3번 문제는, file_get_contents가 GET 방식으로만 값을 넘길 수 있어서 그랬던 것이라는 점을 인지했다. 그래서 file_get_contents가 아닌, POST로 값을 넘겨 응답을 받을 수 있는 PHP 함수를 찾기로 결심!, 그리고 드디어 찾았다.
(최근에 1day1님의 블로그에서 file_get_contents 함수로 우편번호 API를 사용할 수 있게 하는 글을 찾았다. 옵션을 줘야 한다. 저 글에서 제시하는 예제 코드는 아래와 같다.)
$api_key = "우체국에서 받은 API KEY";
$epost_url = "http://biz.epost.go.kr/KpostPortal/openapi?regkey=$api_key&target=post&query=을지로3가";
$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>"Accept-language: ko\r\n"
)
);
$context = stream_context_create($opts);
$fp = file_get_contents($epost_url , false, $context);
cURL로 가져오기
내가 사용한 방법은 PHP의 cURL 라이브러리를 사용한다. 웬만한 호스팅에는 설치돼 있을 거다. 우분투 사용자들이라면 아래 명령어로 간단하게 설치할 수 있다.
sudo apt-get install php5-curl
(혹시나 해서 덧붙이는데, 설치한 다음 아파치를 재시작해야 적용된다.)
cURL을 이용해 웹페이지의 내용을 읽어 오는 함수
이 함수는 [bluesunh님의 노트] cURL Library를 참고했다. (스프링노트 폭파로 링크 유실)
function fetch_page($url,$param,$cookies=NULL,$referer_url=NULL){
if(strlen(trim($referer_url)) == 0) $referer_url= $url;
$curlsession = curl_init ();
curl_setopt ($curlsession, CURLOPT_URL, $url);
curl_setopt ($curlsession, CURLOPT_POST, 1);
curl_setopt ($curlsession, CURLOPT_POSTFIELDS, $param);
//curl_setopt ($curlsession, CURLOPT_POSTFIELDSIZE, 0);
curl_setopt ($curlsession, CURLOPT_TIMEOUT, 60);
if($cookies && $cookies!=""){
curl_setopt ($curlsession, CURLOPT_COOKIE, $cookies);
}
curl_setopt ($curlsession, CURLOPT_HEADER, 1); //헤더값을 가져오기위해 사용합니다. 쿠키를 가져오려고요.
curl_setopt ($curlsession, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.01; Windows NT 6.0)");
curl_setopt ($curlsession, CURLOPT_REFERER, "$referer_url");
ob_start();
$res = curl_exec ($curlsession);
$buffer = ob_get_contents();
ob_end_clean();
$returnVal = array();
if (!$buffer) {
$returnVal['error'] = true;
$returnVal['content'] = "Curl Fetch Error : ".curl_error($curlsession);
}else{
$returnVal['error'] = false;
$returnVal['content'] = $buffer;
}
curl_close($curlsession);
return $returnVal;
}
우편번호 오픈 API에서 xml을 받아 오는 함수
자, 그럼 이제 우편번호 오픈 API에서 xml을 받아 오는 함수를 만들어 보자. 이 함수는 위 함수를 사용한다.
function get_post_code_xml_by_api($query){
$query = iconv('utf-8','euc-kr',$query);
$post_data = array(
'target' => 'post',
'regkey' => '1234567890', //자신의 키를 입력
'query' => $query
);
$url = 'http://biz.epost.go.kr/KpostPortal/openapi';
$param = http_build_query($post_data);
$result = fetch_page($url,$param);
$result['content'] = remove_none_xml_word($result['content']);
return $result;
}
위에서 regkey 는 우편번호 오픈 API 웹사이트에 가서 등록을 한 후 받으면 된다.
$param을 만드는 데 사용한 http_build_query 함수는 내가 쓴 설명을 참고하면 된다.
$query를 받아서 iconv 함수를 이용해 euc-kr로 변환해 줬는데, 내가 기본으로 utf-8 인코딩을 사용한다고 가정했기 때문이다.
위에서 return 직전에 remove_none_xml_word 라는 함수가 보일 거다.
그 놈은 cURL이 넘겨주는 header 값을 지워 버리고 순수 xml만 남기기 위한 함수다. 그놈을 만들어 보자.
function remove_none_xml_word($content){
$content_array = explode("\n", $content);
foreach ($content_array as $key => $value) {
if(substr(trim($value),0,1)!='<'){
$content_array[$key]='';
}
}
unset($content_array[0]);
$content = implode("\n", $content_array);
return trim($content);
}
위에서 unset 함수를 쓴 이유는, 첫 줄이 빈 줄이기 때문이다. 첫 줄이 빈 줄이면 XML 파싱할 때 에러난다.
우편번호에 대시(-)를 넣어 주는 함수
우편번호 오픈 API는 우편번호를 그냥 123456형식으로 넘겨 준다. 사이에 -를 넣어 보기 좋게 만들어야 사용자들에게 좋을 거다.
또한 그러면서 앞 번호와 뒷 번호를 구분하기 위해 span으로 감싸고 클래스를 매겼다. postcd1, postcd2 하는 식으로 말이다.
function add_dash_and_tag_to_postcd($postcd){
$postcd1=substr($postcd,0,3);
$postcd2=substr($postcd,3,3);
return "<span class="postcd1">$postcd1</span>-<span class="postcd2">$postcd2</span>";
}
HTML을 뿌려 주는 함수
이런 함수들을 바탕으로 이제 HTML을 뿌려 주는 함수를 만들어 보자.
function print_postcode_table($xml){
?>
<table class="postcode"><tbody>
<?php
foreach ($xml->itemlist->item as $value) {
$postcd = add_dash_and_tag_to_postcd($value->postcd);
echo '<tr>';
echo "<td><a class='address' href='#{$value->postcd}'>{$value->address}</a></td>";
echo "<td><a class='postcd' href='#{$value->postcd}'>{$postcd}</a></td>";
echo '</tr>';
}
?>
</tbody></table>
<?php
}
print_postcode_table 함수는 simpleXML의 node를 받아서 table 형태로 주소와 우편번호를 뿌려 주는 함수다.
가운데 있는 foreach가 왜 저런 모양이 됐는지는 실행부를 보면 알 수 있을 것이다.
실행부
이제 실행부다. 위 함수들을 functions_postcode.php 에 넣었다고 가정하자.
include_once 'include/functions_postcode.php';
header('Content-Type:text/html;charset=utf-8');
if(!empty($_GET['query'])){
$result = get_post_code_xml_by_api($_GET['query']);
if ($result['error'] == false){
$xml = new SimpleXMLElement($result['content']);
if(count($xml->itemlist->item) == 0){
echo '결과가 없습니다';
}else{
print_postcode_table($xml);
}
}
else {
echo '에러 발생: ' . $result['content'];
}
}else{
echo '검색어를 입력하세요.';
}
우편번호 오픈 API의 인코딩은 euc-kr이다. 하지만 나는 utf-8로 무조건 페이지를 만든다.
물론 SimpleXMLElement 클래스를 생성하면, 지가 알아서 euc-kr인 xml을 utf-8로 변경한다.
그런데 한국 브라우저들은 인코딩 선언이 특별히 없는 경우 기본 인코딩을 euc-kr로 한다. 그래서 header쪽에 인코딩 선언을 넣어 줬다.(둘째 줄) 이 놈은 html로 뿌려줄 용도기 때문에 content-type은 text/html이다.
나머지 if문은 다 이해가 될 것이라고 생각한다.
일단 이렇게 하면 search_post.php?query=삼천포 형식으로 URL을 적었을 때 훌륭한 테이블로 결과값이 펼쳐질 것이다.
특히 js로 주소를 넣고 빼고 하는 것을 제어할 수 있도록, 테이블에 클래스를 넣었고, 내용은 a 태그로 감쌌다. a의 클래스는 무엇을 감싸고 있냐에 따라 각각 address, postcd1, postcd2 다. 우편번호를 삽입하는 부분은 이것을 참고하면 된다.
그러면 우편번호 API 활용법 서버단 끝이다.










댓글 남기기