지금까지는 카피-온-라이트 방식으로 데이터의 불변성을 유지해왔다. 라이브러리나 레거시 코드가 데이터를 변경한다면 카피-온-라이트 방식으로 데이터를 관리할 수 없다. 이런 경우, 어떻게 데이터의 불변성을 유지할 수 있을까?
MegaMart에서 한달에 한 번씩 블랙 프라이데이 세일을 하기로 했다.
🙋♂️ 고객이 장바구니에 제품을 담을 때 행사 가격이 적용되도록 할 수 있을까요?
지금까지 장바구니와 관련된 코드들은 카피-온-라이트를 적용하여 데이터들의 불변성을 유지했다. 그러나 블랙 프라이데이 행사 관련 코드는 오래 전에 만든 코드이면서 많은 곳에서 장바구니 데이터를 변경한다. 당장 고칠 시간도 있지 않아 이런 레거시 코드를 쓸 수 있는 안전한 인터페이스가 필요하다.
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);
}
블랙프라이데이 함수를 추가하면 카피-온-라이트 원칙으로 쓰인 add_item_to_cart
함수를 더 이상 카피-온-라이트 원칙으로 쓰였다고 말할 수 없게 된다.
그렇다고 black_friday_promotion()
함수도 고칠 수 없다.
🤷♀️ 흠냐륑 어쩌지
블랙 프라이데이 행사 함수는 카피-온-라이트를 적용하지 않았기 때문에 데이터의 불변성에 대해 신뢰할 수 없다.
카피-온-라이트를 적용한 코드들은 모두 불변성이 지켜져 걱정없이 쓸 수 있어 안전지대에 있다고 말할 수 있다.
블랙 프라이데이 행사 함수는 안전지대 밖에 있기 때문에 만약 이 블랙 프라이데이 함수를 그냥 사용한다면 이 함수의 입력과 출력을 통해 안전지대에 있는 코드와 데이터를 주고 받게 된다.
그러면 안전지대 밖으로 나가는 데이터가 바뀔 위험이 있고, 안전지대로 들어오는 데이터도 바뀔 위험이 있다. 그래서 카피-온-라이트 원칙을 지킬 수 없게 된다.
🙋♂️ 블랙 프라이데이 행사 함수도 카피-온-라이트하면 되는 거 아녀?
카피-온-라이트 패턴은 무엇이 바뀌는 지 알기 때문에 데이터를 바꾸기 전에 무엇을 복사해야 할 지 예상할 수 있다. 하지만 블랙 프라이데이 행사 코드는 어떤 일이 일어날지 정확히 알 수 없는 레거시코드이기 때문에 카피-온-라이트 패턴을 적용할 수 없다.
그래서 데이터가 바뀌는 것을 완벽히 막아줄 수 있는 방어적 복사 원칙을 사용해야 한다.
바뀔 수도 있는 데이터가 신뢰할 수 없는 코드를 통해 안전지대로 들어오게 되면, 들어온 데이터로 깊은 복사본을 만들고 변경 가능한 원본은 버린다.
반대로 안전지대에서 나가는 데이터도 신뢰할 수 없는 코드를 통해 변경될 수 있기 때문에 나가는 데이터도 깊은 복사본을 만들어 내보내야 한다.
한마디로 들어오고 나가는 데이터의 복사본을 만드는 것이 방어적 복사가 동작하는 방식이다.
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(shopping_cart);
// 들어오는 데이터를 위해 깊은 복사
shopping_cart = deepCopy(cart_copy);
}
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);
// 방어적 복사 함수 사용
shopping_cart = black_friday_promotion_safe(shopping_cart);
}
// 방어적 복사와 관련된 코드
function black_friday_promotion_safe(cart) {
var cart_copy = deepCopy(cart);
black_friday_promotion(cart_copy);
return deepCopy(cart_copy);
}
언제 쓰지?
어디서 쓰지?
복사 방식?
규칙
언제 쓰지?
어디서 쓰지?
복사 방식?
규칙
데이터가 불변성을 가질 수 있는 안전지대를 만들기 위해서 카피-온-라이트 방식이 아닌 방어적 복사 방식을 사용할 수도 있지만, 깊은 복사는 중첩된 데이터 구조의 모든 것을 복사하기 때문에 바뀐 부분만 복사하는 얕은 복사, 카피-온-라이트에 비해 방어적 복사를 사용할 때 많은 비용이 든다.
상황에 따라 적절하게 두 원칙을 사용해야 한다. 방어적 복사만으로 코드를 작성할 수 없고 또 카피-온-라이트만으로도 코드를 작성할 수 없다.
둘은 서로에게 꼭 필요한 존재,,,
방어적 복사는 불변성을 구현하는 원칙
방어적 복사는 깊은 복사를 한다. 그래서 많은 비용이 든다.
방어적 복사는 불변성 원칙을 구현하지 않는 코드로부터 데이터를 보호해준다.
방어적 복사는 신뢰할 수 없는 코드와 함께 사용할 때만 사용한다.
깊은 복사는 중첩된 데이터 전체를 복사하고 얕은 복사는 필요한 부분만 최소한으로 복사한다.
혹시나 잘못된 정보가 있다면 댓글로 알려주세요 ! 저의 성장의 큰 도움이 될 것 같습니다.🌱