프로그래밍/React

[React] Side effect(사이드 이펙트)란? | 부수 효과, useEffect

choar 2022. 6. 3. 17:14
반응형

[React] Side effect(사이드 이펙트)란? | useEffect

 

React 공식 문서를 읽다가 사이드 이펙트(side effect)라는 표현을 처음 봐서 무엇인지 찾아보았다.

찾아보다 좋은 영어 글을 발견해서 번역하며 공부해보았다.

영어 원문을 읽고 싶으신 분은 맨 밑 reference에 있는 주소를 참고하시면 된다.

 

1. 왜 "useEffect"인가?

2018년에 코어 React hooks가 추가되었을 때, 많은 개발자들이 "useEffect"라는 이름에 혼란스러워했다.

 

useEffect에서 "effect"가 의미하는 바는 무엇일까?

effect는 "side effect"라는 함수형 프로그래밍 용어를 나타낸다.

 

side effect가 무엇인지 이해하려면 먼저 순수 함수의 개념을 이해해야 한다.

대부분의 React 컴포넌트는 순수 함수로 만들어졌다.

function MyReactComponent() {}
순수 함수(pure function)
1. 함수의 리턴 값이 동일한 인수(argument)에 대해 동일하다.
2. side effect가 없다. (외부의 상태를 변경하지 않는다.)

 

대부분의 React 컴포넌트는 순수 함수이다. 즉, input을 받아 예측 가능한 JSX 리턴 값을 만들어낸다.

자바스크립트 함수에 대한 input은 인수(argument)이다. 그러나 React 컴포넌트에 대한 입력은 Props이다.

export default function App() {
  return <User name="John Doe" />   
}
  
function User(props) {
  return <h1>{props.name}</h1>; // John Doe
}

위의 React 컴포넌트는 순수 함수이다. 왜냐하면 같은 input이 주어진다면 항상 같은 output을 리턴할 것이기 때문이다.

props로 name="Jone Doe"를 전달하면 output은 항상 Jone Doe가 된다.

 

순수 함수는 예측 가능하고, 신뢰할 수 있고, 테스트하기 쉽다.

반대로 함수 내의 구현 내용이 함수 외부에 영향을 끼치는 경우, 해당 함수는 side effect가 있다고 얘기한다. 여기서 side effect를 일으키는 함수를 예를 들어보면, Math.random() 처럼 값이 랜덤으로 바뀌는 등 함수의 입력이 아닌 다른 값이 함수의 결과에 영향을 미치는 경우에 side effect를 일으킨다고 볼 수 있다. 반면, side effect를 일으키지 않는 순수 함수의 경우엔 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수이다.

 

2. React에서 side effect란 무엇인가?

side effect는 "외부 세계"와 함께 수행되기 때문에 예측할 수 없다.

무언가를 하기 위해 React 컴포넌트 외부에 도달해야 하는 경우 side effect를 수행한다.

그러나 side effect를 수행한 결과는 예측할 수 없다.

예를 들어 서버에 데이터를 요청한 경우, 요청이 실패하면 데이터가 아닌 500 상태 코드를 받을 수 있다.

아주 단순한 애플리케이션을 제외한 사실상 모든 애플리케이션은 어떤 방식으로든 side effect에 의존한다고 한다.

 

일반적인 side effect로는 다음과 같은 것들이 있다.

  • 백엔드 서버에 API로 데이터 요청하기
  • 브라우저 API와 상호 작용 (document, window 직접 사용하기)
  • setTimeout, setInterval 등 예측할 수 없는 타이밍 함수 사용

useEffect는 React 컴포넌트에서 이러한 side effect들을 처리하는 방법을 제공하기 위해 존재한다.

예를 들어, 브라우저 탭의 title 메타 태그를 변경하려는 경우 다음과 같이 컴포넌트 내에서 직접 변경할 수도 있지만, 이렇게 해서는 안된다.

function User({ name }) {
  document.title = name; 
  // This is a side effect. Don't do this in the component body!
    
  return <h1>{name}</h1>;   
}

컴포넌트 안에서 직접 side effect를 수행하는 경우 컴포넌트의 렌더링에 방해가 된다.

side effect는 렌더링 과정과 분리되어야 한다. side effect를 수행해야 하는 경우, 컴포넌트의 렌더링이 끝난 후에 수행되어야 한다.

바로 이 기능을 useEffect가 제공한다.

요컨대, useEffect는 우리가 외부 세계와 상호 작용하면서 해당 컴포넌트의 렌더링이나 성능에는 영향을 미치지 않도록 만들어주는 도구이다.

 

3. useEffect를 어떻게 사용하는가?

useEffect의 기본 문법은 다음과 같다.

// 1. import useEffect
import { useEffect } from 'react';

function MyComponent() {
  // 2. call it above the returned JSX  
  // 3. pass two arguments to it: a function and an array
  useEffect(() => {}, []);
  
  // return ...
}

컴포넌트 내에서 side effect를 수행하는 올바른 방법은 다음과 같다.

  1. useEffect를 import 한다.
  2. 컴포넌트의 return문보다 위에서 useEffect를 사용한다.
  3. useEffect에 두 개의 인수를 전달한다. (1-함수, 2-배열)
import { useEffect } from 'react';

function User({ name }) {
  useEffect(() => {
    document.title = name;
  }, [name]);
    
  return <h1>{name}</h1>;   
}

useEffect의 첫 번째 인수로 전달한 함수는 콜백 함수이다. 이 함수는 컴포넌트가 렌더링 된 이후에 호출된다.

이 함수에서 side effect를 하나에서 여러 개까지 수행할 수 있다.

 

두 번째 인수는 종속성 배열(dependency array)이다. 이 배열은 side effect가 의존하는 모든 값을 포함해야 한다.

위의 예에서는 외부 범위의 값인 name을 기반으로 제목을 변경하고 있으므로, name을 종속성 배열에 포함해야 한다.

이 배열이 하는 일은 렌더링과 렌더링 사이에 값(이 경우 name)이 변경되었는지 확인하는 것이다. 값이 변경되었다면 side effect 함수를 다시 실행할 것이다.

 

 

🌟 내용에 오류가 있다면 댓글 달아주시면 감사하겠습니다.

🌟 원문의 내용이 길어 포스팅을 나누었습니다. useEffect를 사용하며 발생하는 무한루프 해결법, cleanup function 등에 관한 내용은 다음 포스팅에 업로드하였습니다. side effect를 제대로 수행하기 위해 알아야 하는 내용이므로 꼭 확인하시기 바랍니다.

 

[React] useEffect 무한 루프 해결하기, cleanup function

[React] useEffect 무한 루프 해결하기, cleanup function 며칠 전, React에서 side effect가 무엇인지 찾아보다 좋은 글을 발견해 번역해서 포스팅하였다. 전체를 번역해 올리려다 내용이 생각보다 길어 두 개

choar816.tistory.com


References

https://www.freecodecamp.org/news/react-useeffect-absolute-beginners/

https://en.wikipedia.org/wiki/Pure_function

https://velog.io/@ichbinmin2/FE-InterviewReact1.-React-%EA%B8%B0%EC%B4%88

반응형