React와 openweathermap api를 이용해 오늘의 날씨 및 사용자의 위치정보를 얻는 연습을 했다.

이전에 노마드 코더님의 모멘텀 클론코딩 실습을 할 때에도 사용했던 동일한 기능을 이번에는 React에서 해보기로 마음먹었다.

 

핵심 기능

  • JS 제공 Geolocaltion API (사용자 위치정보 얻기)
  • axios + useEffect(API 정보 불러오기)

완성본


import './index.css';
import axios from 'axios';
import { useState, useEffect } from 'react';

export default function App() {
  
  const [coords, setCoords] = useState();
  const [datas, setDatas] = useState();
    
   function handleGeoSucc(position) {
    const latitude = position.coords.latitude;
    const longitude = position.coords.longitude;
    const coordsObj = {
      latitude,
      longitude
    }
    setCoords(coordsObj);
    getWeather(latitude, longitude);
  }

  function handleGeoErr(err) {
    console.log("geo err! " + err);
  }

  function requestCoords() {
    navigator.geolocation.getCurrentPosition(handleGeoSucc, handleGeoErr);
  }

  function getWeather(lat, lon) {
    const API_KEY = `User's API KEY`;
    const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}&units=metric`;
    axios.get(url)
      .then((res)=> {
        setDatas(res.data);
      })
  }

  useEffect(() => {
    requestCoords();
  }, []);

  
    
  return (
    <div id='main_container'>
      <div className='weather_card'>
        <h2 className='location'>{datas && datas.name}</h2>
        <p className='temp'><span className='tag'>현재 온도 : </span>{datas && Math.floor(datas.main.temp)}°C</p>
        <p className='weather'><span className='tag'>날씨 : </span>{datas && datas.weather[0].main}</p>
        <p className='weather'><span className='tag'>습도 : </span>{datas && datas.main.humidity}%</p>
      </div>
    </div>
  )
}

React 코드

 

openweathermap API를 통해 날씨 정보를 불러오기 위해서는 먼저 사용자의 위도와 경도를 얻는 작업이 필요하다.

 

이를 위해 JS에서 제공하는 navigator.geolocation API를 이용해 사용자의 위도 및 경도를 얻는 작업을 먼저 수행한다.

 

Geolocation API에는 getCurrentPosition()이라는 함수가 있다.

getCurrentPosition() 함수를 사용하기 위해서는 기본적으로 두개의 함수를 인자로 받는데, 하나는 위치정보 요청을 성공했을 때 불러올 함수와 실패했을 때 불러올 함수이다. 위의 handleGeoSucc(), handleGeoErr() 함수이다(함수명은 임의로 작명 가능).

 

handleGeoSucc() 함수에는 추가로 position이라는 유용한 인자를 받아올 수 있는데, 그 안에는 사용자의 위치값이 포함되어 있다.

나는 사용자의 위도와 경도값이 필요했기에

position.coords.latitude(위도)와 position.coords.latitude(경도) 값을 받아왔다.

그 후에 state 변경함수를 통해 값 넘겨주기.

 

위도, 경도값을 성공적으로 받아왔다면 useEffect Hook을 통해 비동기 상태로 만들어준다.

 

그 후로는 간단하다. 

openweathermap API에서 제공하는 url을 axios로 불러와 화면에 뿌려준다.

내가 이번에 사용한 api는 Current Weather Data api(무료)이다.

설명에는 약 20만 개 이상의 도시와 날씨 정보를 제공하고 있다고 한다 ㅎㅎ..

 

** openweathermap -- 회원가입 및 api 키 발급 무료. 일부 기능은 유료이다.

 


이번 프로젝트는 사용자의 위도, 경도값을 비동기로 얻는 과정이 생각보다 어려웠다.

위의 함수들을 모두 useEffect에 넣어봤다가 빼봤다가... 

결국 구글링으로 해결.

 

마지막으로 데이터 값을 뿌려줄 때 {datas && datas.name}와 같이 조건문을 사용해서 에러를 해결했는데, 뭔가 찜찜하다. 

다른 해결방법이 분명 있을 것만 같은데,,,

더 좋은 방법이 없는지 찾아봐야겠다.