1. 우편번호 DB 다운받기

http://www.zipfinder.co.kr/zipcode/index.html

우정국에서 제공하는 zipcode 데이터를 받습니다.
여러가지 형태가 있는데 저는 가장 컬럼 갯수가 적은 걸 받았습니다.

2. 도메인 만들기

@Entity
@DomainInfo("우편번호")
public class Zipcode {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    int id;
    @Column(length=7)
    @DomainInfo("zipcode")
    String zipcode;
    @Column(length=4)
    String sido;
    @Column(length=15)
    String gugun;
    @Column(length=52)
    String dong;
    @Column(length=17)
    String bunji;

위에서 받은 필드에 맞게 정의해줍니다.
hbm2ddl을 auto 모드로 놓고 개발중이라 하이버네이트가 돌다가 테이블이 없어서 만들어 줍니다.
제품 단계에서 hbm2ddl을 auto로 설정해두는 것은 매우 위험하오니 꼭 개발중에만 사용하시길..(저는 배포 중에도 쓰지만 ㅋㅋㅋ)

3. zipcode 데이터 넣기

1번에서 받은 데이터를 엑셀로 변환하고 만개 단위로 나눠서 저장했습니다. DBUnit으로 넣었는데 5만개가 넘는걸 한 방에 넣으려고 했더니 POI 쪽에서 에러가 나더군요. 스크롤 기능이 있는지 찾아보려다 귀찮아서 그냥 만개 단위로 잘라서 넣었습니다.

        dbUnitSupport.insertXlsData("zipcode1.xls");
        dbUnitSupport.insertXlsData("zipcode2.xls");
        dbUnitSupport.insertXlsData("zipcode3.xls");
        dbUnitSupport.insertXlsData("zipcode4.xls");
        dbUnitSupport.insertXlsData("zipcode5.xls");

대충 요런식으로..

4. 사용자 추가 화면에 우편번호 자동완성 필드 추가

<k:fzipcode />

이 태그 파일을 만들고 저거 한줄을 사용자를 추가하는 jsp에 추가해줍니다. 저 태그 파일은 대충..

...
<c:set var="pathNS" value="${path != null ? path : 'zipcode'}" />
<c:set var="labelNS" value="${label != null ? label : '우편번호'}" />
<c:set var="popupUrlNS" value="${popupUrl != null ? popupUrl : '/system/zipcode/popupsearch.do'}" />

<o:fSearchPopup label="${labelNS}" url="/ajax/zipcode/dong.do" path="${pathNS}"
    model="zipcodes" size="20"  maxlength="20" />

<script type="text/javascript">
function formatItem(row, i, total){
    return row[1] + " " + row[2] + " " + row[3] + " " + row[4] + " " + row[5];
}
function formatResult(row){
    return row[1];
}
function result(event, row, formatted){
    if (row){
        $("#addr").attr("value", row[2] + " " + row[3] + " " + row[4]);
    }
}
$("#${pathNS}row img").click(function(e) {
    popup("<c:url value='${popupUrlNS}'/>", "itemPopup", 900, 900, "yes", "yes");
});
</script>
...

이런식으로 생겼습니다. 여기서 또 다른 태그 파일을 사용하고 있는데 그녀석이 예전에 만들어둔 Ajax 자동완성 태그 파일입니다.

5. Ajax 요청처리를 구현합니다.

    @RequestMapping("/ajax/zipcode/dong.do")
    public ModelAndView zipcodes(ModelMap map, AjaxParams ajaxParams) {
        map.addAttribute("zipcodes", zipcodeService.findZipcodesByDong(ajaxParams));
        return new ModelAndView("jsonView", map);
    }

Ajax 요청이 왔을 때 우편번호에 필요한 것들을 가져다 주도록 Service -> DAO로 전달 전달. DAO가 가져와서 Service -> Controller 전달 전달.. 뷰까지 ㄱㄱㄱ

6. 검색 버튼 구현

자동완성 오른쪽에는 항상 수동으로 검색할 수 있도록 검색 버튼이 달려있습니다. 팝업이 떠서 검색하고 팝업이 닫힐 때 사용자 추가 화면에 자동으로 값을 넣어 주도록 만드는게 관건.

버튼 눌렀을 때 요청할 URL은 4번 단계에서 태그 파일에 설정해 두었으니 이제 해당 요청을 처리할 컨트롤러와 뷰 만들고 서비스 구현하면 끝.

<o:searchpage title="우편번호 검색">
    <o:buttons>
        <o:searchbtn />
    </o:buttons>
    <o:searchform action="selectgrid.do">
        <o:searchrow>
            <o:text label="읍, 면, 동, 리, 건물명" id="dong" size="30" maxlength="30" />
        </o:searchrow>
    </o:searchform>
</o:searchpage>
<%@ include file="/include/searchfooter.jsp" %>

이게 검색화면 끝.

<o:gridpage>
    <o:zipcodeselectgrid list="${list}">
        <o:col header="id" path="id" hidden="true" type="integer" pattern="#########"/>
        <o:col header="우편번호" path="zipcode" width="80"/>
        <o:col header="시, 도" path="sido" width="50"/>
        <o:col header="구, 군" path="gugun" width="160" />
        <o:col header="동, 면, 건물" path="dong" width="250" />
        <o:col header="번지" path="bunji" width="180" />
    </o:zipcodeselectgrid>
</o:gridpage>

이게 그리드 화면 끝.

    @RequestMapping
    public void popupsearch() {
    }

    @RequestMapping
    public ModelAndView selectgrid(HttpServletRequest req, HttpServletResponse res,
            ModelMap model, ZipcodeParams params, OrderPage orderPage, String view) throws Exception {
        ModelAndView mav = super.grid(req, res, model, params, orderPage, view);
        mav.setViewName("system/zipcode/selectgird");
        return mav;
    }

이게 요청 처리 및 서비스 구현 끝.

7. 완성

팝업으로 검색해서 선택하면 우편번호와 주소에 팍팍 입력되고 팝업 닫히는 것도 되지만 스샷은 생략~