useEffect()

현채은·2024년 4월 24일
0
post-thumbnail

useEffect()

useEffect()는 React에서 부수 효과(side effects)를 다루기 위해 사용되는 Hook입니다. 컴포넌트가 렌더링될 때마다 특정작업을 수행할 수 있도록 설정해줍니다. useEffect 는 React 컴포넌트가 화면에 나타난 후 이제 무엇을 할까?라고 컴포넌트에게 물어보는 것과 같습니다.

부수효과(side effects)

부수 효과란, 컴포넌트의 렌더링 결과에 영향을 주지 않으면서 컴포넌트의 생명주기에 따라 수행해야 하는 작업들을 말합니다. 예를 들어, 데이터 가져오기, 구독 설정, 수동으로 DOM을 조작하는 것 등이 있습니다. useEffect는 함수 컴포넌트에서 이러한 부수 효과를 수행할 수 있게 해줍니다.

생명주기(Life Cycle)

React 컴포넌트는 생명주기를 가집니다. 생명주기란, 컴포넌트가 생성되고, 렌더링된 후 소멸될 때 까지 일련의 과정을 말합니다. Mounting, Updating, Unmountiong 총 3가지의 단계로 이루어집니다.

생명주기(Life Cycle)

  1. Mounting : 컴포넌트가 처음 화면에 렌더링되는 순간입니다.
    • 이때 컴포넌트는 필요한 설정을 하고, 데이터를 불러오는 등 초기작업을 수행합니다.
  2. Updating : 컴포넌트가 화면에 렌더링된 후 데이터가 변경되거나, 사용자와의 상호작용이 발생할 때 마다 컴포넌트가 업데이트되는 과정입니다.
    • 사용자가 버튼을 클릭하거나. 새로운 데이터가 들어오면 컴포넌트는 발생한 이벤트에 따라 컴포넌트를 업데이트합니다.
  3. Unmountiong : 컴포넌트가 화면에서 사라지는 순간입니다.
    • 컴포넌트가 사라지기 전 필요한 정리작업을 수행할 수 있습니다.

클래스 컴포넌트에서는 componentDidMount, componentDidUpdate, componentWillUnmount 같은 생명주기 메서드를 사용할 수 있고, 함수 컴포넌트에서는 useEffect Hook을 사용하여 비슷한 작업을 수행할 수 있습니다.
추가적으로 더 학습하고 싶은 분들은 해당 사이트를 참고해 주세요.
State and Lifecycle – React

사용 방법

import { useEffect } from 'react';  

useEffect(() => {
  // 부수 효과를 수행하는 코드
}, [의존성 배열]);
  • 첫 번째 인자는 부수 효과를 수행하는 함수입니다. 이 함수 내에서 데이터를 가져오는 로직, 이벤트 리스너를 등록하는 로직 등을 실행할 수 있습니다.
  • 두 번째 인자는 의존성 배열(dependency array)입니다. 이 배열에 명시된 값들이 변경될 때만 함수가 실행됩니다.
    • 의존성 배열을 생략하는 경우
      useEffect(() => {
      	// 렌더링될 때마다 실행됩니다.
      });1
    • 의존성 배열이 빈 배열인 경우
      useEffect(() => {
      	// 컴포넌트가 마운트될 때(처음 화면에 나타날 때) 한 번만 함수가 실행됩니다. 
      },[]);
    • 의존성 배열에 값을 넣는 경우
      useEffect(() => {
      	// name 값이 변경될 때마다 실행됩니다.
      },[name]);

데이터 fetching 예시

useEffect는 실제로 프로젝트를 진행하면서, 자주 사용되는 Hook입니다.

예를 들어, 처음 페이지가 렌더링 될 때 서버에서 데이터를 받아와야 하는 상황에서 fetch 메소드를 사용하는 경우를 생각해 봅시다.

만약 useEffect를 사용하지 않고 데이터를 받아온다면 어떤 일이 발생할까요?

  • useEffect를 사용하지 않고 데이터를 받아오는 경우
const [list, setList] = useState([]);

	fetch('data/list.json')
		.then((res) => res.json())
		.then((data) => {
			console.log('리스트 받아옴');
			setList(data);
		});

잠깐의 순간이지만, 렌더링이 3000번 이상 발생하고 있습니다. 왜 이러한 결과가 나오는 것일까요 ?

결과의 원인은 데이터를 파일에서 받아온 후, setList 메소드로 상태를 업데이트하면, 컴포넌트는 useStatestate가 변화하면서 렌더링이 발생합니다. 그럼 자동으로 다시 fetch 함수가 재실행되면서 데이터를 받아오게 되고, 이러한 과정이 무한히 반복되면서 위와 같은 결과가 발생하게 됩니다.

결과의 원인은 데이터를 파일에서 받아온 후, setList 메소드로 상태를 업데이트하면, 컴포넌트는 useStatestate가 변화하면서 렌더링이 발생합니다. 그럼 자동으로 다시 fetch 함수가 재실행되면서 데이터를 받아오게 되고, 이러한 과정이 무한히 반복되면서 위와 같은 결과가 발생하게 됩니다.

  • useEffect를 사용하는 경우
const [list, setList] = useState([]);

useEffect(() => {
	fetch('data/list.json')
		.then((res) => res.json())
		.then((data) => {
			console.log('리스트 받아옴');
			setList(data);
		});
	},[]); // 의존성 배열 : 빈배열 (컴포넌트가 처음 마운트 될 때에만 콜백함수가 실행됨)


useEffect를 사용하는 경우, 처음 마운트 될 때에만 데이터를 호출하는 것을 확인할 수 있습니다.

데이터를 두 번 받아온 것 아닌가요 ?

이 예제에서 데이터가 두 번 로드되는 것을 보셨을 겁니다. 이는 React의 StrictMode기능 때문입니다.

StrictMode는 개발 모드에서 컴포넌트의 렌더링을 두 번 실행하여, 부주의한 사이드 이펙트를 포착하고 앱의 견고성을 높이기 위한 도구입니다. 이러한 이중 렌더링은 오직 개발 환경에서만 발생하며, 프로덕션 빌드에서는 발생하지 않습니다. 따라서 실제 사용자 환경에서는 성능에 영향을 주지 않습니다.

StrictMode를 사용하는 주된 이유는 다음과 같습니다

  • 부적절한 사이드 이펙트를 미리 감지하고 수정할 수 있도록 돕습니다.
  • 레거시 코드의 문제를 식별하고, 미래에 React 업데이트에 더 잘 적응할 수 있도록 준비합니다.
  • 개발 과정에서의 실수를 최소화하고, 코드 품질을 개선합니다.

이 기능은 태그를 사용하여 적용할 수 있으며, 개발 중 버그와 문제를 식별하는 데 매우 유용합니다. 만약 이중 렌더링으로 인해 혼란을 겪고 있다면, 프로덕션 환경에서는 이 기능이 비활성화됨을 기억하시기 바랍니다.

주의 사항

  1. 컴포넌트 최상위에서 useEffect를 호출하여 Effect를 선언할 수 있습니다.

    useState 와 마찬가지로 반복문이나 조건문에서는 사용할 수 없습니다.

    • 조건문 내에서 사용하는 경우
    function App() {
    	if(num === 1) {
    		useEffect(() => {
    			// 수행하고자 하는 함수
    		},[]);
    	}
    }
    • 반복문 내에서 사용하는 경우
    function App() {
      while (num < 9) {
       useEffect(() => {
    			// 수행하고자 하는 함수
    		},[]);
      }
    }
  1. useEffect를 사용하는 경우 import문을 사용하여 호출되어야 합니다.

    import { useEffect } from 'react'; // 중괄호로 감싸 호출해야합니다.
profile
개발 기록 공간

0개의 댓글