내 맘대로 정리한 함수형 프로그래밍

Hong Shik Branden Kim
7 min readMay 29, 2021

https://opensource.com/article/17/6/functional-javascript 블로그를 읽으며 제 자신이 이해하기 어려웠던 내용에 살을 붙여 아래와 같이 정리합니다. 제 블로그에 부족한 부분이 있다면 상기 링크를 좀 더 자세히 읽어보세요.

Photo by Roman Synkevych on Unsplash

Summary

Functional Programming은 Pure Function만 사용하는 프로그래밍 기법입니다. 자바스크립트에서 유용하게 사용됩니다.

Pure Function은 side effect가 없고(Side-effect free), input에 해당하는 output이 늘 같고(Referential transparency), 변하지 않는 함수를 의미합니다.

Details

Why functional programming?

함수나 메소드에 의해서 데이터가 변할 수 있다는 가능성은 개발자에게는 예상 못한 에러가 발생할 수 있다는 것을 의미합니다. 이를 방지하기 위해서 고안된 프로그래밍 기법이 함수형 프로그래밍입니다.

데이터가 변경되지 않으려면, Pure Function을 활용해야 합니다. Pure Function은 아래와 같은 특징을 가지고 있습니다.

  • Referential transparency

특정 함수의 전달인자에 따라, 늘 같은 값이 리턴되는 것을 의미합니다. 당연한 말 처럼 들릴 수 있지만, 사실 이런 경우는 많습니다. 특히 함수의 특정 인자가 변할 수 있는 외부의 값에 의존하게 된다면 다른 값이 리턴될 수 있습니다. 이렇게 어떤 값에 의존한 코드, 함수, 프로그램, etc를 stateful 하다고 합니다.

const numbers = [1, 2, 3, 4, 5]
function countNumbers(){
if (numbers.length){
return numbers.length;
}
}
countNumbers() // 5
numbers.push(6)
countNumbers() // 6

“기대한 값”과 다른 결과가 나오게 된다면, 이 다른 결과에 의해서 에러가 날 가능성이 생깁니다. 이를 원천적으로 차단할 수 있는 것이 함수형 프로그래밍의 장점입니다.

  • Side-effect free

함수의 input, output과 관련된 작업 외의 모든 작업은 side effect가 될 수 있습니다. 예를 들어서 매개변수 외의 변수로 작업을 한다거나, 재할당이 가능한 변수를 사용하거나, 시스템 I/O 등이 side effect가 될 수 있습니다.

let heightRequirement = 46;// Impure because it relies on a mutable (reassignable) variable.
function canRide(height) {
return height >= heightRequirement;
}
// Impure because it causes a side-effect by logging to the console.
function multiply(a, b) {
console.log('Arguments: ', a, b);
return a * b;
}

아래와 같은 행위는 모두 함수형 프로그레밍에서 사용해서는 안됩니다.

  • Loops (반복문)
  • Variable declarations with var or let (재선언, 재할당 금지)
  • Void functions (리턴이 없는 함수)
  • Object mutation (for example: o.x = 5;) (객체 할당)
  • Array mutator methods (배열을 변화시키는 메소드)

위 모든 것을 사용하지 않고 어떻게 코딩을 할 수 있느냐? 재귀를 통해서 가능합니다.

function recursiveFactorial(n) {
// Base case -- stop the recursion
if (n === 0) {
return 1; // 0! is defined to be 1.
}
return n * recursiveFactorial(n - 1);
}

혹은 고차함수 (Higher-Order Function)을 사용할 수 있습니다.

const vehicles = [
{ make: 'Honda', model: 'CR-V', type: 'suv', price: 24045 },
{ make: 'Honda', model: 'Accord', type: 'sedan', price: 22455 },
{ make: 'Mazda', model: 'Mazda 6', type: 'sedan', price: 24195 },
{ make: 'Mazda', model: 'CX-9', type: 'suv', price: 31520 },
{ make: 'Toyota', model: '4Runner', type: 'suv', price: 34210 },
{ make: 'Toyota', model: 'Sequoia', type: 'suv', price: 45560 },
{ make: 'Toyota', model: 'Tacoma', type: 'truck', price: 24320 },
{ make: 'Ford', model: 'F-150', type: 'truck', price: 27110 },
{ make: 'Ford', model: 'Fusion', type: 'sedan', price: 22120 },
{ make: 'Ford', model: 'Explorer', type: 'suv', price: 31660 }
];
const averageSUVPrice = vehicles
.filter(v => v.type === 'suv')
.map(v => v.price)
.reduce((sum, price, i, array) => sum + price / array.length, 0);
console.log(averageSUVPrice); // 33399
// vehicles는 변하지 않았습니다.

하지만, 실제 코딩에서 완전한 함수형 프로그래밍을 하는 것은 쉽지 않습니다.

  • console.log
  • element.addEventListener
  • Math.random
  • Date.now
  • $.ajax (where $ == the Ajax library of your choice)

위와 같이 평소에 자주 사용하는 메소드가 실제 함수형 프로그래밍과 배치되는 경우가 꽤 많습니다. 다만 이런 불가피한 경우를 제외하는 함수형 프로그래밍의 의의를 기억하고 이에 맞추어 개발하려는 노력을 기울여야 합니다. (80 : 20)

Reference

https://opensource.com/article/17/6/functional-javascript

https://whatis.techtarget.com/definition/stateless

https://en.wikipedia.org/wiki/Functional_programming

https://en.wikipedia.org/wiki/Object-oriented_programming

https://en.wikipedia.org/wiki/State_(computer_science)

https://www.youtube.com/watch?v=7Zlp9rKHGD4 (밥 삼촌 영상)

https://www.youtube.com/watch?v=0if71HOyVjY&list=LL&index=5 (GOTO 2018, 40분 내에 소개하는 함수형 프로그래밍)

https://stackoverflow.com/questions/37224520/are-functions-in-javascript-tail-call-optimized

--

--

Hong Shik Branden Kim

Software Engineer, who talks tech in human language. / automation, language enthusiast / @codestates