웹사이트에서 주소를 입력받을 때, 우편번호를 검색하는 기능은 꼭 필요하다. 그러나 행정안전부에서 제공하는 주소 DB를 주기적으로 최신으로 업데이트 해주어야 하기에 작은 프로젝트거나 시간적 여유가 없다면 외부 서비스를 많이들 사용한다. 카카오 우편번호 서비스는 그중 하나로, 아주 편하게 우편번호 검색기능을 구현할 수 있다.
이 서비스의 특징은 팝업과 팝업 크기의 iframe방식 중 원하는 방식으로 검색창을 띄울 수 있다는 것인데, INPOCK에서 모바일 웹을 구현하고 있던 나는 첫 번째 방식은 피해야 하는 상황이기에 iframe을 이용하여 페이지에 끼워 넣기로 했다.
구상한 컴포넌트 설계 스펙은 다음과 같다.
먼저, 카카오 우편번호서비스를 이용하려면 CDN을 통해 제공되는 스크립트 파일을 로드해야 한다. 정상적으로 스크립트가 로드되었다면 브라우저 window 인터페이스에 daum 객체가 생성되며 주소창 생성자를 호출할 수 있다.
if ('daum' in window) {
new daum.Postcode(options)
}
간단하게 검색창을 호출할 수 있지만, 실제로 렌더링이 완료되는 시간은 네트워크 속도에 따라 다소 오래 걸릴 수 있다. 유저가 배송지 검색을 시도할 때, Vue-router Programmatic Navigation을 통해 page stack을 push했기에 최악의 경우 뒤로 가기를 시도하는 등 주문 프로세스에서 이탈할 수 있다.
라이브러리에서는 init이벤트를 발생하지 않기에, 가장 처음 onresize가 발생하는 시점을 init이벤트로 사용했다.
onresize: size =>{
if (!this.ready) {
this.ready = true
}
}
애석하게도, iframe안에서 검색이 한 번 시도될 때마다, 브라우저의 내비게이션 스택이 +1 되어 검색을 마쳤을 때, router.go(-1)가 말을 듣지 않았다. 따라서, 한 번의 검색 결과를 응답받을 때마다 stackCount를 세어주고 router.go(-stackCount)를 호출해야했다.
검색창을 렌더링하는 daum.postCode 생성자는 body아래에 iframe element를 추가한다. 검색이 완료되면, 화면에서는 보이지 않지만 실제로 문서내에 남아있어 SPA환경에서 문제를 발생할 수 있다. 따라서 꼭 beforeDestroy에서 추가된 dom을 지워주자. (dom.remove()는 IE에서 지원하지 않기에, 부모노드에서 자식을 지워주어야 했다.)
beforeDestroy() {
const dom = document.querySelector('div[id^="__daum__layer_"]')
dom.parentNode.removeChild(dom)
}
고난과 역경이 많은 과정이었지만(특히나 내비게이션 스택 부분) 서비스를 이용하는 유저 입장에서는 일관적이고, 웹앱으로서 더 좋은 사용자 경험을 제공했다고 생각한다. 주소를 검색하는 도중 뒤로 가기를 하여 다시 주문정보를 이어서 입력할 수 있고, 주문정보 입력단계에서 배송지 입력 단계를 확실히 구분할 수 있었다.