깊은바다거북
개발 공부 기록
깊은바다거북
전체 방문자
오늘
어제
  • 분류 전체보기 (219)
    • JAVA (9)
    • JavaScript (15)
    • 스파르타코딩클럽 (11)
      • [내일배움단] 웹개발 종합반 개발일지 (5)
      • [내일배움캠프] 프로젝트와 트러블 슈팅 (6)
    • SQL | NoSQL (4)
    • CS 등등 (0)
    • TIL | WIL (173)
    • 기타 에러 해결 (3)
    • 내 살 길 궁리 (4)

인기 글

최근 글

최근 댓글

태그

  • 재귀 함수
  • BFS(너비우선탐색)
  • Leetcode
  • 트러블 슈팅 Troubleshooting
  • TypeScript
  • 혼자 공부하는 자바스크립트
  • 최소 힙(Min Heap)
  • Backtracking(백트래킹)
  • 자바스크립트 기초 문법
  • Til
  • BST(이진 탐색 트리)
  • DFS(깊이우선탐색)
  • POST / GET 요청
  • tree
  • Preorder Traversal(전위 순회)
  • Inorder Traversal(중위 순회)
  • 코딩테스트 연습문제
  • 최대 힙(Max Heap)
  • Trie
  • 자료 구조
  • 팀 프로젝트
  • 자잘한 에러 해결
  • 프로그래머스
  • Linked List
  • 시간 복잡도
  • 점화식(Recurrence Relation)
  • Binary Tree(이진 트리)
  • leetcode-cli
  • 01. 미니 프로젝트
  • TIT (Today I Troubleshot)
hELLO · Designed By 정상우.
깊은바다거북

개발 공부 기록

TIL | WIL

3/16 목 (Geolocation API와 Kakao Map으로 위치 인증 간단히 구현하기) TIL

2023. 4. 7. 21:56

(최종 프로젝트 진행중)

할 일

  • Date input타입을 서버로 보내기
  • 시작 날짜와 끝 날짜를 requests 테이블에 저장하기
  • ‘모집중|모집완료’ 컬럼을 requests 테이블에 추가하기
  • ‘작성 완료’ 버튼 ajax 연결하기
  • 수정하기 페이지에 기본 글과 함께 불러와놓기
  • 작성자 본인이면 수정하기 및 삭제 버튼이 나타나도록 하기
  • ‘수정 완료’ 버튼 ajax 연결하기
  • ‘모집중’→’모집완료’로 바꿀 방법 생각하기
  • 삭제는 마이페이지에 가서 하도록 할 생각. ?

  • user에게서 받은 집주소로 geoCoder.address…()으로 좌표와 동네명 얻기.
  • ‘처음에 테이블 구조를 단순히 address만 있는 항목으로 만들어서 아직 수정하지 못했다”


※ 이하는 스스로 공부하며 적어둔 노트이며 불확실한 내용이 있을 수 있습니다. 학습용으로 적합하지 않음을 유념해주세요. ※

  • (4/12 수정 완료) 다음 우편번호 찾기 API와 카카오 맵 API, HTML5의 Geolocation 웹 API를 이용하여 구현한 최종 ‘위치 인증’ 코드는 다음과 같다:
    • myPage.ejs
      <script defer type="text/javascript" src="/js/myPage/myPage.js"></script>
      
      <!-- 다음 우편번호 찾기 API -->
      <script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
      
      <!-- Kakao Map API -->
      <script src="//dapi.kakao.com/v2/maps/sdk.js?appkey=<%= KAKAO_APP_KEY %>&libraries=services" type="text/javascript"></script>
      
      <div class="title">
          마이 페이지
      </div>
      
      <div class="userContainer">
        <div class="subTitle" id="humanTitle">
          집사 정보
        </div>
        <div class="humanInfo">
          
        </div>
          
      </div>
      ...

    • myPage.js
      // '주소 검색' 버튼 클릭시 다음 우편번호 찾기 api로 주소 검색
      function findAddress() {
        new daum.Postcode({
          oncomplete: function (data) {
            let address_road = data.address; // 최종 도로명 주소
            let address_bname = data.bname ? data.bname : ''; // 동 (지번주소)
      
            // 주소 정보를 해당 필드에 넣는다.
            document.getElementById('address_road').value = address_road;
            document.getElementById('address_bname').value = address_bname;
          },
        }).open();
      }
      
      // '내 위치로 동네 인증' 버튼 클릭시 사용자의 현재 위치를 얻어와 주소지와 비교,
      // 동네명이 같거나 기록된 주소<->현재위치 거리가 5km 이내라면 동네 인증 처리
      function verifyLocation() {
        //주소-좌표 변환 객체를 생성
        let geocoder = new daum.maps.services.Geocoder();
      
        // 유저의 도로명 주소와 동네명을 불러온다 -> DB에서 직접 불러오는 것으로 변경
        let userAddress = user.address_road;
        let userAddressBname = user.address_bname;
      
        // 새 주소찾기를 하였지만 아직 수정 버튼을 눌러 DB를 업데이트하지 않은 상황이면
        if (user.address_road != document.getElementById('address_road').value) {
          alert('수정 버튼을 눌러 정보 업데이트 후 진행해주세요');
          return;
        }
      
        // geolocation.getCurrentPosition 성공시 콜백
        function success(position) {
          // 유저의 현재 위치(좌표)를 불러온다
          const { latitude, longitude } = position.coords;
      
          // 1. 유저가 기입한 주소와 유저의 현재 위치 사이의 거리를 측정하여 비교한다.
          // 2. 유저기 기입한 주소와 유저가 현재 위치한 동네명을 구하여 비교한다.
          // => 3. 둘 중 하나라도 통과하면 위치 인증으로 처리한다. 
      
          // DB로부터 얻어온 유저의 도로명 주소로 좌표 검색 
          geocoder.addressSearch(userAddress, function (results, status) {
            if (status === daum.maps.services.Status.OK) {
              let result = results[0];
              
              // 1. kakao map api를 이용하여 두 좌표 사이의 거리 측정하기
              // 주소로 검색해 kakao map 좌표 객체를 얻고
              let userAddressCoords = new daum.maps.LatLng(result.y, result.x);
              // 현재 좌표로 kakao map 좌표 객체를 얻어서
              let userCurrentCoords = new daum.maps.LatLng(latitude, longitude);
      
              // 두 좌표를 경로로 하는 폴리라인 설정 후 길이 측정
              let line = new kakao.maps.Polyline();
              let path = [userAddressCoords, userCurrentCoords];
              line.setPath(path);
      
              const isInRadius = line.getLength() <= 5000;
      
              // 2. kakao map api를 이용하여 두 좌표의 동네명 비교하기
              geocoder.coord2Address(longitude, latitude, function (results, status) {
                if (status === daum.maps.services.Status.OK) {
                  let result = results[0];
      
                  // 현재 좌표로 동네명 얻고 DB로 부터 불러온 주소값과 비교
                  let userCurrentBname = result.address.region_3depth_name;
                  const isSameBname = userCurrentBname == userAddressBname;
      
                  // 3. 동네명이 같거나 기록된 주소<->현재위치 거리가 5km 이내라면
                  // 사용자의 address_certified 컬럼을 true로 변환시키는 ajax 콜 호출
                  if (isSameBname || isInRadius) {
                    alert('동네 인증을 성공적으로 마쳤습니다! 회원 정보를 수정합니다.');
                    $.ajax({
                      type: 'PATCH',
                      url: `users/address/certify`,
                      contentType: 'application/json; charset=utf-8',
                      data: JSON.stringify({
                        address_certified: true,
                      }),
                      success: function (response) {
                        window.location.reload();
                      },
                      error: function (response) {
                        alert('수정 도중 문제가 발생하였습니다. 관리자에게 문의해주세요')
                        console.log(response);
                      },
                    });
                  } else {
                    alert('현재 위치가 입력된 주소와 다릅니다. 주소를 확인하여 다시 시도하거나 관리자에게 문의해주세요')
                  }
      
                // 좌표로 동네명을 얻어오는 2번 단계 실패
                } else {
                  console.log(
                    'geocoder.coord2Address 도중 문제가 생겼습니다. 상태코드: ',
                    status
                  );
                  return;
                }
              });
      
            // 도로명으로 좌표값을 얻어오는 1번 단계 실패
            } else {
              console.log(
                'geocoder.addressSearch 도중 문제가 생겼습니다. 상태코드: ',
                status
              );
              return;
            }
          });
        }
      
        // geolocation.getCurrentPosition 실패시 콜백
        function error() {
          alert('위치 정보를 불러올 수 없습니다.');
        }
      
        // 실행 가능한 환경이라면 geolocation으로 사용자의 현재 좌표 정보에 접근
        if (!navigator.geolocation) {
          alert(
            '현재 브라우저로는 위치 서비스를 이용하실 수 없습니다. 다른 브라우저로 접속하거나 관리자에게 문의해주세요'
          );
        } else {
          return navigator.geolocation.getCurrentPosition(success, error);
        }
      }

    • ejs-render.controller.ts에서는 KAKAO_APP_KEY 값을 대략 이렇게 넘겨주고 있다:
      // src/ejs-render/ejs-render.controller.ts
      
      @Controller()
      export class EjsRenderController {
        constructor(
          private readonly configService: ConfigService,
      		...
        ) {}
      
      @Get('/mypage')
      @Render('index')
      myPage(@Req() req) {
        const KAKAO_APP_KEY = this.configService.get<string>('KAKAO_APP_KEY');
        return {
          components: 'myPage',
          userId: req.userId,
          KAKAO_APP_KEY,
          user: req.user,
        };
      }


Uploaded by N2T

    'TIL | WIL' 카테고리의 다른 글
    • 3/18 토 (localhost에 HTTPS 연결하기와 Geolocation 웹 API 실험) TIL, TIT
    • 3/17 금 (<img> 경로 설정 문제) TIL, TIT
    • 3/15 수 (Kakao Map으로 위치 서비스 만드는 중) TIL
    • 3/14 화 (ejs는 일일이 눈으로 검사해서 에러를 찾아야 함이 불편) TIL, TIT
    깊은바다거북
    깊은바다거북

    티스토리툴바