Front/JavaScript

비동기 (Async) - 뉴스 API 데이터 가져오기 예제

oodada 2024. 2. 29. 17:02

React 비동기 처리

1. 뉴스 API 데이터 가져오기

- 뉴스 API 키 발급

무료 뉴스 API 추천

2. useEffect로 데이터 가져오기

useEffect(() => { ... }, [deps])

useEffect는 함수 컴포넌트에서 부수 효과를 수행할 수 있도록 하는 Hook이다. useEffect는 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 수 있다.

// src/News.js
import React, { useEffect, useState } from 'react';

function News() {
    const [news, setNews] = useState([]);

    useEffect(() => {
        fetch('https://newsapi.org/v2/top-headlines?country=kr&apiKey=API_KEY')
            .then(response => response.json())
            .then(data => {
                console.log(data);
                setNews(data.articles);
            })
            .catch(error => console.error(error));
    }, []);

    return (
        <div>
            <h1>뉴스</h1>
            <ul>
                {news.map((article, index) => (
                    <li key={index}>
                        <a
                            href={article.url}
                            target="_blank"
                            rel="noreferrer"
                        >
                            <img
                                src={article.urlToImage}
                                alt=""
                            />
                            {article.title}
                        </a>
                    </li>
                ))}
            </ul>
        </div>
    );
}

export default News;

- API Key 숨기기

API Key는 노출되면 안 되는 중요한 정보이므로, API Key를 숨기기 위해 .env 파일을 사용한다. 적용 후 서버를 재시작해야 한다.

  1. 프로젝트 루트 디렉토리에 .env 파일에서 환경 변수를 설정한다.
  2. .env 파일에 API Key를 저장한다.
// .env
REACT_APP_NEWS_API_KEY=API_KEY
  1. .env 파일에 저장한 API Key를 process.env.REACT_APP_NEWS_API_KEY로 시작하는 이름으로 사용한다.
// src/News.js
import React, { useEffect, useState } from 'react'

function News() {
    const [news, setNews] = useState([])

    useEffect(() => {
        // .env 파일에 저장한 API Key를 사용
        fetch(`https://newsapi.org/v2/top-headlines?country=kr&apiKey=${process.env.REACT_APP_NEWS_API_KEY}`)
            (...)
    }, [])

    return (
        (...)
    )
}

export default News

4. async/await로 비동기 처리하기

async/await는 프로미스를 더 쉽게 사용할 수 있도록 해주는 ES8(ECMAScript 2017)의 문법으로 비동기 처리를 더 간결하게 작성할 수 있다.

  • async : 함수 앞에 async 키워드를 붙이면, 해당 함수는 항상 프로미스를 반환한다.
  • await : await 키워드는 async 함수 내부에서만 사용할 수 있으며, 프로미스가 처리될 때까지 기다린 후 결과를 반환한다.
// src/News.js
import React, { useEffect, useState } from 'react'

function News() {
    const [news, setNews] = useState([])

    useEffect(() => {
        // async/await로 비동기 처리하기
        const fetchData = async () => {
            // try: 정상적으로 실행되는 코드
            // catch : 에러가 발생했을 때 실행할 코드
            // fetch 함수를 사용하여 뉴스 데이터를 가져옵니다.
            try {
                const response = await fetch(`https://newsapi.org/v2/top-headlines?country=kr&apiKey=${process.env.REACT_APP_NEWS_API_KEY}`) // API Key를 사용
                const data = await response.json() // JSON 형태로 변환
                console.log(data) // 데이터 확인
                setNews(data.articles) // 뉴스 데이터를 상태로 저장
            } catch (error) {
                console.error(error)
            }
        }

        fetchData()
    }, [])

    return (
        (...)
    )
}

export default News

5. axios로 데이터 가져오기

axios는 브라우저와 Node.js를 위한 Promise 기반 HTTP 클라이언트로, 비동기 방식으로 HTTP 데이터 요청을 수행할 수 있다.
axios를 사용하는 이유는 fetch API보다 더 간결하고 직관적이며, 브라우저 호환성이 더 좋기 때문이다.

- axios 설치

$ npm install axios

- axios로 데이터 가져오기

// src/News.js
import React, { useEffect, useState } from 'react'
import axios from 'axios'

function News() {
    const [news, setNews] = useState([])

    useEffect(() => {
        // axios로 데이터 가져오기
        const fetchData = async () => {
            try {
                const response = await axios.get(`https://newsapi.org/v2/top-headlines?country=kr&apiKey=${process.env.REACT_APP_NEWS_API_KEY}`)
                // data 속성에 뉴스 데이터가 들어있음
                console.log(response.data)
                setNews(response.data.articles)
            } catch (error) {
                console.error(error)
            }
        }

        fetchData()
    }, [])

    return (
        (...)
    )
}

export default News

6. 비동기 처리의 순서

비동기 처리를 할 때, 작업의 순서를 보장하기 위해 async/await를 사용할 수 있다.

// src/News.js
import React, { useEffect, useState } from 'react'
import axios from 'axios'

function News() {
    const [news, setNews] = useState([])

    useEffect(() => {
        const fetchData = async () => {
            try {
                // 첫 번째 요청
                const response1 = await axios.get(`https://newsapi.org/v2/top-headlines?country=kr&apiKey=${process.env.REACT_APP_NEWS_API_KEY}`)
                console.log(response1.data)
                setNews(response1.data.articles)

                // 두 번째 요청
                const response2 = await axios.get(`https://newsapi.org/v2/top-headlines?country=us&apiKey=${process.env.REACT_APP_NEWS_API_KEY}`)
                console.log(response2.data)
            } catch (error) {
                console.error(error)
            }
        }

        fetchData()
    }, [])

    return (
        (...)
    )
}

export default News

위 코드를 실행하면, 한 번에 두 개의 요청을 보내고, 첫 번째 요청이 완료된 후 두 번째 요청이 실행된다.

7. Promise.all로 여러 개의 프로미스 처리하기

Promise.all은 여러 개의 프로미스를 동시에 처리할 수 있는 메서드로, 모든 프로미스가 성공적으로 처리되었을 때 결과를 반환한다.

// src/News.js
import React, { useEffect, useState } from 'react'
import axios from 'axios'

function News() {
    const [news, setNews] = useState([])

    useEffect(() => {
        const fetchData = async () => {
            try {
                // Promise.all로 여러 개의 프로미스 처리하기
                const [response1, response2] = await Promise.all([
                    axios.get(`https://newsapi.org/v2/top-headlines?country=kr&apiKey=${process.env.REACT_APP_NEWS_API_KEY}`),
                    axios.get(`https://newsapi.org/v2/top-headlines?country=us&apiKey=${process.env.REACT_APP_NEWS_API_KEY}`)
                ])

                console.log(response1.data)
                console.log(response2.data)
            } catch (error) {
                console.error(error)
            }
        }

        fetchData()
    }, [])

    return (
        (...)
    )
}

export default News

위 코드를 실행하면, 두 개의 요청을 동시에 보내고, 두 요청이 모두 완료되면 결과를 반환한다.

티스토리 친구하기