useEffect, 클린업 함수, useLayoutEffect, useRef

thisishwarang·2024년 4월 16일
1
post-thumbnail

❓useEffect란

useEffect : React 함수 컴포넌트에서 side effects를 수행하기 위해 사용되는 Hook.

(side effects란 컴포넌트의 상태 변화, 외부 API 호출, 구독 및 구독 해제와 같은 작업을 뜻함.)

즉, 어떤 state의 값이 변경되거나, 외부 API를 동기적으로 호출하는 등 리액트 컴포넌트가 렌더링 될 떄마다 특정 작업을 실행할 수 있도록 하는 Hook이다.

💡 useEffect는 component가 mount 되었을 때, unmount 되었을 때, update 되었을 때 특정 작업을 처리할 수 있다.
(useEffect를 통해 기존의 클래스형 컴포넌트에서 사용하던 생명주기(Life cycle) 메소드를 함수형 컴포넌트에서 사용할 수 있게 되었다.)

⚠️하지만 생명주기 메소드와 완전히 같은 개념은 아님

useEffect의 기본 형태

useEffect( function, deps )

function : 실행하고자 하는 작업
deps : 배열 형태, useEffect내부 코드가 실행되게 하는 의존성 배열

  • 의존성 배열 💡 useEffect 내부에서 사용하는 외부 state나 프로퍼티를 의미. 이 배열의 값이 변경될 때만 useEffect가 실행됨.

useEffect의 예시로 사용자의 입력을 받아 state값을 업데이트 하는 경우에 사용자의 입력값이 변경될 때만 API를 호출하고 싶을 때 의존성 배열에 사용자의 입력값을 넣어주면 된다.

useEffect 예시

useEffect(() => {
  const fetchData = async () => {
    const response = await fetch('API_URL');
    const data = await response.json();
    setData(data);
  };
  fetchData();
}, [inputValue]);
  • 이와같이 의존성 배열에 값을 넣어주면 해당 값이 변경될 때만 useEffect를 실행시킬 수 있고, 빈 배열을 넣어둔다면 컴포넌트가 처음으로 마운트 되었을때 한번만 실행시킬 수 있다.

클린업 함수

클린업 함수는 useEffect 훅 안에 정의되는 함수로, side effect를 정리하는 역할을 한다. 이 함수는 useEffect 훅에서 side effect가 설정된 컴포넌트가 unmount 되기 직전에 실행된다.

클린업 함수의 기본 형태

return () => {제거할 로직}

클린업 함수 예시

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

function ExampleComponent() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('컴포넌트가 마운트됨');

    // 이벤트 리스너 추가
    document.addEventListener('mousedown', handleClick);

    // 클린업 함수 반환
    return () => {
      console.log('컴포넌트가 언마운트됨');

      // 이벤트 리스너 제거
      document.removeEventListener('mousedown', handleClick);
    };
  }, []); // 빈 배열을 전달하여 컴포넌트가 처음 마운트될 때만 실행되도록 함

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>버튼을 클릭한 횟수: {count}</p>
    </div>
  );
}

export default ExampleComponent;

이 예시와 같이 컴포넌트가 마운트 될 때마다 이벤트 리스너를 추가하고, 컴포넌트가 언마운트 될 때마다 클린업 함수를 통해 이벤트 리스너를 제거하는 작업을 수행한다.

❓useLayoutEffect란?

useLayoutEffect는 useEffect와 유사한 hook이다.
이를 알아보기 위해선 먼저 브라우저 렌더링 과정을 알아야 한다.

Render : DOM Tree 를 구성하기 위해 각 엘리먼트의 스타일 속성을 계산하는 과정
Paint : 실제 스크린에 Layout을 표시하고 업데이트하는 과정

state의 변화와 같은 이유로 렌더링이 일어날때 먼저 컴포넌트가 렌더 되고, 이후 렌더된 컴포넌트가 화면에 paint된다. useEffect는 이러한 과정 이후에 실행되므로 useEffect 내부에 만약 DOM에 영향을 주는 코드가 있다면 화면의 깜빡임과 함께 사용자가 변화를 알아차리게 된다.

반면 useLayoutEffect는 useEffect와 호출되는 시간이 다르다.

useLayoutEffect는 컴포넌트가 렌더된 이후 컴포넌트가 화면에 paint되기 전에 실행된다.
-> 따라서 DOM에 영향을 주는 코드가 있더라도 화면의 깜빡임이 없다.

사용법은 useEffect와 100%일치하지만 useLayoutEffect는 성능을 저하시킬 가능성이 높기 때문에 사용을 권장하지 않고, 특히 SSR(Server Side Rendering)인 경우에는 useEffect, useLayoutEffect 모두 자바스크립트가 다운로드 되기 전에 실행되지 않는다.


❓useRef란?

useRef는 리액트 훅 중 하나로, DOM 요소에 대한 참조(reference)를 생성하고 관리하는 데 사용된다. useRef를 통해 함수 컴포넌트에서 DOM 요소를 직접 조작하거나 접근할 수 있고 이를 통해 특정 DOM 요소에 직접 접근이 가능하다면, 불필요한 리렌더링을 막을 수 있다.

useRef의 기본 형태

const 변수명 = useRef(초기값)

<input ref= {변수명}/>

useRef 사용 예시

import React, { useRef, useEffect } from 'react';

function ExampleComponent() {
  const inputRef = useRef(null);

  // 컴포넌트가 마운트될 때 input 요소에 포커스 설정
  useEffect(() => {
    inputRef.current.focus();
  }, []);

  const handleInputChange = () => {
    console.log('입력된 값:', inputRef.current.value);
  };

  return (
    <div>
      <input type="text" ref={inputRef} onChange={handleInputChange} />
    </div>
  );
}

export default ExampleComponent;

이 예시와 같이 useRef를 사용하여 input 요소에 대한 참조를 생성하고, 포커스를 설정할 수 있다.

useRef를 사용하는 이유

1. state와 같은 저장공간

useState를 사용해서도 요소에 접근하고, 상태변경을 통해 관리할 수 있지만, useRef를 사용하는 이유는
useState를 사용했을 때 state에 변화가 생기면 렌더링을 하고, 내부 변수들의 값에 변화가 생긴다.
useRef를 사용했을 때는 렌더링이 일어나지 않고, 내부 변수들의 값이 유지된다.

따라서 useRef는 변화를 감지해야 하지만, 그 변화가 렌더링을 일으키진 않아야 할 때 사용한다.

2. DOM요소에 접근

js에서 getElementById, querySelector 와 유사하게 특정 DOM 요소에 직접적으로 접근이 가능하다.

7개의 댓글

comment-user-thumbnail
2024년 4월 16일

useEffect, 클린업 함수, useLayoutEffect, useRef의 각 개념 및 사용 이유, 사용 시 주의사항 등에 대해 자세히 설명되어 잘 이해가 갑니다 😊
좋은 글 감사합니다 !

답글 달기
comment-user-thumbnail
2024년 4월 17일

그동안 useEffect를 대충 알고 쓰고 있었는데 이렇게 정리해서 보니까 확실히 이해가 되고 정리되는 느낌이네요!! useRef에 대해서도 예시와 함께 알기 쉽게 작성해주셔서 이해가 잘 되었어요. 다음에 꼭 써보겠습니다:)

답글 달기
comment-user-thumbnail
2024년 4월 17일

각 내용마다 어떤 역할을 하는지 뿐만 아니라 왜 사용해야 하는지도 적어 주셔서 이해하는데 많은 도움이 되었습니다!! 특히 예제를 간단한 사용 방법이 아니라 실제로 사용될만한 예제를 설명해 주셔서 어떨 때 사용해야 하는지 더 와닿았던 것 같네요!! 감사합니다 🔥

답글 달기
comment-user-thumbnail
2024년 4월 17일

아티클 흐름이 넘 매끄러워서 쇽샥 다 읽어버리게 되네요!
각 함수에 대해 기본 형태와 왜 사용하는지, 어떻게 사용하는지를 읽기 쉽게 정리해주신 것 같아서 이해에 많은 도움이 됐습니다. 코드 중간중간 주석을 달아주셔서 해당 코드를 이해하는게 더 수월하게 느껴졌던 것 같습니다! 그리고 중간중간 단어들의 의미도 짚어주신 것도 너무 좋았어요. 유용한 아티클 감사해요~

답글 달기
comment-user-thumbnail
2024년 4월 17일

Hook의 이론적인 설명뿐만 아니라 실제 코드에서의 예시도 들어주셔서 이해하기 더욱 쉬웠습니다! useEffect와 useRef의 사용 예시와 사용 이유도 적어주셔서 해당 Hook 을 왜 써야하고 어떻게 써야하는지 알 수 있었습니다! 좋은 아티클 감사합니다!!

답글 달기
comment-user-thumbnail
2024년 4월 17일

useEffect, useLayoutEffect, useRef 에 대해서 자세히 알 수 있던 시간이었습니다!
특히, 정말 필요한 내용만 잘 정리해두신 것 같아서 읽기 좋았어요! ㅎㅎ
핵심 내용들을 잘 정리해주셔서 잘 읽고 갑니다 👍

답글 달기
comment-user-thumbnail
2024년 4월 17일

아티클을 읽고 나니, React의 훅을 이용한 다양한 기능 구현에 대해 좀 더 깊게 이해할 수 있었습니다. 특히, useEffect에 대한 설명이 인상 깊었습니다! 이 훅이 어떻게 작동하고 컴포넌트의 생명주기에 어떻게 영향을 미치는지에 대한 설명이 깔끔하네요! 좋은 아티클 감사합니다 수고하셨습니다 :)

답글 달기