[자바스크립트] 함수 결합
💡 tl;dr
- 함수 결합(Function Composition)의 정의
- 예시 및 활용
함수 결합이란
- 두 개 이상의 함수를 결합하여 새 함수를 생성하는 프로세스
- 함수를 결합하는 것은 데이터가 흐르기 위해 파이프를 까는 것과 같음
예를 들어, 는 자바스크립트에서 f(g(x))
와 같고, 이는 아래처럼 안에서 밖으로 순서대로 계산된다.
함수 결합의 활용
아래처럼 chain
으로 구성된 간단한 코드가 있다.
1 | const toSlug = input => encodeURIComponent( |
이를 함수 결합
형태로 다음과 같이 바꿀 수 있다.
1 | const toSlug = input => encodeURIComponent( |
첫 함수보다 가독성이 떨어져 보이지만, 결합의 방향성은 확연히 보인다.
.reduceRight()
Javascript
에는 이를 개선할 수 있는 Array
메서드 .reduce()
가 있다.
그러나 .reduce()
는 값의 전달 방향이 (왼쪽에서 오른쪽)으로, 예제 toSlug
의 형태와는 정 반대의 방향성을 보인다. 이때 사용할 수 있는 함수가 .reduceRight()
다. .reduce()
와 마찬가지로 reducer
함수와 초기값 x
를 사용하고, 배열 함수를 (오른쪽에서 왼쪽)으로 반복하며 누적된 값(v
)에 차례로 적용한다.
1 | const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x); |
이를 적용하면 중첩 없이 위 함수 결합
을 다시 작성할 수 있다.
1 | const toSlug = compose( |
.reduce()
마찬가지로 .reduce()
를 사용하면 (왼쪽에서 오른쪽)으로 순서대로 적용되는 함수의 흐름을 구현할 수 있다. 이를 pipe
라고 표현한다.
1 | const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x); |
사용 방법 또한 앞선 compose
함수와 똑같다. 단지 방향성이 바뀌었을 뿐이다.
이를 적용하여 toSlug
를 다음과 같이 수정할 수 있다.
1 | const toSlug = pipe( |
함수의 진행 방향이 정확히 반대가 되었다.
trace
데이터가 흐르는 파이프를 구현해놨다면, 이를 검증할 수 있는 trace
를 사용할 수 있다.
trace
란 파이프 사이사이에서 데이터의 흐름이 올바른지 확인할 수 있는 전략으로, 일반적으로 다음과 같이 구현한다.
1 | const trace = curry((label, x) => { |
사용 방법은 다음과 같다.
1 | const toSlug = pipe( |
tap
tap
이란 파이프를 통해 흐르는 데이터에 몇 가지 작업을 수행할 수 있도록하는 기법으로, trace()
는 일반적인 tap()
의 한 형태일 뿐이다.
다음과 같이 tap()
을 작성할 수 있다.
1 | const tap = curry((fn, x) => { |
이제 tap
을 이용해 trace
를 구현할 수 있다.
1 | const trace = label => { |
이러한 예제들을 통해 함수형 프로그래밍이 무엇인지, 어떻게 함수 결합을 활용하여 더 적은 boilerplate
로 더 읽기 쉬운 프로그램을 작성하는지 이해할 수 있다.
참고
해당 글은 Master the JavaScript Interview: What is Function Composition?을 번역 및 수정한 글입니다.
[자바스크립트] 함수 결합