React를 쓰다 보면 거의 반사적으로 useEffect를 사용하게 됩니다. 데이터 가져오기, 상태 동기화, DOM 조작… 어떤 이유에서든 useEffect를 쓰고 있지만, 정말 지금 이 순간 useEffect가 필요한 걸까요?
이 글에서는 useEffect를 과용했을 때 생기는 문제와 정말로 필요한 순간, 그리고 대체할 수 있는 다른 React 훅들을 정리합니다. 🤓
많은 경우 useEffect는 단순히 어떤 값을 계산하거나 상태를 업데이트하는 데 사용됩니다. 하지만 이는 React의 "렌더링 → DOM 반영 → 이펙트 실행" 순서를 고려하지 않은 접근입니다. 불필요한 이펙트 실행은 컴포넌트 렌더링 타이밍을 예측하기 어렵게 만들고, 성능을 떨어뜨립니다.
// ❌ 잘못된 예시
useEffect(() => {
const result = expensiveCalculation(input);
setResult(result);
}, [input]);
위 코드는 input이 바뀔 때마다 expensiveCalculation을 수행하고 상태를 업데이트합니다. 하지만 이건 사실 useMemo로 처리할 수 있는 계산입니다.
// ✅ 올바른 예시
const result = useMemo(() => expensiveCalculation(input), [input]);
렌더링 도중 실행돼야 할 계산은 useMemo, 부수 효과(side effect)는 useEffect. 이 두 역할을 구분해야 합니다.
const [count, setCount] = useState(0);
const [double, setDouble] = useState(0);
useEffect(() => {
setDouble(count * 2);
}, [count]);
double은 오직 count로부터 계산될 수 있는 값이기 때문에 굳이 별도로 상태로 관리할 이유가 없습니다. 이렇게 다른 상태에 전적으로 의존해서 파생되는 값은 useMemo나 그냥 렌더링 안에서 직접 계산하는 것이 훨씬 명확하고 효율적입니다.
// ✅ 더 나은 방식
const double = useMemo(() => count * 2, [count]);
// 또는 그냥 const double = count * 2; 도 충분함
=> 상태는 "사용자가 직접 바꿀 수 있는 값"에만 써야 의미가 있습니다.
const [user, setUser] = useState(null);
useEffect(() => {
setUser(defaultUser);
}, []);
useEffect 없이도 초기값은 직접 줄 수 있습니다.
const [user, setUser] = useState(defaultUser);
진짜 필요한 경우는 다음과 같습니다.
| 상황 | 예시 |
|---|---|
| 외부 API 호출 | fetch, axios 등 비동기 데이터 가져오기 |
| 이벤트 리스너 등록/해제 | window.addEventListener, document.addEventListener |
| 타이머 설정 | setTimeout, setInterval |
| 외부 라이브러리 연동 | 지도, 차트, 3rd-party 라이브러리 연결 |
| 상태 → 외부 동기화 | localStorage, URL, document.title 등 브라우저에 반영 |
이 모든 공통점은 "렌더링 결과와 무관한 외부 동작"입니다. React의 렌더링 "흐름" 안에서는 일어날 수 없는 일이라는 뜻입니다.
React는 렌더링 → DOM 반영 → effect 실행이라는 순서를 따릅니다.
즉, useEffect는 React 입장에서 말하면 "렌더링에는 직접 관여할 수 없는 시점에 실행되는 동작"이에요.
간단히 정리하면,
| 목적 적절한 훅 | |
|---|---|
| 렌더 중 계산 | (파생값) useMemo |
| 함수 캐싱 | useCallback |
| 외부 동작 | useEffect |
| 상태 저장 | useState |
| DOM 접근 | useRef + useEffect |
React에서 useEffect는 사이드 이펙트를 위한 훅입니다. 계산, 값 추론, 상태 파생 등은 React의 렌더링 흐름 안에서 처리되어야 하고, useEffect는 렌더링 외부의 일을 수행할 때만 사용해야 합니다.
📌 렌더링 중 처리 가능한 일은 useEffect로 미루지 마세요.
useEffect는 필요한 순간에만, 단호하게 써야 합니다. 😎
정답이 너무나 명확한 문제입니다
https://react.dev/learn/you-might-not-need-an-effect
They let you “step outside” of React and synchronize your components with some external system like a non-React widget, network, or the browser DOM.
언제 어떻게 써야하는지 아예 정해져있어요
좋은 글이네요!!