Chapter 13

함수형 도구 체이닝

  • 13.1 함수형 도구 체이닝
  • 13.2 체인을 명확하게 만드는 방법
  • 13.3 반복문을 함수형 도구로 바꾸기
  • 13.4 체이닝의 디버깅
  • 13.5 다양한 함수형 도구들

map, filter, reduce를 하나씩 쓰면 for 루프 대체 정도지만, **여러 개를 연결(체이닝)**하면 복잡한 데이터 변환을 선언적으로 표현할 수 있어.

MegaMart에서 이런 요구사항이 온다고 해봐: "VIP 고객 중에서, 최근 한 달 이내에 구매한 사람들의 이메일 목록을 뽑아줘." 명령형으로 작성하면 중첩된 if문과 for 루프로 가득 차겠지만, 함수형 도구를 체이닝하면:

customers
  .filter(isVIP)
  .filter(isRecentPurchase)
  .map(getEmail);

각 단계가 무엇을 하는지 바로 읽히잖아: VIP 필터 → 최근 구매 필터 → 이메일 추출.

체인이 길어지면 읽기 어려워질 수 있는데, 저자가 제안하는 방법이 있어. 첫째, 단계에 이름 붙이기 — 중간 결과에 의미 있는 이름을 붙이면 각 단계가 명확해지거든:

var vips = filter(customers, isVIP);
var recentVIPs = filter(vips, isRecentPurchase);
var emails = map(recentVIPs, getEmail);

둘째, 콜백에 이름 붙이기 — 익명 함수 대신 이름이 있는 함수를 쓰면 체인 자체가 문장처럼 읽혀. 셋째, 두 단계를 하나로 합치기 — filter를 두 번 하는 대신 조건을 합칠 수도 있지만, 너무 합치면 각 단계의 의미가 흐려지니 적절히 판단해야 해.

기존 for 루프를 함수형 도구로 바꾸는 방법도 있어. for 루프 안에서 if가 있으면 filter, 변환이 있으면 map, 누적이 있으면 reduce야. 이 패턴을 눈에 익히면 기계적으로 변환할 수 있거든.

체인이 기대한 결과를 안 낼 때 디버깅하는 방법도 알아야 해. tap 함수를 쓰거나 각 단계의 결과를 변수에 담아서 하나씩 확인하면 돼. 체이닝의 좋은 점이 여기 있어 — 각 단계가 독립적인 계산이라서 중간에 끊어서 확인하기 쉽거든.

function tap(value, fn) {
  fn(value);
  return value;
}

map, filter, reduce 외에도 유용한 함수형 도구들이 있어. pluck은 객체 배열에서 특정 필드만 뽑기(map의 특수 케이스), concatMap / flatMap은 map 후 flatten, groupBy는 특정 기준으로 그룹핑, sortBy는 특정 기준으로 정렬, take / drop은 앞에서 n개 가져오기/버리기, zip은 두 배열을 쌍으로 묶기야. 이런 도구들은 대부분 reduce로 구현 가능하지만, 자주 쓰는 패턴에 이름을 붙여 두면 코드가 더 읽기 쉬워져.


정리

13장 읽고 기억할 거 세 가지:

  1. 체이닝 = map/filter/reduce를 연결해서 복잡한 데이터 변환을 선언적으로 표현. 각 단계가 "무엇을" 하는지 바로 읽힌다
  2. 체인을 명확하게 만드는 핵심은 이름 붙이기. 중간 변수에 이름, 콜백에 이름을 붙이면 문장처럼 읽힌다
  3. for 루프를 함수형으로 바꾸는 법: if → filter, 변환 → map, 누적 → reduce. 이 패턴만 기억하면 기계적으로 변환 가능