[React]useEffect

sujin·2022년 9월 13일
0

React

목록 보기
8/16
post-thumbnail

이번엔 useEffect에 대해서 알아보쟈
useEffect는 리액트 hook중 하나로 변화된 상태 값을 랜던링 후 실행되는 함수라고 할 수 있다. useEffect가 정확히 무엇이고 언제 어떻게 쓰이는지에 대해서 알아보려면 먼저 sideEffect라는 개념에 대한 이해가 필요하다!

sideEffect

sideEffect 는 부작용 즉, 부수효과라는 뜻으로 주요한 효과에 따라서 발생하는 부수적인 효과라는 의미이다. 예를 들어 감기약을 먹으면 감기에 낫을 수 있지만 졸음이 오는 효과가 발생한다. 이처럼 어떠한 효과에 따라서 오는 부수적인 효과를 부수효과라고 칭하는 것이다.

💡코드에서의 부수효과란?

  • 코드가 의도한 주된 효과 외에 추가적으로 발생하는 효과이다.
  • 주로 함수에서 사용되는 용어이다.
  • 함수의 주된 효과는 input을 받아서 output을 산출하는 것이다.
  • 따라서, 함수의 sideEffect는 input을 받아서 output을 산출하는 것 이외의 모든 행위를 뜻한다.
// 순수 함수
const sum = (x) => {
  return x + 1;
};

위와 같이 input을 받아서 output을 내는 행위 외의 다른 행위를 하지 않는 함수가 sideEffect가 없는 함수 이며, 이를 순수 함수 라고 칭한다.


// 1.외부의 상태를 읽어오기
const num = 1;

const sum = (x) => {
  return x + num;
};

// 2.외부의 상태를 변경시키기
let num;

const sum = (x) => {
  num = x + 1;
};

// 3.DOM에 접근하여 상태 변경시키기
const printNum = (x) => {
  console.log(x);
};

const changeTitle = (newTitle) => {
  const title = document.getElementById('title');

  title.innerText = newTitle;
};

위와 같은 경우 함수에서 함수 외부의 값을 읽어오거나 외부의 값을 변경하는 행위를 할 경우는 모두 프로그래밍에서 sideEffect가 발생했다고 할 수 있다.

💡console.log만 출력하는 함수의 경우도 sideEffect인가?

  • 콘솔 패널에 문자를 출력하는 행위 또한 함수 외부에 존재하는 DOM의 상태를 변경시키는 것임으로 sideEffect가 있는 함수라고 할 수 있다.

💡 그렇다면, sideEffect를 기피해야하는 걸까?

  • 함수의 동작 결과를 예측하기 쉽지 않기 때문에 기피해야하지만, 프로그램이 어떤 값도 외부로 출력하지 않는다면 그 프로그램은 의미가 없다.
  • 또한, 데이터를 저장하고 값을 읽어오는 행위는 프로그래밍에서 필수 불가결한 요소이다.
  • 따라서, 개발자들은 sideEffect를 최소화 하면서 프로그램을 설계하되 필요한 상황에서 통제 가능하게 만들어 유지보수에 악영향을 주지 않도록 해야한다.

React에서의 sideEffect

리액트의 함수 컴포넌트의 본질은 stateprops를 통해 JSX를 만들어 내는 것이라고 할 수 있다. 따라서 리액트에서의 sideEffectstateporps를 통해서 JSX를 만들어 내는 외의 모든 행위를 뜻하며, 종류는 다음과 같다.

1. Data Fetching

  • 프론트엔드가 백엔드 API를 통해서 필요한 데이터를 가져오는 행위를 말한다.

2. DOM 접근 및 조작

  • 리액트는 dom의 조작을 리액트에서 처리해주기 떄문에 개발자는 ui와 핵심 로직에만 신경쓰는 선언적인 개발이 가능하다.
  • 따라서, dom에 직접 접근할 일이 많지 않고 권장되지 않는다.
  • 하지만 특정 상황에서 직접 dom을 조작해야하는 일이 발생할 수 있기 때문에 이는 곧 외부의 값(dom)을 읽어오고 변경하는 것이기에 sideEffect인 것이다.

3. 구독(Subscribe)

  • 프로그래밍에서 구독이란 어떤 것을 계속해서 관찰하다가 변화가 발생하면 특정 액션을 취하는 것
  • 개발에서 구독을 활요하는 가장 보편적인 예시는 “시간을 구독하는 것”
    • 특정 시간이 지났을 때 액션을 취하거나, 특정한 시간 주기마다 액션을 취하는 등의 행위를 시간을 구독함으로서 구현할 수 있다. ex) setTimeout setInterval
  • 구독은 외부의 값의 변화를 계속해서 관찰하고 동작하는 것이기 때문에 sideEffect라고 할 수 있다.

useEffect

리액트에서의 sideEffect의 올바른 발생 시점

  • 함수의 return문 위에서 바로 하고 싶은 동작을 실행시키거나
  • 함수 컴포넌트의 본문에서 바로 sideEffect를 발생 시키는 것이다.

하지만 이때 문제점이 발생하게 되는데

  • sideEffect가 랜더링을 blocking한다.
    • 리턴문 위에 sideEffect가 있다면 함수 컴포넌트가 JSX를 리턴하기 전까지 브라우저 상에 UI가 렌더링이 되지 않게된다.
  • 매 랜더링마다 sideEffect가 수행된다.
    • dataFetching 등 특정한 상황에서만 필요한 sideEffect가 매 랜더링마다(사소한 ui변화, 좋아요 버튼 클릭 등) 무조건 발생하게 된다.

따라서, 이러한 문제점을 해결하기 위해 등장한 것이 useEffect hook인 것이다.

  • 변화된 상태 값 랜더링 후 실행되는 함수
  • import { useEffect } from "react";
  • useEffet( 함수 )
    • 첫번째 매개변수로 함수가 들어간다.
    • 함수 호출 타이밍은 랜더링 결과가 dom에 반영된 직후이다.
  • useEffect( 함수, [값] )
    • 두번째 매개변수는 배열이 들어가며, 의존성 배열 이라고 부른다.
    • 의존성 배열 은 불필요한 함수의 호출을 막으며, 의존성 배열의 값이 변경되는 경우에만 함수가 실행되도록 한다.
    • [] 빈배열 입력시, 랜더링 직후 한번만 실행한다는 의미이다.

// 예시1

import { useEffect, useState } from "react";

const Count = () => {
  const [count, setCount ] = useState(0);
  
  function clickAction(){
    setCount(count + 1);
  }
  
  useEffect(() => {
    console.log('count change!');
  }) 

  return(
    <button onClick = {clickAction}>{count}</button>
  )
}
export default Count
  • 버튼을 누를때마다 count가 올라가고 console창에 count change! 가 찍히게 된다.

// 예시2

import { useEffect, useState } from "react";

const Count = () => {
  const [count, setCount ] = useState(0);
  const [day, setDay] = useState([]);
  
  function clickAction(){
    setCount(count + 1);
  }
  
  function addAction(){
    setDay([
      ...day,
      {
        id: Math.random(),
        day: 'DAY'
      }
    ])
  }
  
  useEffect(() => {
    console.log('count change!');
  }, [count]) 

  return(
    <button onClick = {clickAction}>{count}</button>
    <button onClick = {addAction}>ADD DAY</button>
  )
}
export default Count
  • ADD DAY 버튼을 클릭할때 마다 DAY버튼이 생성된다.
  • 의존성 배열에 [count]를 지정해줬기 때문에 count가 변경되는 함수 clickAction 실행될 때에만 useEffect함수가 실행된다.

마무리✨

아직 잘 sideEffect라는 개념이 잘 와닿지는 않지만 나중에 fetch라는 함수와 함께 백엔드 통신할때 사용된다고 하니 개념을 잘 익혀뒀다가 써먹어야 겠다...!!!

profile
개발댕발

0개의 댓글