본문 바로가기
리액트(React)

리액트로 뉴스뷰어 만들어 보기(1)

by 즐거운코딩 2023. 6. 5.
반응형

비동기 방식 통신의 대표적인 API를 활용하는 예제로 newsapi 를 이용하여 전체 뉴스와 특정 카테고리 뉴스를 불러와서 보여주는 프로젝트를 만들어 봅니다.

1. newsapi key 발급받기

발급받은 API 키는 API를 요청할 때 API 주소의 쿼리 파라미터로 넣어서 사용하면 됩니다.

한국 뉴스를 가져오는 API 설명서는 아래의 링크에서 확인 가느합니다.

https://newsapi.org/s/south-korea-news-api

import { useState } from 'react';
import axios from 'axios';

function App() {
  const [data, setData] = useState(null);
  const onClick = async () => {
    try {
      const response = await axios.get(
        'https://newsapi.org/v2/top-headlines?country=kr&apiKey=발급받은key',
      );
      setData(response.data);
    } catch (e) {
      console.log(e);
    }
  };

  return (
    <div>
      <div>
        <button onClick={onClick}>불러오기</button>
      </div>
      {data && (
        <textarea
          rows={7}
          value={JSON.stringify(data, null, 2)}
          readOnly={true}
        />
      )}
    </div>
  );
}

export default App;

2. 뉴스 뷰어 UI 만들기

styled-components 사용하여 뉴스 뷰어 컴포넌트를 만듭니다. 우선 styled-components 를 설치합니다.

>npm i styled-components

2-1. NewsItem 만들기

    {
      "source": {
        "id": null,
        "name": "Yonhapnewstv.co.kr"
      },
      "author": null,
      "title": "선관위·감사원 '감사' 두고 충돌…여야, 국정조사 추진 - 연합뉴스TV",
      "description": "선관위·감사원 '감사' 두고 충돌…여야, 국정조사 추진\n\n[앵커]\n\n자녀 특혜 채용 의혹을 받는 선거관리위원회가 감사원 감사 수용 불가로 최종 결론을 냈습니다.\n\n감사원이 즉각 반",
      "url": "https://www.yonhapnewstv.co.kr/news/MYH20230602018700641",
      "urlToImage": "https://yonhapnewstv-prod.s3.ap-northeast-2.amazonaws.com/article/MYH/20230602/MYH20230602018700641_P1.jpg",
      "publishedAt": "2023-06-02T10:12:46Z",
      "content": "<ul><li>()TV 2()\r\n</li><li> : </li><li> : 02-398-7800</li><li> : 101-86-62619</li></ul>\r\nCopyright 2019 © TV :: . 23 All rights reserved.\r\n () , ·· ."
    },

API 로 불러온 JSON 객체로 다음 필드를 리액트 컴포넌트에 표출하도록 하겠습니다.

  • title : 제목
  • description : 내용
  • url : 링크
  • urlToImage : 뉴스이미지

우선 전체 뉴스에 해당하는 article 객체(뉴스 리스트 전체)를 props로 받아와서 사용합니다.

NewsItem 컴포넌트를 다음과 같이 만듭니다.

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="_black" 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;

이번에는 NewsList 컴포넌트를 만들겠습니다. 이 컴포넌트에서 API를 요청하겠지만 우선 샘플 데이터로 화면만 구성해보겠습니다.

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;

App컴포넌트에서  기존 작성했던 것 지우고 NewsList가 보이도록 바꿔줍니다.

import NewsList from './components/NewsList';

function App() {
  return <NewsList />;
}

export default App;

뉴스 목록이 만들어 졌습니다.  이제 API 를 불러와서 뉴스를 표출하는 것은 다음 블로그에서 이어서 작성하도록 하겠습니다.

반응형