
React – 상태 관리와 Hooks – 기본 Hooks – 1 – useEffect의 의존성 배열과 정리(clean-up)
안녕하세요 여러분! 😊
이번 시간에는 **React의 대표적인 훅 중 하나인 useEffect
**에 대해 알아보겠습니다.
이 훅은 말 그대로 컴포넌트에서 “효과(effect)”, 즉 렌더링 이외의 작업을 처리할 수 있게 해주는 친구예요.
예를 들면, API 호출, 이벤트 리스너 등록, 타이머 설정 등과 같은 작업을 useEffect
안에서 처리하게 됩니다.
하지만 useEffect
는 언제 실행되느냐, 어떻게 정리되느냐에 따라 동작이 완전히 달라지기 때문에
의존성 배열(dependency array) 과 정리(clean-up) 개념을 꼭 함께 이해해야 해요!
1. useEffect란 무엇인가요?
useEffect
는 컴포넌트가 렌더링된 후 특정 작업을 수행하도록 설정하는 훅이에요.
import { useEffect } from 'react';
useEffect(() => {
// 이 안에서 side effect 발생!
});
🧠 비유하자면?
useEffect는 마치 “집 청소 후 커피 한잔 하는 것” 같아요.
뭔가 주 업무(렌더링)가 끝난 후에 추가로 처리하고 싶은 일을 맡기는 거예요!
2. 기본 사용 예시
useEffect(() => {
console.log('컴포넌트가 렌더링될 때마다 실행됨');
});
이렇게 쓰면 모든 렌더링 이후에 항상 실행됩니다.
즉, setState
로 상태가 바뀌어서 리렌더링이 발생할 때마다 계속 실행돼요.
3. 의존성 배열 (Dependency Array)
useEffect
의 두 번째 인자로 배열을 넣으면, 해당 값이 변경될 때만 effect가 실행됩니다.
예시 1: 처음 한 번만 실행 (Mount 시)
useEffect(() => {
console.log('처음 한 번만 실행됨!');
}, []);
- 의존성 배열이
[]
이면 컴포넌트가 처음 마운트될 때 딱 한 번만 실행돼요. - 마치
componentDidMount
같은 역할!
예시 2: 특정 값이 바뀔 때만 실행
useEffect(() => {
console.log('카운트가 바뀌었습니다:', count);
}, [count]);
count
가 바뀔 때만 실행됩니다.- 이전과 현재 값을 비교해 변경되었을 때만 반응해요.
4. Clean-up 함수란?
useEffect
는 컴포넌트가 사라질 때나 effect가 다시 실행되기 전에 정리(clean-up) 함수를 호출할 수 있어요.
사용 예시
useEffect(() => {
const timer = setInterval(() => {
console.log('타이머 동작 중...');
}, 1000);
return () => {
clearInterval(timer);
console.log('타이머 정리됨');
};
}, []);
- 마운트 시 타이머 시작
- 언마운트 시 정리(clean-up) 실행
🧹 정리 함수는 마치 퇴근 전에 사무실 불 끄고 나가는 느낌이에요!
5. 정리 함수가 필요한 이유
-
메모리 누수 방지
이벤트 리스너, 타이머, API 스트림 등은 사용 후 반드시 정리해야 해요. -
정확한 동작 보장
오래된 effect가 남아있으면 예상치 못한 결과가 발생할 수 있어요. -
클로저 문제 방지
오래된 상태에 접근하는 문제를 방지하기 위해 최신 값을 반영하려면 정리 후 다시 effect를 적용해야 해요.
6. 실전 예제: 윈도우 리사이즈 이벤트 등록
function WindowSizeLogger() {
useEffect(() => {
const logSize = () => {
console.log(`현재 창 크기: ${window.innerWidth}px`);
};
window.addEventListener('resize', logSize);
// 정리 함수
return () => {
window.removeEventListener('resize', logSize);
console.log('리스너 정리 완료!');
};
}, []);
return <div>창 크기를 바꿔보세요!</div>;
}
- 리사이즈 이벤트를 등록했다면, 컴포넌트가 사라질 때 꼭 제거해야 합니다.
- 그렇지 않으면 불필요한 이벤트가 계속 남아서 성능 저하가 생겨요.
7. 의존성 배열 관리 팁
상황 | 의존성 배열 |
---|---|
항상 실행하고 싶다 | 없음 |
처음 한 번만 실행 | [] |
특정 값이 바뀔 때 실행 | [값1, 값2] 등 포함 |
함수를 의존성에 넣을 때 | useCallback 으로 메모이제이션 필요 |
🔍 의존성 배열이 비었는데 내부에서 사용하는 변수나 함수가 있으면 의존성 누락 경고가 뜰 수 있어요.
이럴 땐 ESLint가 도와주기도 하니 참고해주세요!
8. 자주 하는 실수
실수 | 예시 | 해결 방법 |
---|---|---|
의존성 누락 | useEffect(() => { fetchData(); }, []) → fetchData는 외부 함수인데 의존성 없음 |
useCallback 또는 의존성 배열에 포함 |
정리 함수 누락 | 이벤트 등록했는데 제거 안 함 | return () => {...} 작성 |
내부에서 상태 변경 무한 루프 | useEffect(() => { setValue(count + 1); }, [count]) |
조건문 또는 플래그로 제어 필요 |
9. 한눈에 정리 – useEffect 패턴
패턴 | 설명 |
---|---|
useEffect(() => {...}) |
모든 렌더링 이후 실행 |
useEffect(() => {...}, []) |
마운트 시 한 번만 실행 |
useEffect(() => {...}, [val]) |
val이 바뀔 때마다 실행 |
useEffect(() => {...; return () => {...}; }, [...]) |
실행 전에 항상 정리하고 새 effect 적용 |
마무리하며
useEffect
는 React에서 side effect를 제어하는 가장 핵심적인 도구입니다.
정확히 동작 시점을 컨트롤하고, 불필요한 자원을 제거하는 습관을 들이면 성능 최적화와 버그 방지에 큰 도움이 돼요!
🔥 핵심 요약!
useEffect = 사이드 이펙트 + 타이밍 조절 + 정리까지 책임지는 슈퍼 도우미
이제부터는 데이터를 불러오거나, 이벤트를 연결하거나, 타이머를 다룰 때
무조건 useEffect
를 먼저 떠올려 보세요!
다음 시간에는 useEffect
와 함께 자주 쓰이는 또 다른 훅, useMemo
, useCallback
등을 통해
성능 최적화까지 살펴볼게요! 🚀