웹 개발을 하다 보면, 프론트엔드에서 서버로부터 데이터를 가져와야 할 상황이 자주 발생한다. 이런 상황에서는 프론트엔드와 백엔드 간의 효과적인 데이터 소통이 중요해지는데, 이를 위해선 React의 useEffect 훅과 fetch API의 사용법을 정확히 이해해야 한다.
이에, 오늘은 이 두 기능을 어떻게 사용해 React 애플리케이션에서 원격 데이터를 효율적으로 불러오고 관리하는지 살펴보고자 한다.
useEffect는 React의 함수형 컴포넌트에서 side effects(부수 효과)를 다루기 위해 사용되는 Hook으로, 컴포넌트가 화면에 나타날 때, 사라질 때, 또는 업데이트 될 때 특정 작업을 수행하도록 설정할 수 있다.
주의 사항으로, 상태를 변경할 때는 무한 루프에 빠지지 않도록 의존성 배열을 적절히 관리해야 한다.
cf> 응용 사례
- 마운트 시: 컴포넌트가 처음 나타날 때 API 요청 같은 초기화 작업을 수행
- 업데이트 시: 지정된 의존성 값이 변할 때 마다 리소스를 업데이트
- 언마운트 시: 이벤트 리스너 제거와 같은 정리 작업을 실행
컴포넌트가 처음 마운트될 때만 useEffect를 실행하려면, 빈 배열 []을 의존성 배열로 사용한다.
아래 코드는 컴포넌트가 마운트될 때 한 번만 실행되며, 언마운트 시나 업데이트 시에는 실행되지 않는다. 이는 API 호출, 이벤트 리스너 등록 등의 작업을 초기에 한 번만 실행할 필요가 있을 때 유용하다.
useEffect(() => {
// 실행할 코드
}, []);
특정 값이 바뀔 때마다 useEffect 함수를 실행하려면, 해당 값을 dependency list에 포함시키면 된다.
아래 코드에서 dep1, dep2, dep3 등은 컴포넌트의 상태나 props 중 useEffect 함수가 의존하는 값들이다. 이때, 이 값들 중 하나라도 변경되면, useEffect 함수가 실행되게 된다. 따라서, 이 방식은 컴포넌트가 업데이트될 때마다 필요한 로직을 실행할 때 적합하다.
useEffect(() => {
// 실행할 코드
}, [dep1, dep2, dep3, ...]);
아래 예제에서는 useEffect를 사용하여 상태가 변경될 때마다 로그를 출력한다:
이 코드를 통해 useEffect가 상태의 변경에 따라 어떻게 반응하는지 확인 가능하니 예제를 다양하게 번형해보며 useEffect의 동작 원리에 대해 명확히 이해해보자.
import { useEffect, useState } from 'react';
function App() {
const [state, setState] = useState(0);
useEffect(() => {
console.log('상태 변경됨:', state);
}, [state]);
return (
//...
);
}
export default App;
React에서 데이터를 불러오기 위해 흔히 fetch API를 사용한다. fetch는 네트워크 요청을 간단하게 할 수 있는 브라우저 내장 함수로, 아래 글에서 조금 더 자세히 확인 가능하다.
Fetch에 대해서는 다음 글에서 조금 더 자세히 확인 가능하다: Fetch 함수의 기본 원리와 응답 처리 방법
아래 예제는 fetch를 사용하여 원격 데이터를 불러오고 상태에 저장하는 예제이다.
이 코드에서 useEffect는 컴포넌트가 마운트될 때 원격 데이터를 불러오는 데 사용된다. 이 때, 데이터가 성공적으로 불러와지면, 상태가 업데이트되어 리렌더링되며, 데이터가 화면에 표시되게 된다.
// api.js
export async function getPosts() {
const response = await fetch("https://jsonplaceholder.typicode.com/posts");
const posts = await response.json();
return posts;
}
// App.js
import { useEffect, useState } from 'react';
import { getPosts } from "../api";
function App() {
const [data, setData] = useState(null);
const handleLoad = async () => {
const { posts } = await getPosts();
setData(posts);
};
useEffect(() => {
handleLoad();
}, []);
return (
<ul>
{data.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
export default App;
이번 글을 통해 React의 useEffect 훅과 fetch API를 사용하여 원격 데이터를 불러오고 관리하는 방법에 대해 알아보았다. 핵심 정리로, useEffect는 컴포넌트의 라이프사이클에 맞춰 side effects를 실행하며, fetch는 서버로부터 필요한 데이터를 쉽게 불러올 수 있게 해준다는 사실을 알 수 있었다.
원격 데이터를 불러오다보면 마음대로 안되는 경우가 정말 많다. 이에, 다양한 실습을 통해 useEffect의 동작 원리를 체험하고, fetch를 이용한 데이터 호출 방법을 익혀 이에 대해 명확히 숙지하는 것이 중요하다고 생각된다.
마지막으로, 원격 데이터를 불러올 때 이에 관한 상태를 확인하기 위해 개발자 도구의 Network탭을 통해 항상 확인하며 교차 검증하는 습관을 들이도록 노력하자. 이러한 작은 습관이 전체 애플리케이션의 안정성과 성능에 있어 큰 차이를 만든다는 사실, 꼭 명심하자.