Skip to content

Create Weather information Application by using React-Native (리액트 네이트브로 날씨 정보앱 개발)

Notifications You must be signed in to change notification settings

chihyeonwon/NomadWeather

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Create Weather information Application by using React-Native (리액트 네이트브로 날씨 정보앱 개발)

프로젝트 시작

프로젝트 NomadWeather를 다음 명령으로 실행한다.

expo init 프로젝트명

다음 명령으로 expo 아이디, 비밀번호를 기입하여 로그인을 시도한다.

expo login

로그인이 완료되면 다음 명령으로 휴대폰에서 expo 어플리케이션을 통해 시뮬레이터를 작동할 수 있다.

npm start

기본 레이아웃 지정

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>

    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "tomato",
  },
});

날씨를 측정할 도시 이름와 기온, 날씨 정보를 생성

날씨를 측정할 도시 이름 생성

<View style={styles.city}>
        <Text style={styles.cityName}>Seoul</Text>
      </View>

스타일

city:{
    flex: 1,
    justifyContent: 'center',
    alignItems:'center',
  },  
  cityName:{
    fontSize: 68,
    fontWeight: "500",
  }, 

기온과 날씨 정보 생성

<View style={styles.weather}>
        <View style={styles.day}>
          <Text style={styles.temp}>27</Text>
          <Text style={styles.desc}>Sunny</Text>
        </View>
      </View>

스타일

day: {
    justifyContent:'center',
    alignItems:'center',
  },
  temp: {
    marginTop: 50,
    fontSize: 178,
  },
  desc: {
    marginTop: -30,
    fontSize: 60,

weather안의 day View를 여러개 생성하고 weather를 ScrollView로 변경

스크롤기능을 제공하는 API인 ScrollView를 Import 해준다.

import {ScrollView} from 'react-native'

그리고 weather를 ScrollView로 감싸준다.

<ScrollView style={styles.weather}>
        <View style={styles.day}>
          <Text style={styles.temp}>27</Text>
          <Text style={styles.desc}>Sunny</Text>
        </View>
        <View style={styles.day}>
          <Text style={styles.temp}>27</Text>
          <Text style={styles.desc}>Sunny</Text>
        </View>
        <View style={styles.day}>
          <Text style={styles.temp}>27</Text>
          <Text style={styles.desc}>Sunny</Text>
        </View>
        <View style={styles.day}>
          <Text style={styles.temp}>27</Text>
          <Text style={styles.desc}>Sunny</Text>
        </View>
        <View style={styles.day}>
          <Text style={styles.temp}>27</Text>
          <Text style={styles.desc}>Sunny</Text>
        </View>
        <View style={styles.day}>
          <Text style={styles.temp}>27</Text>
          <Text style={styles.desc}>Sunny</Text>
        </View>
      </ScrollView>
    </View>

스크롤을 수직이 아닌 수평으로 만들어주는 horizontal 속성을 ScrollView에 적용

<ScrollView horizontal style={styles.weather}>

ScrollView 사용시 생기는 문제점

weather와 day의 flex 값을 삭제한다. (ScrollView가 ScrollView의 Childern보다 커야하기 때문)

weather:{
    backgroundColor:'blue',
  },
  day: {
    alignItems:'center',
  },

ScrollView의 style을 contentContainerStyle로 수정한다.

<ScrollView horizontal contentContainerStyle={styles.weather}>

Dimensions로 사용자의 디바이스의 크기를 측정

react-native의 Dimensions를 import한다.

import {Dimensions} from 'react-native';

사용자 디바이스의 가로 너비를 Dimensions의 get 메서드로 구한 뒤 SCREEN_WIDTH에 저장한다.

const {width: SCREEN_WIDTH} = Dimensions.get('window');

SCREEN_WIDTH를 여러개의 day에 적용한다.

day:{
  width: SCREEN_WIDTH,
  alignItems: 'center',
}

ScrollView에 pagingEnabled 속성을 추가하여 스크롤의 이동을 제한한다.

<ScrollView pagingEnabled horizontal contentContainerStyle={styles.weather}>

ScrollView에 showHorizontalScrollIndicator={false}를 설정하여 Scroll Indicator를 제거

<ScrollView pagingEnabled horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.weather}>

사용자의 위치 정보를 가져오기

다음 명령을 터미널에서 실행하여 expo가 제공하는 위치정보 API를 설치한다.

expo install expo-location

expo-location에서 제공하는 Location을 import한다.

import {Location} from 'expo-location';

사용자의 권한 요청

개발문서 https://docs.expo.dev/versions/latest/sdk/location/#locationrequestpermissionsasync 의 Usage 탭에서 사용자의 권한을 요청하는 requestPermissionAsync()

위치 정보의 상태를 useState 함수에 저장

const [location, setLocation] = useState();
const [ok, setOK] = useState(true);

렌더링 된 후 ask 함수를 호출하는 useEffect 함수 생성

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

ask 함수가 호출되면 앱 사용중에만 위치정보권한을 요청하는 requestForegroundPermissionsAsync() 함수를 호출

const ask = async() => {
    const { granted } = await Location.requestForegroundPermissionsAsync(); // 앱 사용중에만 위치정보권한을 사용하는 requestForegroundPermissionAsync()
    if(!granted) { // 위치정보 권한을 거절하면
      setOk(false); // setOk = false 로 설정
    }
  };

사용자 위치 정보 획득

getCurrentPositionAsync 함수를 사용하여 사용자의 현재 위치에 대한 경도와 위도를 얻기

다음 코드를 실행하여 latitude와 longitude를 얻는다. accuracy는 1 ~ 6의 정확도값을 얻는 속성값이다.

const {coords:{latitude, longitude}} = await Location.getCurrentPositionAsync({accuracy: 5});

reverse Geocoding 사용하기

얻은 사용자 위치의 latitdude와 longitude로 reverse geocoding을 하여 사용자가 위치한 지역의 country, district, isoCountryCode, name, postalCode, region를 가지는 객체를 배열의 형태로 사질 수 있다.

reverseGeocodeAsync 함수의 사용에 앞서 Google Platform 에서 Geolocation API key를 발급받는다.

발급받은 키를 다음과 같이 Location.setGoogleApiKey의 매개변수로 전달한다.

Location.setGoogleApiKey('발급받은 키(영문자,대문자,숫자로 이루어짐)')

API key 설정이 끝나면 reverseGeocodeAsync 함수의 첫번째 매개변수로 얻은 latitude, longitude 값을 넣고 두번째 매개변수로 useGoogleMaps 속성의 값을 false로 설정한다.

const location = await Location.reverseGeocodeAsync({latitude, longitude}, {useGoogleMaps: false});

useState를 사용하여 city, setCity의 초기화면을 ...Loading 으로 설정한다.

const [city, setCity] = useState("...Loading");

setCity의 매개변수로 얻은 객체 중 region 값을 location[0].region으로 전달한다.

setCity(location[0].region

얻은 region 값을 다시 본문의 고정된 city 값을 useState를 사용한 {city}로 전달한다.

<Text style={styles.cityName}>{city}</Text>

날씨 정보 얻기

https://home.openweathermap.org/api_keys 에서 api를 받아와서 API_KEY에 저장한다.

const API_KEY ="발급받은 api키값";

https://openweathermap.org/api/one-call-api 에서 API call의 코드를 복사해서 붙여넣고 앞서 얻은 latitude, longitude, API_KEY 값을 넣어준다.

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

위의 exclude 속성은 minute, hour alert 등 얻는 값중에 제외할 값을 설정할 수 있는데 이때는 alert를 제외한다.

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

json 변수에 response.json()으로 api에서 얻은 데이터를 저장한다.

const json = await response.json();

빈 배열 상태인 useState에 날짜 배열정보를 넣고

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

날짜 json.daily setDays의 useState에 셋팅한다.

 setDays(json.daily);

기존의 day를 모두 삭제하고 삼항연산자로 days의 배열의 길이가 0 이면 ActivityIndicator 를 사용해 로딩 중 표시를 하고 배열의 길이가 0이 아닐때는 날씨 정보를 보여주도록 변경한다.

<ScrollView pagingEnabled horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.weather}>
       {days.length === 0 ? (
         <View style={styles.day}>
           <ActivityIndicator
             color="white"
             style={{ marginTop: 10 }}
             size="large"
           />
         </View>
       ) : (
         days.map((day, index) => (
           <View key={index} style={styles.day}>
             <Text>
                 {new Date(day.dt * 1000).toString().substring(0, 10)}
             </Text>
             <Text style={styles.temp}>
               {parseFloat(day.temp.day).toFixed(1)}
             </Text>
             <Text style={styles.des}>{day.weather[0].main}</Text>
             <Text style={styles.tinyText}>{day.weather[0].description}</Text>
           </View>
         ))
       )}
     </ScrollView>

About

Create Weather information Application by using React-Native (리액트 네이트브로 날씨 정보앱 개발)

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published