📍 axios
HTTP 요청을 보낼 수 있는 JavaScript 기반 HTTP 클라이언트 라이브러리
- RESTful API와 통신하거나 서버로 데이터를 송수신하는 데 널리 사용됨.
- Promise를 기반으로 작동하며, 비동기 요청을 쉽게 처리할 수 있음.
- Axios를 사용하면 GET, POST, PUT, DELETE 요청을 쉽게 보낼 수 있음.
- 요청에 포함되는 데이터를 자동으로 JSON으로 변환하거나, 응답 데이터를 JSON으로 파싱함.
- 📍 axios 라이브러리 설치하기
npm install axios
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 객체이다.
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로 통째로 받아와서 사용한다.
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 만들기
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 컴포넌트에서 보여주기
import React, { useState } from 'react';
import NewsList from './components/NewsList';
const App = () => {
return <NewsList />;
};
export default App;

이제 NewsList 컴포넌트에서 연습 삼아 사용했던 API를 호출해 보자!
컴포넌트가 화면에 보이는 시점에 API를 요청해 볼 건데, 이때
useEffect를 사용해 컴포넌트가 처음 렌더링되는 시점에 API를 요청하면 된다.
✅ 이때 주의사항
useEffect에 등록하는 함수에 async를 붙이면 안 된다는 것!
❓🤔 왜?
useEffect에서 반환해야 하는 값은 뒷정리 함수이기 때문이다.
❓🤔 useEffect 내부에서 async/await를 사용하고 싶다면?
함수 내부에 async 키워드가 붙은 또 다른 함수를 만들어서 사용해야 한다.
추가로 loading이라는 상태도 관리하여 API 요청이 대기 중인지 판별할 거임.
✔ 요청이 대기 중일 때는 loading 값이 true가 됨.
✔ 요청이 끝나면 loading 값이 false가 되어야 함.
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;
