🚀 94sssh
Published on

2024.01.10

[함수형 코딩] - 06. 변경 가능한 데이터 구조를 가진 언어에서 불변성 유지하기

동작은 읽기 또는 쓰기 또는 둘 다 하는 것으로 분류할 수 있다.

  • 읽기 : 데이터를 바꾸지 않고 정보를 꺼내는 것
  • 쓰기 : 데이터를 바꾼다.

쓰기 동작은 어디서 쓰일지 모르므로 바뀌지 않도록 주의해야 한다.
그러므로 쓰기 동작은 불변성 원칙에 따라 구현해야 하는데, 불변성 원칙을 카피-온-라이트라고 한다.

카피-온-라이트 원칙 세 단계

  1. 복사본 만들기
  2. 복사본 변경하기
  3. 복사본 리턴하기

카피-온-라이트를 통해 함수를 수정하면, 데이터를 바꾸지 않게 되고, 정보를 리턴하므로 읽기가 된다.
카피 -온-라이트는 쓰기를 읽기로 바꾼다.

연습문제가 많았는데, 짧게 짧게 나눠놓아서 평소에 연습문제 파트를 건너뛰는 나도 해보기 좋았다. 지하철에서 눈으로 해보면서 왔는데, 하다가 잠듦

쓰기를 하면서 읽기도 하는 동작은 어떻게 해야 할까요?

.shift() 메서드는 값을 리턴하고 있으므로, 이미 읽기 작업을 하고 있다.
이런 경우에는 두 가지 접근법이 있다.

  1. 읽기와 쓰기 함수로 각각 분리하기
  2. 함수에서 값을 두 개 리턴하기
    이 중 가능하다면 첫 번째 접근법이 더 좋은 방법이다. 책임이 확실히 분리되기 때문.

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

읽기와 쓰기 동작으로 분리하기
기존 메서드가 리턴하는 값을 리턴하는 계산 함수를 만든다.

쓰기 동작을 카피-온-라이트로 바꾸기
읽기와 쓰기를 분리하는 방법은 분리된 함수를 따로 쓸 수 있어 더 좋은 방법이다.

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

동작을 감싸기
메서드 자체를 감싸는 새로운 함수를 만든다. 함수 리턴값을 무시해서는 안된다.

function shift(array) {
  return array.shift()
}

읽으면서 쓰기도 하는 함수를 읽기 함수로 바꾸기
기존 메서드가 리턴하는 항목과 인자를 복사한 항목을 함께 리턴한다.

카피-온-라이트를 통해 불변성을 구현하는 작업은 확실히 외부에 영향을 주지 않아 좋은 것 같지만, 같은 동작에 대해 코드가 늘어나는 것 같다고 생각했다. 마침 책에서 이 부분을 짚어주는데 저자는 이것이 시간을 들여 작업할 만한 가치가 있다고 말해준다. 확실히 최근에는 시간을 더 들여서라도 꼼꼼하게 만들고, 검토하고, 실수 등을 줄이는 것이 돌아보면 더 시간을 절약하는 것이라는 생각이 든다. 특히 오늘...

불변 데이터 구조를 읽는 것은 계산이다

  1. 변경 가능한 데이터를 읽는 것은 액션
  2. 쓰기는 데이터를 변경 가능한 구조로 만든다
  3. 어떤 데이터에 쓰기가 없다면 데이터는 변경 불가능한 데이터이다
  4. 불변 데이터 구조를 읽는 것은 계산이다
  5. 쓰기를 읽기로 바꾸면 코드에 계산이 많아진다

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

일반적으로는 불변 데이터 구조가 변경 가능한 데이터 구조보다 메모리를 더 쓰고 느리다.
이에 대한 논점이 있는데 다음과 같다.

  1. 언제든 최적화할 수 있다.
    불변 데이터 구조를 사용하고 속도가 느린 부분이 있다면 그때 최적화하면 된다.
  2. 가비지 콜렉터는 매우 빠르다
  3. 생각보다 많이 복사하지 않는다. 얕은 복사하기 때문
  4. 함수형 프로그래밍 언어네는 빠른 구현체가 있다.

객체도 배열과 마찬가지로 카피-온-라이트 3단계를 적용하면 된다.
객체의 경우는 Object.assign()등을 사용할 수 있다.

얕은 복사
중첩된 데이터 구조의 최상위 데이터만 복사하는 것
구조적 공유
두 개의 중첩된 데이터 구조가 어떤 참조를 공유하는 경우

중첩된 쓰기를 읽기로 바꾸기

가장 안쪽에 있는 쓰기 동작부터 바꾸는 것이 쉽다.
이때 중요한 것은 중첩된 데이터 구조는 모든 부분이 불변형이어야 한다. 중첩된 데이터의 일부를 바꾸려면 변경하려는 값과 상위의 모든 값을 복사해야 한다.