불변성

불변성

데이터 값이 생성된 이후 변경되지 않는 것을 의미한다.

중첩된 데이터 (nested data)

데이터 구조 안에 데이터 구조가 중첩으로 되있는 것을 중첩된 데이터라고 한다.

  • Ex:) 배열 안에 객체가 있는 경우 중첩된 데이터

  • 이런 경우 객체가 배열에 중첩 되었다고 볼 수 있다.

깊이 중첩 (deeply nested)

중첩이 이어지는 것을 깊이 중첩이라 한다.

  • 어떤 객체가 객체 안에 배열, 그 배열 안에 객체 이런 구조처럼 중첩은 계속 이어질 수 있다.

  • 중첩된 모든 데이터 구조가 변하지 않아야 불변 데이터라고 볼 수 있다.

동작을 읽기, 쓰기 또는 둘 다로 분류하기

읽기(Read)

데이터를 바꾸지 않고 정보를 꺼내는 것

  • 데이터를 변경하지 않기 때문에 다루기 쉬움

  • 인자에만 의존해 정보를 가져오는 읽기 동작은 계산이다.

변경 가능한 데이터는 실행 시점(읽는 시점)에 따라 달라질 수 있으므로, 변경 가능한 데이터를 읽는 것은 액션이다.

쓰기(Write)

쓰기 동작은 데이터를 바꾸기 때문에, 데이터를 변경 가능한 구조로 만든다.

  • 쓰기 동작은 불변성 원칙(copy-on-write)에 따라 구현해야 한다.

  • 자바스크립트는 기본적으로 변경 가능한 데이터 구조를 사용하기 때문에 불변성 원칙을 적용하기 위해서는 직접 구현해야 한다.

  • 쓰기를 모두 없앤다면 변경할 수 없는 값이 되므로, 불변 데이터가 된다

카피-온-라이트(copy-on-write)

데이터를 불변형으로 유지할 수 있는 원칙

  • 복사본을 만들고 변경하는 것을 말함

  • 값을 변경하기 전에 얕은 복사를 하고 반환한다. 이렇게하면 통제할 수 있는 범위에서 불변성을 구현할 수 있다.

원칙 3단계

  1. 복사본 만들기

  2. 복사본 변경하기

  3. 복사본 반환하기

카피-온-라이트 원칙은 데이터(원본)을 변경하지 않고 반환했기 때문에 읽기(Read)이다.

즉, 카피-온-라이트 원칙은 쓰기(Write) → 읽기(Read)로 바꾼다.

쓰기를 읽기로 바꾸면 코드에 계산이 많아진다.

즉, 데이터 구조를 불변형으로 만들 수록 코드에 더 많은 계산이 생기고 액션은 줄어든다.

쓰기도 하면서 읽기도 하는 동작을 copy-on-write로 변경하기

  • 읽고 변경하는 일을 동시에 하는 동작은 값을 변경하고 반환한다.

const nums = [1, 2, 3, 4];
const shiftNums = nums.shift(); // 1
console.log(shiftNums); // [2, 3, 4]

copy-on-write 원칙 적용

  1. 읽기와 쓰기 함수로 각각 분리

  2. 함수에서 값을 두개 리턴

const lastElement = <T>(array: T[]) => array.at(-1);
const dropLast = <T>(array: T[]) => [...array.slice(0, array.length - 1)];

const pop = <T>(array: T[]) => ({last: lastElement(arrat), array: dropLast(array)});

불변 데이터의 진실

불변 데이터는 충분히 빠르다.

  • 일반적으로 불변 데이터 구조는 변경 가능한 데이터 구조보다 메모리를 더 많이 쓰고 느리다.

  • 불변 데이터 구조를 사용하면서 대용량 고성능 서비스를 구현하는 사례도 많이 있다. 즉, 불변 데이터도 일반 애플리케이션 서비스에서 쓰기 충분히 빠르다는 증거

  • 가비지 컬렉터는 충분히 매우 빠름

  • 생각보다 많이 복사하지 않는다. 얕은 복사(shallowd copy)는 중첩된 데이터 구조에서 최상위 단계만 복사한다. 내부 중첩된 데이터는 참조에 대한 복사본으로 같은 메모리를 가리키는데 이것을 구조적 공유라 한다.

언제든 최적화 가능

  • 성능 최적화는 미리 하지 않는것이 국룰

  • 불변 데이터를 사용하고 성능 부분에서 이슈가 생긴다면 그 때 최적화하자.

데이터가 모두 불변형이면 시간에 따라 변하는 애플리케이션 상태를 어떻게 다룰수 있는가?

모든 값을 불변형으로 만들더라도 시간에 따라 바뀌는 값(최신값)을 다룰수 있어야 하는데 함수형 프로그래밍에서는 필요할 때 새로운 값으로 교체(swapping)하는 방법을 흔히 사용한다.

Last updated