[ReactJS] Side Effect와 useEffect

2023. 1. 24. 15:34·◼ FrontEnd/ReactJS
반응형

Side Effect란?

  • Side Effect란 부작용이다.
  • 부작용 === 부수효과
    • 부수효과 : 주요한 효과에 따라서 발생하는 부수적인 효과
  • 부작용이란 용어 자체는 부정적인 의미를 내포하지 않는다. 단지 부수적으로 발생하는 효과를 의미하는 단어이다.

 

프로그래밍에서 Side Effect (부작용) 란?

  • 코드가 의도한 주된 효과 외에 추가적으로 발생하는 부수 효과
  • 특히 프로그램을 구성하는 가장 작은 단위인 함수에서 자주 사용되는 용어
    • 함수의 본질적인 역할 (주된 효과)
      • Input을 받아서 Output을 산출하는 것
      • Input => Output
    • 함수의 부작용 (Side Effect)
      • Input을 받아서 Output을 산출하는 것 외의 모든 행위
        • 함수에서 함수 외부의 값을 읽어오는 행위
        • 함수에서 함수 외부의 값을 변경하는 행위

 

Side Effect가 있는 함수

const sun = (x) => {
  return x + 1;
};
  • x를 입력받아서 x+1을 출력하는 함수
  • Input을 받아서 Output을 내는 행위 외에 다른 행위를 하지 않으므로, 위 함수는 Side Effect가 없는 순수함수이다.
    • 순수 함수 : Side Effect가 없는 함수

 

const num = 1;

const sum = (x) => {
  num = x + 1;
  return num;
};
  • 위 예시처럼 함수가 함수 내부의 값이 아닌 외부의 값을 읽어오거나 변경할 때 Side Effect가 있다고 표현할 수 있다.

 

const printNum = (x) => {
  console.log(x);
};
const changeTitle = (newTitle) => {
  const title = document.getElementById("title");

  title.innerText = newTitle;
};
  • 외부의 값 !== 외부의 변수
  • 콘솔 패널에 문자를 출력하는 행위, DOM을 조작하는 행위 또한 함수 외부에 존재하는 DOM, 콘솔 상태를 변경시키는 것이다.
  • 따라서 위 두 함수는 모두 Side Effect가 있는 함수이다.



Side Effect는 기피해야 하는 대상일까?

  • 프로그래밍에서 Side Effect는 기피해야 하는 대상이다. 그 이유는..
    • Side Effect가 있는 함수는 동작 결과를 예측하기 어렵게 만든다.
    • 이는 곧 프로그래밍이 어떻게 동작할 지 예측하기 힘들게 만들어 유지 보수의 어려움도 야기한다.
  • 하지만 프로그래밍에서 외부의 값을 읽어오거나 변경하는 행위를 완전히 무시할 순 없다. 오히려 프로그래밍에 반드시 있어야 하는 동작이다.
  • 따라서 개발자들은 Side Effect를 최소화하면서 프로그램을 설계하되, Side Effect를 적재적소에 사용하고 통제할 수 있도록 하여, 관리 시 예측 가능하고 유지 보수하기 쉬운 프로그램을 만들어야 한다.

 


React에서의 Side Effect

함수 컴포넌트의 Input과 Output

  • React에서 렌더링이란 state, props를 기반으로 UI를 그려내는 행위이다.
  • React에서는 함수 컴포넌트를 통해 만든 컴포넌트를 조합하여 UI를 만들어낸다.
  • 즉 React의 함수 컴포넌트는 state, props를 통해서 JSX를 만들어 내는 것이 본질적인 역할이다.
    • Input : state, props
    • Output : JSX
    • (state, props) => JSX

 

함수 컴포넌트의 Side Effect

  • React에서 함수 컴포넌트의 Side Effect는 함수 컴포넌트의 본질적인 역할 외 모든 행위를 의미한다.
    • Data Fetching
    • DOM 접근 및 조작
    • 구독 (Subscribe)

 

Data Fetching

  • 프론트엔드가 백엔드 API를 통해 필요한 데이터를 받아오는 행위로, 프론트와 백의 역할이 분리된 현대 개발에서 필수적인 행위이다.
  • 하지만, 이 역시 외부에서 데이터를 가져오는 것이므로 Side Effect이다.

 

DOM 접근 및 조작

  • 프론트엔드에서 웹 개발 시 DOM에 접근 및 조작하는 행위는 필수적이다.
  • 그러나 React의 선언적인 개발 방식(DOM 조작을 직접 React에서 처리함)으로 인해, 이제 개발자가 직접 DOM에 접근할 일은 많지 않고 권장되지도 않는다.
  • 하자만 특정 상황에서 직접 DOM(외부의 값)을 읽고 변경하는 일은 여전히 존재한다.

 

구독 (Subscribe)

  • 프로그래밍에서 구독이란 어떤 것을 계속 관찰하다가 변화가 생길 시 특정한 액션을 취하는 것이다.
  • 개발에서 구독을 활용하는 보편적 예시는 "시간을 구독하는 것"이다.
  • 시간은 계속해서 변하기에, 특정 시간이 지났을 때 액션을 취하거나(setTimeout 매서드), 특정 시간 주기마다 액션을 취하는(setInterval 매서드) 등의 행위는 시간을 구독함으로서 구현할 수 있다.
  • 이 또한 외부의 값의 변화를 계속해서 관찰하고 거기에 맞춰 동작을 하는 것이기에 Side Effect이다.



React에서 Side Effect의 올바른 발생 시점

  • 아래 코드처럼 함수 컴포넌트 본문에서 바로 Side Effect를 발생시킬 때의 문제점
    1. Side Effect가 렌더링을 Blocking 한다.
    2. 매 렌더링마다 Side Effect가 수행된다.
const App = () => {
  const doSideEffect = () => {
    // do some side effect
  };

  doSideEffect();

  return <h1>Hello World</h1>;
};

 

  • React에서 Side Effect를 발생시키기 위한 조건
    1. 렌더링을 Blocking 하지 않기 위해서 렌더링이 모두 완료된 후에 Side Effect가 실행될 수 있어야 한다.
    2. 매 렌더링마다 Side Effect가 실행되는 것이 아니라 필요할 때만 Side Effect가 조건부로 실행되도록 해주어야 한다.
  • React엔 위 두 조건을 모두 만족시켜주면서 편하게 Side Effect를 발생시켜주는 hook이 존재한다.
  • => useEffect

 


useEffect

  • useEffect는 React에서 Side Effect를 편리하고 안전하게 발생시킬 수 있도록 도와주는 Hook이다.
  • useEffect는 함수이고, 매개변수로 콜백 함수를 가진다. 이 콜백 함수에서 특정한 Side Effect를 수행시킬 수 있다.
  • useEffect(콜백 함수);
  • 하나의 useEffect엔 하나의 Side Effect만을 담는 것이 좋다. (관리 용이, 가독성 ↑)

 

useEffect는 (Side Effect를 발생시키는) 콜백 함수를 랜더링 이후 실행시킨다.

import { useEffect } from "react";

const App = () => {
  console.log("Side Effect 실행");
  useEffect(() => {
    // do some side effect
    console.log("Side Effect with useEffect");
  });

  console.log("render");
  return <h1>Hello World</h1>;
};

export default App;
Side Effect 실행
render
Side Effect with useEffect
  • 코드의 실행결과를 확인하니, 랜더링이 모두 끝난 이후 콜백 함수가 실행되었다.
  • 이를 통해 React에서 Side Effect를 발생시키기 위한 첫 번째 조건인 '렌더링이 모두 완료된 후에 Side Effect가 실행될 수 있어야 한다'는 것이 useEffect를 통해 만족될 수 있음을 알 수 있다.

 

useEffect는 (Side Effect를 발생시키는) 콜백 함수를 조건부로 실행시킨다.

  • 또한, useEffect의 콜백 함수는 기본적으로 최초의 랜더링 과정에서만 한 번 실행되고 그 뒤로는 다시 실행되지 않는다.
  • 만일 콜백 함수를 특정 조건에서 실행할 수 있도록 하려면, useEffect의 두 번째 인자에 들어가는 의존성 배열을 활용하면 된다.
useEffect(콜백 함수, 의존성 배열);

 

  • useEffect의 동작 방식
    • 첫 번째 렌더링 이후에는 무조건 useEffect에 전달된 콜백 함수를 호출하고, 다음 렌더링부터는 아래의 조건에 따라 동작한다.
      1. 의존성 배열이 전달되지 않았다면 매 렌더링마다 콜백 함수를 호출한다.
      2. 의존성 배열이 전달되었다면 의존성 배열의 값을 검사한다.
      • a. 의존성 배열에 있는 값 중 하나라도 이전 렌더링과 비교했을 때 달라졌다면 콜백 함수를 호출한다.
      • b. 의존성 배열에 있는 값이 이전 렌더링과 비교했을 때 모두 동일하다면 콜백 함수를 호출하지 않는다.

 

  • 이를 통해 React에서 Side Effect를 발생시키기 위한 두 번째 조건인 '필요할 때만 Side Effect가 조건부로 실행되도록 해주어야 한다'는 것이 useEffect를 통해 만족될 수 있음을 알 수 있다.

 


Clean Up Effect

  • 컴포넌트가 삭제(언마운트)될 때 특정 작업을 수행할 수 있도록 한 장치이다.
  • Side Effect가 불필요하게 계속 남아있으면 프로그램이 비효울적으로 동작하거나 의도에 벗어나게 동작할 수 있다.
  • 따라서 이러한 Side Effect는 반드시 Clean Up을 해주어야 한다.
function Hello() {
  function byFn() {
    console.log("byebye");
  }

  function hiFn() {
    console.log("hello");
    return byFn;
  }

  useEffect(hiFn, []);

  return <h1>Hello</h1>;
}
const Hello = () => {
  useEffect(() => {
    console.log("hello");
    return () => console.log("byebye");
  }, []);

  return <h1>Hello</h1>;
};
  • 만일 Hello 컴포넌트가 사라지면, useEffect 콜백 함수 hiFn의 반환 함수인 byFn이 실행된다.

 

  • useEffect에서 Clean Up 함수가 호출되는 조건
    • 다음 Side Effect를 발생하기 전
    • 컴포넌트가 Unmount될 때

 

반응형

'◼ FrontEnd > ReactJS' 카테고리의 다른 글

[ReactJS] Component의 분리와 재사용 (관심사의 분리)  (0) 2023.01.24
[ReactJS] 상수 데이터 & Mock Data + fetch 매소드  (0) 2023.01.24
[ReactJS] Hook & State & Props  (0) 2023.01.24
[ReactJS] SPA & Routing  (0) 2023.01.22
[ReactJS] JSX와 컴포넌트 (Component)  (0) 2023.01.22
'◼ FrontEnd/ReactJS' 카테고리의 다른 글
  • [ReactJS] Component의 분리와 재사용 (관심사의 분리)
  • [ReactJS] 상수 데이터 & Mock Data + fetch 매소드
  • [ReactJS] Hook & State & Props
  • [ReactJS] SPA & Routing
SangYoonLee (SYL)
SangYoonLee (SYL)
Slow, But Steady Wins The Race 😎
    반응형
  • SangYoonLee (SYL)
    ◆ Slow, But Steady ◆
    SangYoonLee (SYL)
  • 전체
    오늘
    어제
    • ◻ 전체 글 수 : (131) N
      • ✪ 취미, 경험 회고 및 일상 (26) N
        • [취미] Room Escape (2)
        • [회고] IT 관련 경험 회고 (18) N
        • [일상] 일상 생각 (4)
        • [일상] 독후감 (1)
      • ◼ FrontEnd (29) N
        • Web & HTML, CSS (8)
        • JavaScript (4) N
        • TypeScript (1)
        • ReactJS (16)
      • ◼ CS (3)
        • 자료구조 & 알고리즘 (1)
        • 컴퓨터 구조 (1)
        • 운영체제 (1)
      • ◼ PS Note (40)
        • 백준 (38)
        • 프로그래머스 (2)
      • ◼ IT Etc. (33)
        • (Until 2021) (21)
        • Python (6)
        • C | C# | C++ (1)
        • Git (1)
        • Unity (4)
        • Game Dev. (0)
  • 블로그 메뉴

    • 홈
    • 💻 GitHub
    • 🟢 Velog
    • 🧩 온라인 방탈출 출시 작품 모음
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    C++
    위코드
    React
    유니티
    코드숨
    pygame
    프로젝트
    미궁 게임
    파이썬
    unity
    더라비린스
    후기
    프로그래머스
    소수 구하기
    리엑트
    주간 회고
    백준
    개인 프로젝트
    코딩 일기
    회고
    관심사의 분리
    1929
    Component
    알고리즘
    CodeSoom
    Python
    Cpp
    JavaScript
    wecode
    방탈출고사
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
SangYoonLee (SYL)
[ReactJS] Side Effect와 useEffect
상단으로

티스토리툴바