React - 4. sideEffect와 useEffect

AM_I_TRASH·2022년 7월 31일

React

목록 보기
4/5

What

side effect가 뭘까? 다들 잘 알듯이, 부작용이라는 뜻이다.

현실에서와 프로그래밍에서의 부작용의 뜻이 약간 다른데, 프로그래밍에선 말 그대로 내가 의도치 않은 부수적인 작용이 일어나는 것을 말한다.

예를 들자면,

let count = 0

function greetWithSideEffect(name) { // Input
  count = count + 1 // Side Effect!

  return `${name}님 안녕하세요!` // Output
}

greetWithSideEffect() 라는 함수는 이름을 받아 인삿말을 리턴하는 함수이다.

하지만 이 함수는 단순히 input과 output만 존재하는 함수가 아니다. 실행하는 중간에 함수 스코프 외부에 있는 count 변수의 값을 변경하는 프로세스가 섞여있다. 이는 함수의 결과값 이외의 다른 상태를 변경시키는 행위에 해당하므로 Side Effect 가 있다고 할 수 있는 것이다.

이러한 예시 말고도, 우리에게 아주 친숙한 예로 console.log 등이 있다!
console.log 함수를 사용하면 값을 계산해서 리턴하는 게 아니라 콘솔 창에 문자열을 출력하게 되는데, 이 자체가 외부 상태를 변경해서 문자열을 출력하는 것이다.

이렇게 함수 내부에서 함수 외부에 있는 값 또는 상태를 변경하는 행위를 'side effect'라고 한다.

Why

하지만 이 side effect가 단어 뜻 그대로 나쁘기만한 순수 쓰레기같은 친구인가 하면~~~
그건 또 아니다.

useEffect 는 리액트 컴포넌트 함수 안에서 이 side effect를 실행하고 싶을 때 사용하는 함수이기 때문이다.

DOM 노드를 직접 변경하기도 하며,
브라우저에 데이터를 저장할 수도 있고,
네트워크 통신 요청를 보내는 것처럼 말이다.

상기하였듯, 주로 리액트 외부에 있는 데이터나 상태를 변경할 때 사용하는데,
간단한 예시를 보면 이해에 좀 더 좋을 것 같다.

페이지 내 데이터 변경
useEffect(() => {
  document.title = title;
}, [title]);


네트워크 요청
useEffect(() => {
  fetch('https://alpha.bravo/delta')
    .then((res) => res.json())
    .then((result) => setData(result));
}, [])


데이터 저장
useEffect(() => {
  localStorage.setItem('Echo', Echo);
}, [Echo]);


타이머
useEffect(() => {
  const tikTok = setInterval(() => {
    setSecond((prevSec) => prevSec + 1);
  }, 1000);
  
  return () => {
    clearInterval(tikTok);
  }
}, []);

How

useEffect는 보통 '동기화'에 쓰면 유용한 경우가 많다. 여기서 동기화란, 컴포넌트 내부의 데이터와 그 외부에 있는 데이터를 일치시키는 것을 의미한다.

이게 뭔 개소리요 싶으실텐데, 어떤 의미인지 이번에도 간단한 예시를 가져왔다.

import { useEffect, useState } from 'react';

const TITLE = 'Untitled';

export default function ChangeTitle() {
  const [title, setTitle] = useState(Title);

  const titleChangeHandler = (e) => {
    const inputText = e.target.value;
    setTitle(inputText);
  };

  const titleClearHandler = () => {
    setTitle(TITLE);
  };

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

  return (
    <div>
      <input value={title} onChange={titleChangeHandler} />
      <button onClick={titleClearHandler}>RESET</button>
    </div>
  );
}

상단의 ChangeTitle컴포넌트는 입력 값에 따라 페이지 타이틀을 바꾸는 컴포넌트이다.

만약 이 코드를 핸들러 함수만 사용해서 처리를 하려 했다면, 핸들러마다

document.title = inputText or TITLE;

을 포함하는 코드가 있었어야 할 것이다.

하지만 우리는 useEffect를 사용함으로써 document.title이라는 side effect를 다루는 부분만 따로 처리할 수 있었고,
document.title 을 변경하는 코드를 신경 쓰지 않고 사용할 수 있어 편리해 질 수 있겠다!

즉, useEffect 를 사용했을 때 반복되는 코드를 줄이고, 동작을 쉽게 예측할 수 있는 코드를 작성할 수 있게 되는 것이다.

profile
짝퉁 프로그래머

0개의 댓글