Skip to content

Commit d6e840f

Browse files
authored
docs: 7장 정리
1 parent 61ada27 commit d6e840f

File tree

1 file changed

+117
-0
lines changed
  • 김서현/07. 신뢰할 수 없는 코드를 쓰면서 불변성 지키기

1 file changed

+117
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# 07. 신뢰할 수 없는 코드를 쓰면서 불변성 지키기
2+
3+
- [방어적 복사를 사용해 레거시 코드에서 불변성 지키기](#방어적-복사를-사용해-레거시-코드에서-불변성-지키기)
4+
- [일반적으로 쓰이는 방어적 복사](#일반적으로-쓰이는-방어적-복사)
5+
- [카피-온-라이트와 방어적 복사 비교](#카피-온-라이트와-방어적-복사-비교)
6+
- [얕은 복사와 깊은 복사 비교](#얕은-복사와-깊은-복사-비교)
7+
8+
# 방어적 복사를 사용해 레거시 코드에서 불변성 지키기
9+
10+
- 방어적 복사
11+
12+
- 동작 방식: 들어오고 나가는 데이터의 깊은 복사본 만듦
13+
- 들어오는 데이터 보호: 신뢰할 수 없는 들어온 데이터로 깊은 복사본 만듦, 변경 가능한 원본은 버림. 신뢰할 수 있는 코드만 복사본 사용
14+
- 나가는 데이터 보호: 깊은 복사본을 만들어 데이터 내보냄. 신뢰할 수 없는 코드가 나가는 데이터 값을 변경 못하도록.
15+
- 목적: 안전지대에 불변성 유지. 가변성 있는 데이터가 안전지대로 들어오지 못하도록 하는 것
16+
- 규칙
17+
1. 데이터가 안전한 코드에서 나갈 때 복사하기
18+
1. 불변성 데이터를 위한 깊은 복사본 만듦
19+
2. 신뢰할 수 없는 코드로 복사본 전달
20+
2. 안전한 코드로 데이터가 들어올 때 복사하기
21+
1. 변경될 수도 있는 데이터가 들어오면 바로 깊은 복사본 만들어 안전한 코드로 전달
22+
2. 복사본을 안전한 코드에서 사용
23+
- 구현
24+
25+
- 기존 코드
26+
```tsx
27+
function add_item_to_cart(name, price) {
28+
shopping_cart = add_item(shopping_cart, name, price);
29+
var total = calc_total(shopping_cart);
30+
set_cart_total_dom(total);
31+
update_shipping_icons(shopping_cart);
32+
update_tax_dom(total);
33+
// 명세 추가
34+
black_friday_promotion(shopping_cart);
35+
}
36+
```
37+
- 방어적 복사 적용
38+
```tsx
39+
function add_item_to_cart(name, price) {
40+
// ...
41+
// 넘기기 전 복사
42+
var cart_copy = deepCopy(shopping_cart);
43+
black_friday_promotion(cart_copy);
44+
// 들어오는 데이터를 위한 복사
45+
shopping_cart = deepCopy(cart_copy);
46+
}
47+
```
48+
- 방어적 복사 코드 분리해 신뢰할 수 없는 코드 감싸기
49+
50+
```tsx
51+
function add_item_to_cart(name, price) {
52+
// ...
53+
shopping_cart = black_friday_promotion_safe(shopping_cart);
54+
}
55+
56+
function black_friday_promotion_safe(cart) {
57+
var cart_copy = deepCopy(cart);
58+
black_friday_promotion(cart_copy);
59+
return deepCopy(cart_copy);
60+
}
61+
```
62+
63+
- 분리 이유
64+
- 나중에 코드 보면 복사본 만든 이유 모를 수 있음
65+
- black_friday_promotion() 코드를 나중에 쓸 수도 있음
66+
- 코드가 하는 일 명확하게 만들기 위함
67+
68+
# 일반적으로 쓰이는 방어적 복사
69+
70+
-API 속 방어적 복사
71+
- API에 요청으로 들어오고 응답으로 보내는 JSON 데이터는 깊은 복사본
72+
- 방어적 복사로 서로 다른 코드와 원칙을 가진 서비스들이 문제 없이 통신 가능
73+
- 비공유 아키텍처: shared nothing architecture. 모듈이 서로 통신하기 위해 방어적 복사 공유함. 모듈이 어떤 데이터의 참조도 공유하지 않음.
74+
- 함수형 프로그래밍 언어인 얼랭과 엘릭서에서의 방어적 복사
75+
- 두 프로세스가 서로 메시지 주고받을 때 데이터 복사. 고가용성 보장
76+
- 방어적 복사 예제
77+
78+
```tsx
79+
function payrollCalc(employees) {
80+
// ...
81+
return payrollChecks;
82+
}
83+
84+
function payrollCalcSafe(employees) {
85+
const copied_employees = deepCopy(employees);
86+
const payrollChecks = payrollCalc(copied_employees);
87+
return deepCopy(payrollChecks);
88+
}
89+
```
90+
91+
```tsx
92+
userChanges.subscribe(function (user) {
93+
const userCopy = deepCopy(user);
94+
// 안전지대에서 데이터가 나가지 않음 -> 데이터 복사할 필요 없음
95+
procssUser(userCopy);
96+
});
97+
```
98+
99+
# 카피--라이트와 방어적 복사 비교
100+
101+
| | 카피--라이트 | 방어적 복사 |
102+
| ------------------------------------------ | --------------------------------------- | ---------------------------------------- |
103+
| 사용 시점 | 통제 가능한 데이터 변경 | 신뢰할 수 없는 코드와 데이터 주고받기 |
104+
| 사용 장소 | 안전지대 안 어디서나<br/> 카피--라이트가 불변성 가진 안전지대 만듦 | 안전지대의 경계에서 데이터가 오고 갈 때 |
105+
| 복사 방식 | 얕은 복사 (비용 저렴) | 깊은 복사 (비용 비쌈) |
106+
| 복사 시점 | 데이터가 바뀔 때마다 | 안전지대에서 데이터가 들어오고 나갈 때만 |
107+
| 규칙 | 1. 바꿀 데이터의 얕은 복사 만듦 <br/>2. 복사본 변경<br/>3. 복사본 리턴 | 1. 안전지대로 들어오는 데이터에 깊은 복사 만듦<br/>2. 안전지대에서 나가는 데이터에 깊은 복사 만듦 |
108+
109+
## 얕은 복사와 깊은 복사 비교
110+
111+
| | 얕은 복사 | 깊은 복사 |
112+
| ------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- |
113+
| 원본과의 데이터 구조 공유 | O | X. 어떠한 데이터 구조도 공유하지 않음 (→ 신뢰할 수 없는 코드로부터 원본 데이터 보호 가능) |
114+
| 복사 대상 | 바뀐 부분만 복사. 바뀌지 않은 값이면 원본과 복사본이 데이터 공유함 | 모든 것 복사. 중첩된 모든 객체 배열 다 복사. |
115+
| 구현 난이도 | 비교적 용이 | 어려움 → lodash 라이브러리의 .cloneDeep() 사용 권장 |
116+
117+
→ 카피--라이트를 쓸 수 없는 곳에만 방어적 복사를 사용하는 게 좋음

0 commit comments

Comments
 (0)