[우체국의 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 활용법 서버단 끝이다.
댓글 남기기