사용한 api - OpenWeatherMap
5 day weather forecast - OpenWeatherMap
openweathermap.org
api 사용 방법


OpenWeatherMap 을 들어가면 무료, 유료 사용 가능한 api 가 존재한다
1. API key 가 필요하기 때문에 사이트에 회원가입 해야한다.
2. api key를 받은 것을 확인 후 .env 파일을 생성한다. (.env 파일 앞에 이름은 안 적어도 된다.)
확인은 My API keys 에서 확인하면 되며, 파일 생성은 pakage.json 과 동일한 위치에 두면 된다.



이건 사이트 배포까지 진행할 사람들은 개인정보 보호를 위해 필수로 하는 것이 좋지만,
배포까지 하지 않을 거라면 따로 페이지를 만들지 않고 실습하여도 된다.
3.(API KEY를 .env 파일 내에 넣었다면) .env 파일 내에 REACT_APP_ 으로 시작하도록 환경 변수를 설정 한다.
설정 후 다시 프로젝트를 재 실행해야한다.
REACT_APP_[key이름] = [생성된 api key]
4. 사용할 페이지에 apiKey 를 불러오고, console.log 를 통해 제대로 불러오는지도 확인한다.
여기서 api url을 살펴보면 1. weather, 2. forecast 가 존재한다. 차이는 아래 표와 같다.
weather | forecast |
현재 날씨 정보를 제공, 입력한 도시 이름으로 날씨 데이터를 요청, 해당 도시에 대한 현재 날씨만 반환 |
미래 날씨 예보 정보를 제공, 위도(lat)와 경도(lon)를 사용, 미래 날씨 예보(일반적으로 5일간의 3시간 간격 날씨 예보)를 반환 |
1. weather?q=${}&appid=${}
따로 url을 설정하여도 좋고, await fetch() 괄호 안에 직접 작성해도 된다.
// 환경 변수로 저장한 API 키 호출
const apiKey = process.env.REACT_APP_[key 이름];
console.log("apiKey: ", apiKey);
// url 설정
const url =`https://api.openweathermap.org/data/2.5/weather?q=${region}&appid=${apiKey}&units=metric`;
api 주소 옵션 | &units=metric : 섭씨 변경 | &lang=kr : 한국어도 검색 가능 | cnt : 반환할 데이터 수 |
전체 코드
forecastDataimport React, { useEffect, useState, useCallback } from 'react';
import '../css/main.css';
import '../reset.css';
const WeatherTest = () => {
const [weatherData, setWeatherData] = useState(null); // 날씨 데이터 저장
const [region, setRegion] = useState(''); // 사용자가 입력한 지역
const [inputValue, setInputValue] = useState(''); // 입력 필드의 상태
const [loading, setLoading] = useState(false); // 로딩 상태
const [error, setError] = useState(null); // 오류 상태
// 환경 변수로 저장한 API 키 호출
const apiKey = process.env.REACT_APP_API_KEY;
// console.log("apiKey: ", apiKey);
// fetchWeatherData 함수를 useCallback으로 래핑
const fetchWeatherData = useCallback(async () => {
if (!region) return; // 입력된 지역이 없으면 호출하지 않음
setLoading(true);
setError(null);
// URL 설정, &units=metric - 섭씨 변환
const url = `https://api.openweathermap.org/data/2.5/weather?q=${region}&appid=${apiKey}&units=metric`;
try {
const resp = await fetch(url);
if (!resp.ok) {
throw new Error('API 호출 실패');
}
const data = await resp.json();
// console.log(data);
// 날씨 데이터 상태 저장
setWeatherData(data);
} catch (error) {
console.error("API 호출 실패", error);
setError(error.message); // 오류 메시지 설정
} finally {
setLoading(false);
}
}, [region, apiKey]); // region과 apiKey를 의존성으로 추가
// region이 변경될 때마다 fetchWeatherData 호출
useEffect(() => {
if (region) {
fetchWeatherData();
}
}, [region, fetchWeatherData]); // fetchWeatherData를 의존성으로 추가
const handleSubmit = (e) => {
e.preventDefault();
setRegion(inputValue); // 입력된 값으로 지역 업데이트
fetchWeatherData(); // 날씨 데이터 요청
};
return (
<div className="container">
<form onSubmit={handleSubmit}>
<div className="searchRegion">
<div className='search'>
<h3>원하는 지역을 검색해 주세요 : </h3>
<input type="text" value={inputValue}
onChange={(e) => setInputValue(e.target.value)} />
<button type="submit">검색</button>
</div>
</div>
</form>
{loading ? (
<p>로딩 중...</p>
) : error ? (
<p>{error}</p> // 오류 메시지 표시
) : (
weatherData && (
<div className='result'>
<h4>{weatherData.name} 날씨</h4>
<p>온도: {weatherData.main.temp}°C</p>
<p>상태: {weatherData.weather[0].description}</p>
</div>
)
)}
</div>
);
}
export default WeatherTest;
2. forecast?lat=${lat}&lon=${lon}&appid=${}
1. 우선 바뀌는 옵션은 위도, 경도를 가져와야 한다.
openWeatherMap 에서는 Geocoding 을 사용하라고 하여 api를 가져온다.
// 위도, 경도 가져오는 Geoapi
const geo = `http://api.openweathermap.org/geo/1.0/direct?q=${region}&limit=1&appid=${apiKey}`;

2. try ~ catch 를 사용하여 data를 가져온다.
try{
const geoResp = await fetch(geo);
const geoData = await geoResp.json();
if(geoData.length > 0) {
// 첫 번째 결과에서 위도와 경도 추출
const {lat, lon} = geoData[0];
console.log(geoData[0]);
const url =`http://api.openweathermap.org/data/2.5/forecast?lat=${lat}&lon=${lon}&appid=${apiKey}&units=metric&lang=kr&cnt=5`;
const resp = await fetch(url);
const data = await resp.json();
if(data.cod === '200') {
setForecastData(data);
} else{
throw new Error(data.message);
}
} else {
throw new Error("지역을 찾을 수 없습니다.");
}
geoData[0] console

3. 데이터 출력
{loading ? (
<p>로딩 중...</p>
) : Error ? (
<p>{error}</p>
): (
forecastData && (
<div className='result'>
<h4>{forecastData.city.name} 날씨</h4>
{forecastData.list.map((item) => (
<div key={item.dt}>
<p>날짜: {item.dt_txt}</p>
<p>온도: {item.main.temp}°C</p>
<p>상태: {item.weather[0].description}</p>
</div>
))}
</div>
)
}
전체 코드
import React, {useCallback, useEffect, useState} from 'react'
import '../css/main.css';
import '../reset.css';
const ForecastTest = () => {
const [forecastData, setForecastData] = useState(null); // 미래 날씨 데이터 저장
const [region, setRegion] = useState(''); // 사용자가 입력한 지역
const [inputValue, setInputValue] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
// 환경 변수로 저장한 API 키 호출
const apiKey = process.env.REACT_APP_API_KEY;
const fetchForecastData = useCallback(async () => {
// 입력된 지역이 없으면 호출하지 않음
if (!region) return;
setLoading(true);
setError(null);
// 위도, 경도 가져오는 Geoapi
const geo = `http://api.openweathermap.org/geo/1.0/direct?q=${region}&limit=1&appid=${apiKey}`;
try{
const geoResp = await fetch(geo);
const geoData = await geoResp.json();
if(geoData.length > 0) {
// 첫 번째 결과에서 위도와 경도 추출
const {lat, lon} = geoData[0];
const url =`http://api.openweathermap.org/data/2.5/forecast?lat=${lat}&lon=${lon}&appid=${apiKey}&units=metric&lang=kr&cnt=5`;
const resp = await fetch(url);
const data = await resp.json();
if(data.cod === '200') {
setForecastData(data);
} else{
throw new Error(data.message);
}
} else {
throw new Error("지역을 찾을 수 없습니다.");
}
} catch(error){
console.error("API 호출 실패", error);
setError(error.message);
} finally {
setLoading(false);
}
});
const handleSubmit = (e) => {
e.preventDefault();
setRegion(inputValue);
setInputValue('');
};
useEffect(() => {
if(region) {
fetchForecastData();
}
}, [region, apiKey]);
return(
<div className="container">
<div className='title'>
<h3>forecast test page </h3>
</div>
<form onSubmit={handleSubmit}>
<div className="searchRegion">
<div className='search'>
<h3>원하는 지역을 검색해 주세요 : </h3>
<input type="text" value={inputValue}
onChange={(e) => setInputValue(e.target.value)} />
<button type="submit">검색</button>
</div>
</div>
</form>
{loading ? (
<p>로딩 중...</p>
) : error ? (
<p>{error}</p>
) : (
forecastData && (
<div className='result'>
<h4>{forecastData.city.name} 날씨</h4>
{forecastData.list.map((item) => (
<div key={item.dt}>
<p>날짜: {item.dt_txt}</p>
<p>온도: {item.main.temp}°C</p>
<p>상태: {item.weather[0].description}</p>
</div>
))}
))}
</div>
)
}
export default ForecastTest;
3. 출력 결과


'개인 공부 > 프론트' 카테고리의 다른 글
[React] 공공데이터 기상청 API (정보보관용) (0) | 2024.10.22 |
---|---|
[React] CORS 에러 (0) | 2024.10.16 |
[React] 기본 브라우저 모든 css 제거하기 (0) | 2024.10.12 |
[Spring] 깃허브 : 사이트 배포하기 (서버 내, Github Actions: 실습 예정) (0) | 2024.10.03 |