STUDY/[ React ]

useEffect

Lim임 2025. 11. 22. 04:00

useEffect란?

컴포넌트가 렌더링된 후에 실행되는 “사이드 이펙트(side effect)” 전용 함수.

리액트는 렌더링 = 화면을 그리는 과정인데,
이 렌더링 과정에서는 순수한 계산만 있어야 해.

하지만 실제 앱에서는 이런 게 필요함:

  • API 요청
  • DOM 직접 조작
  • 네트워크 / 타이머 / 이벤트 등록
  • 데이터 저장/불러오기(localStorage)
  • 외부 라이브러리 초기화 등등…

이런 “부수효과(=side effect)”를 수행하는 공간이 useEffect야.


기본 형태

useEffect(() => { // 실행할 코드 }, [deps]);
deps = dependency array(의존성 배열)
어떤 상황에 effect를 실행할지 결정하는 “조건” 역할.

상황별로 정리한 useEffect의 3가지 동작

의존성 배열이 없는 경우

useEffect(() => { console.log("컴포넌트가 렌더링될 때마다 실행"); });

↳ 언제 쓰냐?

  • 매 렌더링마다 동작해야 하는 로그, 디버깅
  • 렌더링 기반으로 DOM을 계산해야 하는 상황

거의 사용 안 함

렌더링마다 실행되면 성능상 손해라 대부분 피함.


빈 배열인 경우: 첫 렌더링만 실행

 
useEffect(() => { console.log("마운트될 때 딱 1번 실행!"); }, []);

↳ 언제 쓰냐?

  • 처음 페이지 열릴 때 한 번만 실행해야 하는 작업
    ✔ API 데이터 fetch
    ✔ WebSocket / Firebase 연결
    ✔ setInterval 등록
    ✔ 외부 라이브러리 초기화

React에서 componentDidMount 역할.


특정 값이 변경될 때 실행

 
useEffect(() => { console.log(`count가 ${count}로 바뀔 때마다 실행`); }, [count]);

↳ 언제 쓰냐?

  • 상태가 바뀔 때 특정 작업 수행
  • 검색어가 바뀌면 API 요청
  • 어떤 props가 바뀌면 로직 다시 실행
  • 폼 입력값 변화 감지 후 debouncing

useEffect의 또 하나의 핵심: cleanup(정리 함수)

 
useEffect(() => { const timer = setInterval(() => { console.log("Tick"); }, 1000); return () => { clearInterval(timer); // 정리 }; }, []);

왜 필요?

컴포넌트가 사라지거나 다시 실행될 때
이전에 사용하던 리소스를 “정리해주어야” 메모리 누수가 안 발생함.

cleanup이 필요한 경우

  • setInterval, setTimeout
  • 이벤트 리스너(window.addEventListener)
  • WebSocket 연결 종료
  • 외부 라이브러리 instance 해제

useEffect로 만들 수 있는 주요 효과들 정리

 1) API 데이터 가져오기

useEffect(() => { fetch('/api/todos') .then(res => res.json()) .then(data => setTodos(data)); }, []);

 2) 타이머 / 인터벌 만들기

useEffect(() => { const id = setInterval(() => { setTime(t => t + 1); }, 1000); return () => clearInterval(id); }, []);

 3) 이벤트 리스너 등록

useEffect(() => { const handleResize = () => setWidth(window.innerWidth); window.addEventListener("resize", handleResize); return () => window.removeEventListener("resize", handleResize); }, []);

 

4) 상태 변경 시 추가 로직 실행
useEffect(() => { console.log("검색어:", keyword); // debounce 후 API 요청 등 }, [keyword]);

 

 5) props 변경 기반 로직
useEffect(() => { console.log("props로 받은 userId가 바뀌었어!"); }, [userId]);

 6) localStorage 저장/불러오기

useEffect(() => { const saved = localStorage.getItem("todo"); if (saved) setTodo(JSON.parse(saved)); }, []); useEffect(() => { localStorage.setItem("todo", JSON.stringify(todo)); }, [todo]);

 useEffect를 쓸 때 고려해야 할 것

 1) “언제 실행되어야 하는지”가 가장 중요

동작 조건 → 의존성 배열.

 2) 불필요한 effect 금지

  • 상태 업데이트가 또 effect를 불러오면 무한 루프 가능.

 3) 상태를 읽어야 하면 의존성 배열에 반드시 넣기

리액트 strict모드에서는 더 엄격하게 검사함.


useEffect는 언제 쓰나? (한 줄 요약)

렌더링과 직접 관련 없는 작업을 하고 싶을 때.
≠ 화면을 그리는 로직
= 외부 세계와 상호작용하는 로직(API, 이벤트, 타이머 등)

'STUDY > [ React ]' 카테고리의 다른 글

forwardRef 사용법 - 장기 프로젝트  (0) 2025.11.22
useRef  (0) 2025.11.22
CSS opacity와 brightness 비교 + filter 속성  (0) 2025.11.20
CSS 가상 요소 , Clip Path  (0) 2025.11.20
리액트 jsx  (0) 2025.11.14