개발/엘리스 AI 트랙

엘리스 AI 트랙 08주차 - OpenAPI 심화 (2/20)🔥

Max 2021. 2. 21. 23:11
반응형

✔ 08주차. Open API 활용

<학습 목표>

  1. React로 제작한 웹 사이트에서 Redux를 활용해 상태관리를 수행할 수 있습니다.

  2. Axios를 이용하여 Create, Read, Update, Delete 를 할 수 있습니다.

  3. OpenAPI를 활용하여 React로 제작한 웹 사이트에 사용할 수 있습니다.


[01 API 사용법 익히기]

1. 비동기 처리
  -  비동기 처리를 하기 위해서 .then을 이용한 콜백 함수를 자주 사용하면 가독성이 나빠짐

axios.get(`요청할 url 1`)
  .then(res => axios.get(`요청할 url 2`))
  .then(res => {
    const ps = res.data.map(user => axios.get(`요청할 url 3`));
    ···
  })
  .then(ress => ···)))
  .then(repoArrs => {
    ···
    }
    ···
  })

  - 위와 같은 예를 콜백 지옥이라고 하는데, 콜백지옥을 벗어나기 위해 async와 await를 이용함 (콜백 함수와 .then을 사용하지 않고 비동기 처리)
  - async / await
    - Promise : 비동기 처리에서 사용되는 객체, Promise가 상태를 관리함으로써 다른 코드가 비동기적으로 실행될 수 있도록 해주는 객체
    - async : 해당 함수에서 비동기 처리를 위한 Promise 동작을 한다는 것을 명시함, 
    - await : 호출되는 함수가 적절한 결과를 반환할 때까지 기다리도록 동작합니다. 
    → 실질적인 동작은 await, await을 사용하기 위해 async를 명시

import React from 'react';
import axios from 'axios';

class Users extends React.Component {
    constructor() {
        super();
        this.state = { users: [] };
    }
    // async 추가
    async componentDidMount() {
        const response = await axios.get('https://jsonplaceholder.typicode.com/users');
                                this.setState({ users : response.data })
        
    }
    
    render() {
        const userName = this.state.users.map(
            (user) => (<li key={user.id}> {user.name} </li>)
        );
        return (
            <>
                <h4>사용자 리스트</h4>
                <div> {userName} </div>
            </>
        );
    }
}

export default Users;

  - Hook으로 API 다루기

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function Users() {
    const [users, setUsers] = useState([]);
    
    // async와 await를 이용한 useEffect()
    useEffect(() => {
        async function fetch() {
            const response = await axios.get( 'https://jsonplaceholder.typicode.com/users' );
            setUsers(response.data);
        };
        fetch();
    }, []);
    
    const userName = users.map(
        (user) => (<li key={user.id}> {user.name} </li>)
    );
    
    return (
        <>
            <h4>사용자 리스트</h4>
            <div>{userName}</div>
        </>
    );
}

export default Users;

  - API 호출 에러 핸들링

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function Users() {
    const [users, setUsers] = useState([]);
    const [error, setError] = useState(null);
    
    useEffect(() => {
        async function fetchUser() {
            try {
                const response = await axios.get(
                'https://jsonplaceholder.typicode.com/error'
                );
                setUsers(response.data);
            } catch(e) {
                setError(e);
            }
        };
        fetchUser();
    }, []);
    
    const userName = users.map(
        (user) => (<li key={user.id}> {user.name} </li>)
    );

    if (error) return <h4>에러 발생!</h4>;
    return (
        <>
            <h4>사용자 리스트</h4>
            <div> {userName} </div>
        </>
    );
}

export default Users;

  - 버튼으로 API 호출

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function Users() {
    const [users, setUsers] = useState([]);
    const [error, setError] = useState(null);
    const [loading, setLoading] = useState(false);
    
    useEffect(() => {
        
    }, []);
    async function fetchUser() {
        // 함수가 처음 시작할 때 loading state를 true, 끝날 때 false
        setLoading(true)
        try {
            const response = await axios.get(
                'https://jsonplaceholder.typicode.com/users'
            );
            setUsers(response.data);
        } catch (e) {
            setError(e);
        }
        setLoading(false)
    };
    
    const clickHandler = (e) => {
        e.preventDefault();
        fetchUser();
    }
    
    const userName = users.map(
        (user) => (<li key={user.id}> {user.name} </li>)
    );
    
    if(loading)
        return <h4>로딩중...</h4>;
    if (error) return <h4>에러 발생!</h4>;
    return (
        <>
            <h4>사용자 리스트</h4>
            <div> {userName} </div>
            <button onClick={clickHandler}>다시 불러오기</button>
        </>
    );
}

export default Users;

[02 OpenAPI 활용하기]

1. 포켓몬 API
  - 포켓몬 API : Pokémon 메인 게임 시리즈에 등장하는 포켓몬들에 대한 모든 것을 자세히 설명하는 API
  - 포켓몬 API 특징과 구조
    ① HTTP GET 요청으로 API의 자원을 사용할 수 있음
    ② 사용자가 입력한 값에 따라 포켓몬 이미지, 이름, 높이, 무게 정보를 확인
    ③ 포켓몬 API에 없는 값 입력 시 404 에러 반환

2. API 요청 함수 만들기
  - axios.get() 에 { cancelToken: new axios.CancelToken(c => cancel = c) }을 함께 넘겨야함 (cancelToken : Axios에서 제공하는 것으로 API 요청을 취소하는데 사용되는 토큰)

// PokemonList.js

import React from 'react'

export default function PokemonList({ pokemon }) {
  return (
    <div>
      {pokemon.map(p => (
        <div key={p}>{p}</div>
      ))}
    </div>
  )
}
// Pagination.js

import React from 'react'

export default function Pagination({ gotoNextPage, gotoPrevPage }) {
  return (
    <div>
      {gotoPrevPage && <button onClick={gotoPrevPage}>Previous</button>}
      {gotoNextPage && <button onClick={gotoNextPage}>Next</button>}
    </div>
  )
}
// app.js
import React, { useState, useEffect } from 'react';
import axios from 'axios'
import PokemonList from './PokemonList'
import Pagination from './Pagination';

function App() {
  const [pokemon, setPokemon] = useState([])
  const [currentPageUrl, setCurrentPageUrl] = useState("https://pokeapi.co/api/v2/pokemon")
  const [nextPageUrl, setNextPageUrl] = useState("")
  const [prevPageUrl, setPrevPageUrl] = useState("")
  const [loading, setLoading] = useState(true)

  const [] = useState()
  useEffect(() => {
    setLoading(true)
    let cancel
    // axios.get()으로 currentPageUrl와 cancelToken을 함께 넘기고 state 설정
    axios.get(currentPageUrl, { cancelToken: new axios.CancelToken(c => cancel = c) })
            .then(response => {
                console.log(response)
                setPokemon(response.data.results.map(p => p.name));
                setNextPageUrl(response.data.next)
                setPrevPageUrl(response.data.previous)
                setLoading(false)
            })
    // 페이지 이동이 취소되면 현재 페이지 유지
    return () => cancel()
  }, [currentPageUrl])

  function gotoNextPage() {
    setCurrentPageUrl(nextPageUrl)
  }

  function gotoPrevPage() {
    setCurrentPageUrl(prevPageUrl)
  }
  
  if (loading) return "로딩중..."
  
  return (
    <>
      <PokemonList pokemon={pokemon} />
      <Pagination
        gotoNextPage={nextPageUrl ? gotoNextPage : null}
        gotoPrevPage={prevPageUrl ? gotoPrevPage : null}
      />
    </>
  );
}

export default App;

※ 수업 자료의 출처는 K-Digital Training x 엘리스 인공지능 서비스 개발 기획 1기 (elice.io/)입니다.

반응형