우편번호 검색을 위한 자바스크립트 소스다

epost.go.kr의 우편번호 검색에 사용된 자바스크립트 소스를 이용하여 수정을 했다.

 

ASP소스와 자바스크립트 소스만 있으면 기본적으로 우편번호 검색은 끝난다

유용하게 사용하길....

 

/************************************************************************************
' 단위업무명 : 우편번호 검색을 위한 자바스크립트
' 작  성  자 : 가치노을(pobiplus@gmail.com) http://www.newnnow.co.kr
' 작  성  일  : 2011-12-01
' 수  정  자  :
' 수  정  일 :
' 내   용 : epost.go.kr에서 우편번호 검색화면 소스를 차용한것임
' 주의  사항 :
'************************************************************************************/

function eventonblur(img_name){
 var keyvalue = document.getElementById("keyword").value;
 var gubun = document.getElementById('gubun').value;
 if(gubun == "road"){
  img_url="/__cmsimg/zipcode/srch_bg.gif";
 }
 else if(gubun == "dong"){
  img_url="/__cmsimg/zipcode/srch_bg2.gif";
 }
 else if(gubun == "oldpost"){
  img_url="/__cmsimg/zipcode/srch_bg3.gif";
 }
    if((img_name.value == "") && (keyvalue == "")){
        img_name.style.background="url("+img_url+") no-repeat 2px 2px";
        img_name.style.backgroundColor="#fff";
    }
}

function fnInit(val){
 // 라디오 버튼 value 값 조건 비교
 if(val == "road"){
  document.getElementById('notitab3_list').style.display = "";
  document.getElementById('notitab4_list').style.display = "";
  document.getElementById('notitab5_list').style.display = "none";
  document.getElementById('notitab6_list').style.display = "none";
  document.getElementById('gubun').value="road";
  if(document.getElementById("keyword").value.length==0){      
   document.getElementById("keyword").style.background="url(/__cmsimg/zipcode/srch_bg.gif) #fff no-repeat 2px 1px";
  }
 
 }
 else if(val == "dong"){
  document.getElementById('notitab3_list').style.display = "none";
  document.getElementById('notitab4_list').style.display = "none";
  document.getElementById('notitab5_list').style.display = "";
  document.getElementById('notitab6_list').style.display = "none";
  document.getElementById('gubun').value="dong";
  if(document.getElementById("keyword").value.length==0){      
   document.getElementById("keyword").style.background="url(/__cmsimg/zipcode/srch_bg2.gif) #fff no-repeat 2px 1px";
  }
 }
 else if(val == "oldpost"){
  document.getElementById('notitab3_list').style.display = "none";
  document.getElementById('notitab4_list').style.display = "none";
  document.getElementById('notitab5_list').style.display = "none";
  document.getElementById('notitab6_list').style.display = "";
  document.getElementById('gubun').value="oldpost";
  if(document.getElementById("keyword").value.length==0){      
   document.getElementById("keyword").style.background="url(/__cmsimg/zipcode/srch_bg3.gif) #fff no-repeat 2px 1px";
  }
 }
}

function fnGubun(obj){
 // 라디오 버튼 value 값 조건 비교
 document.getElementById("keyword").value = "";
 if(obj.value == "road"){
  document.getElementById('notitab3_list').style.display = "";
  document.getElementById('notitab4_list').style.display = "";
  document.getElementById('notitab5_list').style.display = "none";
  document.getElementById('notitab6_list').style.display = "none";
  if(document.getElementById("keyword").value.length==0){      
   document.getElementById("keyword").style.background="url(/__cmsimg/zipcode/srch_bg.gif) #fff no-repeat 2px 1px";
  }
 
 }
 else if(obj.value == "dong"){
  document.getElementById('notitab3_list').style.display = "none";
  document.getElementById('notitab4_list').style.display = "none";
  document.getElementById('notitab5_list').style.display = "";
  document.getElementById('notitab6_list').style.display = "none";
  if(document.getElementById("keyword").value.length==0){      
   document.getElementById("keyword").style.background="url(/__cmsimg/zipcode/srch_bg2.gif) #fff no-repeat 2px 1px";
  }
 }
 else if(obj.value == "oldpost"){
  document.getElementById('notitab3_list').style.display = "none";
  document.getElementById('notitab4_list').style.display = "none";
  document.getElementById('notitab5_list').style.display = "none";
  document.getElementById('notitab6_list').style.display = "";
  if(document.getElementById("keyword").value.length==0){      
   document.getElementById("keyword").style.background="url(/__cmsimg/zipcode/srch_bg3.gif) #fff no-repeat 2px 1px";
  }
 }
}

function fnCheckForm(srcEl)
{
 var gubun, keyword,stitle;
 keyword = fnCheckstring(srcEl.keyword.value);
 stitle = srcEl.keyword.title;
 gubun = srcEl.gubun.value;
 //alert(gubun);
 if(keyword.length == 0){
  if (gubun == "road"){
   alert("도로명+건물번호를 입력하세요!\n\n검색방법 : 도로명(~로,~길)+건물번호\n- 서울시 중구 소공로 70 \n  예) '소공로(도로명) 70(건물번호)'");
  }
  else if (gubun == "dong"){
     alert("동/읍/면/리/명+지번을 입력하십시오!\n\n검색방법 : 동/읍/면/리명+지번\n- 서울시 중구 충무로1가 21-1 \n  예) '중무로1가(동명) 21-1(지번)'");
  }
  else{
     alert("동/읍/면/리/명을 입력하십시오!\n\n검색방법 : 동/읍/면/리명\n-  서울시 중구 충무로1가 \n  예) '충무로1가(동명) 또는 충무로'");
  }
  srcEl.keyword.style.backgroundImage="";
  srcEl.keyword.focus();
  return false;
 }else if(keyword.length < 2){
    alert("검색어를 2글자이상으로입력하세요!");
    srcEl.keyword.style.backgroundImage="";
    srcEl.keyword.focus();
    return false;
 }

  if (gubun == "road"){
      var str = srcEl.keyword.value.split(" ").join("");
      var strlen = str.length;
      var strdiv = "";
      for(var i = strlen-1; i > -1; i--){
          if(IsRoad(str.charAt(i))){
              strdiv = i+1;
              break;
          }
      }
      srcEl.searchKey.value = str.substring(0,strdiv);
      srcEl.MainNo.value = str.substring(strdiv,strlen);
     
      if(srcEl.searchKey.value == "시장북로"){
        alert("\"시장북로\"는 지번주소(법정동) 입니다.");
        return false;
      }
     
      if ((gubun == "road")&&((srcEl.searchKey.value == "")||(srcEl.MainNo.value == ""))) {
          alert("도로명+건물번호를 입력하세요!\n\n검색방법 : 도로명(~로,~길)+건물번호\n- 서울시 중구 소공로 70 \n  예) '소공로(도로명) 70(건물번호)'");
          return false;
      }
     
      var Temp    = srcEl.MainNo.value.split("-");
      srcEl.MainNo.value   = Temp[0];
      srcEl.SubNo.value = "";
      for (var i = 1; i < Temp.length; i++) {
          srcEl.SubNo.value = Temp[i];
          break;
      }
     
      srcEl.SubNo.value = srcEl.SubNo.value.replace(" ", "");
     
      if (srcEl.SubNo.value.length == 0) {
          srcEl.SubNo.value = "";
      }

      if ( (gubun == "road")&&(!IsNumeric(srcEl.MainNo.value) || !IsNumeric(srcEl.SubNo.value)) ) {
          alert("건물번호는 반드시 숫자만 입력하세요!");
          return false;
      }
      else{
       srcEl.MainNo.value = escape(srcEl.MainNo.value);
      }                  

  }
  //2007.11.02 동명 검색 추가 (천우관)
  else if (gubun == "dong"){
      var str = srcEl.keyword.value.split(" ").join("");
      var strlen = str.length;
      var strdiv = "";
      for(var i = strlen-1; i > -1; i--){
          if(IsDong(str.charAt(i))){
              strdiv = i+1;
              break;
          }
      }
      srcEl.searchKey.value = str.substring(0,strdiv);
      srcEl.MainNo.value = str.substring(strdiv,strlen); 

      if ((gubun == "dong")&&((srcEl.searchKey.value == "")||(srcEl.MainNo.value == ""))) {
          alert("동/읍/면/리/명+지번을 입력하십시오!\n\n검색방법 : 동/읍/면/리명+지번\n-  서울시 중구 충무로1가 21-1 \n  예) '충무로1가(동명) 21-1(지번)'");
          return false;
      }
     
      srcEl.MainNo.value = srcEl.MainNo.value.replace("산", "");
      var Temp     = srcEl.MainNo.value.split("-");
 
      srcEl.MainNo.value  = Temp[0];
      srcEl.SubNo.value = "";
 
      for (var i = 1; i < Temp.length; i++) {
          srcEl.SubNo.value = Temp[i];
          break;
      }
     
      srcEl.SubNo.value = srcEl.SubNo.value.replace(" ", "");
     
      if (srcEl.SubNo.value.length == 0) {
          srcEl.SubNo.value = "";
      }
     
      if ( (gubun == "dong")&&(!IsNumeric(srcEl.MainNo.value) || !IsNumeric(srcEl.SubNo.value)) ) {
          alert("번지는 반드시 숫자만 입력하세요!");
          return false;
      }                  
      else{
       srcEl.MainNo.value = escape(srcEl.MainNo.value);
      }                  

  }
  else if (gubun == "oldpost"){
  
      if(srcEl.keyword.value==""){
          alert("검색어를 입력하세요!");
          srcEl.keyword.focus();
          return false;
      }else if(srcEl.keyword.value.length<2){
          alert("검색어를 2글자이상으로입력하세요!");
          srcEl.keyword.focus();
          return false;
      }
      srcEl.searchKey.value = srcEl.keyword.value;
  }

  return true;
 
}

function IsNumeric(sText){
    var ValidChars = "0123456789";
    var IsNumber=true;
    var Char;

    for (i = 0; i < sText.length && IsNumber == true; i++) {
        Char = sText.charAt(i);
        if (ValidChars.indexOf(Char) == -1){
            IsNumber = false;
        }
    }
    return IsNumber;
}

function IsRoad(sText){
    var ValidChars = "개길도로리";
    var IsRoad=true;
   
    if (ValidChars.indexOf(sText) == -1){
        IsRoad = false;
    }
    return IsRoad;
}

function IsDong(sText){
    var ValidChars = "읍면동리로가";
    var IsDong=true;

    if (ValidChars.indexOf(sText) == -1){
        IsDong = false;
    }
    return IsDong;
}

function fnCheckstring(str)
{
 var index, len
 while(true) {
  index = str.indexOf(" ")
  if (index == -1) break
  len = str.length
  str = str.substring(0, index) + str.substring((index+1),len)
 }
 str = escape(str)
 while(true) {
  index = str.indexOf("%0D%0A")
  if (index == -1) break
  len = str.length
  str = str.substring(0, index) + str.substring((index+6),len)
 }
 str = unescape(str)

 return str
}

// 우편번호 검색결과 반영
function use_post(zipcode, road_address){
 post = zipcode.split("-");

 opener.parent.document.getElementById("post1").value = post[0];
 opener.parent.document.getElementById("post2").value = post[1];
 opener.parent.document.getElementById("addr").value = road_address;
 opener.parent.document.getElementById("addr2").focus();
 self.close();
}

 

혹시 소스가 파일로 필요하신분들은 메일(본문 내용을 살피면 있다)이나 댓글로 남겨주면 보내드리겠습니다

 

top


우편번호 검색 소스를 공개하고자 한다.

우편번호 검색은 data.go.kr에서 제공하는 openapi를 이용하여 제작하였다

사용된 언어는 ASP와 자바스크립트로 구성되어 있다

먼저 asp소스를 공개한다.

 

 

 

<% @CodePage = "65001" %>
<%
'************************************************************************************
' 단위업무명 : 우편번호 검색화면
' 작  성  자 : 가치노을(pobiplus@gmail.com) http://www.newnnow.co.kr
' 작  성  일  : 2011-12-01
' 수  정  자  :
' 수  정  일 :
' 내   용 : data.go.kr에서 우편번호 API를 이용한 우편번호 검색화면
' 주의  사항 :
'************************************************************************************
response.buffer = True
Response.Charset = "UTF-8"
%>
<%
 gubun = request("gubun") 'road - 도로명과 건물번호로 검색 dong- 동(읍/면/리)명과 지번으로 검색 , oldpost-구 지번 검색
 if (IsNULL(gubun) OR len(gubun) < 1) then
  gubun = "road"
 end if

 searchKey = trim(request("searchKey")) '도로명
 MainNo = trim(request("MainNo")) '건물 주번호
 SubNo = trim(request("SubNo")) '건물 부번호
 inSearch = searchKey
 if len(MainNo) > 0 then
  inSearch = inSearch & " " & MainNo
 end if
 if len(SubNo) > 0 then
  inSearch = inSearch & "-" & SubNo
 end if
 
 rows = 0

 if not IsNULL(inSearch) and len(inSearch) then
  '도로명 주소 중 한글 처리를 위한 변환 루틴
  Session.CodePage=949
  Response.CharSet = "euc-kr"
  
  cngSearch = server.URLEncode(inSearch)
  
  Session.CodePage=28591
  Response.CharSet = "ISO-8859-1"
  
  cngSearch = URLDecode(cngSearch)
  
  Session.CodePage=65001
  Response.CharSet = "utf-8"
  
  cngSearch = server.URLEncode(cngSearch)
  
  '주소 정보 가져오기
  if gubun = "oldpost" then
   sPath ="http://openapi.epost.go.kr/postal/retrieveLotNumberAdressService/retrieveLotNumberAdressService/getDetailList?searchSe=dong&srchwrd="&cngSearch&"&serviceKey="&server.URLEncode("인증키")&""
  else
   sPath = "http://openapi.epost.go.kr/postal/retrieveNewAdressService/retrieveNewAdressService/getNewAddressList?searchSe="&gubun&"&srchwrd="&cngSearch&"&serviceKey=인증키"
  end if

  Set oDOM = Server.CreateObject("Microsoft.XMLDOM")
  with oDOM
      .async = False ' 동기식 호출
      .setProperty "ServerHTTPRequest", True ' HTTP로 XML 데이터 가져옴
      .Load(sPath)
  end with  
    
  successYN = "Y"
  
  Set ResultNodes = oDOM.selectNodes("//cmmMsgHeader")
  
  if ResultNodes.Length > 0 then
   For each ResultSubNodes in ResultNodes
    successYN = ResultSubNodes.getElementsByTagName("successYN")(0).Text
   next
  end if
  Set ResultNodes = nothing
  
  ' XML 에서 반복적인 상위키를 기준으로 가져옵니다.
  if successYN = "Y" then
   if gubun = "oldpost" then
    Set Nodes = oDOM.selectNodes("//detailList")
   else
    Set Nodes = oDOM.selectNodes("//newAddressList")
   end if
   
   rows = Nodes.Length
  else
   rows = 0
  end if
  
 end if

 

'특수문자 변환작업
 Function URLDecode(sConvert)
     Dim aSplit
     Dim sOutput
     Dim I
     If IsNull(sConvert) Then
        URLDecode = ""
        Exit Function
     End If
 
     ' convert all pluses to spaces
     sOutput = REPLACE(sConvert, "+", " ")
 
     ' next convert %hexdigits to the character
     aSplit = Split(sOutput, "%")
 
     If IsArray(aSplit) Then
       sOutput = aSplit(0)
       For I = 0 to UBound(aSplit) - 1
         sOutput = sOutput & _
           Chr("&H" & Left(aSplit(i + 1), 2)) &_
           Right(aSplit(i + 1), Len(aSplit(i + 1)) - 2)
       Next
     End If
 
     URLDecode = sOutput
 End Function

%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 
<title>우편번호 검색</title>
<link rel="stylesheet" type="text/css" href="/css/__style.css" />
<link type="text/css" rel="stylesheet" href="/css/__post.css" />
<script type="text/javascript" language="javascript" charset="utf-8" src="postxml.js"></script>

</head>
<body onload="fnInit('<%=gubun%>')">
 
<div id="wrap_pop">
 <h1><img src="/images/tit_post.jpg" alt="우편번호 검색" /></h1>
 <p id="btnClose"><a href="javascript:self.close();" title="팝업창 닫기"><img src="/images/close.gif" alt="CLOSE" /></a></p>
 
 <div id="popBox" class="pd-inF">
     <!-- contents --> 
  
  <fieldset>
   <div class="zip_srchbox" id="srch1">
          <form action="zipcode.asp" method="post" class="zip_w" name="srch_f" onsubmit="return fnCheckForm(this);">
     <input type="hidden" name="searchKey" value="" />
     <input type="hidden" name="MainNo" value="" />
     <input type="hidden" name="SubNo" value="" />
    <legend>우편번호 상세검색</legend>
    <!-- 검색구분 선택 -->
     <dl class="dlline">
      <dt><strong><label for="sido">검색 구분</label></strong></dt>
      <dd>
       <select id="gubun" title="검색 구분" name="gubun" onchange="fnGubun(this)">
        <option value="road">도로명+건물번호</option>
        <option value="dong">동(읍/면/리)명+지번</option>
        <option value="oldpost">구 지번</option>
       </select>
      </dd>
 
      <dt><strong><label for="gugun">검색어</label></strong></dt>
      <dd>
       <input id="keyword" type="text" class="srch_btn" title="검색어를 입력하세요!" style="IME-MODE:active;" value="<%=inSearch%>"  onclick="this.style.backgroundImage='';" onkeydown="this.style.backgroundImage='';" onblur="eventonblur(this);" size="25" name="keyword" />
       <input type="image" alt="검색" src="/images/zip_srch.gif" />
      </dd>
     </dl>
          </form>

   </div>
   
   <!-- 검색안내 -->
   <div class="zip_info">
    <p id="notitab3_list"><span class="first">*</span> 검색방법 : 도로명(~로,~길)+건물번호<br />
     ☞ 서울시 중구 <em>소공로  70</em>일 경우<br />
       예) <em>소공로</em>(도로명)&nbsp;<em>70</em>(건물번호)
    </p>
    <p id="notitab4_list">
    <span class="first">※</span> 도로명인 "성남대로997번길"인 경우 한 단어이므로 다음과 같이 띄워쓰기 없이 쓰셔야 합니다. <br />
       ☞성남대로, 성남대로997번, 성남대로997번길
    </p>
    
    <p id="notitab5_list" style="display:none"><span class="first">*</span> 검색방법 : 도로명(~로,~길)+건물번호<br />
     ☞ 서울시 중구 <em>충무로1가 20-1</em> 일 경우<br />
      예) <em>충무로1가</em>(동명)&nbsp;<em>20-1</em>(지번)
    </p>

    <p id="notitab6_list" style="display:none"><span class="first">*</span> 검색방법 : 읍/면/동/건물명 등 검색어 입력<br />
     ☞ 서울시 중구 <em>충무로1가</em> 일 경우<br />
      예) <em>충무로1가</em>(검색어)
    </p>

    <p>
    <span class="first">※</span> 도로명주소가 검색되지 않는 경우는 <strong>행정안전부 새주소 안내시스템 (<a href="http://juso.go.kr" target="_blank" title="새창열림">http://juso.go.kr</a>) 에서 <br />
     확인</strong>하시기 바랍니다
    </p>
   </div>
   <!-- //검색안내 -->

   <!-- 검색결과 -->
   <div class="srch_result">
    <table class="zip_t" summary="우편번호, 도로명주소, 지번주소">
     <caption>우편번호 검색결과</caption>
     <colgroup>
      <col width="14%"></col>
      <col width="86%"></col>
     </colgroup>
     <thead>
      <tr>
       <th>우편번호</th>
       <th>주소</th>
      </tr>
     </thead>
     <tbody>
   <%
   if rows > 0 then
    For each SubNodes in Nodes
     if gubun = "oldpost" then
      zipcode = SubNodes.getElementsByTagName("zipNo")(0).Text
      post_address = SubNodes.getElementsByTagName("adres")(0).Text
      strPostAddr = post_address
     else
      zipcode = SubNodes.getElementsByTagName("zipNo")(0).Text
      post_address = SubNodes.getElementsByTagName("lnmAdres")(0).Text
      dong_address = SubNodes.getElementsByTagName("rnAdres")(0).Text
      strPostAddr = post_address & "<BR />(" & dong_address & ")"
     end if
   %>
      <tr>
       <td><strong><a href="#" onclick="use_post('<%=zipcode%>','<%=post_address%>');"><%=zipcode%></a></strong></td>
       <td style="text-align:left;"><%=strPostAddr%></td>
      </tr> 
    <%Next%>
   <%Else%>
      <tr>
       <td colspan="2" class="none"><strong>- 검색결과가 없습니다. -</strong></td>
      </tr>
   <%End If%>
     </tbody>
    </table>
   </div>
   <!-- //검색결과 -->

  </fieldset>
  
        <!-- // contents -->
    </div>
</div>
<%
set oDOM = nothing
set Nodes = nothing
%>
</body>
</html>
 

top


우편번호가 새주소로 바뀌면서 개발에 상당히 불편함을 초래했습니다.

기존에는 5만건 정도 되던 우편번호 주소록이 새주소로 바뀌면서 600만건이 넘어섰습니다.

단순 DB에 업로드하기도 힘들뿐 아니라...

너무 자주 바뀌고 업데이트되는 바람에 개발자 입장에서는 여간 곤혹스럽지 않습니다

더군다나 DB에서 600만건 검색하는것도 검색시간으로 인해 클레임이 들어오기 일쑤입니다.

그래서 찾아본것이 API였습니다.

 

다행히 http://www.data.go.kr에서 신주소와 구주소에 대한 API를 제공하고 있었습니다.

 

도로명주소조회서비스는

https://www.data.go.kr/#L2NvbW0vY29tbW9uU2VhcmNoL29wZW5hcGkkQF5tMDIkQF5wYmxvbnNpcFJlc3JjZVBrPXVkZGk6YmRhNzM0ZWYtZWZjYi00YzhiLWIxYmItOTUwN2RlMjM3N2NmJEBeSXJvc1NlYXJjaF9kZXRhaWxGbGFnPU9QRU5BUEk=

 

여기서 등록을 하고 API를 사용하면 됩니다

결과는 XML로 제공하고 있습니다

 

구주소에 따른 우편번호는

https://www.data.go.kr/#L2NvbW0vY29tbW9uU2VhcmNoL29wZW5hcGkkQF5tMDIkQF5wYmxvbnNpcFJlc3JjZVBrPXVkZGk6ODk2ZDVlNzAtNTM2Yi00ZWQzLWIzNzEtZTBlMTk0YjVkNDg2JEBeSXJvc1NlYXJjaF9kZXRhaWxGbGFnPU9QRU5BUEk=

에서 가져와서 사용하면 됩니다

물론 결과는 XML로 제공됩니다

 

사용방법이나 활용사례까지 나와 있습니다

그런데 ASP로 된 예제가 없어서 기존 JSP나 자바로 된 소스를 분석해서 만들어야 합니다.

 

ASP로 변환하여 사용할때 가장 곤혹스러웠던 부분이 URL로 테스트를 하면 되는데 ASP소스에서 하면 에러가 발생하는 것이었습니다.

 

문제는 인코딩의 문제였습니다.

 

도로면 주소에서 검색키워드에 대한 한글처리는 먼저 eu-kr로  변환을 한다음 ISO-8859-1로 변환을 다시 한번 하고 그 다음에 UTF-8로 변환을 해야 합니다

이부분을 찾는게 가장 어려웠습니다

요즘 워낙 ASP를 사용하는 데가 적어서 활용도가 있을지는 모르겠습니다.

그래도 혹시 필요한 분이 있으면 소스를 제공할려고 합니다.

댓글로 필요한 분이 계시면 남겨주시길 바랍니다

 

그럼 분석할수 있는 소스를 보내드리든가 많으면 포스트로 다시 한번 소스를 공개하겠습니다

감사합니다

 

 

 

top