[DAY - 101] #10 개인프로젝트 '오늘 하날'

2023. 7. 26. 21:00·🔥 부트캠프-웹 개발 🔥/오늘하날(개인프로젝트)

게시글, 궁금해요 질문/답변을 업로드할 때 현재 위치와 날씨가 같이 저장된다.

오늘은 해당 기능을 구현해보기 위해 여러 가지 방법을 알아보았다.

 

1) 현재 위치

 

현재 위치는 geolocation을 사용하여 비교적 쉽게 구현할 수 있었다.

https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API/Using_the_Geolocation_API

 

Using the Geolocation API - Web APIs | MDN

The Geolocation API is used to retrieve the user's location, so that it can for example be used to display their position using a mapping API. This article explains the basics of how to use it.

developer.mozilla.org

import React, { Component } from 'react';

class GeolocationKakaoAPI extends Component {
  state = {
    latitude: null,
    longitude: null,
    address: '',
    error: null,
  };

  componentDidMount() {
    if (navigator.geolocation) {
      // Geolocation API를 지원하는 경우
      navigator.geolocation.getCurrentPosition(
        this.handleSuccess,
        this.handleError
      );
    } else {
      // Geolocation API를 지원하지 않는 경우
      this.setState({ error: 'Geolocation is not supported in this browser.' });
    }
  }

  handleSuccess = (position) => {
    const { latitude, longitude } = position.coords;
    this.setState({ latitude, longitude });
  };

  handleError = (error) => {
    this.setState({ error: error.message });
  };


  render() {
    const { latitude, longitude, error } = this.state;
    console.log(this.state);
    return (
      <div>
        {error ? (
          <p>Error: {error}</p>
        ) : (
          <p>
            Latitude: {latitude}, Longitude: {longitude}
            <br />
          </p>
        )}
      </div>
    );
  }
}

export default GeolocationKakaoAPI;

위도 경도

2) 위경도 주소 변환

 

위도와 경도값을 가져왔으면 XX시 XX구와 같은 행정구역으로 변환을 해야 한다.

이 부분은 kakao api를 사용했다.

https://developers.kakao.com/docs/latest/ko/local/dev-guide#coord-to-district

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

응답 예시

import React, { Component } from 'react';

class GeolocationKakaoAPI extends Component {
  state = {
    latitude: null,
    longitude: null,
    address: '',
    error: null,
  };

  componentDidMount() {
    if (navigator.geolocation) {
      // Geolocation API를 지원하는 경우
      navigator.geolocation.getCurrentPosition(
        this.handleSuccess,
        this.handleError
      );
    } else {
      // Geolocation API를 지원하지 않는 경우
      this.setState({ error: 'Geolocation is not supported in this browser.' });
    }
  }

  handleSuccess = (position) => {
    const { latitude, longitude } = position.coords;
    this.setState({ latitude, longitude });

    // Kakao 지도 API로 Reverse Geocoding 요청
    this.getKakaoAddress(latitude, longitude);
  };

  handleError = (error) => {
    this.setState({ error: error.message });
  };

  getKakaoAddress = (latitude, longitude) => {
    const KAKAO_API_KEY = 'key'; // 본인의 Kakao API 키로 대체

    // Kakao 지도 API로 Reverse Geocoding 요청
    fetch(
      `https://dapi.kakao.com/v2/local/geo/coord2regioncode.json?x=${longitude}&y=${latitude}`,
      {
        headers: {
          Authorization: `KakaoAK ${KAKAO_API_KEY}`,
        },
      }
    )
      .then((response) => response.json())
      .then((data) => {
        const address =
          data.documents.length > 0 ? data.documents[0].address_name : 'Unknown';
        this.setState({ address });
      })
      .catch((error) => {
        this.setState({ error: 'Failed to get address from Kakao API.' });
      });
  };

  render() {
    const { latitude, longitude, address, error } = this.state;

    return (
      <div>
        {error ? (
          <p>Error: {error}</p>
        ) : (
          <p>
            Latitude: {latitude} <br/>Longitude: {longitude}
            <br />
            Address: {address}
          </p>
        )}
      </div>
    );
  }
}

export default GeolocationKakaoAPI;

위경도와 주소

 

address_name을 모두 출력했으므로 시/구/동까지 나왔는데 아마 해당 프로젝트에선 시/구까지만 사용할 것 같다.

 

3) 기상청 API

 

현재 위치를 기반으로 한 날씨를 가져오기 위해 기상청 API를 사용했다.

https://www.data.go.kr/data/15084084/openapi.do

 

기상청_단기예보 ((구)_동네예보) 조회서비스

초단기실황, 초단기예보, 단기((구)동네)예보, 예보버전 정보를 조회하는 서비스입니다. 초단기실황정보는 예보 구역에 대한 대표 AWS 관측값을, 초단기예보는 예보시점부터 6시간까지의 예보를,

www.data.go.kr

 

공공 API를 사용하려면 공공데이터포털에 가입을 한 후 활용신청을 하면 바로 사용이 가능하다.

출력되는 JSON의 형식을 보기 위해 예시를 확인했다.

 

기상청

{
  "response": {
    "header": {
      "resultCode": "00",
      "resultMsg": "NORMAL_SERVICE"
    },
    "body": {
      "dataType": "JSON",
      "items": {
        "item": [
          {
            "baseDate": "20230726",
            "baseTime": "1700",
            "category": "PTY",
            "nx": 55,
            "ny": 127,
            "obsrValue": "0"
          },
          {
            "baseDate": "20230726",
            "baseTime": "1700",
            "category": "REH",
            "nx": 55,
            "ny": 127,
            "obsrValue": "81"
          },
          {
            "baseDate": "20230726",
            "baseTime": "1700",
            "category": "RN1",
            "nx": 55,
            "ny": 127,
            "obsrValue": "0"
          },
          {
            "baseDate": "20230726",
            "baseTime": "1700",
            "category": "T1H",
            "nx": 55,
            "ny": 127,
            "obsrValue": "28.8"
          },
          {
            "baseDate": "20230726",
            "baseTime": "1700",
            "category": "UUU",
            "nx": 55,
            "ny": 127,
            "obsrValue": "2.9"
          },
          {
            "baseDate": "20230726",
            "baseTime": "1700",
            "category": "VEC",
            "nx": 55,
            "ny": 127,
            "obsrValue": "258"
          },
          {
            "baseDate": "20230726",
            "baseTime": "1700",
            "category": "VVV",
            "nx": 55,
            "ny": 127,
            "obsrValue": "0.6"
          },
          {
            "baseDate": "20230726",
            "baseTime": "1700",
            "category": "WSD",
            "nx": 55,
            "ny": 127,
            "obsrValue": "3"
          }
        ]
      },
      "pageNo": 1,
      "numOfRows": 1000,
      "totalCount": 8
    }
  }
}

 

입력한 X좌표, Y좌표 위치의 날씨 정보 기준이 되는 날짜, 시간을 확인할 수 있다.

category는 어떠한 정보인지 알려주고 obsrValue에 해당 정보의 값이 나와있다.

정확이 어떤 값을 의미하는지 알아보려면 가이드의 워드 파일을 확인하면 된다.

 

가이드

 

내가 원하는 초단기실황의 category에는 기온, 강수량, 습도, 풍속등 여러 정보가 나온다.

 

하지만 해당 기상청 API를 사용하려면 위도 경도 값을 input 하는 것이 아닌 X좌표, Y좌표를 입력해야 한다. 

만약 위도와 경도를 그대로 사용하게 되면 obsrValue값이 -999로 출력된다.

 

 

4) 위도경도 좌표계 변환

 

geolocation를 이용해 위도와 경도를 받아왔다면 기상청 API에 사용하기 위해 변환이 필요하다.

proj4 라이브러리를 추가해 보고 다른 블로그의 글을 참고해 보았지만 실패했고 가이드에 나와있는 변환 코드를 javascript로 다른 분이 업로드해주신 것을 찾았다.

 

가이드

https://gist.github.com/fronteer-kr/14d7f779d52a21ac2f16

 

기상청 격자 <-> 위경도 변환

GitHub Gist: instantly share code, notes, and snippets.

gist.github.com

 

위 Gist에는 javascript 외에 C#, 파이썬, 안드로이드 등 코드들이 있었다.

해당 코드에선 XY 좌표와 위도경도를 서로 원하는 방식으로 변환할 수 있었는데, 나는 위도 경도로 XY좌표를 구하는 한 가지 방식만 필요하기에 함수를 호출할 때 쓸 매개변수도 지우고 if문도 생략했다.

 

import React from 'react';

class MyComponent extends React.Component {
  // LCC DFS 좌표변환을 위한 기초 자료
  RE = 6371.00877; // 지구 반경(km)
  GRID = 5.0; // 격자 간격(km)
  SLAT1 = 30.0; // 투영 위도1(degree)
  SLAT2 = 60.0; // 투영 위도2(degree)
  OLON = 126.0; // 기준점 경도(degree)
  OLAT = 38.0; // 기준점 위도(degree)
  XO = 43; // 기준점 X좌표(GRID)
  YO = 136; // 기준점 Y좌표(GRID)

  dfs_xy_conv = (v1, v2) => {
    let DEGRAD = Math.PI / 180.0;
    let RADDEG = 180.0 / Math.PI;

    let re = this.RE / this.GRID;
    let slat1 = this.SLAT1 * DEGRAD;
    let slat2 = this.SLAT2 * DEGRAD;
    let olon = this.OLON * DEGRAD;
    let olat = this.OLAT * DEGRAD;

    let sn = Math.tan(Math.PI * 0.25 + slat2 * 0.5) / Math.tan(Math.PI * 0.25 + slat1 * 0.5);
    sn = Math.log(Math.cos(slat1) / Math.cos(slat2)) / Math.log(sn);
    let sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5);
    sf = Math.pow(sf, sn) * Math.cos(slat1) / sn;
    let ro = Math.tan(Math.PI * 0.25 + olat * 0.5);
    ro = re * sf / Math.pow(ro, sn);
    let rs = {};
    rs['lat'] = v1;
    rs['lng'] = v2;
    let ra = Math.tan(Math.PI * 0.25 + v1 * DEGRAD * 0.5);
    ra = re * sf / Math.pow(ra, sn);
    let theta = v2 * DEGRAD - olon;
    if (theta > Math.PI) theta -= 2.0 * Math.PI;
    if (theta < -Math.PI) theta += 2.0 * Math.PI;
    theta *= sn;
    rs['x'] = Math.floor(ra * Math.sin(theta) + this.XO + 0.5);
    rs['y'] = Math.floor(ro - ra * Math.cos(theta) + this.YO + 0.5);
    return rs;
  };

  componentDidMount() {
    // Example usage:
    let rs = this.dfs_xy_conv(37, 126);
    console.log(rs.x, rs.y);
  }

  render() {
    return <div>React Component</div>;
  }
}

export default MyComponent;

XY좌표
가이드

 

위도 37과 경도 126을 넣었을 때 X 55 Y 124 좌표가 변환이 잘 되는 것을 확인할 수 있다.

'🔥 부트캠프-웹 개발 🔥/오늘하날(개인프로젝트)' 카테고리의 다른 글
  • [DAY - 108] #12 개인프로젝트 '오늘 하날'
  • [DAY - 102] #11 개인프로젝트 '오늘 하날'
  • [DAY - 99] #9 개인프로젝트 '오늘 하날'
  • [DAY - 98] #8 개인프로젝트 '오늘 하날'
Yeonhub
Yeonhub
✨ https://github.com/yeonhub 📧 lsy3237@gmail.com
  • Yeonhub
    비 전공자의 Be developer
    Yeonhub
  • 전체
    오늘
    어제
    • 전체보기 (169)
      • 🔍 Tech 🔍 (19)
        • Front-End (11)
        • Back-End (4)
        • AI (1)
        • Server (1)
        • Etc (2)
      • 💡 원티드 프리온보딩 챌린지 💡 (14)
        • PRE-ONBOARDING_AI (11월) (1)
        • PRE-ONBOARDING_FE (2월) (2)
        • PRE-ONBOARDING_FE (1월) (2)
        • PRE-ONBOARDING_FE (12월) (9)
      • 🔥 부트캠프-웹 개발 🔥 (118)
        • HTML5 (7)
        • CSS3 (21)
        • JavaScript (27)
        • JavaScript_advanced (9)
        • React (24)
        • Next (1)
        • MYSql (5)
        • Node (5)
        • 오늘하날(개인프로젝트) (12)
        • 이젠제주투어(팀프로젝트) (7)
      • 💻 CS 💻 (1)
        • 알고리즘 (1)
      • ⚡ 코딩테스트 ⚡ (11)
        • JavaScript (11)
      • 📚 Books 📚 (6)
        • 클린 아키텍처 (2)
        • 인사이드 자바스크립트 (4)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Github
  • 공지사항

  • 인기 글

  • 태그

    Node
    react native firebase analytics
    expo map
    bottom sheet
    라스콘4
    expo admob
    프론트엔드 테스트코드
    expo deep linking
    expo fcm
    expo node fcm
    node.js fcm
    expo fcm push
    react native admob
    python node
    php node
    react native expo fcm
    javascript fcm
    node crontab
    컴파운드 컴포넌트 패턴
    react vite
    expo 지도
    expo 길찾기
    node fcm
    react native analytics
    node cron
    rn bottom sheet
    rn admob
    expo google map
    라스콘
    react native bottom sheet
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Yeonhub
[DAY - 101] #10 개인프로젝트 '오늘 하날'
상단으로

티스토리툴바