useEffect 가 호출되는 시점

Woody·2025년 8월 16일
0

매일메일

목록 보기
9/13

오늘의 질문

useEffect가 호출되는 시점에 대해 설명해 주세요.

내답변

useEffect 는 마운트 언마운트 업데이트시에 실행된다고 볼 수 있을 것 같다. 의존성 배열을 주어 의존성 값이 변경되었을때 실행할 수 있는데 해당 배열을 주지 않으면 최초 실행시에만 작동한다. 또한 언마운트시에 실행하고 싶으면 return 값을 통한 클린업 함수 호출이 가능할것이다.

다만 리액트에서 안티패턴으로 useEffect 를 통한 단순 마운트시의 동작을 위해 사용하는건 잘못된 방식이다.

처음한번만 실행되어야 하는 경우 함수등으로 동작시켜야 하며 주의해야한다

정답

useEffect는 컴포넌트의 특정 시점에 자동으로 호출되는 훅으로, 크게 컴포넌트가 마운트 , 업데이트, 언마운트 되는 시점에 호출된다.

먼저 useEffect 는 컴포넌트가 마운트될 때, 즉 처음 렌더링되고 나서 호출된다. 이때 데이터의 초기화나 외부 API호출 구독 설정등의 작업을 실행할 수 있다. useEffect는 컴포넌트가 처음 마운트 될때 필요한 초기 작업을 수행할 수 있도록 해준다.

또한, useEffect 는 의존성 배열에 지정된 갑싱 변경될 때 마다 다시 호출된다. 이때 useEffect의 return 값으로 지정된 클린업 함수가 이전 props 및 state와 함께 먼저 호출된 후, 본문의 실행 로직이 업데이트된 props및 state와 함께 실행된다.

두번째 인자로 주어지는 의존성 배열은 useEffect가 어떤 상태나 props의 변화에 반응할지를 결정한다. 예를 들어 useEffect(()=>{...}, [count]) 처럼 count 상태가 의존성 배열에 있을 경우, count 값이 변경될 때마다 useEffect가 호출됩니다. 이를 통해 특정 상태나 props가 변경될 때마다 필요한 동작을 수행하도록 할 수 있으며, 컴포넌트의 변화에 따라 동적으로 실행되는 로직을 설정할 수 있습니다.
단, 의존성 배열을 넘기지 않을 경우 매 렌더링마다 호출됩니다.

마지막으로, 컴포넌트가 언마운트될 때 useEffect의 return 값으로 지정된 클린업 함수가 호출됩니다. 이 정리 함수를 이용하여 이벤트 리스너 제거, 타이머 해제, 구독 취소등의 작업을 수행할 수 있습니다. 이를 통해 useEffect를 통해 발생한 부수효과를 정리하는 것이다.

요약하자면, useEffect는 컴포넌트가 처음 렌더링된 후, 의존성 배열의 값이 변경될 때, 그리고 컴포넌트가 언마운트될 때 호출된다.

추가공부

답변에 대한 피드백 :

  1. 배열을 생략하면 매 렌더링마다 실행된다. 최초 실행은 빈배열일때만
  2. 클린업 함수의 경우 언마운트 뿐만이 아닌 의존성 배열 값이 바뀔 때도 실행된다
  3. 안티패턴의 경우 명확히는 '렌더링과 상관없는 동작' 을 사용하지 말라는 뜻이다. 렌더링 안에서 바로 해도되는 값이 들어가는 경우를 감안해야한다

useEffect vs useLayoutEffect

useEffect: 브라우저 페인트(화면그리기)가 끝난 후 실행 -> 사용자에게 깜빡임 없는 부드러운 렌더링

useLayoutEffect: DOM이 업데이트된 직후, 페인트되기 전에 동기적으로 실행 -> 레이아웃 계산/DOM 읽기 쓰기 작업에 적합.

이에 DOM 크기를 측정하거나 스크롤 위치의 에저에 사용하면 좋음

서버컴포넌트와 클라이언트 컴포넌트
nextjs 에서 servercomponent 사용시 useEffect 사용이 불가능하다. 클라이언트에서만 실행되는 훅.

데이터 fetching 은 useEffect 보다는 server component + fetch 혹은 react query (tanstack) 로 위임하는게 좋다.

useEffect 는 브라우저에서만 필요한 사이드 이팩트에 집중해야 함 (리스너, 애니메이션, 추적)

상태 동기화 문제
useEffect 안에서 사용하는 변수는 렌더 시점의 값이 클로저로 캡처

이때문에 최신이 아닌 옛날 상태를 참조하는 문제 (stale closure)

의존성 배열을 정확히 넣어야 해결이 된다.

profile
프론트엔드 개발자로 살아가기

0개의 댓글