[React] axios로 API 호출해서 데이터 받아 오기

겨레·2024년 12월 4일

[React] 리액트 스터디

목록 보기
79/95

📍 axios
HTTP 요청을 보낼 수 있는 JavaScript 기반 HTTP 클라이언트 라이브러리

  • RESTful API와 통신하거나 서버로 데이터를 송수신하는 데 널리 사용됨.
  • Promise를 기반으로 작동하며, 비동기 요청을 쉽게 처리할 수 있음.
  • Axios를 사용하면 GET, POST, PUT, DELETE 요청을 쉽게 보낼 수 있음.
  • 요청에 포함되는 데이터를 자동으로 JSON으로 변환하거나, 응답 데이터를 JSON으로 파싱함.

  • 📍 axios 라이브러리 설치하기
npm install axios

newsapi에서 제공하는 API를 사용해 뉴스 뷰어를 만들어보자!


1. newsapi API 키 발급받기

  • newsapi에 가입하면 API 키를 발급받을 수 있음.
    • apiKey 값에는 발급받았던 API 키를 입력하면 된다.

  • 예제에서 사용할 API는 [한국 뉴스]
    근데... 데이터가 없는지 렌더링 안 되길래 미국껄로 함...
    (https://newsapi.org/s/south-korea-news-api)!
    • 사용할 API 주소는 두 가지 형태이다.
      1) 전체 뉴스 불러오기
      GET https://newsapi.org/v2/top-headlines?country=kr&apiKey=0a8c4202385d4ec1bb93b7e277b3c51f
      2) 특정 카테고리 뉴스 불러오기
      GET https://newsapi.org/v2/top-headlines?country=kr&category=business&apiKey=0a8c4202385d4ec1bb93b7e277b3c51f

위 코드는 각 뉴스 데이터가 지니고 있는 정보로 이루어진 JSON 객체이다.



2. 뉴스 뷰어 UI 만들기

styled-components를 사용하여 뉴스 정보를 보여 줄 컴포넌트 만들기


먼저 UI 만들 때 필요한 라이브러리를 설치해주자.

  • styled-components 설치
    npm install styled-components

components 디렉터리를 생성한 뒤, 그 안에 NewsItem.jsx와 NewsList.jsx 파일을 생성한다.

✔ NewsItem
각 뉴스 정보를 보여 주는 컴포넌트

✔ NewsList
API를 요청하고 뉴스 데이터가 들어 있는 배열을 컴포넌트 배열로 변환하여 렌더링해 주는 컴포넌트


newsapi API 키 발급받기 쪽에서 본 코드 중에서 title(제목), description(내용), url(링크), urlToImage(뉴스 이미지) 필드를 리액트 컴포넌트에 나타내보자!

①-1. NewsItem 만들기
먼저 NewsItem 컴포넌트는 article이라는 객체를 props로 통째로 받아와서 사용한다.

  • NewsItem.jsx
import React from 'react';
import styled from 'styled-components';

const NewsItemBlock = styled.div`
  display: flex;

  .thumbnail {
    margin-right: 1rem;
    img {
      display: block;
      width: 160px;
      height: 100px;
      object-fit: cover;
    }
  }
  .contents {
    h2 {
      margin: 0;
      a {
        color: black;
      }
    }
    p {
      margin: 0;
      line-height: 1.5;
      margin-top: 0.5rem;
      white-space: normal;
    }
  }
  & + & {
    margin-top: 3rem;
  }
`;

const NewsItem = ({ article }) => {
  const { title, description, url, urlToImage } = article;

  return (
    <NewsItemBlock>
      {urlToImage && (
        <div className="thumbnail">
          <a href={url} target="_blank" rel="noopener noreferrer">
            <img src={urlToImage} alt="thumbnail" />
          </a>
        </div>
      )}
      <div className="contents">
        <h2>
          <a href={url} target="_blank" rel="noopener noreferrer">
            {title}
          </a>
        </h2>
        <p>{description}</p>
      </div>
    </NewsItemBlock>
  );
};

export default NewsItem;

①-2. NewsList 만들기

  • NewsList.jsx
    • 나중에 NewsList 컴포넌트에서 API를 요청할 예정!
    • 지금은 데이터를 불러오지 않고 있어 sampleArticle이라는 객체에 미리 데이터를 넣고, 각 컴포넌트에 전달해 임시 내용이 보이게 함.
      import styled from 'styled-components';
      import NewsItem from './NewsItem';
      
      const NewsListBlock = styled.div`
      box-sizing: border-box;
      padding-bottom: 3rem;
      width: 768px;
      margin: 0 auto;
      margin-top: 2rem;
      @media screen and (max-width: 768px) {
        width: 100%;
        padding-left: 1rem;
        padding-right: 1rem;
      }
      `;
      
      const sampleArticle = {
      title: '제목',
      description: '내용',
      url: 'https://google.com',
      urlToImage: 'https://via.placeholder.com/160',
      };
      
      const NewsList = () => {
      return (
        <NewsListBlock>
          <NewsItem article={sampleArticle} />
          <NewsItem article={sampleArticle} />
          <NewsItem article={sampleArticle} />
          <NewsItem article={sampleArticle} />
          <NewsItem article={sampleArticle} />
          <NewsItem article={sampleArticle} />
        </NewsListBlock>
      );
      };
      
      export default NewsList;

①-3. NewsList 컴포넌트를 App 컴포넌트에서 보여주기

  • App.jsx
import React, { useState } from 'react';
import NewsList from './components/NewsList';

const App = () => {
  return <NewsList />;
};

export default App;



3. 데이터 연동하기

이제 NewsList 컴포넌트에서 연습 삼아 사용했던 API를 호출해 보자!

컴포넌트가 화면에 보이는 시점에 API를 요청해 볼 건데, 이때
useEffect를 사용해 컴포넌트가 처음 렌더링되는 시점에 API를 요청하면 된다.

✅ 이때 주의사항
useEffect에 등록하는 함수에 async를 붙이면 안 된다는 것!

❓🤔 왜?
useEffect에서 반환해야 하는 값은 뒷정리 함수이기 때문이다.

❓🤔 useEffect 내부에서 async/await를 사용하고 싶다면?
함수 내부에 async 키워드가 붙은 또 다른 함수를 만들어서 사용해야 한다.

추가로 loading이라는 상태도 관리하여 API 요청이 대기 중인지 판별할 거임.
✔ 요청이 대기 중일 때는 loading 값이 true가 됨.
✔ 요청이 끝나면 loading 값이 false가 되어야 함.

  • NewsList.jsx
import styled from 'styled-components';
import NewsItem from './NewsItem';
import { useEffect, useState } from 'react';
import axios from 'axios';

const NewsListBlock = styled.div`
  box-sizing: border-box;
  padding-bottom: 3rem;
  width: 768px;
  margin: 0 auto;
  margin-top: 2rem;
  @media screen and (max-width: 768px) {
    width: 100%;
    padding-left: 1rem;
    padding-right: 1rem;
  }
`;

// const sampleArticle = {
//   title: '제목',
//   description: '내용',
//   url: 'https://google.com',
//   urlToImage: 'https://via.placeholder.com/160',
// };

const NewsList = () => {
  const [articles, setArticles] = useState(null);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    // async를 사용하는 함수 따로 선언
    const fetchData = async () => {
      setLoading(true);
      try {
        const response = await axios.get(
          'https://newsapi.org/v2/top-headlines?country=us&apiKey=발급받은 api 키값',
        );
        setArticles(response.data.articles);
      } catch (e) {
        console.log(e);
      }
      setLoading(false);
    };
    fetchData();
  }, []);

  // 대기 중일 때
  if (loading) {
    return <NewsListBlock>대기 중...</NewsListBlock>;
  }
  // 아직 articles 값이 설정되지 않았을 때
  if (!articles) {
    return null;
  }

  // articles 값이 유효할 때
  return (
    <NewsListBlock>
      {articles.map((article, index) => (
        <NewsItem key={article.url || index} article={article} />
      ))}
    </NewsListBlock>
  );
};

export default NewsList;



profile
호떡 신문지에서 개발자로 환생

0개의 댓글