58 lines
8.0 KiB
Markdown
58 lines
8.0 KiB
Markdown
# [[useEffect]]
|
|
|
|
## 📌 Brief Summary
|
|
`useEffect`는 리액트(React) 함수형 컴포넌트에서 사이드 이펙트(side effects)를 관리하고 수행하기 위해 사용되는 핵심 훅(Hook)입니다 [1, 2]. 이 훅을 효과적으로 사용하기 위해서는 실행 타이밍을 제어하는 의존성 배열(dependency array)과 리소스 해제를 위한 클린업(cleanup) 함수를 올바르게 관리해야 합니다 [2, 3]. 코드를 작성할 때 남용하거나 관리를 소홀히 하면 예기치 않은 리렌더링과 성능 저하, 심각한 메모리 누수를 유발할 수 있습니다 [3, 4].
|
|
|
|
## 📖 Core Content
|
|
- **사이드 이펙트 관리**: `useEffect`는 주로 함수형 컴포넌트 내에서 데이터 구독, 이벤트 리스너 등록 등의 외부 시스템과의 동기화 및 부수 효과를 처리하는 데 사용됩니다 [2].
|
|
- **의존성 배열(Dependency Array)의 중요성**: `useEffect`가 언제 실행될지 결정하는 의존성 배열을 정확하게 설정해야 합니다. 배열이 잘못 제공되면 예기치 않은 동작, 컴포넌트의 불필요한 리렌더링, 혹은 꼭 필요한 업데이트가 누락되는 버그가 발생할 수 있습니다 [2]. 만약 JSX 내부나 렌더링 도중 선언된 익명 함수를 `useEffect`의 의존성으로 전달하면, 매 렌더링마다 함수 참조가 새로 생성되어 `useEffect`가 불필요하게 재실행되는 원인이 됩니다 [5].
|
|
- **클린업(Cleanup) 패턴**: 이벤트 리스너나 구독처럼 종료 시 처리가 필요한 사이드 이펙트는 `useEffect` 내부에서 반드시 클린업 함수를 반환해야 합니다 [3]. 컴포넌트가 언마운트(unmount)될 때 이 클린업 함수가 리소스를 해제하지 않으면, 참조가 메모리에 계속 남아 점진적인 성능 저하를 유발하는 메모리 누수(Memory Leak)가 발생합니다 [3, 6].
|
|
- **서버 컴포넌트(Server Components) 환경에서의 제한**: Next.js 13 이상에서 사용되는 리액트 서버 컴포넌트(RSC)에서는 상태나 라이프사이클을 가질 수 없으므로 `useEffect`를 사용할 수 없습니다 [7]. 서버 컴포넌트는 클라이언트 측 스크립트 없이 서버에서 데이터를 직접 페칭(fetching)할 수 있게 해주어, 전통적인 `useEffect` 기반 데이터 로딩 패턴을 상당 부분 대체합니다 [8].
|
|
|
|
## ⚖️ Trade-offs & Caveats
|
|
- **성능 오버헤드와 렌더링 악순환**: `useEffect`를 남용하여 너무 많은 로직을 처리하게 되면 잦은 컴포넌트 리렌더링이 발생하여 애플리케이션의 전반적인 성능과 사용자 경험이 크게 저하될 수 있습니다 [4].
|
|
- **메모리 누수 제약**: 개발자의 부주의로 인해 클린업 함수가 누락되거나 의존성 배열 관리가 잘못되면, 컴포넌트가 화면에서 사라진 후에도 백그라운드 연산이 계속 진행되거나 DOM 참조가 메모리에 남아(Detached DOM nodes) 치명적인 메모리 누수 제약 상황을 초래합니다 [3, 4, 6].
|
|
- **코드 복잡도 증가**: 레거시 리액트 코드베이스 리팩토링 시, 불필요한 `useEffect` 제거가 핵심 과제로 꼽힙니다 [9]. 상태(state) 도출이나 파생 데이터 생성에 `useEffect`를 오용하면 유지보수성이 떨어지며, 이를 해결하기 위해 로직을 걷어내고 `useMemo`나 `useCallback` 등으로 구조를 다시 설계해야 하는 부담이 생깁니다 [4, 9].
|
|
|
|
## 🔗 Knowledge Connections
|
|
|
|
### Related Concepts
|
|
|
|
#### [최적화 및 대안 기술]
|
|
- [[useMemo]]
|
|
- 연결 이유: `useEffect`를 남용하여 파생 데이터를 계산하는 대신, 계산 비용이 높은 값을 메모이제이션할 때 적합한 대안으로 권장됩니다 [4].
|
|
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 불필요한 연산과 리렌더링을 방지하고 상태 파생 최적화를 구현하는 방법.
|
|
|
|
- [[useCallback]]
|
|
- 연결 이유: `useEffect`의 의존성 배열에 들어가는 함수의 참조(Reference Identity)를 렌더링 간에 안정적으로 유지시키기 위해 사용됩니다 [4, 5].
|
|
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 자바스크립트의 참조 동등성(Reference Equality)이 리액트 렌더링 사이클 및 이펙트 실행 빈도에 미치는 영향.
|
|
|
|
#### [아키텍처 및 디버깅 도구]
|
|
- [[React Server Components]]
|
|
- 연결 이유: 서버 컴포넌트 환경에서는 `useEffect`의 사용이 원천적으로 차단되며, 이를 통해 `useEffect`에 의존하던 클라이언트 사이드 데이터 페칭 구조를 서버로 전환할 수 있습니다 [7, 8].
|
|
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 클라이언트 상태(Client State)와 서버 컴포넌트의 역할 분리 및 하이드레이션(Hydration) 최적화 방식.
|
|
|
|
- [[Memory Leaks]]
|
|
- 연결 이유: `useEffect`에서 클린업을 누락하는 것이 자바스크립트 환경에서 발생하는 메모리 누수의 대표적인 원인 중 하나입니다 [3, 6].
|
|
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: Chrome DevTools의 Heap Snapshot 등을 활용하여 분리된 DOM 노드 및 정리되지 않은 구독을 추적하고 디버깅하는 원리.
|
|
|
|
### Deeper Research Questions
|
|
- `useEffect`의 의존성 배열 내부에서 얕은 비교(Shallow Comparison)가 동작하는 방식은 객체나 배열 같은 참조 타입 데이터에 어떤 부작용을 일으키는가?
|
|
- `useEffect`를 이용한 클라이언트 사이드 데이터 페칭을 TanStack Query (React Query)나 Server Components로 대체했을 때 얻을 수 있는 아키텍처적 이점과 성능 차이는 무엇인가?
|
|
- 불필요한 `useEffect`를 식별하고 제거하기 위해 `why-did-you-render`나 React Profiler와 같은 도구를 어떻게 활용하여 성능 측정의 지표로 삼을 수 있는가?
|
|
- 컴포넌트가 언마운트되는 시점에 `useEffect`의 클린업 함수가 실행되는 과정은 브라우저의 가비지 컬렉션(Garbage Collection)과 어떻게 상호작용하는가?
|
|
- `useEffect` 훅 내부의 로직을 `useTransition`이나 `useDeferredValue` 등 동시성(Concurrent) 기능과 결합할 때 고려해야 할 동기화 문제는 무엇인가?
|
|
|
|
### Practical Application Contexts
|
|
- **Implementation:** 함수형 컴포넌트에서 이벤트 리스너(예: 스크롤, 리사이즈)를 붙이거나 외부 라이브러리를 마운트할 때 활용하며, 반환 함수를 통해 명시적인 클린업(removeEventListener 등)을 구현해야 합니다 [2, 3].
|
|
- **System Design:** 애플리케이션의 렌더링 성능을 설계할 때, 자주 변경되는 상태의 사이드 이펙트는 컴포넌트 트리의 최하단으로 격리하거나 Context API 대신 Zustand와 같은 상태 관리자를 활용하여 리렌더링 범위를 제한해야 합니다 [10, 11].
|
|
- **Operation / Maintenance:** 프로덕션 환경에서 시간이 지남에 따라 앱이 느려지거나 멈추는 현상이 발생할 경우, Chrome DevTools의 Memory 탭을 통해 `useEffect`의 구독 해제 누락 여부를 프로파일링하고 메모리 누수를 디버깅합니다 [6, 12].
|
|
- **Learning Path:** 리액트를 처음 배우는 단계에서 훅의 규칙(Rules of Hooks)을 이해하고, 생명주기(Lifecycle) 메서드가 함수형의 `useEffect`로 어떻게 대체되는지, 그리고 의존성 배열 관리가 왜 중요한지를 파악하는 핵심 학습 경로입니다 [2, 13].
|
|
- **My Project Relevance:** 레거시 리액트 프로젝트를 리팩토링하거나 클래스 기반 컴포넌트를 마이그레이션할 때, 불필요한 `useEffect` 체인을 제거하고 의존성 배열을 교정하여 코드 스멜(Code Smell)을 없애고 확장성을 높이는 실무 과제와 직결됩니다 [9].
|
|
|
|
### Adjacent Topics
|
|
- [[Rules of Hooks]]
|
|
- 확장 방향: `useEffect`를 포함한 모든 리액트 훅이 반복문, 조건문 내부가 아닌 컴포넌트의 최상위에서만 일관되게 호출되어야 하는 구조적 원리를 이해하는 데 도움을 줍니다 [13].
|
|
|
|
---
|
|
*Last updated: 2026-04-30* |