대부분의 React 개발자는 useEffect에 대해 이것을 잘못 이해하고 있다
Source: Dev.to

React에서 useEffect는 강력한 도구입니다. 이 훅을 사용하면 컴포넌트가 React 외부의 것들과 “소통”할 수 있습니다 — 예를 들어 타이머를 설정하거나, 서버와 데이터를 동기화하거나, 브라우저를 직접 다루는 작업(예: 페이지 제목 변경) 등을 할 수 있습니다. 외부 시스템과 작업할 때 유용합니다.
하지만 많은 사람들이 필요하지 않을 때도 useEffect를 사용합니다. 불필요한 useEffect는 다음과 같은 문제를 일으킬 수 있습니다:
- 코드 가독성이 떨어짐
- 버그가 발생할 가능성 증가
- 앱 성능 저하
useEffect가 필요하지 않은 경우를 이해하고, 대신 무엇을 해야 하는지 알아봅시다.
Effect를 사용해 데이터를 변환하지 마세요
첫 번째와 마지막 이름을 합쳐 전체 이름을 만들고 있다고 가정해 보세요. 이를 위해 Effect를 사용할 생각이 들 수 있습니다:
import { useState, useEffect } from 'react';
function Form() {
const [firstName, setFirstName] = useState('Taylor');
const [lastName, setLastName] = useState('Swift');
// ❌ 불필요한 useEffect
const [fullName, setFullName] = useState('');
useEffect(() => {
setFullName(firstName + ' ' + lastName);
}, [firstName, lastName]);
}
이는 과도한 작업입니다. React가 렌더링 과정에서 자연스럽게 할 수 있는 계산을 Effect로 수행하고 있기 때문입니다.
더 나은 방법:
function Form() {
const [firstName, setFirstName] = useState('Taylor');
const [lastName, setLastName] = useState('Swift');
// ✅ Effect가 필요 없음
const fullName = `${firstName} ${lastName}`;
}
이렇게 하면 더 간단하고, 빠르며, 이해하기 쉬워집니다. firstName이나 lastName이 변경될 때 React가 자동으로 컴포넌트를 다시 렌더링하고, fullName도 업데이트됩니다.
사용자 이벤트를 처리하기 위해 Effect를 사용하지 마세요
버튼 클릭이나 입력 변경 후 상태를 업데이트하기 위해 Effect가 필요하지도 않습니다.
흔한 실수
function Counter() {
const [count, setCount] = useState(0);
const [double, setDouble] = useState(0);
// ❌ 파생된 상태에 Effect 사용 금지
useEffect(() => {
setDouble(count * 2);
}, [count]);
return (
<>
<button onClick={() => setCount(count + 1)}>Increment</button>
<div>Double: {double}</div>
</>
);
}
더 나은 접근법
function Counter() {
const [count, setCount] = useState(0);
// ✅ Effect가 필요 없음
const double = count * 2;
return (
<>
<button onClick={() => setCount(count + 1)}>Increment</button>
<div>Double: {double}</div>
</>
);
}
독립적으로 변하는 상태만 저장하면 됩니다. 기존 상태에서 값을 계산할 수 있다면, 그냥 계산하세요.
언제 Effect가 필요할까?
React 외부의 무언가를 다룰 때 Effect가 필요합니다. 다음은 몇 가지 예시입니다:
API에서 데이터 가져오기
useEffect(() => {
fetch('/api/user')
.then(res => res.json())
.then(data => setUser(data));
}, []);
이벤트 구독하기
useEffect(() => {
function handleResize() {
setWidth(window.innerWidth);
}
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
타이머 설정하기
useEffect(() => {
const id = setInterval(() => {
console.log('Tick');
}, 1000);
return () => clearInterval(id); // 정리
}, []);
요약
useEffect를 사용하기 전에 스스로에게 물어보세요:
- React 외부와 동기화하고 있나요?
- 아니면 렌더링 중에 바로 계산할 수 있나요?
계산할 수 없는 데이터에만 상태를 사용하세요. 중복된 상태와 불필요한 Effect를 피하십시오. 이렇게 하면 React 코드가 더 깔끔하고, 빠르며, 디버깅이 쉬워집니다.
빠른 참고
useEffect가 필요하나요?
- 두 개의 상태를 결합하기 – ❌ 아니오
- 파생값 업데이트하기 – ❌ 아니오
- 사용자 클릭에 반응하기 – ❌ 아니오
- API에서 데이터 가져오기 – ✅ 예
- 타이머나 인터벌 설정하기 – ✅ 예
- 외부 이벤트 구독하기 – ✅ 예
React가 무거운 작업을 대신해 주도록 하세요 — 정말 필요할 때만 Effect를 사용하세요!