FrontEnd
[함수형 프로그래밍] 6장 변경 가능한 데이터 구조를 가진언어에서 불변성 유지하기
mingg123
2023. 10. 14. 14:18
6장 변경 가능한 데이터 구조를 가진언어에서 불변성 유지하기
장바구니를 예시로 들었을때 동작에서 읽기, 쓰기를 분류할 수 있음
읽기
- 데이터를 바꾸지 않고 정보를 꺼내는 것
쓰기
- 데이터를 바꾸는 것
장바구니 동작
- 제품 개수 가져오기 => 읽기
- 제품 이름으로 제품 가져오기 => 읽기
- 제품 추가하기 => 쓰기
- 제품 이름으로 제품 빼기 => 쓰기
- 제품 이름으로 제품 구매 수량 바꾸기 => 쓰기
함수형 프로그래밍에선 쓰기 동작은 불변성 원칙에 따라 구현해서 최대한 읽기로 바꾸어야함.
카피-온-라이트 원칙 3단계
- 복사본 만들기
- 복사본 변경하기
- 복사본 리턴하기
연습문제 1
적용 전
var mailing_list = [];
function add_contact(email) {
mailing_list.push(email);
}
function submit_form_handler(event) {
var form = event.target;
var email = form.elements['email'].value;
add_contact(email);
}
내가 작성한 해답
var mailing_list = [];
function add_contact(mailList, email) {
var newMailList = mailList.slice();
newMailList.push(email);
return newMailList;
}
function submit_form_handler(event) {
var form = event.target;
var email = form.elements['email'].value;
mailing_list = add_contact(email);
}
연습문제 2
적용 전
var a = [1, 2, 3, 4];
var b = a.pop ();
console.log(b); // 4를 출력 console.log(a); // [1, 2, 3] 을 출력
내가 작성한 해답
// 읽기, 쓰기 함수로 나누기
function drop_element(array) {
var newArray = array.slice();
newArray.pop();
return newArray;
}
// 값 두개를 리턴하는 함수로 만들기
function print(array) {
var newArray = array.slice();
var first = newArray.pop();
return {
first: first,
array: newArray,
};
}
연습문제 3
Q. push 함수를 카피- 온 라이트형식으로 변경
내가 작성한 해답
function push(array, elem) {
var newArray = array.slice();
newArray.push(elem);
return newArray;
}
요약
- 변경 가능한 데이터를 읽는 것은 액션
- 쓰기는 데이터를 변경 가능한 구조로 만듬
- 어떤 데이터에 쓰기가 없다면 데이터는 변경 불가능한 데이터임
- 불변 데이터 구조를 읽는 것은 계산임
- 쓰기를 읽기로 바꾸면 코드에 계산이 많아짐
매번 복사 객체를 만드는건 너무 비효율적인 것이 아닌가?
- 변경 가능한 데이터 구조보다 메모리를 더 많이쓰고 느린 것은 맞음
- 언제든 최적화 할 수 있음
- 불변의 데이터 구조를 사용하고 속도가 느린 부분이 있다면 그때 최적하 해라
- 가비지 콜렉터가 매우 빠름
- 언어에서 제공하는 GC를 사용해라
- 생각보다 많이 복사하지 않음
- 얕은 복사는 같은 메모리를 가르키는 참조에 대한 복사본을 만듬
- 함수형 프로그래밍 언어에는 빠른 구현체가 있음
- 데이터 구조를 복사할 때 최대한 많은 구조를 공유하여, 적은 매모리를 사용함. (클로저 내부) 이는 카피 - 온 라이트 구조를 띰
객체애 대한 카피-온-라이트
var object = {a:1, b:2};
var object_copy = Object.assign({}, object);
난 spread 연산자를 많이써서 Object.assign은 잘 사용하지 않았음.
중첩된 쓰기를 읽기로 바꾸기
적용 전
function setPriceByName(cart, name, price) {
for (var i = 0; i < cart.lenth; i++) {
if (cart[i].name === name)
cart[i].price = price;
}
}
수정 후
function setPriceByName(cart, name, price) {
var cartCopy = cart.slice();
for (var i = 0; i < cartCopy.length; i++) {
if (cartCopy[i].name === name) cartCopy[i] = setPrice(cartCopy[i], price);
}
return cartCopy;
}
function setPrice(item, new_price) {
return objectSet(item, 'price', new_price);
}
function objectSet(object, key, value) {
var copy = Object.assign({}, object);
copy[key] = value;
return copy;
}
- objectSet을 살펴보면 두번째 인자로 key를 받음으로써 price 뿐만 아니라 다른 속성을 불변으로 만듬에 사용 가능하다.
- Object.assign은 얕은 복사 임으로 최상위 데이터 구조만 복사한다.
- 위 사진을 보면 shoes의 price만 10 -> 13으로 변경됨을 확인할 수 있다.
요약
- 함수형 프로그래밍에서 불변 데이터가 필요함
- 카피-온-라이트는 데이터를 불변형으로 유지할 수 있는 원칙임. 복사본을 만들고 원본 대신 복사본을 변경하는것을 의미함
- 카피-온-라이트는 값을 변경하기 전에 얕은 복사를 진행하고 리턴함.
- 보일러 플레이트 코드를 줄이기 위해 기본적인 배열과 객체 동작에 대한 카피-온-라이트 버전을 만들어두는 것이 좋음