불변성&순수함수

박지현·2023년 2월 11일

React 입문

목록 보기
9/12
post-thumbnail

2023.02.06

불변성

불변성이란?

불변성이란 메모리에 있는 값을 변경할 수 없는 것을 말한다. 자바스크립트의 데이터 형태중에 원시 데이터(숫자, 문자, 불리언등)는 불변성이 있고, 원시 데이터가 아닌 객체, 배열, 함수는 불변성 없다.

변수를 저장하면, 메모링에는 어떻게 저장이 되나?

만약 우리가 let number = 1 이라고 선언을 하면, 메모리에는 1 이라는 값이 저장이 된다. 그리고 number 라는 변수는 메모리에 있는 1을 참조하게된다. 이어서 우리가 let secondNumber = 1 이라고 다른 변수를 선언을 했다고 가정할때, 자바스크립트는 이미 메모리에 생성되어 있는 1이라는 값을 참조한다. 즉, number와 secondNumber는 변수의 이름은 다르지만, 같은 메모리의 값을 바라보고 있는 것이다. 콘솔에 number === secondNumber 를 하면 true가 나오게된다.

하지만 원시데이터가 아닌 값(객체, 배열, 함수)는 이렇지 않다. let obj_1 = {name: ‘kim’} 이라는 값을 선언하면 메모리에 obj_1이 저장이 되고, 이어서 let obj_2 = {name: ‘kim’} 이라고 같은 값을 선언하면 obj_2라는 메모리 공간에 새롭게 저장이 됩니다. 그래서 obj_1 === obj_2false 가 된다.

데이터를 수정하면 어떻게 될까?

기존에 1이던 number를 number = 2 라고 새로운 값을 할당하게되면 원시 데이터는 불변성이 있기때문에, 기존 메모리에 저장이 되어 있는 1이라는 값이 변하지 않고, 새로운 메모리 저장공간에 2가 생기고 number라는 값을 새로운 메모리 공간에 저장된 2를 참조하게 된다. 그래서 secondNumber를 콘솔에 찍으면 여전히 1이라고 콘솔에 보이게된다. number와 secondNumber는 각각 다른 메모리 저장공간을 참조하고 있기 때문이다.

obj_1.name = ‘park’ 이라고 새로운 값을 할당하면 객체는 불변성이 없기때문에, 기존 메모리 저장공간에 있는 {name: ‘kim’} 이라는 값이 {name : ‘park’} 으로 바뀌어 버린다.

원시데이터는 수정을 했을 때 메모리에 저장된 값 자체는 바꿀 수 없고, 새로운 메모리 저장공간에 새로운 값을 저장한다. 원시데이터가 아닌 데이터는 수정했을 때 기존에 저장되어 있던 메모리 저장공간의 값 자체를 바꿔버린다.

왜 리액트에서는 원시데이터가 아닌 데이터의 불변성을 지켜주는 것을 중요시할까?

리액트에서는 화면을 리렌더링 할지 말지 결정할 때 state의 변화를 확인한다. 이때, state가 변했는지 변하지 않았는지 확인하는 방법이 state의 변화 전, 후의 메모리 주소를 비교하는 것이다. 만약 리액트에서 원시데이터가 아닌 데이터를 수정할 때 불변성을 지켜주지 않고, 직접 수정을 가하면 값은 바뀌지만 메모리주소는 변함이 없게 되는것이다. 즉, 개발자가 값은 바꿨지만 리액트는 state가 변했다고 인지하지 못하게 된다. 마땅히 일어나야 할 리렌더링이 일어나지 않게되버리는 것이다.

리액트 불변성 지키기 예시

배열을 setState 할 때 불변성을 지켜주기 위해, 직접 수정을 가하지 않고 전개 연산자를 사용해서 기존의 값을 복사하고, 그 이후에 값을 수정하는 식으로 구현해야한다.

import React, { useState } from "react";

function App() {
  const [dogs, setDogs] = useState(["말티즈"]);

  function onClickHandler() {
		// spread operator(전개 연산자)를 이용해서 dogs를 복사합니다. 
	  // 그리고 나서 항목을 추가합니다.
    setDogs([...dogs, "시고르자브르종"]);
  }

  console.log(dogs);
  return (
    <div>
      <button onClick={onClickHandler}>버튼</button>
    </div>
  );
}

export default App;

순수함수

개념

하나 이상의 인자를 받고, 인자를 변경하지 않고, 참조하여 새로운 값을 반환하는 함수
즉, 같은 input동일한 인자가 전달되면 항상 동일한 결과를 반환하는 함수(코드 블록)입니다.

예시

(1) 순수함수

// 매개변수를 복사한 값을 변경하는 순수함수
const addSixPure = (arr) => {
  // 펼침 연산자로 새로운 배열에 6 추가
  newArr = [...arr, 6];
  return newArr;
};

(2) 순수함수가 아닌 것

const num_arr = [1, 2, 3, 4, 5];

// 매개변수의 값을 직접 변경하는 불순함수
const addSixImpure = (arr) => {
  // 매개변수에 직접 6 추가
  arr.push(6);
  return arr;
};

리액트 과정에서 갑자기 왜 순수함수?

  1. 컴포넌트의 많은 루틴을 순수 함수로서 작성하기를 요구하고 있다.
    1. 컴포넌트에서 state와 props가 같으면, 항상 같은 값을 반환해야합니다.
    2. 다른 Side effects를 발생시키지 않아야 합니다. (HTTP 요청, 데이터 저장, 쿠키 조작 등)
  2. 컴포넌트의 상탯값은 불변 객체(Immutable Object)로 관리해야만 한다.
    1. 수정할 때에는 기존 값을 변경하는 것이 아니라, 같은 이름의 새로운 객체를 생성합니다.
  3. 이를 통해, UI 개발의 복잡도를 낮추고, 버그 발생 확률도 줄인다.
    1. 같은 입력에 대해 항상 같은 출력을 보장하니, 테스트 하기도 훨씬 수월하다.
profile
프론트엔드가 목표!

0개의 댓글