만들면서 배우는 리액트 튜토리얼 - 7.Async와 Await

by - September 01, 2018

이전에 배운 Promise의 .then만 사용하면 프로그램이 커졌을 때 

.then .then .then이 끝없이 반복되는 '콜백 지옥'에 빠질 수 있다. 

하지만 Async와 Await을 사용하면 이 문제를 깔끔하게 해결할 수 있다.

Cf) await은 async 함수 내에서만 동작한다.

import React, { Component } from 'react';
import './App.css';
import Movie from './Movie'

class App extends Component {

  state = [

  ]

  componentDidMount() {
    this._getMovies();
  }

  _renderMovies = () => {
    const movies = this.state.movies.map((movie, index) =>
      <Movie title={movie.title} poster={movie.large_cover_image} key={movie.id}
 />
    )
    return movies
  }

  _getMovies = async () => {
    // await은 그 함수가 successed가 아니라 just finished되면
    // 그 return value가 무엇이든 그 value를 return한다
    const movies = await this._callApi()
    // 따라서 _callApi()가 끝나기 전까지 setState()는 실행되지 않는다
    this.setState({
      movies // ES5 movies: movies
    })
  }
 
  _callApi = () => {
    // fetch라는 이름의 promise를 return
    return fetch('https://yts.am/api/v2/list_movies.json?sort_by=rating')
    .then(potato => potato.json()) // 사람이 읽을 수 있게 byte -> json으로 변경
    .then(json => json.data.movies)
    .catch(err => console.log(err))
  }

  render() {
    return (
      <div className="App">
        {/*
          this.state.movies 데이터가 존재하면 기존 state mapping을 실행하고,
          아니면 Loading... string을 띄워준다
        */}
        {this.state.movies ? this._renderMovies() : "Loading..."}
      </div>
    );
  }
}

export default App;

Async, Await 예시


componentDidMount()에는 주로 많은 함수들이 실행된다. 

그렇기 때문에 componentDidMount() 코드 사이즈를 줄이기 위해서 위 코드에서는 

기존 내용을 _getMovies()라는 이름의 함수로 새로 선언해서 사용했다.


_getMovies는 동시에 여러 API를 이용하여 데이터를 가지고 올 수 있도록 asnyc를 이용했고

Api로부터의 데이터 로딩이 다 끝나지 않았을 때 setState가 실행되면 안되기 때문에 

_callApi()는 await을 사용했다. 

즉, 데이터는 여러 군데에서 동시에 가져올 수 있지만 그 데이터를 state로 넘기는 것은 

모든 데이터가 로딩된 뒤에 실행된다는 것이다. 


_callApi()는 기존 fetch 코드를 거의 재사용 했는데 우선 fetch promise를  

JSON형태로 바꾸고(.then(potato => potato.json())) json.data.movies을 통해 

그 데이터 중에서 movies 데이터를 뽑아 return한다.

movies 객체 안에 더 이상 우리가 만들었던 poster라는 데이터는 없고 대신 

large_cover_image가 존재하기 때문에 poster={movie.large_cover_image} 로 코드를 변경했다.


마지막으로 컴포넌트의 key에 map에서 자동생성된 index를 사용하는 것이 너무 느리고


이제 각 영화 데이터에 id가 존재하기 때문에 key={movie.id}로 바꿔주었다.

You May Also Like

0 comments