본문 바로가기

코딩 개발일지

[개발일지]스파르타코딩클럽_앱개발 종합반 4-2 날씨 API

서버API를 통해 날씨정보를 가져와 화면에 출력하기

 

서버 API란?

서버가 제공하는 도메인을 그대로 사용하는 방식

- 날씨 데이터를 제공해주는 일정 요청에 대해선 무료 API를 제공해주는 openweathermap api 를 사용

--------------------------------

API를 통해 날씨 데이터를 가져온다는 것은 다음 순서로 진행

1) 현재 위치(좌표) 데이터 필요, 가져오기 (어디의 날씨인지 알아야 하니까요!)

2) 위치 데이터를 이용해 현재 위치 날씨 데이터 가져오기

--------------------------------

위치데이터 얻는 도구 공식문서 참조

https://docs.expo.dev/versions/latest/sdk/location/

 

Location - Expo Documentation

Expo is an open-source platform for making universal native apps for Android, iOS, and the web with JavaScript and React.

docs.expo.dev

설치방법 : expo install expo-location

--------------------------

MainPage 샘플

import React,{useState,useEffect} from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native';

import data from '../data.json';
import Card from '../components/Card';
import Loading from '../components/Loading';
import { StatusBar } from 'expo-status-bar';
import * as Location from "expo-location";
export default function MainPage({navigation,route}) {
  //useState 사용법
  //[state,setState] 에서 state는 이 컴포넌트에서 관리될 상태 데이터를 담고 있는 변수
  //setState는 state를 변경시킬때 사용해야하는 함수

  //모두 다 useState가 선물해줌
  //useState()안에 전달되는 값은 state 초기값
  const [state,setState] = useState([])
  const [cateState,setCateState] = useState([])

  //하단의 return 문이 실행되어 화면이 그려진다음 실행되는 useEffect 함수
  //내부에서 data.json으로 부터 가져온 데이터를 state 상태에 담고 있음
  const [ready,setReady] = useState(true)

  useEffect(()=>{
    navigation.setOptions({
      title:'나만의 꿀팁'
    })  
    //뒤의 1000 숫자는 1초를 뜻함
    //1초 뒤에 실행되는 코드들이 담겨 있는 함수
    setTimeout(()=>{
        //헤더의 타이틀 변경
        getLocation()
        setState(data.tip)
        setCateState(data.tip)
        setReady(false)
    },1000)
 
   
  },[])

  const getLocation = async () => {
    //수많은 로직중에 에러가 발생하면
    //해당 에러를 포착하여 로직을 멈추고,에러를 해결하기 위한 catch 영역 로직이 실행
    try {
      //자바스크립트 함수의 실행순서를 고정하기 위해 쓰는 async,await
      await Location.requestForegroundPermissionsAsync();
      const locationData= await Location.getCurrentPositionAsync();
      console.log(locationData)

    } catch (error) {
      //혹시나 위치를 못가져올 경우를 대비해서, 안내를 준비합니다
      Alert.alert("위치를 찾을 수가 없습니다.", "앱을 껏다 켜볼까요?");
    }
  }

  const category = (cate) => {
    if(cate == "전체보기"){
        //전체보기면 원래 꿀팁 데이터를 담고 있는 상태값으로 다시 초기화
        setCateState(state)
    }else{
        setCateState(state.filter((d)=>{
            return d.category == cate
        }))
    }
}

  //data.json 데이터는 state에 담기므로 상태에서 꺼내옴
  // let tip = state.tip;
  let todayWeather = 10 + 17;
  let todayCondition = "흐림"
  //return 구문 밖에서는 슬래시 두개 방식으로 주석
  return ready ? <Loading/> :  (
    /*
      return 구문 안에서는 {슬래시 + * 방식으로 주석
    */

    <ScrollView style={styles.container}>
      <StatusBar style="light" />
      {/* <Text style={styles.title}>나만의 꿀팁</Text> */}
       <Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition} </Text>
       <TouchableOpacity style={styles.aboutButton} onPress={()=>{navigation.navigate('AboutPage')}}>
          <Text style={styles.aboutButtonText}>소개 페이지</Text>
        </TouchableOpacity>
      <Image style={styles.mainImage} source={{uri:main}}/>
      <ScrollView style={styles.middleContainer} horizontal indicatorStyle={"white"}>
      <TouchableOpacity style={styles.middleButtonAll} onPress={()=>{category('전체보기')}}><Text style={styles.middleButtonTextAll}>전체보기</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton01} onPress={()=>{category('생활')}}><Text style={styles.middleButtonText}>생활</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton02} onPress={()=>{category('재테크')}}><Text style={styles.middleButtonText}>재테크</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton03} onPress={()=>{category('반려견')}}><Text style={styles.middleButtonText}>반려견</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton04} onPress={()=>{navigation.navigate('LikePage')}}><Text style={styles.middleButtonText}>꿀팁 찜</Text></TouchableOpacity>
      </ScrollView>
      <View style={styles.cardContainer}>
         {/* 하나의 카드 영역을 나타내는 View */}
         {
          cateState.map((content,i)=>{
            return (<Card content={content} key={i} navigation={navigation}/>)
          })
        }
       
      </View>
   
    </ScrollView>)
}

const styles = StyleSheet.create({
  container: {
    //앱의 배경 색
    backgroundColor: '#fff',
  },
  title: {
    //폰트 사이즈
    fontSize: 20,
    //폰트 두께
    fontWeight: '700',
    //위 공간으로 부터 이격
    marginTop:50,
    //왼쪽 공간으로 부터 이격
    marginLeft:20
  },
weather:{
    alignSelf:"flex-end",
    paddingRight:20
  },
  mainImage: {
    //컨텐츠의 넓이 값
    width:'90%',
    //컨텐츠의 높이 값
    height:200,
    //컨텐츠의 모서리 구부리기
    borderRadius:10,
    marginTop:20,
    //컨텐츠 자체가 앱에서 어떤 곳에 위치시킬지 결정(정렬기능)
    //각 속성의 값들은 공식문서에 고대로~ 나와 있음
    alignSelf:"center"
  },
  middleContainer:{
    marginTop:20,
    marginLeft:10,
    height:60
  },
  middleButtonAll: {
    width:100,
    height:50,
    padding:15,
    backgroundColor:"#20b2aa",
    borderColor:"deeppink",
    borderRadius:15,
    margin:7
  },
  middleButton01: {
    width:100,
    height:50,
    padding:15,
    backgroundColor:"#fdc453",
    borderColor:"deeppink",
    borderRadius:15,
    margin:7
  },
  middleButton02: {
    width:100,
    height:50,
    padding:15,
    backgroundColor:"#fe8d6f",
    borderRadius:15,
    margin:7
  },
  middleButton03: {
    width:100,
    height:50,
    padding:15,
    backgroundColor:"#9adbc5",
    borderRadius:15,
    margin:7
  },
  middleButton04: {
    width:100,
    height:50,
    padding:15,
    backgroundColor:"#f886a8",
    borderRadius:15,
    margin:7
  },
  middleButtonText: {
    color:"#fff",
    fontWeight:"700",
    //텍스트의 현재 위치에서의 정렬
    textAlign:"center"
  },
  middleButtonTextAll: {
    color:"#fff",
    fontWeight:"700",
    //텍스트의 현재 위치에서의 정렬
    textAlign:"center"
  },
  cardContainer: {
    marginTop:10,
    marginLeft:10
  },
  aboutButton: {
    backgroundColor:"pink",
    width:100,
    height:40,
    borderRadius:10,
    alignSelf:"flex-end",
    marginRight:20,
    marginTop:10
  },
  aboutButtonText: {
    color:"#fff",
    textAlign:"center",
    marginTop:10
  }


});

외부 API 요청 작업은 try /catch로 감싸야 한다. API 사용 할 때 주로 사용하는 에러 처리 방지 코드로
try{} 부분엔 API요청 같은 작업 코드를,
catch{} 부분엔 에러가 발생 했을 때 실행 할 코드를 작성함

const getLocation = async () => {
  //수많은 로직중에 에러가 발생하면
  //해당 에러를 포착하여 로직을 멈추고,에러를 해결하기 위한 catch 영역 로직이 실행
  try {
    //자바스크립트 함수의 실행순서를 고정하기 위해 쓰는 async,await
    await Location.requestForegroundPermissionsAsync();
    const locationData= await Location.getCurrentPositionAsync();
    console.log(locationData)

  } catch (error) {
    //혹시나 위치를 못가져올 경우를 대비해서, 안내를 준비합니다
    Alert.alert("위치를 찾을 수가 없습니다.", "앱을 껏다 켜볼까요?");
  }
}

-------------------------------

함수 실행 순서를 정해주는 async / await

이는 단순히 외부 API 호출 및 휴대폰 기기에 대한 정보/파일 등에 접근할 때 사용하는 키워드로

쓰는 이유는 함수의 실행 순서를 고정하기 위해서임. 외부 네트워크 작업(API 호출)이나 휴대폰의 파일 시스템 또는 위치정보 가져오기 같이 무거운 작업을들 하는 경우 어떤 작업부터 할지 알수가 없어서 순서를 정해줌

 

1) 외부 API 작업과 
2) 앱이 아닌 휴대폰 자체 기능(위치 정보 권한 물어보기 등)을 
사용할 땐 async / await를 사용

 

사용 할 땐 함수들을 감싸는 함수 선언 부 앞에 async
사용하는 함수들 앞엔 await 입니다

============

이제 쉽게 코드 해석해보면, 가장먼저 위치도구를 쓰겠다고 맨 위에 임포트 부터한다

import * as Location from "expo-location";

getLocation 이라는 함수를 선언하고 async() =>{ 이렇게 시작되는데 화살표는 async function(){ 이걸 줄였을 뿐이고 앞에 async를 붙이는 이유는 await를 사용하기 위해서다.
-------------------
await를 왜 쓰냐면 위에도 적혀있지만 굳이 예를 들자면,
라면을 끓인다고 했을때 1)냄비를 올린다 2)물을 붓는다 3) 불을 켠다 4) 라면을 넣는다 5) 스프를 넣는다 6) 그릇에 옮겨 담는다.
라는 순서로 실행이 되어야 정상적인 라면이 나올텐데 이 순서를 지키지 않고 내맘대로 1>5>3>6>2>4 이런 순서로 실행한다면 아마 이상한 음식이 나올거기 때문에 단계 단계마다 await를 써준다.  
--------------------
이후 나오는 try{} 부분은 에러 발생시 감지하여 -> catch{} (에러 안내 팝업 등) 을 실행시키기 위해서 넣는부분
--------------------
첫번째 await 이후 Location.requestForegroundPermissionsAsync(); 이 부분은 문자 그대로 해석하자면
Location.은 맨 위에 임포트했던 위치도구이고 .점 이 들어갔으니까 이 도구에서 위치권한허락요청을 한다 
request 요청/  Foreground 위치/ Permissions 허락/ Async();  라는 의미 인것 같다.
------------------
이후 locationData 를 선언후에 그 안에 (Location에서 가져온) 현재위치(get CurrentPosition) 정보를 집어 넣는다.
물론 중간에 await이 들어있는 이유는 위치권한을 허락받은 후에야 현재위치를 얻을수 있기 때문에 await이 필요하다  
const locationData= await Location.getCurrentPositionAsync();
----------------------
뒤에 console.log(locationData
콘솔로그는 사실 필요 없는것인데, 어떤 정보가 있는지 궁금할까봐 넣어둔것인데 찍어보면 
"accuracy": 정확도 , "altitude": 고도, "altitudeAccuracy": 고도 정확도, "heading": 방향, "latitude": 위도,  "longitude": 경도,  "speed": 속도 등의 정보가 들어가 있다.
우리가 필요한것은 "latitude": 위도,  "longitude": 경도
------------------------
 
여기까지 locationData안에 현재 위치 정보를 가져오는것까지 성공했다.
이제 날씨 API를 사용해야한다
 
무료 날씨 API 공식문서 
 

Weather API - OpenWeatherMap

Please, sign up to use our fast and easy-to-work weather APIs. As a start to use OpenWeather products, we recommend our One Call API 3.0. For more functionality, please consider our products, which are included in professional collections.

openweathermap.org

--------------------------

서버가 제공하는 도메인 형식의 API를 사용하려면, 사용을 위한 도구 axios 가 필요하다

설치 : yarn add axios

MainPage에서 API사용하는 코드

import React,{useState,useEffect} from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native';

import data from '../data.json';
import Card from '../components/Card';
import Loading from '../components/Loading';
import { StatusBar } from 'expo-status-bar';
import * as Location from "expo-location";
import axios from "axios"

export default function MainPage({navigation,route}) {
 
  const [state,setState] = useState([])
  const [cateState,setCateState] = useState([]
  const [ready,setReady] = useState(true)

  useEffect(()=>{
    navigation.setOptions({
      title:'나만의 꿀팁'
    })  
    setTimeout(()=>{
        getLocation()
        setState(data.tip)
        setCateState(data.tip)
        setReady(false)
    },1000)
  },[])

  const getLocation = async () => {
    try {
      await Location.requestForegroundPermissionsAsync();
      const locationData= await Location.getCurrentPositionAsync();
      console.log(locationData)
      console.log(locationData['coords']['latitude'])
      console.log(locationData['coords']['longitude'])
      const latitude = locationData['coords']['latitude']
      const longitude = locationData['coords']['longitude']
      const API_KEY = "cfc258c75e1da2149c33daffd07a911d";
      const result = await axios.get(
        `http://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}&units=metric`
      );

      console.log(result)

    } catch (error) {
      Alert.alert("위치를 찾을 수가 없습니다.", "앱을 껏다 켜볼까요?");
    }
  }

  const category = (cate) => {
    if(cate == "전체보기"){
        setCateState(state)
    }else{
        setCateState(state.filter((d)=>{
            return d.category == cate
        }))
    }
}

  let todayWeather = 10 + 17;
  let todayCondition = "흐림"
  return ready ? <Loading/> :  
    <ScrollView style={styles.container}>
      <StatusBar style="light" />
      {/* <Text style={styles.title}>나만의 꿀팁</Text> */}
       <Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition} </Text>
       <TouchableOpacity style={styles.aboutButton} onPress={()=>{navigation.navigate('AboutPage')}}>
          <Text style={styles.aboutButtonText}>소개 페이지</Text>
        </TouchableOpacity>
      <Image style={styles.mainImage} source={{uri:main}}/>
      <ScrollView style={styles.middleContainer} horizontal indicatorStyle={"white"}>
      <TouchableOpacity style={styles.middleButtonAll} onPress={()=>{category('전체보기')}}><Text style={styles.middleButtonTextAll}>전체보기</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton01} onPress={()=>{category('생활')}}><Text style={styles.middleButtonText}>생활</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton02} onPress={()=>{category('재테크')}}><Text style={styles.middleButtonText}>재테크</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton03} onPress={()=>{category('반려견')}}><Text style={styles.middleButtonText}>반려견</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton04} onPress={()=>{navigation.navigate('LikePage')}}><Text style={styles.middleButtonText}>꿀팁 찜</Text></TouchableOpacity>
      </ScrollView>
      <View style={styles.cardContainer}>
         {
          cateState.map((content,i)=>{
            return (<Card content={content} key={i} navigation={navigation}/>)
          })
        }
      </View>
    </ScrollView>)
}

const styles = StyleSheet.create({
  container: 
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 20,
이하 생략

이제 날씨 API를 사용해야 하니, 사용을 위해서 import axios from "axios" 먼저 임포트 해주고

const getLocation = async () => {
    try {
      await Location.requestForegroundPermissionsAsync();
      const locationData= await Location.getCurrentPositionAsync();
      console.log(locationData)
      console.log(locationData['coords']['latitude'])
      console.log(locationData['coords']['longitude'])
      const latitude = locationData['coords']['latitude']
      const longitude = locationData['coords']['longitude']
      const API_KEY = "cfc258c75e1da2149c33daffd07a911d";
      const result = await axios.get(
        `http://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}&units=metric`
      );
      console.log(result)
    } catch (error) {
      Alert.alert("위치를 찾을 수가 없습니다.", "앱을 껏다 켜볼까요?");
    }
  }

locationData안에 coords오브젝트 안에있는 latitude 위도와 longitude 경도 정보를 각각 같은 이름의 latitude와 longitude안에 넣는다. 

 const latitude = locationData['coords']['latitude']
 const longitude = locationData['coords']['longitude']

밑에 API_KEY 라고 적힌 부분은 스파르타코딩클럽에 무료버전으로 제공해준 키값으로, 원래는 API 제공 업체에 가입해서 부여받은 키 값을 같이 넣어줘야함.

----------------------

const result = await axios.get( `

http://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}&units=metric`);

----------------------

result에 (await 한 이후) axios에서 날씨 정보를 가져오는데 어떤 날씨 정보를 가져오냐면, 우리가 제공해준 위도와 경도 그리고 부여받은 키값을 제공하면 받을수 있는 상당히 많은 분량의 날씨정보 데이터를 제공받는다.

-----------------

공식문서를 보면 제공받은 데이터들에 대한 내용이 나와있는데, 그 안에서 우리에게 필요한 기온정보와 날씨 컨디션 상태만 가져오면 된다.

적용코드

import React,{useState,useEffect} from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native';

import data from '../data.json';
import Card from '../components/Card';
import Loading from '../components/Loading';
import { StatusBar } from 'expo-status-bar';
import * as Location from "expo-location";
import axios from "axios"

export default function MainPage({navigation,route}) {
 
  const [state,setState] = useState([])
  const [cateState,setCateState] = useState([])

  //날씨 데이터 상태관리 상태 생성!
  const [weather, setWeather] = useState({
    temp : 0,
    condition : ''
  })

 
  const [ready,setReady] = useState(true)

  useEffect(()=>{
    navigation.setOptions({
      title:'나만의 꿀팁'
    })  
    setTimeout(()=>{
        //헤더의 타이틀 변경
        getLocation()
        setState(data.tip)
        setCateState(data.tip)
        setReady(false)
    },1000)
 
   
  },[])

  const getLocation = async () => {
    try {
      await Location.requestForegroundPermissionsAsync();
      const locationData= await Location.getCurrentPositionAsync();
      console.log(locationData)
      console.log(locationData['coords']['latitude'])
      console.log(locationData['coords']['longitude'])
      const latitude = locationData['coords']['latitude']
      const longitude = locationData['coords']['longitude']
      const API_KEY = "cfc258c75e1da2149c33daffd07a911d";
      const result = await axios.get(
        `http://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}&units=metric`
      );

      console.log(result)
      const temp = result.data.main.temp;
      const condition = result.data.weather[0].main
     
      console.log(temp)
      console.log(condition)

      //오랜만에 복습해보는 객체 리터럴 방식으로 딕셔너리 구성하기!!
      //잘 기억이 안난다면 1주차 강의 6-5를 다시 복습해보세요!
      setWeather({
        temp,condition
      })

    } catch (error) {
      //혹시나 위치를 못가져올 경우를 대비해서, 안내를 준비합니다
      Alert.alert("위치를 찾을 수가 없습니다.", "앱을 껏다 켜볼까요?");
    }
  }

  const category = (cate) => {
    if(cate == "전체보기"){
        setCateState(state)
    }else{
        setCateState(state.filter((d)=>{
            return d.category == cate
        }))
    }
}
  let todayWeather = 10 + 17;
  let todayCondition = "흐림"
  //return 구문 밖에서는 슬래시 두개 방식으로 주석
  return ready ? <Loading/> :  (
    /*
      return 구문 안에서는 {슬래시 + * 방식으로 주석
    */

    <ScrollView style={styles.container}>
      <StatusBar style="light" />
      {/* <Text style={styles.title}>나만의 꿀팁</Text> */}
      <Text style={styles.weather}>오늘의 날씨: {weather.temp + '°C   ' + weather.condition} </Text>
       <TouchableOpacity style={styles.aboutButton} onPress={()=>{navigation.navigate('AboutPage')}}>
          <Text style={styles.aboutButtonText}>소개 페이지</Text>
        </TouchableOpacity>
      <Image style={styles.mainImage} source={{uri:main}}/>
      <ScrollView style={styles.middleContainer} horizontal indicatorStyle={"white"}>
      <TouchableOpacity style={styles.middleButtonAll} onPress={()=>{category('전체보기')}}><Text style={styles.middleButtonTextAll}>전체보기</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton01} onPress={()=>{category('생활')}}><Text style={styles.middleButtonText}>생활</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton02} onPress={()=>{category('재테크')}}><Text style={styles.middleButtonText}>재테크</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton03} onPress={()=>{category('반려견')}}><Text style={styles.middleButtonText}>반려견</Text></TouchableOpacity>
        <TouchableOpacity style={styles.middleButton04} onPress={()=>{navigation.navigate('LikePage')}}><Text style={styles.middleButtonText}>꿀팁 찜</Text></TouchableOpacity>
      </ScrollView>
      <View style={styles.cardContainer}>
         {/* 하나의 카드 영역을 나타내는 View */}
         {
          cateState.map((content,i)=>{
            return (<Card content={content} key={i} navigation={navigation}/>)
          })
        }
       
      </View>
   
    </ScrollView>)
}

const styles = StyleSheet.create({
  container: {
    //앱의 배경 색
    backgroundColor: '#fff',
  },
  title: {
    marginTop:10
이하생략
const temp = result.data.main.temp;
const condition = result.data.weather[0].main
temp라는 변수를 선언해서 result(API 로부터 받은 현재위치데이터) . data . main . temp 위치에 있는 기온 정보를 집어넣고, condition 이라는 변수도 선언해서 위와같이 날씨 데이터를 받아서 넣는다.( 맑음, 흐림, 비 등과같은 데이터)
 
그리고 상태관리를 해주는데, 
setWeather({
        temp,condition
      })
 이렇게 적혀 있는데, 객체 리터럴 방식으로 구성되어 있어서 당황스러울수 있는데,
결국은 위에서 받은 변수 temp데이터를 상태 temp에 넣어주는것이다.
 
[기존 방식]
var name = "스파르타";
var job = "developer";

var user = {
  name: name,
  job: job
}
[최신 방식]
var name = "스파르타";
var job = "developer";

var user = {
  name,
  job
}

위쪽에 보면 이렇게 날씨 초기값 상태를 선언해둔 부분이 있다.

const [weather, setWeather] = useState({
    temp : 0,
    condition : ''
  })

--------------------------

그런데 여기서 상태관리를 왜 하느냐? 날씨 데이터는 매번 현재위치의 날씨정보를 받아서 화면에 그려져야 하는 변동성 있는 데이터이기 때문이 아닐까? 앱 화면이 바뀌려면 상태관리를 꼭 해야한다고 한다. 

---------------------

순서대로 해석하자면

  처음에 temp : 0 그리고 condition : '' 상태로  return문 실행-> ready상태가 true이므로 로딩창이뜨면서 화면이 그려지고 -> useEffect 문이 실행-> getLocation() 함수를 통해서 위치정보허락 ->위치데이터받기 -> 위도경도받아서 -> 날씨API 를 통해 날씨정보 받아서 result에 넣고 -> result안의 많은 데이터중에 temp와 condition만 꺼내서변수에 넣는다 -> 그 변수를 상태 temp와 상태 condition으로 넣는다 -> 다시 return문 실행(이번엔 ready가 false이므로) -> View 화면 출력

-----------------

이렇게 프론트화면에 텍스트 함수로 띄워주게된다

<Text style={styles.weather}>오늘의 날씨: {weather.temp + '°C   ' + weather.condition} </Text>

styles.weather부분은 글씨 크기나 색깔 등 스타일을 준 부분이고, 뒤에 나오는 weather.temp 부분이 setWeather된 초기값이 아닌 새롭게 제공받은 현재위치데이터의 temp값을 꺼내 오는것이다. condition역시 같은 방식으로 출력된다.

 

-----------------

처음이라 이해하는데 조금 어려웠지만, API를 사용하는 기본적인개념을 익히는데 큰 도움이 되었다.