주소 API활용 (KAKAO)

기완·2021년 6월 13일
7
post-thumbnail

카카오 우편번호 API로 주소창 구현

프로젝트를 하면서 회원가입페이지 구현 중 주소입력창 구현을 위해 주소제공해주는 외부 API가 필요했다. 다음 카카오가 가장 편하다고 들어서 다음 API 가이드북을 통해 사용법을 익힌뒤 적용 해보았다.

👉 카카오 주소 API의 특징

  • Key를 발급받을 필요가 없다.
  • 사용량에 대한 제한은 전혀 없다.
  • 기업용이든 상업적 용도이든 상관없이 무조건 무료로 사용 가능하다.
  • 도로명 주소, 지번 주소, 영문 주소까지 모두 확인 가능하다.
  • 행정안전부에서 제공하는 주소 DB를 직접 업데이트 받고 있으므로 가장 최신의 데이터를 이용할 수 있다.
  • JS API의 최신화는 업데이트시마다 자동으로 된다.

👉 Daum 우편번호 서비스 종류


<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<script>
    new daum.Postcode({
        oncomplete: function(data) {
            // 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분
        }
    }).open();
</script>

1)팝업을 이용하여 도로명 주소와 지번 주소 모두 보여주기
기본적인 팝업을 이용하여 사용자가 선택한 주소의 도로명 주소와 지번 주소를 모두 보여주는 방식

2)iframe을 이용하여 레이어 띄우기
모바일웹에서는 팝업을 띄우는게 부담스러울 수도 있으니, 아래 코드와 같이 특정 element에 크기를 지정하여 iframe으로 끼워넣는 방식을 이용가능

3)iframe을 이용하여 페이지에 끼워 넣기
화면내에 끼워넣는 방식일 경우, 내부 스크롤이 거슬릴수도 있습니다. 이때 onresize 속성을 추가해서 iframe 높이를 조절하면 스크롤이 사라짐

👉 속성

daum.Postcode의 생성자 속성들은 아래와 같습니다.

  • oncomplete
    우편번호 검색 결과 목록에서 특정 항목을 클릭한 경우, 해당 정보를 받아서 처리할 콜백 함수를 정의하는 부분
    이 함수를 정의할때 넣는 인자에는 우편번호 검색 결과 목록에서 사용자가 클릭한 주소 정보가 들어감

💻반환되는 데이터 값

속성속성정보
zonecode13494국가기초구역번호
address경기 성남시 판교역로 235기본 주소
addressEnglish235 Pangyoyeok-ro, Bundang-gu기본 영문 주소
buildingName혜강빌딩건물명
bname갈산동법정동/법정리 이름
addressTypeR/J검색된 기본 주소 타입: R(도로명), J(지번)

  • onresize

검색 결과로 인해 우편번호 서비스의 화면 크기가 변한 경우, 화면 크기 정보를 받아서 처리할 콜백 함수를 정의하는 부분
size 파라미터의 width의 경우 외부 wrapper DOM의 크기에 영향을 받기 때문에, 최초 렌더링 값으로 유지되며, height 값은 수시로 변하기 때문에 이 height 값을 이용하고자 할때 사용하는 것을 추천

new daum.Postcode({
    onresize: function(size) {
        //size는 우편번호 찾기 화면의 크기 데이터 객체
    }
});
  • onclose

우편번호 찾기 화면을 팝업으로 띄운 후, 검색 결과를 선택하거나, 브라우저의 닫기버튼을 통해 닫았을 때 발생하는 콜백 함수를 정의하는 부분.

이 중 검색결과를 선택한 경우에는 onComplete콜백함수가 완료된 후에 실행
이 함수를 정의할때 넣는 인자에는 우편번호 찾기 화면이 어떻게 닫혔는지에 대한 상태 변수가 들어가게 됨

new daum.Postcode({
    onclose: function(state) {
  //state는 우편번호 찾기 화면이 어떻게 닫혔는지에 대한 상태 변수 이며, 
  //상세 설명은 아래 목록에서 확인
        if(state === 'FORCE_CLOSE'){
  //사용자가 브라우저 닫기 버튼을 통해 팝업창을 닫았을 경우, 
  //실행될 코드를 작성하는 부분

        } else if(state === 'COMPLETE_CLOSE'){
  //사용자가 검색결과를 선택하여 팝업창이 닫혔을 경우, 
  //실행될 코드를 작성하는 부분
  //oncomplete 콜백 함수가 실행 완료된 후에 실행
        }
    }
});
  • onsearch

주소를 검색할 경우에 실행되는 콜백함수
onresize콜백보다 먼저 실행되며, 검색어와 검색결과에 대한 간단한 정보가 콜백함수의 인자로 넘어가게 된다.

new daum.Postcode({
    onsearch: function(data) {
        //data는 검색결과에 대한 검색어와 갯수를 가지고 있는 데이터 객체
    }
});

👉 함수

daum.Postcode의 함수는 아래와 같다.

  • open
    ({q: '검색어', left: '팝업위치 x값', top: '팝업위치 y값', popupName: '팝업이름', autoClose: '자동닫힘유무'})
    -우편번호 찾기 화면을 팝업으로 띄움.
    -특정 검색어를 넘겨 바로 실행할 수 있으며, 팝업의 위치를 지정
    또한 팝업의 이름을 설정하여, 여러개의 팝업이 뜨는 것을 방지
    -우편번호 서비스의 기본동작은 검색결과 선택 후 자동 닫힘이나 autoClose옵션을 통해 이를 제어가능
  //일반적인 팝업 오픈
new daum.Postcode({...}).open();
//특정 검색어를 넘겨 팝업 오픈
new daum.Postcode({...}).open({
    q: '판교역로 235'
});
//팝업 위치를 지정(화면의 가운데 정렬)
var width = 500; //팝업의 너비
var height = 600; //팝업의 높이
new daum.Postcode({
    width: width, //생성자에 크기 값을 명시적으로 지정
    height: height,
    ...
}).open({
    left: (window.screen.width / 2) - (width / 2),
    top: (window.screen.height / 2) - (height / 2)
});
//여러개의 팝업창이 뜨는 것을 방지하기 위해 팝업이름을 지정
//지정하지 않을시 기본값은 '_blank'로 설정되어 계속 새창으로 열림
new daum.Postcode({...}).open({
    popupName: 'postcodePopup' //팝업 이름을 설정
});
//검색 결과 선택 후, 자동으로 팝업이 닫히는 것을 방지
new daum.Postcode({...}).open({
    autoClose: false //기본값 true
});
  • embed
    ( element, {q: '검색어', autoClose: '자동닫힘유무'} )
    -우편번호 찾기 화면을 iframe으로 삽입
    이때 iframe을 삽입할 element를 첫번째 매개변수로 넘겨주어야 한다.
    -특정 검색어를 넘겨 바로 실행할 수도 있다.
    -우편번호 서비스의 기본동작은 검색결과 선택 후 자동 닫힘이나 autoClose옵션을 통해 이를 제어할 수 있다.
//일반적인 iframe 삽입
new daum.Postcode({...}).embed(element);
//특정 검색어를 넘겨 iframe 삽입
new daum.Postcode({...})..embed(element, {
    q: '판교역로 235'
});

👉 프로젝트 실습

숙지한부분을 바탕으로 프로젝트에 직접 사용해보았다.

  • 적용순서
  1. react-daum-postcode install
    💻터미널에서 $ npm install react-daum-postcode 입력하여 설치

  2. 주소 검색을 이용할 컴포넌트에 import
import DaumPostcode from 'react-daum-postcode';
  1. 주어진 가이드 북을 활용해 필요에 맞게 커스텀하여 사용
    (주소창구현 한 코드만 적음) , 편의상 우편번호는 사용하지않음

1)

class Signup extends Component {
  constructor(props) {
    super(props);
    this.state = {
      address: '',         //통신을 위한 key값
      firstAddress: '',     //주소api를 통해받는 주소
      secondAddress: '',   //직접 작성하는 상세주소
      isDaumPost: false,    //주소 api불러오기

🙄먼저 state 초기값 설정해주었다.

2)

render() {
    // const { isModalOpen, isModalClose } = this.props;  모달창사용x
    const { isDaumPost, firstAddress } = this.state;     
// 주소창 style
    const width = 505;
    const height = 420;
    const modalStyle = {
      position: 'absolute',
      zIndex: '100',
      border: '1px solid #333333',              
    };
    return (

🙄Component 페이지가 따로 있지않아 스타일속성을 scss가아닌 js에 직접 작성하였다. absolute display속성을 지정하여 레이아웃이 깨지지않게 해주었다.

3)

           <div className="addressBox">
              <div className="cellFirst">
                <input
                  placeholder="주소"
                  className="main_Address"
                  value={firstAddress}
                />
                <button
                  className="btn-serch"
                  type="button"
                  onClick={this.handleOpenPost}  //버튼이벤트
                >
                  주소 찾기
                </button>
/// 버튼이벤트 후 true값으로 Daumpost 컴포넌트 불러오기 , 속성
                {isDaumPost && (
                  <DaumPostCode
                    onComplete={this.handleAddress}
                    autoClose
                    width={width}
                    height={height}
                    style={modalStyle}
                    isDaumPost={isDaumPost}
                  />
                )}
              </div>

              <div className="spec_Address">
                <input
                  type="text"
                  name="secondAddress"
                  placeholder="상세주소"
                  className="second_Address"
                  onChange={this.handleOnChange}
                />
              </div>

🙄불러올 컴포넌트 위치를 정해 속성값과 함께 넣어주었다.
autoClose : 주소값 클릭시 자동 닫힘

4)

handleOpenPost = () => {
    this.setState({
      isDaumPost: true,
    });

🙄버튼 클릭이벤트로 DaumPost 불러오기

5) DaumPost 내부 함수

// daum api 불러오기 함수
handleAddress = data => {
 let AllAddress = data.address;    //주소 변수
 let extraAddress = '';     //()안 참고항목 변수
 
 if (data.addressType === 'R') {     // 사용자가 도로명 주소를 선택했을 경우
   if (data.bname !== '' && /[동|로|가]$/g.test(data.bname)) {  
// 법정동명이 있을 경우 추가한다. (법정리는 제외)
// 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
     extraAddress += data.bname;
   }
   if (data.buildingName !== '') {   // 건물명이 있고
     //공동주택제한일 경우 if안에  && data.apartment === 'Y' 추가
     extraAddress +=
       extraAddress !== '' ? ', ' + data.buildingName : data.buildingName;
      // 아래와 같이 바꿔쓸수있다.
     // extraAddress !== '' ? `, ${data.buildingName}` : data.buildingName;
   }
   AllAddress += extraAddress !== '' ? `(${extraAddress})` : ''; //템플릿 리터럴 표현
 }    // 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
 this.setState({
   firstAddress: AllAddress,
 });
};

data.address : 데이터 속 기본주소
extraAddress : ()속 참고 주소
🙄 위 두개를 변수로 지정하고
기본주소칸에 쓰일 기본주소(data.address)를 불러오고, 조건문과 속성들을 활용하여 ()안에 쓰일 값을 만든다.
bname(동/로/가) 를 빈 문자 extraAddress에 추가시키고, buildingName(건물명) 또한 추가한다.
마지막으로 기본주소에 추가항목(소괄호안 항목)을 더해서 반환 해준다.
🖊(${extraAddress}) : 템플릿 리터럴 문법(참고)

✔추가적으로 깔끔한 구현을 위해 팝업창으로 구현 하도록 수정이 필요해보인다.

profile
기록하는 습관을 기를 수 있을까....?!

2개의 댓글

comment-user-thumbnail
2021년 8월 13일

공동주택 부분을 어떻게 해야할지 몰라서 헤매고 있었는데, 감사합니다 ! :D

1개의 답글