함수형 프로그래밍 - Curry

2023.12.09

Table of Contents

함수형 프로그래밍을 처음 접하고 curry라는 개념을 듣고 쉽게 이해하지 못했다. 이 패러다임을 학습하고 이해하기 위해서는 개인적으로 정리가 필요하다고 생각했다. partial application와 curry의 차이점은 따로 다루지 않지만 이해하고 있다면 좋을 내용이 될 것 같다.

Currying?

커링으로 불리는 이 개념은 partial application의 특수한 형태로 여러 개의 매개변수를 가지는 함수를 단일 인자로 호출이 가능한 프로세스로 바꾸는 함수를 말한다. 고민해서 최대한 간단하게 설명해 보려고 했지만 이해가 어렵다. 코드를 보면 그나마 이해가 쉬워진다.
 
// 일반적인 함수 someFunction(a, b, c); // currying을 적용한 함수 someFunction(a)(b)(c);
우선 일반적인 방법과 커링를 적용한 someFunction을 호출하는 방법이다.
HOC를 떠오르게 하는 모습을 가지고 있고 실제로 HOC도 currying을 통해 구현되었기 때문이다.
JavaScript의 함수는 일급으로 함수를 값으로 다룰 수 있다는 특징이 있기에 함수를 반환해 curry를 구현한다.

구현

const curry = (fn, ...args) => args.length >= fn.length ? fn(...args) : (...nextArgs) => curry(fn, ...args, ...nextArgs);
call, apply, bind를 통해 구현하는 다른 방법도 있지만 ES6의 전개 연산자를 사용해 curry 함수를 구현할 수 있다.
인자를 모두 받았다면 함수를 즉시 실행하고 그렇지 않다면 재귀를 활용해 그 이후에 받은 인자들을 병합해서 실행하는 로직을 가지고 있다.
커리 함수 내부의 함수에 접근할 수 있는 것은 JavaScript의 클로저 특징을 활용하기 때문이다. 객체 지향 프로그래밍(OOP)에서는 변수를 은닉하거나 접근을 제한하기 위해 사용되었으나 함수형 프로그래밍에서는 다른 이유로 활용되는 점이 재밌었다.
추가적으로 여러 글을 확인하며 curry는 인자를 하나씩만 고정해야 한다는 점을 특징으로 설명하기도 하지만 위와 같은 방법으로 꼭 하나의 인자가 아니여도 충분히 동작하도록 구현할 수 있다.

어떤 점이 좋을까?

  • partial application이 가능하여 반복되는 인자를 고정할 수 있다
    • curry를 보고 처음 떠올렸던 장점으로 반복되는 인자를 부분 적용해 재사용성을 높일 수 있다.
      const mult = (a, b) => a * b; const mult2 = curry(mult)(2); console.log(mult2(3)); // 6
  • 함수들과의 조합
    • 함수형 프로그래밍의 각 함수들과 go 를 활용하면 가독성과 재사용성을 높일 수 있다.
    • // 기존 const arr = [1, 2, 3, 4, 5, 6] go( arr, arr => filter(n => n % 2), arr => map(n => n * 2), // [2, 6, 10] DoubledArr => reduce(add, DoubledArr) ) // 18 // curry 적용 go( [1, 2, 3, 4, 5, 6], filter(p => p % 2), map(p => p * 2), reduce(add) ) // 18
    • 함수 인자를 미리 받아두고 필요한 시점에 평가가 가능하다. 지연성과 연관되어 성능 최적화가 가능하다.

추가적으로..

  • lodash나 ramda와 같은 라이브러리는 curry 함수를 지원한다.
  • 함수를 작성할 때 인자의 순서에 유의할 필요가 있다. 변동이 많은 인자일수록 뒤에 배치해서 코드를 설계해야 한다.

마치며

함수형 프로그래밍 걸음마 단계이지만 currying을 이해한다면 코드를 작성하는데 도움이 될 것이라고 생각했고 결과적으로 함수형 프로그래밍에 조금은 더 관심을 가질 수 있는 계기를 만들어보고 싶었다.
학습하면서 클로저나 HOC 같은 개념들을 다시 한번 생각해 볼 수 있었고 변수 네이밍 컨벤션을 잘 지킨다면 가독성이나 재사용성을 개선할 수 있을 것 같아서 어느 정도 목표는 달성했다는 생각한다.
 

참조


Prev
WebSocket 활용기 with Next.js, Socket.io
Next
블로그 스크롤 스파이(TOC) 구현기