본문 바로가기

React Native

React Native 날씨앱 만들기2 (노마드코더)

React Native 날씨앱 만들기1 (노마드코더)Weather API를 사용해서 날씨를 가져올 것이다.

사용할 API는 유명한 OpenWeatherMap API를 사용한다.

https://openweathermap.org/api

 

Weather API - OpenWeatherMap

Please, sign up to use our fast and easy-to-work weather APIs for free. In case your requirements go beyond our freemium account conditions, you may check the entire list of our subscription plans. You can read the How to Start guide and enjoy using our po

openweathermap.org

 

1. API Key 받기

회원가입을 하게 되면 사용자에 대한 API Key 값이 나오게 된다.

해당 API를 App.js에 선언하여 추가해준다.

const API_KEY = `~~~~~~~`;

지금은 무료 API Key를 사용하고 있음으로 공개적인 부분에 Key 값을 선언하여 사용하여도 무관하지만,

추후 돈을 내고 API Key를 사용하거나 실제 프로젝트에서는 Key 값을 보이도록 선언해서 사용하면 안 된다.

보통 서버에 저장해두었다가 불러오는 형식으로 사용한다.

선언할 때 주의할 점은 쌍따옴표 혹은 작은따옴표를 사용하는 것이 아닌 1번 옆에 있는~ 표시를 사용하여 선언해주어야한다. (`선언할 때 주의`);

 

2. One Call API

그 다음 사용해줄 것은 One Call API를 사용할 것이다.

API Doc을 클릭하여 문서를 보면 된다.

문서를 보면 알 수 있다시피 여기서 제공해주는 것은 우리 지역의 현재 날씨 등을 제공해주고 있다.

 

문서의 밑에 부분을 보면 어떻게 API를 call 할 수 있는지가 설명되어있다.

해당 내용을 참고하여 API를 call해줄 것이다. 

 

setCity 해줬던 부분 밑에 fetch를 만들어주자!

...이하생략
setCity(location[0].city);
fetch('https://api.openweathermap.org/data/2.5/onecall?lat={lat}&lon={lon}&exclude={part}&appid={API key}');

{} 이렇게 되어있는 부분은 해당 값을 가져와서 붙이기만 하면 된다.

const response = await fetch("https://api.openweathermap.org/data/2.5/onecall?lat=${latitude}&lon=${longitude}&exclude=alerts&appid=${API_KEY}");

fetch 해오는 부분 중에 가져와서 붙일 수 없는 부분이 있다.

exclude=${part}이다.

이 부분은 문서에서 확인해볼 수 있고 시간을 가져오는 부분이라는 것을 알 수 있다.

해당 부분은 alerts를 사용해서 제외시키자!

const [days, setDays] = useState([]);

const response = await fetch("https://api.openweathermap.org/data/2.5/onecall?lat=${latitude}&lon=${longitude}&exclude=alerts&appid=${API_KEY}");
const json = await response.json();
// setDays(json.daily);

fetch 해온 값을 response로 받아서 json 형태로 치환해줄 것이다.

 

값을 가져오고 셋팅하는 부분은 끝이 났다.

이제는 View에서 해당 값이 보일 수 있도록 앞단을 만들어보자.

 

3. View 앞단 만들기

만약 불러올 값이 없다면 로딩하는 표시를 띄워주고 싶다.

해당 표시를 띄우기 위해서 ActivityIndicator라는 React Native 공식 문서에서 제공해주는 API를 사용할 것이다.

일단 import 해주자!

https://reactnative.dev/docs/activityindicator

 

ActivityIndicator · React Native

Displays a circular loading indicator.

reactnative.dev

import {  ActivityIndicator } from 'react-native';

그리고 View에 하드코딩 되어있던 부분을 삭제하고 아래와 같이 수정해줄 것이다.

return <View style={styles.container}>
      <View style={styles.city}>
        <Text style={styles.cityName}>{city}</Text>
      </View>
      <ScrollView 
        pagingEnabled 
        horizontal 
        showsHorizontalScrollIndicator={false}
        contentContainerStyle={styles.weather}
      >
        {days.length === 0 ? (
          <View style={styles.day}>
            <ActivityIndicator color="white" 
                               style={{marginTop: 10}} 
                               size="large" />
          </View>
        ) : (
          <View style={styles.day}>
          
          </View>
        )}
      </ScrollView>
    </View>;

json으로 치환하여 setDays하여 days에 셋팅해놓았다.

days의 length가 0일 경우, 즉 아무런 데이터도 불러오지 못하였을 경우, 우리는 로딩 표시를 넣어줄 것이다.

문서에서도 알 수 있다시피 기본 형태는 밑줄 쳐져있는 형태이다.

여러가지 스타일을 주어 원하는 형태로 만들어주면 된다.

그리고 setDays 부분을 주석 해제 시키면 해당 로딩 표시가 없어지는 것을 확인할 수 있다.

 

만약에 days의 length가 0이 아닐 경우의 View도 만들어보자.

이 경우에는 Weather API를 사용해서 값을 가져와야한다.

일단 문서를 보면서 내가 긁어오고 싶은 내용을 정리하면 된다.

가져오고 싶은 값은 아래처럼 정리하였다. 

1) 온도 (temp)

2) 날씨 (weather.main)

3) 자세한 날씨 설명 (weather.description)

이런 식으로 긁어올 것이다.

weather은 "[]" 배열로 이루어져있는 것을 확인할 수 있을 것이다.

배열이므로 [0].~~~ 이런 형태로 가져와야하는 것만 주의해서 가져오면 된다. 

 (
	days.map( (day, index) => 
		<View key={index} style={styles.day}>
 			<Text style={styles.temp}>{day.temp.day}</Text>
			<Text style={styles.description}>{day.weather[0].main}</Text>
			<Text style={styles.tinyText}>{day.weather[0].description}</Text>
		</View>
)

저장하고 뜨는 화면을 확인하면 날씨의 셋팅이 마음에 들지 않을 것이다.

숫자의 형태를 미터형식으로 바꿔주자.

바꿔주는 방법은 API에서 가져올 때 파라미터를 붙여서 가져오면 된다.

&units=metric
const response = await fetch(
	`https://api.openweathermap.org/data/2.5/onecall?lat=${latitude}&lon=${longitude}&exclude=alerts&appid=${API_KEY}&units=metric`
 );
const json = await response.json();
setDays(json.daily);

셋팅하는 방법은 toFixed() 메서드를 사용해서 소수점도 지정할 수 있다.

나는 소수점 아래로 숫자 하나만 나오게 셋팅할 것이다.

또한, 숫자 크기가 너무 크므로 parseFloat() 메서드를 사용하여 핸드폰 크기에 숫자를 맞춰줄 것이다.

(
	days.map( (day, index) => 
		<View key={index} style={styles.day}>
			<Text style={styles.temp}>{parseFloat(day.temp.day).toFixed(1)}</Text>
            <Text style={styles.description}>{day.weather[0].main}</Text>
            <Text style={styles.tinyText}>{day.weather[0].description}</Text>
        </View>
)

그러면 아래와 같은 화면이 나올 것이다.

전체적인 기능 구현은 끝이 났다.

 

SMALL