안녕하세요, React 개발자 여러분! 👋 오늘은 React 16.8에서 도입된 가장 강력한 기능 중 하나인 useEffect 훅에 대해 자세히 알아보는 시간을 갖겠습니다. 함수형 컴포넌트에서 사이드 이펙트를 효율적으로 관리하는 방법을 이해하면 여러분의 React 개발 능력을 한 단계 더 끌어올릴 수 있습니다.
사이드 이펙트란 무엇인가요?
useEffect의 심도 있는 이해를 위해 먼저 "사이드 이펙트(Side Effect)" 가 무엇을 의미하는지 명확히 할 필요가 있습니다. React 컴포넌트의 렌더링 과정에서 발생하는 부수적인 작업들을 사이드 이펙트라고 합니다. 이는 렌더링의 정상적인 흐름을 벗어나 발생하며, 올바르게 관리되지 않으면 예기치 않은 동작을 초래할 수 있습니다.
일반적인 사이드 이펙트의 예시는 다음과 같습니다:
- 데이터 가져오기 (Data Fetching): 외부 API를 호출하여 데이터를 가져오는 작업.
- 구독 설정 (Setting up Subscriptions): WebSocket 연결과 같은 이벤트 리스너를 설정하는 작업.
- DOM 조작 (DOM Manipulation): React의 가상 DOM을 통하지 않고 직접적으로 실제 DOM 요소를 수정하는 작업.
useEffect의 기본 구문과 작동 방식
useEffect 훅의 기본 구문은 매우 직관적입니다.
import { useEffect } from 'react';
useEffect(() => {
// 여기에 사이드 이펙트 로직 작성
}, [종속성]);
여기서 두 가지 주요 인수를 주목해야 합니다:
- 첫 번째 인수는 함수입니다. 이 함수는 여러분이 수행하고자 하는 사이드 이펙트 로직을 포함합니다.
- 두 번째 인수는 종속성 배열입니다. 이 배열은
useEffect훅이 언제 다시 실행되어야 하는지를 결정하는 핵심적인 요소입니다.
useEffect는 기본적으로 모든 렌더링 후에 실행됩니다. 하지만 종속성 배열에 값이 지정되어 있다면, 해당 배열 내의 어떤 값이라도 변경될 때만 다시 실행됩니다. 이를 통해 불필요한 사이드 이펙트 실행을 방지하고 애플리케이션의 성능을 최적화할 수 있습니다.
실용적인 useEffect 예제
1. 데이터 가져오기: 컴포넌트 마운트 시 데이터 로드
컴포넌트가 처음 화면에 나타날 때 (마운트될 때) 외부 API에서 사용자 데이터를 가져오는 시나리오를 살펴보겠습니다.
import React, { useState, useEffect } from 'react';
const UserList = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
const fetchUsers = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const data = await response.json();
setUsers(data);
};
fetchUsers();
}, []); // 빈 종속성 배열은 마운트 시 한 번만 실행됨을 의미
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
이 예제에서 주목할 점은 useEffect의 두 번째 인수로 빈 배열([]) 을 전달했다는 것입니다. 이는 해당 useEffect 훅이 UserList 컴포넌트가 처음 마운트될 때 단 한 번만 실행되도록 합니다. 마치 클래스 컴포넌트의 componentDidMount와 같은 역할을 수행하는 것이죠. API 호출을 통해 가져온 사용자 데이터는 setUsers를 통해 상태에 저장되고, 이로 인해 컴포넌트가 리렌더링되어 화면에 사용자 목록이 표시됩니다.
2. 구독 설정 및 정리: 이벤트 리스너 관리
useEffect는 구독을 설정하고 해제하는 데에도 매우 유용합니다. 예를 들어, 브라우저 창의 크기가 변경될 때마다 너비를 추적하는 컴포넌트를 만들어 봅시다.
import React, { useState, useEffect } from 'react';
const WindowWidthTracker = () => {
const [width, setWidth] = useState(window.innerWidth);
const handleResize = () => {
setWidth(window.innerWidth);
};
// 마운트 시 구독 설정 및 언마운트 시 정리
useEffect(() => {
window.addEventListener('resize', handleResize);
// 정리 함수
return () => window.removeEventListener('resize', handleResize);
}, []); // 마운트 시 한 번 실행
return <div>창 너비: {width}px</div>;
};
이 예제에서는 useEffect 훅의 첫 번째 인수로 전달된 함수가 정리 함수(Cleanup Function) 를 반환합니다. 이 정리 함수는 컴포넌트가 언마운트되기 전이나 다음 이펙트가 실행되기 전에 호출됩니다. 여기서는 window 객체에 추가했던 resize 이벤트 리스너를 제거함으로써 메모리 누수를 방지하고 불필요한 동작을 막습니다. 이 역시 빈 종속성 배열([])을 사용하여 컴포넌트 마운트 시 한 번만 이벤트 리스너를 추가하고, 언마운트 시 한 번만 제거하도록 합니다.
종속성 배열의 중요성
useEffect를 효과적으로 사용하기 위해서는 종속성 배열의 작동 방식을 정확히 이해하는 것이 필수적입니다.
- 빈 배열(
[]): 이펙트가 컴포넌트의 초기 렌더링 후에 단 한 번만 실행되도록 합니다.componentDidMount와 유사한 동작을 합니다. - 특정 변수 포함(
[var1, var2]): 배열 내부에 명시된 변수들 중 하나라도 변경될 때마다 이펙트가 다시 실행됩니다.
예를 들어, increment 프롭이 변경될 때마다 콘솔에 메시지를 로깅하는 CounterWithEffects 컴포넌트를 보겠습니다.
const CounterWithEffects = ({ increment }) => {
const [count, setCount] = useState(0);
// 이 코드는 increment가 변경될 때마다 실행됩니다.
useEffect(() => {
console.log(`Increment가 변경되었습니다! 새 값은 ${increment}입니다.`);
}, [increment]); // increment 값이 변경될 때마다 실행
return (
<button onClick={() => setCount(count + 1)}>
카운트: {count}
</button>
);
};
여기서 useEffect는 increment 값이 변경될 때마다 실행되므로, 부모 컴포넌트의 업데이트 등으로 인해 increment 프롭이 변경되면 해당 메시지가 콘솔에 기록됩니다.
결론
useEffect 훅은 React 함수형 컴포넌트에서 사이드 이펙트를 선언적으로 관리할 수 있게 해주는 강력한 도구입니다. 데이터 가져오기, 구독 설정, DOM 조작 등 다양한 시나리오에서 useEffect를 활용하여 코드를 더욱 간결하고 가독성 있게 작성할 수 있습니다. 종속성 배열과 정리 함수의 개념을 완벽하게 이해하고 마스터한다면, 여러분은 ReactJS를 활용하여 더욱 동적이고 효율적인 애플리케이션을 구축할 준비가 될 것입니다.
'프로그래밍 > ReactJS' 카테고리의 다른 글
| React Hooks: 깔끔하고 효율적인 코드 작성을 위한 필수 규칙 파헤치기 🚀 (0) | 2025.09.24 |
|---|---|
| React 개발의 게임 체인저: 커스텀 훅으로 효율성 높이는 방법 (0) | 2025.09.24 |
| React 개발의 핵심: useState Hook 완전 정복! (0) | 2025.09.24 |
| React Hooks: 함수형 컴포넌트의 혁신! (0) | 2025.09.23 |
| React 개발의 핵심: 컴포지션 vs. 상속, 언제 무엇을 사용할까? (0) | 2025.09.23 |