주소 찾기 + 위도 경도 값도 같이 찾기

지원·2023년 7월 1일
2
post-custom-banner

Daum에서 제공하는 주소찾기 서비스로 주소는 저장했는데,
이를 저장해두었다가 kakao map에 띄우기 위해서는 위도값과 경도값이 필요하다.

오늘은 이 내용에 대해서 써보려고 한다!

우선 이것을 구현하기 전에 미리 알고있어야 하는 것은
'주소찾기 api'와 '지도에 표시 및 위도경도 찾기 api'가 별개라는 것이다. 주소찾기 서비스에서는 위도경도를 함께 반환해주지 않는다 ㅠㅠ

주소찾기 api === 다음 지도찾기 서비스
지도에 표시 및 위도경도 찾기 api === 카카오 맵 api

두가지 모두 사용해야함!

그럼 시작해보자!

1. 'Daum 주소 찾기'로 도로명/지번주소 찾기

우선은 주소 찾기 서비스를 구현해보자.

주소를 그냥 input으로 입력받지 않고 주소찾기 api를 사용하는 이유는 뭐 당연하다.. 그냥 input 사용 시 입력에 사용자의 오류가 엄청 많아 데이터가 매우 뒤죽박죽 될 것이다.

참고 문서

https://postcode.map.daum.net/guide

어떻게 사용하면 되는가~

  1. script에 url 추가해주기
  • 다음주소찾기 api는 별도의 key가 필요하지 않아서 아주 간단하다!
  • script src에 아래 url만 넣어주면 바로 사용 가능!
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
  1. 원하는 곳에서 daum.postcode() 생성자 사용하기
new daum.Postcode({
    oncomplete: function(data) {
        // data는 사용자가 선택한 주소 정보를 모두 담고 있는 객체이다.
   		// 시,군,구, 도로명주소, 우편번호, 빌딩이름, 영어주소이름 등등 다 있음!
    }
});

그래서 다음과 같이 주소찾기 팝업 컴포넌트를 작성했다.

import { useEffect, useRef } from 'react';

interface P {
  isOpen: boolean;
  handleAddressChange: (mainAddress: string) => void;
  close: () => void;
}

const PostcodePopup = ({ isOpen, handleAddressChange, close }: P) => {
  const ref = useRef<HTMLDivElement>(null);

  const handlePostcode = () => {
    new daum.Postcode({
      submitMode: false,
      oncomplete: (data: Oncomplete) => {
        let mainAddress = '';
        let zipCode = '';

        mainAddress = data.roadAddress || data.jibunAddress;
        zipCode = data.zonecode;

        handleAddressChange(mainAddress);

        close();
      },

      width: '100%',
      height: '100%',
    }).embed(ref.current);
  };

  useEffect(() => {
    if (isOpen) {
      handlePostcode();
    }
  }, [isOpen]);

  return (
    <Container>
      <Header>
        <div>우편번호 검색</div>
        <button onClick={() => close()}>닫기</button>
      </Header>
      <div ref={ref} />
    </Container>
  );
};

export default PostcodePopup;

new daum.Postcode에서 타입스크립트 에러가 발생한다면?

  • 타입스크립트 컴파일 에러를가 발생한다면 최상단 index.ts 파일에 아래와 같이 저장해두면 된다.
  • 컴파일 에러를 방지하기 위해서 daum이라는 애에 대해서 미리 알려주는 것임
  • 다른 외부 api도 마찬가지로 사용할 수 있다.
declare global {
  interface Window {}
  var daum: any;
}

2. kakao api로 addressSearch로 위도, 경도 값 구하기

여기서 부터는 약간 단계가 더 많다! 단계가 많다고 복잡한 것은 아님 ㅠㅠ

  1. 카카오 맵 api 사이트에서 app key를 발급 받는다.

    https://apis.map.kakao.com/

  2. 마찬가지로 script src에 app key를 포함한 url 넣어주고

<script src=`//dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.NEXT_PUBLIC_KAKAO_APP_JS_KEY}&libraries=services,clusterer&autoload=false`></script>
  1. 이제 위의 post code 팝업 컴포넌트를 일부 수정하여서, 주소를 클릭하였을 때에 바로 위도 경도 값을 알아오는 코드를 추가해보자.
  • 주소를 string으로 받아서, x, y값을 반환하는 method는 addressSearch이다.

참고 문서

https://apis.map.kakao.com/web/documentation/#services_Geocoder_addressSearch

addressSearch() method에 대한 간단한 사용법은 아래와 같다.

1) geocoder 생성자

 const geoCoder = new kakao.maps.services.Geocoder();

2) 주소찾기에서 클릭하여 얻은 string을 파라미터로 받는 함수를 만든다.

참고로 coords는 coordinates의 줄임말로, 좌표(위도와 경도)를 말함!
그리고 진짜 너무 헷갈리는데 (나만 헷갈릴 수도 있음)
X : latitude 위도
Y : longitude 경도

  const getAddressCoords = (address: string) => {
    return new Promise((resolve, reject) => {
      geoCoder.addressSearch(address, (result: any, status: any) => {
        if (status === kakao.maps.services.Status.OK) {
          const coords = new kakao.maps.LatLng(result[0].x, result[0].y);
          resolve(coords);
        } else {
          reject(status);
        }
      });
    });
  };

3) 주소 찾기에서 검색 후, 주소 선택 시 실행되는 oncomplete 함수를 일부 수정한다.

  const handlePostcode = async () => {
    new daum.Postcode({
      submitMode: false,
      oncomplete: async (data: Oncomplete) => {
        let mainAddress = '';
        let zipCode = '';
        let x = 0;
        let y = 0;

        mainAddress = data.roadAddress || data.jibunAddress;
        zipCode = data.zonecode;

        const coords = await getAddressCoords(mainAddress);
        x = coords.getLng();
        y = coords.getLat();

        handleAddressChange(mainAddress);
        handlePosInfoChange(x, y);

        close();
      },

      onresize: (size: { height: string }) => {
        if (ref.current) {
          ref.current.style.height = size.height + 'px';
        }
      },

      width: '100%',
      height: '100%',
    }).embed(ref.current);
  };

이리하여 완성!

다음 주소 api 및 카카오 api는 이번 프로젝트 뿐만 아니라 정말 자주 사용되는 외부 api이기 때문에 종종 들어와서 셀프 참고용으로 남겨보았다.

profile
안녕하세요 지원입니다.
post-custom-banner

0개의 댓글