본문 바로가기
Web Development/React

React/ part.3 useEffect

by Krystal K 2023. 4. 26.

 

useEffect

이전 글인 sideEffect에 이어 useEffect의 개념과 필요성 그리고 사용방법에 대해 다룹니다.

sideEffect에 대해 모른다면 해당 링크를 통해 이전 글을 먼저 읽으시기를 추천합니다.


 

1. useEffect란?

useEffect가 하는 일은 무엇일까?

useEffect Hook을 이용하여 컴포넌트가 렌더링 이후에 어떤 일을 수행할 지  리액트에게 알려준다.

React는 우리가 넘긴 함수를 기억했다가 DOM 업데이트를 수행한 이후에 호출한다.

(이 함수를 ‘effect’라고 한다.)

 

useEffect를 컴포넌트 안에서 불러내는 이유

useEffect를 컴포넌트 내부에 둠으로써 effect를 통해 변수에 접근할 수 있다.

함수 범위 안에 존재하기 때문에 특별한 API 없이도 값을 얻을 수 있다.

리액트는 한정된 API를 고안하는 것보다 자바스크립트가 이미 가지고 있는 방법을 이용하여 문제를 해결한다.

useEffect는 렌더링 이후에 매번 수행된다.

useEffect를 사용해 sideEffect의 발생 시점을 정할 수 있다.

 

 

2. useEffect 사용법

useEffect(() => {
랜더링 이후에 실행될 동작
}, [의존성 배열])

 

useEffect는 함수이고, 매개변수로 콜백 함수를 가진다.

콜백함수 : 실행시킬 동작

의존성 배열 : 실행시킬 타이밍

 

 

 

3. React에서 Side Effect의 올바른 발생 시점

렌더링 단계(UI를 만들어내는 과정)에서 side effect를 발생시킬 때 문제점

1. side effect가 렌더링을 blocking

2. 매 렌더링마다 side effect가 수행

 

 

1. side effect가 렌더링을 blocking 한다.

 

코드는 위에서 아래로 순차적으로 실행됨

doSideEffect()의 동작이 끝날 때까지 JSX를 return하는 코드로 넘어가지 않는다.

함수 컴포넌트가 JSX를 리턴하기 전까지 브라우저상의 UI는 랜더링 되지 않는다.

결국 사이드 이펙트가 끝나기 전까지 랜더링을 하지 못하고 브라우저가 멈춰있게 된다.

⇒ blocking

사용자가 UI가 업데이트 되는 것을 보기까지 상당한 시간이 소요된다.

 좋지 않는 사용자 경험으로 이어진다.

const App = () => {
  const doSideEffect = () => {
    // do some side effect
  };

  doSideEffect();

  return <h1>Hello World</h1>;
};

 

 

 

2. 매 랜더링마다 side effect가 수행된다. 

 

데이터들을 가져오는(Data Fetching) side effect 발생

⇒ 매 랜더링마다  데이터를 새로 가져올 필요가 없는 경우 불필요하다.

const App = () => {
  // 코드 생략

  // data fetching side effect
  getFeeds();

  return 피드리스트;
};

 

 

 

4. side effect를 발생시킬 조건이 필요

렌더링을 Blocking 하지 않기 위해서 렌더링이 모두 다 완료되고 난 후 실행할 수 있어야 한다.

매 렌더링마다 실행되는 것이 아니라 내가 원할 때만 조건부로 실행할 수 있어야 한다.

그리고 위의 두가지 조건을 모두 충족하면서 발생시키는 것이 가장 좋다.

React에서는 위의 요구사항을 모두 충족시키면서,

편하게 side effect를 발생시킬 수 있게 도와주는 useEffect hook을 지원한다.

 

 

조건 1

렌더링을 Blocking 하지 않기 위해서 렌더링이 모두 다 완료되고 난 후 실행할 수 있어야 한다.

side effect가 렌더링 이후에 실행

useEffect의 인자로 전달된 콜백 함수는 곧바로 호출되는 것이 아니라,

모든 렌더링이 완료된 후에 호출된다.

즉 렌더링을 blocking 하지 않고 side effect를 발생시킬 수 있게 되는 것이다.

 

조건 2

매 렌더링마다 실행되는 것이 아니라 내가 원할 때만 조건부로 실행할 수 있어야 한다.

1. 의존성 배열이 전달되지 않았을 때

⇒ 매 렌더링마다 콜백 함수를 호출한다.

 

2. 의존성 배열이 전달되었을 때

⇒ 의존성 배열의 값을 검사한다.

 

a. 의존성 배열에 있는 값 중 하나라도 이전 렌더링과 비교했을 때 달라졌다면 콜백 함수를 호출한다.

b. 의존성 배열에 있는 값이 이전 렌더링과 비교했을 때 모두 다 같다면 콜백 함수를 호출하지 않는다.

따라서 의존성 배열에 빈 배열을 넣을 경우 처음 랜더링 했을 때 한번만 실행된다.

⇒ 비교할 대상이 없기 때문에 실행되지 않는다.

 

 

5. Rendering & Effect Cycle

함수 컴포넌트의 렌더링과 useEffect가 발생하는 과정을 풀어서 설명하자면 아래와 같다.

 

mount

컴포넌트가 렌더링 된다.

(최초로 진행되는 렌더링은 브라우저에 처음으로 이 컴포넌트가 보였다는 의미로 mount 라고 표현)

(Side Effect)

useEffect 첫 번째 인자로 넘겨준 콜백 함수가 호출된다. 

 (update)

컴포넌트의 state 또는 props가 변경되었을 경우 리렌더링이 발생한다.

(Side Effect)

useEffect는 두 번째 인자에 들어있는 의존성 배열을 확인한다

의존성 배열이 전달되지 않았거나 /

 의존성 배열 내부의 값 중 이전 렌더링과 비교했을 때 변경된 값이 하나라도 있을 떼

첫 번째 인자로 넘겨준 콜백 함수가 호출된다.

or 

의존성 배열 내부의 값 중 이전 렌더링과 비교했을 때 변경된 값이 없다면 

콜백 함수를 호출하지 않는다.

 (update)

 state 또는 props가 변경된다면 위의 과정을 반복

unmount

컴포넌트가 더 이상 필요 없어지면 화면에서 사라진다.

(컴포넌트가 브라우저의 화면에서 사라졌다는 의미로 unmount라고 표현)

 

 

6. useEffect 실행 순서

부모 컴포넌트가 랜더링 된 후에 자식 컴포넌트가 랜더링 된다.

자식 컴포넌트까지 랜더링 된 후에 useEffect가 실행된다.

마운트 될 때는 무조건 useEffect가 한번씩 실행된다.

이후부터는 조건이 맞을 경우에만 실행된다.

자식 컴포넌트 내부에서 state의 변화가 일어날 경우는 부모 컴포넌트에 영향을 주지않고 자식 컴포넌트만 리랜더링한다.

useState를 부모 컴포넌트에서 선언하고 자식 컴포넌트에서 이벤트 발생해서 state가 변경 될때는 자식 컴포넌트가 먼저 랜더링 되지 않고, 부모 컴포넌트 랜더링이 되고 그로 인해 자식 컴포넌트도 랜더링 된다. state 끌어올리기

 

 

7. Clean Up의 필요성

위에서 정리(clean-up)가 필요하지 않은 side effect를 살펴보았다.

하지만 정리(clean-up)가 필요한 effect도 있다.

정리가 필요하다는 말은 불필요하게 계속 작동하는 effect의 동작을 종료시키는 것이다.

 

외부 데이터에 구독(subscription)을 설정해야 하는 경우에는

메모리 누수가 발생하지 않도록 정리(clean-up)하는 것은 매우 중요하다.

 

React가 effect를 정리(clean-up)하는 시점은 정확히 언제일까?

clean up 함수를 return만 해준다면,

clean up 함수를 적절한 시점에 호출해 주는 일은 useEffect가 알아서 처리한다.

 

useEffect는 clean up 함수를 두가지 경우에 호출해준다.

 

다음 side effect를 발생시키기 전

컴포넌트가 unmount 될 때

 

React는 컴포넌트가 마운트 해제되는 때에 정리(clean-up)를 실행한다.

하지만 effect는 한번이 아니라 렌더링이 실행되는 때마다 실행된다.

⇒ React가 다음 차례의 effect를 실행하기 전에 이전의 렌더링에서 파생된 effect 또한 정리하는 이유이다.

 

 


 

공식문서 참고

버그를 방지하는 데에 어떻게 도움이 되는지

성능 저하 문제가 발생할 경우 effect를 건너뛰는 방법

 


잘못된 정보가 있다면 댓글로 피드백주세요. 확인 후 수정하겠습니다^-^

더 정확한 정보 혹은 더 효율적인 방식이 있을 경우 댓글로 의견을 공유해주세요!

728x90

'Web Development > React' 카테고리의 다른 글

React/ part.3 Mock Data  (0) 2023.04.29
React /part.3 상수 데이터  (0) 2023.04.29
React / part.3 sideEffect  (0) 2023.04.26
React/ part.3 state  (0) 2023.04.24
React / part.3 props  (0) 2023.04.24