중첩된 데이터에 함수형 도구 사용하기
- 14.1 객체를 다루는 함수형 도구가 필요하다
- 14.2 update() 도출하기
- 14.3 nestedUpdate() 도출하기
- 14.4 재귀를 이용한 구현
- 14.5 깊이 중첩된 데이터 다루기
깊이 중첩된 경로를 직접 쓰지 말고, 추상화 벽 뒤에 숨겨라 — 이건 9장의 추상화 벽 패턴과 정확히 같은 아이디어야.
12~13장에서 배열을 다루는 함수형 도구를 배웠지만, 현실의 데이터는 배열만 있는 게 아니거든 — 중첩된 객체가 훨씬 많아. MegaMart의 장바구니 아이템 데이터에서 options.size를 바꾸려면 카피-온-라이트로 objectSet 안에 objectSet을 넣어야 하고, 중첩이 깊어질수록 코드가 지저분해져. 더 좋은 도구가 필요해.
패턴을 보면 — 객체에서 특정 키의 값을 읽고 → 변환하고 → 다시 설정하는 게 반복돼. 이 "읽고 → 변환 → 설정" 패턴을 추상화하면:
function update(object, key, modify) {
var value = object[key]; // 읽기
var newValue = modify(value); // 변환
return objectSet(object, key, newValue); // 설정
}
var newItem = update(item, "price", function(price) {
return price * 0.9;
});
**update()**는 객체의 특정 키에 함수를 적용하는 도구야. map이 배열의 모든 원소에 함수를 적용하는 것처럼, update는 객체의 특정 키에 함수를 적용하지.
한 단계 중첩은 update()로 해결됐어. 두 단계는? update 안에 update를 넣으면 돼. 세 단계면 update 안에 update 안에 update. 이걸 일반화하면:
function nestedUpdate(object, keys, modify) {
if (keys.length === 0)
return modify(object);
var key = keys[0];
var restOfKeys = keys.slice(1);
return update(object, key, function(value) {
return nestedUpdate(value, restOfKeys, modify);
});
}
var newItem = nestedUpdate(item, ["options", "size"], function(size) {
return 11;
});
경로(keys 배열)와 변환 함수(modify)만 주면 어떤 깊이의 중첩이든 불변으로 업데이트할 수 있어.
여기서 **재귀(recursion)**가 자연스럽게 등장했지. 재귀 함수의 두 가지 요소는 종료 조건(base case)(keys.length === 0)과 재귀 단계(recursive case)(첫 번째 키로 한 단계 들어가고, 나머지 키로 재귀)야. 핵심은 **"문제를 점점 작게 만든다"**는 것이야. keys 배열이 호출할 때마다 하나씩 줄어들어서 결국 0에 도달하거든.
nestedUpdate()는 강력하지만 주의할 점이 있어. 경로가 길어지면 추상화 벽이 필요해:
// 나쁜 예 — 경로가 너무 구체적
nestedUpdate(data, ["users", "kim", "address", "city"], capitalize);
// 좋은 예 — 추상화 벽으로 감싸기
function updateUserCity(data, userId, modify) {
return nestedUpdate(data, ["users", userId, "address", "city"], modify);
}
updateUserCity(data, "kim", capitalize);
경로에 대한 지식을 한 곳에 모아두면, 데이터 구조가 바뀔 때 한 군데만 고치면 돼.
정리
14장 읽고 기억할 거 세 가지:
- update() = 객체의 특정 키에 함수를 적용. "읽기 → 변환 → 설정" 패턴의 추상화
- nestedUpdate() = 경로(keys 배열)를 따라가며 깊은 중첩도 불변으로 업데이트. 재귀로 구현
- 깊은 경로는 추상화 벽으로 감싸라. 데이터 구조에 대한 지식을 한 곳에 모아야 유지보수가 쉽다