React에서 useEffect 훅은 컴포넌트의 라이프사이클을 관리하는 데 필수적인 도구입니다. 이 글에서는 useEffect 훅의 기본 사용법부터 고급 활용법까지 상세히 설명합니다. 또한, 성능 최적화를 고려한 실용적인 팁과 함께 실제 프로젝트에서 자주 겪는 문제와 해결 방법도 소개합니다.
1. useEffect란 무엇인가?
useEffect는 React 함수형 컴포넌트에서 **사이드 이펙트(Side Effect)**를 처리하기 위해 사용되는 훅입니다. 전통적으로 클래스형 컴포넌트에서는 componentDidMount, componentDidUpdate, componentWillUnmount와 같은 라이프사이클 메서드를 사용했습니다. useEffect는 이 모든 기능을 하나로 통합하여 더욱 간결하고 직관적인 코드를 작성할 수 있도록 도와줍니다.
사이드 이펙트란?
- 데이터 가져오기(Fetching Data)
- 구독 설정(Subscriptions)
- DOM 변경(Document Title 변경 등)
- 타이머 설정/해제
2. useEffect 기본 사용법
기본 구조
import React, { useEffect } from "react";
function MyComponent() {
useEffect(() => {
// 이 곳에 사이드 이펙트를 작성합니다.
console.log("컴포넌트가 렌더링되었습니다!");
return () => {
// 이 곳에 정리(clean-up) 로직을 작성합니다.
console.log("컴포넌트가 제거됩니다.");
};
});
return <div>MyComponent</div>;
}
동작 원리
- 초기 렌더링 후 실행: 컴포넌트가 화면에 처음 렌더링되면 useEffect 안의 코드가 실행됩니다.
- 정리(clean-up) 작업: 컴포넌트가 언마운트되거나, 의존성이 변경되기 전 return 구문 안의 코드가 실행됩니다.
3. 의존성 배열(Dependency Array)
의존성 배열이란?
useEffect의 두 번째 매개변수로 전달되는 배열로, 어떤 값이 변경될 때만 useEffect를 실행할지 제어합니다.
useEffect(() => {
// 이 코드는 의존성 배열에 있는 값이 변경될 때 실행됩니다.
}, [dependency1, dependency2]);
의존성 배열의 동작
- 빈 배열([]): useEffect가 오직 한 번(초기 렌더링 시)에만 실행됩니다.
useEffect(() => { console.log("초기 렌더링 시 한 번만 실행"); }, []);
- 특정 값 배열([값]): 배열에 포함된 값이 변경될 때만 실행됩니다.
useEffect(() => { console.log("count 값이 변경될 때 실행"); }, [count]);
- 의존성 배열 생략: 매 렌더링마다 실행됩니다.
useEffect(() => { console.log("매 렌더링마다 실행"); });
4. 실용적인 예제
4.1 API 데이터 가져오기
import React, { useState, useEffect } from "react";
function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
async function fetchData() {
const response = await fetch("https://api.example.com/data");
const result = await response.json();
setData(result);
}
fetchData();
}, []); // 빈 배열로 설정해, 초기 렌더링 시 한 번만 실행
if (!data) return
;
return
;
}
4.2 이벤트 리스너 추가 및 제거
import React, { useState, useEffect } from "react";
function WindowResize() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
function handleResize() {
setWidth(window.innerWidth);
}
window.addEventListener("resize", handleResize);
// 정리(clean-up): 리스너 제거
return () => {
window.removeEventListener("resize", handleResize);
};
}, []); // 빈 배열로 설정해, 리스너는 한 번만 추가
return <div>Window width: {width}px</div>;
}
5. 주의점과 모범 사례
5.1 무한 루프 방지
의존성 배열을 적절히 설정하지 않으면 무한 루프가 발생할 수 있습니다.
잘못된 예:
useEffect(() => {
setCount(count + 1); // 상태를 변경하면 다시 렌더링 -> useEffect 실행 반복
}, [count]);
수정된 예:
useEffect(() => {
console.log(count);
}, [count]);
5.2 클린업 함수 사용하기
클린업(clean-up)은 컴포넌트가 제거되거나 useEffect가 다시 실행되기 전에 리소스를 정리하는 데 필요합니다.
useEffect(() => {
const id = setInterval(() => {
console.log("타이머 실행 중");
}, 1000);
return () => {
clearInterval(id); // 타이머 정리
};
}, []);
5.3 의존성 배열 자동 추가 문제
eslint-plugin-react-hooks는 의존성 배열에 누락된 값을 자동으로 추가하도록 경고합니다. 하지만, 경우에 따라 의존성을 명시적으로 조정해야 할 때도 있습니다.
useEffect(() => {
// 의존성 배열을 조정하여 불필요한 실행 방지
}, [customDependency]);
6. 고급 활용법
6.1 비동기 함수와 useEffect
비동기 함수는 직접적으로 useEffect에 사용할 수 없습니다. 대신 함수 내부에 비동기 로직을 작성합니다.
useEffect(() => {
const fetchData = async () => {
const response = await fetch("https://api.example.com/data");
console.log(await response.json());
};
fetchData();
}, []);
7. 결론
React의 useEffect 훅은 컴포넌트의 라이프사이클을 효과적으로 관리하는 데 매우 강력한 도구입니다. 의존성 배열을 잘 활용하고, 클린업 로직을 정확히 작성하면 안정적이고 최적화된 애플리케이션을 만들 수 있습니다. 위 내용을 실제 프로젝트에 적용하며 useEffect의 강력함을 경험해 보세요!
'React' 카테고리의 다른 글
React 리스트 렌더링의 기본 (0) | 2024.12.11 |
---|---|
React 컴포넌트의 생명주기 이해하기 (0) | 2024.12.09 |
React에서 조건부 렌더링 사용하기 (0) | 2024.12.09 |
React에서 useState 훅 사용법 (0) | 2024.12.09 |
React 상태(State)란 무엇인가? (0) | 2024.12.09 |