함수형 프로그래밍 언어는 커링이라는 기법을 가지고 있습니다. 논리학자 헤스켈 브룩 커리의 이름에서 유래했고 여러개의 인자를 받는 함수를 나머지 인자를 받는 함수로 변환하는 메커니즘입니다. (위키피디아) 쉽게 말해 두 개의 인자를 받는 함수를 하나의 인자를 받는 함수로 변환하는 기법이라고 설명 드릴 수 있습니다.
커링을 이해 하기 위해서 스칼라 코드를 보겠습니다.
// 선언 def mulOneAtATime(x: Int) = (y: Int) => x * y // 실행 mulOneAtATime(6)(7) // 42
대충 감이 오시죠? 그러면 Javascript는 커링을 어떻게 표현할까요?
다음은 Javascript에서 커링을 표현하는 가장 잘 알려진 방법입니다.
// 선언 function mulOneAtATime(x) { return function(y) { return x * y; }; } // 실행 mulOneAtATime(6)(7); // 42
제대로 동작하는 것 같지만 커링과 거리가 멉니다.
위에서 커링은 인자 두 개를 받는 함수를 인자 하나를 받는 함수로 바꾸는 메커니즘이라고 말씀드렸습니다. 하지만 위 코드는 애초부터 1개의 전달인자를 요구 합니다. 2개의 전달인자를 전달하여 사용할 수 없습니다.
이 문제를 해결하기 위해 헬퍼 함수를 작성하여 커링을 표현합니다.
// 헬퍼 함수. var curry = function(fn /*, ... */){ var curryArgs = Array.prototype.slice.call( arguments, 1 ); return function( /* ... */ ) { var newArgs = Array.prototype.slice.call( arguments, 0 ), mergedArgs = curryArgs.concat( newArgs ); return fn.apply( this, mergedArgs ); } }; // 선언 function mul(x, y) { return x * y; } // 실행 mul(6, 7); // 42 curry(mul, 6)(7); // 42
별도의 헬퍼 함수를 구현하여 억지로 커링을 흉내내고 있습니다. 복잡해 보이고 세련되지 못하네요.
대부분 Function.prototype.bind 메소드는 context를 bind 하는 용도로 사용합니다만 이를 이용해 커링을 거의 완벽하게 표현할 수 있습니다.
// 선언 function mul(x, y) { return x * y; } var mulOneAtATime = mul.bind(null, 6); // 실행 mul(6, 7); // 42 mul.bind(null, 6)(7); // 42 mulOneAtATime(7); // 42
따로 헬퍼 함수를 작성할 필요도 없을 뿐더러 코드도 읽기 쉬워졌습니다.
그럼 커링을 실무에서 어떻게 쓸 수 있을까요? 음… 이렇게 써볼 수 있지 않을까요?
// 선언 function template(name, money){ return '<h1>'+ name +'</h1><span>'+ money +' </span>'; } var tmplGildong = template.bind(null, '홍길동'); var tmplCheolsu = template.bind(null, '김철수'); // 실행 template('김병수', 30); // <h1>김병수</h1><span>30원</span> tmplGildong(10); // <h1>홍길동</h1><span>10원</span> tmplGildong(100); // <h1>홍길동</h1><span>100원</span> tmplGildong(130); // <h1>홍길동</h1><span>130원</span> tmplCheolsu(500); // <h1>김철수</h1><span>500원</span> tmplCheolsu(1000); // <h1>김철수</h1><span>1000원</span>
이 외에도 메소드 오버로딩이 안되는 Javascript에서 커링으로 우아한 코드를 생산할 수 있을 것 같습니다. 그렇지만 가독성이나 흐름을 크게 해칠 우려가 있기 때문에 조심히 다뤄야 합니다.
여기까지 Function.prototype.bind 메소드를 사용해서 커링을 표현해봤습니다.
참고 자료 :
1개의 댓글
CHoi · 2020년 2월 21일 6:02 오후
부럽습니다. 저도 취미생활있으면서 코딩도잘하고싶네요.