본문 바로가기

React

useEffect

우선 LifeCycle에 대해 살펴보고 useEffect에 대해 정리해보겠습니다.

 

 

[이미지 출처] https://www.google.com/url?sa=i&url=https%3A%2F%2Fwww.dentalzero.com%2Fnews%2FarticleView.html%3Fidxno%3D21200&psig=AOvVaw30SJgT8VdgfpthBhTKFoyd&ust=1665754380174000&source=images&cd=vfe&ved=0CAgQjRxqFwoTCNCfreKo3foCFQAAAAAdAAAAABAE

 

사람에게 LifeCycle이란 시간이 흐름에 따라, 탄생부터 죽음에 이르는 순간에 따른 단계적인 과정입니다.

 

이때 사람은 LifeCycle 주기 별로 각각 다른 욕구, 즉 무언가를 하고자 하는 욕구가 다르게 나타납니다.

 

이런 LifeCycle은 software에서도 많이 사용됩니다.

 

사람이 태어나서 죽음에 이르는 순간과 같이 어떤 프로그램이 실행되고 종료되는 순간을 나타내기 위해 LifeCycle이란 단어를 자주 사용하게 됩니다.

 

물론 React의 컴포넌트 또한 탄생 > 변화 > 죽음과 같은 LifeCycle을 가지게 됩니다.

 

[이미지출처]https://www.google.com/url?sa=i&url=https%3A%2F%2Fsoldonii.tistory.com%2F113&psig=AOvVaw3vHxQWjnRI5OfDJ1XicSBE&ust=1665754798425000&source=images&cd=vfe&ved=0CAkQjRxqFwoTCKCzhrGq3foCFQAAAAAdAAAAABAD

 

컴포넌트가 화면에 Mount 되었을 때를 탄생이라고 생각하시면 되며, 컴포넌트가 업데이트되었을 때를 변화, 컴포넌트가 UnMount 되었을 때를 죽음이라 생각하시면 됩니다.

 

정리를 해보면 생성은 컴포넌트가 화면에 Mount 되었을 때, 업데이트는 컴포넌트가 Update 되었을 때, 제거는 컴포넌트가 UnMount 되었을 때입니다.

 

 

다음으로 컴포넌트의 생명주기인 LifeCycle을 제어한다는 것은 어떤 의미를 가지는지 정리해보겠습니다.

[이미지출처]한입 크기로 잘라먹는 리액트(이정환)

컴포넌트의 LifeCycle을 제어한다는 것은 어떤 일련의 어려운 기술을 요구하는 것이 아닌 컴포넌트가 Mount > Update > UnMount 되는 순간에 어떠한 작업을 실행시킬 수 있다는 것을 LifeCycle 제어한다고 말할 수 있습니다.

 

Mount시 초기화 작업을 시킨다거나, Update가 발생할 때 해당 Update로 인해 발생할 수 있는 예외 처리 작업을 추가로 한다거나, UnMount 될 때 해당 컴포넌트가 사용하는 메모리를 반환하게 하는 작업을 예로 들 수 있습니다.

 

React를 보다 견고하게 사용하기 위해서는 LifeCycle을 온전히 이해하고 사용하는 것이 중요합니다.

 

React는 기본적으로 LifeCycle 별로 실행할 수 있는 메서드를 가지고 있습니다.

 

componentDidMount는 컴포넌트가 Mount 되는 순간에 어떠한 작업이 실행될 수 있게 해주는 메서드이며, 

 

componentDidUpdate는 컴포넌트가 Update 되는 순간에 어떠한 작업이 실행될 수 있게 해주는 메서드이고

 

componentWillUnmount는  컴포넌트가 UnMount 되기 이전에 어떠한 작업이 실행될 수 있게 해 주는 메서드입니다.

 

위의 메서드들은 class 형태의 컴포넌트에서만 사용이 가능하지만 React Hooks의 도입으로 useEffect hook을 사용하여 함수형 컴포넌트에서도 컴포넌트 LifeCycle 제어가 가능하게 되었습니다.

 

 


 

useEffect

함수형 컴포넌트에서 LifeCycle을 제어하기 위해서는 useEffect hook을 사용해야 합니다.

import React, { useEffect } from "react";

useEffect(() => { todo... }, []);

 

useEffect의 사용 형태는 위와 같습니다.

 

useEffect에는 두 개의 인수를 전달하며 첫 번째 인수는 Callback 함수를 전달하며, 두 번째 인수는 Dependency Array(의존성 배열)을 전달합니다.

 

두 번째 인수로 전달하는 의존성 배열은 해당 배열 안에 들어 있는 값들 중 하나라도 변화하면 Callback함수가 실행됩니다.

 

자세한 사용법은 아래 예제 코드와 함께 살펴보겠습니다.

 

import React, { useEffect, useState } from "react";

const LifeCycle = () => {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");

  return (
    <div style={{ padding: "20px" }}>
      <div>
        {count}
        <button onClick={() => setCount(count + 1)}>+</button>
      </div>
      <div>
        <input value={text} onChange={(e) => setText(e.target.value)} />
      </div>
    </div>
  );
};

export default LifeCycle;

해당 코드는  input 태그와 버튼을 클릭했을 때 숫자가 1씩 증가하는 간단한 코드입니다.

 

이제 컴포넌트의 LifeCycle 제어를 해보도록 하겠습니다.

 

import React, { useEffect, useState } from "react";

const LifeCycle = () => {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");

  useEffect(() => {
    console.log("Mount!");
  }, []);

  return (
    <div style={{ padding: "20px" }}>
      <div>
        {count}
        <button onClick={() => setCount(count + 1)}>+</button>
      </div>
      <div>
        <input value={text} onChange={(e) => setText(e.target.value)} />
      </div>
    </div>
  );
};

export default LifeCycle;

의존성 배열에 아무 값도 넣지 않고 useEffect를 사용하면 컴포넌트가 Mount 될 때 useEffect에 첫 번째 인수로 전달한 Callback함수가 실행되게 됩니다.

 

위의 코드의 경우 console.log("Mount!")가 실행됩니다.

 

이때 + 버튼을 클릭을 해도 콘솔에는 더 이상 Mount가 찍히지 않는 것을 확인할 수 있습니다.

 

즉 count State가 업데이트되면서 해당 컴포넌트가 업데이트되는데 useEffect 첫 번째 인수로 전달된 Callback 함수는 컴포넌트가 Mount(화면에 나타날 때)될 때만 실행되게 됩니다.

 

 

import React, { useEffect, useState } from "react";

const LifeCycle = () => {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");

  useEffect(() => {
    console.log("Update!");
  });

  return (
    <div style={{ padding: "20px" }}>
      <div>
        {count}
        <button onClick={() => setCount(count + 1)}>+</button>
      </div>
      <div>
        <input value={text} onChange={(e) => setText(e.target.value)} />
      </div>
    </div>
  );
};

export default LifeCycle;

useEffect에 두 번째 인수로 의존성 배열을 주지 않으면 컴포넌트가 Update 될 때마다 useEffect에 첫 번째 인수로 전달한 Callback함수가 실행되게 됩니다.

 

즉 컴포넌트 내부에 존재하는 State나 전달받는 props가 변화할 때마다 console.log("Update!")가 실행됩니다.

 

 useEffect(() => {
    console.log(`count is update ${count}`);
  }, [count]);

상단에서 의존성 배열에 담긴 값이 변화할 때마다 Callback 함수가 실행된다고 정리했었습니다.

 

위의 코드처럼 의존성 배열에 count State를 넣게 되면 해당 State의 값이 변화할 때마다 Callback 함수가 실행되어 아래와 같은 결과가 나오게 됩니다. (버튼을 클릭할 때마다 Callback 함수 실행)

이렇게 의존성 배열을 활용하면 원하는 값이 변화하는 순간에만 Callback함수가 실행되게 코드를 작성할 수 있습니다.

 

 

 useEffect(() => {
    console.log(`count is update ${count}`);
    if (count > 5) {
      alert("count가 5를 넘었습니다. 따라서 0으로 초기화 합니다.");
      setCount(0);
    }
  }, [count]);

만약 count State의 최댓값을 지정하고 지정한 최댓값을 넘으면 0으로 초기화하고 싶다면 위의 코드처럼 작성할 수 있습니다.

 

count가 변화할 때마다 count의 값을 검사하는 코드를 실행시킬 수 있습니다.

 

useEffect를 사용하지 않고 if 조건문을 사용했다면 text State가 변화하여 컴포넌트가 update 될 때도 해당 조건문은 실행되게 되었을 것입니다.

 

 

마지막으로 컴포넌트가 UnMount 될 때입니다.

 

import React, { useState } from "react";

const UnMountTest = () => {
  return <div>UnMount Testing</div>;
};

const LifeCycle = () => {
  const [isVisible, setIsVisible] = useState(false);

  const toggle = () => setIsVisible((prev) => !prev);

  return (
    <div style={{ padding: "20px" }}>
      <button onClick={toggle}>ON / OFF</button>
      {isVisible && <UnMountTest />}
    </div>
  );
};

export default LifeCycle;

버튼을 클릭했을 때마다 자식 컴포넌트인 UnMountTest가 나타났다 사라졌다 하는 간단한 코드입니다.

 

const UnMountTest = () => {
  useEffect(() => {
    // 컴포넌트가 Mount되는 시점에 실행
    console.log("Mount!");

    return () => {
      // 리턴되는 함수는 UnMount되는 시점에 실행됩니다.
      console.log("UnMount!");
    };
  }, []);
  return <div>UnMount Testing</div>;
};

이때 버튼을 클릭해서 컴포넌트가 사라질 때, 즉 isVisible State가 false가 되어 UnMountTest 컴포넌트가 UnMount 될 때를 제어하기 위해 UnMountTest 컴포넌트 내부에 useEffect를 사용해보겠습니다.

 

useEffect에 첫 번째 인수로 전달하는 함수에서 리턴되는 함수는 컴포넌트가 UnMount(화면에서 사라질 때)되는 시점에 실행되는 함수입니다.

 

의존성 배열에 아무 값도 전달하지 않았기 때문에 컴포넌트가 Mount(화면에 나타날 때) 시점에서 Callback 함수가 실행되어 Mount! 가 콘솔에 찍히고, 컴포넌트가 UnMount(화면에서 사라질 때) 시점에서 CallBack 함수에서 리턴되는 함수가 실행되게 됩니다.

 

 

'React' 카테고리의 다른 글

Custom Hooks  (0) 2022.10.23
React Routing  (0) 2022.10.18
Memoization(React.memo, useMemo, useCallback)  (2) 2022.10.11
useContext  (0) 2022.10.09
Hook 사용 규칙  (0) 2022.10.08