쏙쏙 들어오는 함수형 코딩 CH7

Yunes·2023년 9월 30일
0
post-thumbnail

바쁜 현대인을 위한 요약

Ch7 에서는 방어적 복사를 통해 레거시 코드를 사용하면서 어떻게 불변성을 유지할 수 있는지 알려주고 있다.

Ch7 요약

카피 온 라이트는 불변성이 확보된 안전지대 안에서 데이터를 주고받는다면 방어적 복사 defensive copy 는 신뢰할 수 없는 코드와 데이터를 주고받을 때 복사본을 만들어 전달한다.

방어적 복사는 깊은 복사를 하여 모든 것을 복사하기에 카피 온 라이트에 비해 비용이 많이 든다. 신뢰할 수 없는 코드와 함께 사용할 때만 DC 를 사용한다.

신뢰할 수 없는 코드가 있다면 방어적 복사를 사용해 감싸자

웹 기반 API 도 암묵적으로 방어적 복사를 한다. request, response 를 주고받을때 JSON 형식으로 직렬화하여 데이터를 전송하는 것도 방어적 복사로 데이터를 복사해서 복사본을 전달하는 것이다.

방어적 복사는 비공유 아키텍처를 구현하기 좋다.

방어적 복사의 구현

// 원본
function add_item_to_cart(name, price) {
  var item = make_cart_item(name, price);
  shopping_cart = add_item(shopping_cart, item);
  var total = calc_total(shopping_cart);
  set_cart_total_dom(total);
  update_shipping_icons(shopping_cart);
  update_tax_dom(total);
  black_friday_promotion(shopping_cart);
}

책에서는 black_friday_promotion 가 레거시 코드이며 신뢰할 수 없는 코드라 불변성을 유지하기 위해 방어적 복사 기법을 사용할 수 있다고 소개하고 있다.

책의 내용대로 방어적 복사는 데이터를 가져오고 내보낼 때 복사본을 만들어 전달한다.

/// Copy before sharing data

function add_item_to_cart(name, price) {
  var item = make_cart_item(name, price);
  shopping_cart = add_item(shopping_cart, item);
  var total = calc_total(shopping_cart);
  set_cart_total_dom(total);
  update_shipping_icons(shopping_cart);
  update_tax_dom(total);
  var cart_copy = deepCopy(shopping_cart);
  black_friday_promotion(cart_copy);
}

/// Copy before and after sharing data

function add_item_to_cart(name, price) {
  var item = make_cart_item(name, price);
  shopping_cart = add_item(shopping_cart, item);
  var total = calc_total(shopping_cart);
  set_cart_total_dom(total);
  update_shipping_icons(shopping_cart);
  update_tax_dom(total);
  var cart_copy = deepCopy(shopping_cart);
  black_friday_promotion(cart_copy);
  shopping_cart = deepCopy(cart_copy);
}

카피 온 라이트와 방어적 복사의 비교

주제카피 온 라이트방어적 복사
언제 사용하나요?통제할 수 있는 데이터를 바꿀 때신뢰 할 수 없는 코드와 데이터를 주고받을 때
어디서 쓰나요?안전지대 어디서나 사용
카피 온 라이트가 불변성을 가진 안전지대를 만든다.
안전지대의 경계에서 데이터가 오고 갈 때
복사 방식은?얕은 복사깊은 복사
규칙1. 바꿀 데이터의 얕은 복사본을 생성
2. 복사본 변경
3. 복사본 리턴
1. 안전지대로 들어오는 데이터에 깊은 복사를 만든다.
2. 안전지대에서 나가는 데이터에 깊은 복사를 만든다.

자바스크립트에서의 깊은 복사

자바스크립트에서는 표준 라이브러리가 좋지 않아 깊은 복사를 만들기가 어렵다.. 깊은 복사를 하고 싶을때는 아래와 같은 방법을 활용할 수 있다.

  • JSON.parse(JSON.stringify(obj))
  • structuredClone(obj)
  • lodash 라이브러리의 .cloneDeep()

책갈피 - 기억에 남는 책의 내용과 그에 대한 생각 정리

카피 온 라이트 패턴은 무엇이 바뀌는지 알기 때문에 무엇을 복사해야 할지 예상할 수 있습니다.

신뢰할 수 없는 레거시 코드는 어떤 일이 일어날지 정확히 알 수 없어 데이터가 바뀌는 것을 완전히 막아주는 원칙이 필요하며 이 원칙을 방어적 복사라고 한다. - 149p

생각
막연히 카피 온 라이트가 얕은 복사고 방어적 복사가 깊은 복사라고 생각했는데 그렇게 이분법적으로 분리할 수 없다는 생각이 들었다. 카피 온 라이트는 신뢰할 수 있도록 코드를 변경하기 전에 어떻게 변경될지 예측이 가능하므로 복사본을 만들고 그 뒤에 복사본을 수정한다.

카피 온 라이트는 변경 가능한 쓰기를 불변의 읽기로 전환시켜주니 신뢰할 수 있는 코드를 만들어준다.

들어오고 나가는 데이터의 복사본을 만드는 것이 방어적 복사가 동작하는 방식이다. 방어적 복사를 사용하면 데이터가 바뀌는 것을 막아 불변성을 지킬 수 있다. - 151 p

생각
방어적 복사는 신뢰할 수 있는 코드로 만들 수 없는 코드를 사용해야 할 때 변경될 수 있는 데이터를 그대로 사용하지 않고 입력과 출력으로 해당 데이터가 넘어올 때 그대로 사용하지 말고 깊은 복사를 하여 원본을 건드리지 않고 복사본만으로 작업을 진행하는 것으로 이해했다.

카피 온 라이트는 복사본을 만들어 복사본에 쓰기를 하니 카피 - 온 - 라이트인 것 같고 방어적 복사는 원본이 바뀌지 않도록 방어해서 방어적 복사라고 하는것 같다.

함수형 프로그래밍에서는 유일한 객체로 사용자를 표현하지 않는다. 데이터는 이벤트에 대한 사실이다. 이벤트가 발생할 때처럼 필요할 때마다 여러 번 복사할 수 있다. - 157p

생각
책에서 이런 부분이 참 마음에 들었다. 마치 여러 사람들과 같이 책을 읽으며 새로운 관점에서 내용을 다시 바라볼 수 있는 부분이 좋았다. 방어적 복사니 카피 온 라이트니 계속 뭘 복사하는데 복사본이 여러개면 문제가 발생하지 않을까 하는 염려에 대해 애초에 데이터는 이벤트에 대한 사실이니 여러 번 복사해서 사용할 수 있다는 답변을 제공한다.

용어

레거시 코드 legacy code - 오래 전에 만들어 지금 당장 고칠 수 없어 그대로 사용해야 하는 코드

깊은 복사 deep copy - 위에서 아래로 모든 계층에 있는 중첩된 데이터 구조를 복사한다.

plus

앞에 함수형 코딩 Ch4 에서 map 이 얕은 복사를 한다고 생각했다.

그런데 다시 코드를 좀 수정해보니 깊은 복사를 한다는 것을 알 수 있었다. 사실 깊은 복사, 얕은 복사라고 구분하기는 어렵고 배열의 각 요소를 돌면서 콜백 함수를 실행하고 그 결과를 배열로 반환해주는데 반환할때 처음 예시는 수정된 바가 없으니 원본을 참조하고 있어 변경사항이 원본과 공유된 것이고 두번째 예시코드의 경우 spread 문법을 사용하는 순간이 깊은 복사가 일어났을 때인데 spread 는 기본적으로 깊은 복사를 수행하며 2차원 이상에서 얕은 복사를 수행한다. 다만 저 코드에서는 깊은 복사를 수행하여 원본과 복사본이 다른 참조를 가리키게 되어 복사본에 수정을 해도 원본에 영향이 없던 것이다.

profile
미래의 나를 만들어나가는 한 개발자의 블로그입니다.

0개의 댓글