React 개발자를 위한 useEffect 올바르게 사용하는 방법
2025-02-21 02:13:10React에서 useEffect 올바르게 사용하기
React의 useEffect 훅은 함수형 컴포넌트에서 부수 효과를 관리하는 매우 강력한 도구입니다. 그러나 이를 잘못 사용하면 무한 루프와 같은 문제를 일으킬 수 있습니다. 이 글에서는 useEffect의 사용법을 정확히 이해하여 이런 문제를 방지하는 방법을 살펴보겠습니다.
사용 사례별 useEffect 소개
데이터 가져오기
useEffect(() => {
fetch('/api/data')
.then(response => response.json())
.then(data => setData(data));
}, []); // 빈 배열은 마운트 시에만 효과 한 번 실행.
설명
이 예제는 컴포넌트가 마운트될 때 API로부터 데이터를 가져오는 방법을 보여줍니다. 빈 종속성 배열 []은 이 효과가 초기에 딱 한 번만 실행된다는 것을 의미합니다. 이는 컴포넌트가 처음 로드될 때만 필요한 데이터 가져오기에 적합합니다.
외부 서비스 구독
useEffect(() => {
const subscription = subscribeToService((data) => setData(data));
return () => {
subscription.unsubscribe(); // 언마운트 시 정리.
};
}, []);
설명
이 예제는 WebSocket이나 이벤트 리스너와 같은 외부 서비스에 구독하는 방법을 보여줍니다. 컴포넌트가 마운트되었을 때만 효과가 실행되고, 언마운트될 때 정리 함수가 호출되어 메모리 누수를 방지합니다.
무한 루프 예방하기
종속성 배열의 올바른 사용
useEffect에서 두 번째 인자로 넘기는 종속성 배열을 올바르게 사용해야 합니다. 이 배열에는 효과가 의존하는 모든 변수나 속성을 포함해야만 불필요한 리렌더링을 방지할 수 있습니다.
useEffect(() => {
// 로직
}, [dependency1, dependency2]); // dependency1이나 dependency2가 변경될 때만 효과 실행.
상태 갱신에 따른 무한 루프 방지
useEffect 내에서 상태를 업데이트하면, 그 상태가 종속성 배열에 있을 경우 무한 루프가 발생할 수 있습니다. 이를 피하려면 상태 변경이 의도치 않게 효과를 다시 트리거하지 않도록 해야 합니다.
useEffect(() => {
setCount(count + 1);
}, [count]); // 무한 루프 발생 가능.
해결책: 조건부로 상태 갱신
useEffect(() => {
if (count < 10) {
setCount(count + 1);
}
}, [count]);
안정적인 종속성을 위한 Callback 또는 Ref 사용
종속성이 함수나 매 렌더링 시 변경되는 객체일 경우, 이는 매번 효과를 트리거합니다.
useEffect(() => {
const handler = () => {
// 로직
};
window.addEventListener('resize', handler);
return () => {
window.removeEventListener('resize', handler);
};
}, [someFunction]); // someFunction이 매 렌더링 시 변경되면 무한 루프.
해결책: useCallback 또는 useRef 사용
const stableFunction = useCallback(() => {
// 안정적인 로직
}, []);
useEffect(() => {
const handler = stableFunction;
window.addEventListener('resize', handler);
return () => {
window.removeEventListener('resize', handler);
};
}, [stableFunction]);
고급 사용 사례
조건부 효과
때때로 특정 조건이 만족될 때만 useEffect를 실행하고 싶을 수 있습니다. 이는 성능을 최적화하거나 특정 조건에 맞춰 효과가 실행되도록 하는 데 유용합니다.
useEffect(() => {
if (condition) {
// 로직 실행
}
}, [condition]);
여러 효과 사용
하나의 컴포넌트에서 여러 useEffect 훅을 사용할 수 있습니다. 이는 코드의 가독성을 높이고, 각 효과가 특정한 작업에 집중할 수 있게 합니다. 서로 다른 종속성을 사용하여 필요할 때만 효과가 실행되도록 하면 복잡한 논리도 관리하기가 쉬워집니다.
useEffect(() => {
// 효과 A
}, [dependencyA]);
useEffect(() => {
// 효과 B
}, [dependencyB]);
다수 종속성의 결합
여러 종속성을 사용하는 경우, 그들이 서로 어떻게 상호작용하는지를 주의 깊게 살펴야 합니다. 종속성 중 하나라도 변경되면 효과가 다시 실행됩니다. 효과의 내부 로직을 구조적으로 구성하여 각 종속성 변경에 대해 의도되는 행동만 수행하도록 해야 합니다.
useEffect(() => {
if (dependencyA && dependencyB) {
// 로직 실행
}
}, [dependencyA, dependencyB]);
흔한 실수 및 방지 방법
모든 종속성을 포함하지 않음
흔히 저지르는 실수로, useEffect 내에서 사용된 변수와 속성을 종속성 배열에 빠뜨리는 것입니다. 이는 효과가 예상대로 실행되지 않거나 오래된 값을 사용하여 문제가 생길 수 있습니다. 항상 모든 변수와 속성을 종속성 배열에 포함하여 일관성을 유지하고 예기치 않은 동작을 방지하십시오.
useEffect(() => {
doSomething(data); // 'data'는 종속성 배열에 포함되어야 함
}, [data]);
라이프사이클 메서드 대용으로 usoEffect 사용
useEffect를 componentDidMount나 componentDidUpdate와 같은 라이프사이클 메서드의 대체물로 사용하지 마십시오. useEffect는 부수 효과를 관리하기 위한 훅입니다.
결론
- 종속성 배열: 반드시 필요한 변수만 포함하여 불필요한 트리거를 피하세요.
- 무한 루프 방지: 상태 변경이 효과를 다시 트리거하지 않도록 주의하세요.
- 안정적인 종속성: useCallback이나 useRef를 사용하여 함수나 객체의 불필요한 변경을 방지하세요.
- 논리를 여러 useEffect로 나누기: 관리하기 쉬운 코드를 유지하면서 버그 발생 가능성을 줄여줍니다.
이러한 모범 사례를 따름으로써 useEffect를 보다 효과적으로 사용할 수 있고, 무한 루프와 같은 흔한 함정을 피할 수 있습니다.
참고 자료
이외에도 겨냥한 자료 및 도구에 대한 유용한 링크를 포스트 하단의 백링크를 통해 발견할 수 있습니다.