JavaScript/함수형 프로그래밍

[JavaScript]함수형 프로그래밍 - 합성(composition)

DevStory 2021. 8. 15.

앞에서 설명한 내용들을 기반으로 필요한 기능 및 로직을 순수 함수로 나누어 개발합니다.

 

이렇게 나누어진 순수 함수들을 합쳐야 하는 경우가 존재합니다.

 

예를 들어 A 함수를 실행 후 B 함수를 실행하거나 또는 A 함수를 실행 후 C 함수를 실행해야 하는 경우 (A, B), (A, C)처럼 함수를 조합하는 과정이 필요합니다.

 

이러한 과정을 함수 합성(function composition)이라고 합니다.

 

이번 포스팅에서는 함수 합성의 내용을 정리합니다.


메서드 체이닝도 합성의 일부다.

메서드 체이닝을 사용하면, 이전에 호출한 함수의 결과에 다음 함수를 호출할 수 있습니다.

 

아래 코드는 replace 함수를 사용하여 문자열을 변경하고 변경된 문자열에 또 replace 함수를 사용하는 코드입니다.

따라서, 메서드 체이닝을 사용해 함수를 연쇄적으로 호출하고 있습니다.

var strEncrypt = '###B...D---F';

var strDecrypt = strEncrypt.replace('###', 'A')
                           .replace('...', 'C')
                           .replace('---', 'E')
                           .replace('ABCDEF', 'Composition');
                           
console.log(strDecrypt);
// Composition

 

 

작성한 코드는 다음과 같은 규칙과 순서가 존재합니다.

  1. '###'을 'A'로 변환
  2. '...'를 'C'로 변환
  3. '---'을 'E'로 변환
  4. 'ABCDEF'를 'Composition'으로 변환

순서 1~4는 무조건 순차적으로 실행되어야 합니다.


함수를 조합하여 고차 함수를 생성

앞에서 메서드 체이닝을 사용하여 함수를 합성하는 방법에 대해 알아보았습니다.

 

합성의 다른 방법으로 함수를 조합하여 고차 함수를 생성하는 것입니다.

 

원화를 천 원 단위로 반올림하여 반환합니다.

function getCellMoney(money) {
  return Math.ceil(money / 1000) * 1000;
}

 

그리고 원화를 달러로 계산하여 반환합니다.

(※ 달러는 변동적이지만, 예시에서는 1원 =  0.00086달러로 고정 값입니다.)

function getUSDMoney(money) {
  return money * 0.00086;
}

 

원화를 엔으로 계산하여 반환하는 경우도 있다고 합시다.

function getJPYMoney(money) {
  return money * 0.094;
}

 

이제 compose 함수를 생성하여 함수를 조합합니다.

(※ 아래 코드는 충분히 개선의 여지가 있고 좋은 코드는 아닙니다. compose 함수의 예를 들어서 설명하기 위해 작성했다는 점 참고해주세요.)

const compose = (...fns) => 
  (x) => 
    fns.reduce((curr, fn) => fn(curr), x);
    
function getCellMoney(money) {
  return Math.ceil(money / 1000) * 1000;
}

function getUSDMoney(money) {
  return money * 0.00086;
}

function getJPYMoney(money) {
  return money * 0.094;
}

var getConvertMoney = compose(getCellMoney, getUSDMoney);

console.log(getConvertMoney(12345.123));
// 11.18

 

compose 함수는 여러 함수를 인자로 받아서 하나의 함수를 반환합니다.

const compose = (...fns) => 
  (x) => 
    fns.reduce(
      (curr, fn) => fn(curr), 
      x
    );

 

compose 함수를 사용한 방법과 사용하지 않은 방법 둘 다 결과합니다.

단, 대부분 글을 읽을 때 왼쪽부터 시작하므로 compose 함수를 사용한 방법이 좀 더 직관적입니다.

// compose를 사용한 방법
var getConvertMoney = compose(getCellMoney, getUSDMoney();
console.log(getConvertMoney(12345.123));

// compose를 사용하지 않은 방법
console.log(getUSDMoney(getConvertMoney(12345.123)));

 

반응형

댓글