함수형 프로그래밍이란 프로그래밍 패러다임 중 하나로써, 함수의 조합으로 작업을 수행하는 걸 의미합니다. 부수효과를 멀리하고 조합성을 강조하는 프로그래밍 패러다임인데요. 부수 효과를 멀리하는 이유는 두 가지를 위해서 입니다.
자바스크립트로 함수형 프로그래밍이 가능한 이유는 함수는 일급 객체이고 클로저가 지원되기 때문입니다.
함수 프로그래밍의 예로 _reduce 함수를 만들어 보겠습니다.
EX
function sum(arr) {
const len = arr.length;
let sum = 0;
for (let i = 0; i < len; i++) {
sum += arr[i];
}
return sum;
}
const arr = [1, 2, 3, 4];
console.log(sum(arr)); // 10
위의 코드는 배열을 넣어 각 원소의 합을 구하는 함수입니다.
물론 ES6 문법에 있는 reduce함수를 사용하면 되긴 합니다만 함수형 프로그래밍의 예제를 위해 for 문법으로 구현했습니다.
이번엔 모두 곱하는 함수를 만들어 보고, 더하거나 곱하는 방식을 합친 _reduce 함수를 만들어 봅시다.
EX
function multiply(arr) {
const len = arr.length;
let sum = 0;
for (let i = 0; i < len; i++) {
sum *= arr[i];
}
return sum;
}
const arr = [1, 2, 3, 4];
console.log(sum(arr)); // 24
모두 곱하는 함수는 더하는 sum 함수와 multiply의 차이점은 연산자가 '+'냐, '*'냐 뿐입니다.
reduce
const sum = (x, y) => x + y;
const multi = (x, y) => x * y;
function _reduce(func, arr, initial) {
const len = arr.length;
let sum = initial;
for (let i = 0; i < len; i++) {
sum = func(sum, arr[i]);
}
return sum;
}
const arr = [1, 2, 3, 4];
console.log(_reduce(multi, arr, 1)); // 24
console.log(_reduce(sum, arr, 0)); // 10
더하는 함수 sum을 만들고, 곱하는 함수 multi를 만들어 봤습니다. 그리고 함수를 인자로 받아 연산하는 함수를 만들었습니다. 그 결과 이전보다 코드가 줄어들었고, 모듈화도 이룰 수 있었습니다. 만약 여기서 빼기 연산을 하고 싶다면 miuns라는 함수를 새로 만들면 됩니다.
함수형 프로그래밍의 대표적인 예로는 '커링'이 있습니다. 고차 함수라고도 말합니다.
ES6 문법을 활용해 함수형 프로그래밍을 구현해 보겠습니다.
const dogs = [
{
name : 'max',
weight : 10,
location : 'seoul',
color : 'black',
},
{
name : 'big',
weight : 90,
location : 'seoul',
color : 'black',
},
{
name : 'shy',
weight : 40,
location : 'busan',
color : 'brown',
},
]
다음과 같은 dogs 배열이 있다고 생각해 봅시다.
원하는 조건에 맞춘 강아지 이름을 반환해 보도록 하겠습니다.
color가 brown인 강아지 이름을 반환하는 함수입니다.
function getDogs(dogs, filter) {
const [key, value] = filter;
return dogs.filter((dog) => dog[key] === value).map((dog) => dog["name"]);
}
const dogName = getDogs(dogs, ["color", "brown"]);
console.log(dogName); // ["shy"]
이 함수의 훌륭하지만, 필터 조건이 다양하지 않다는 점이 아쉽습니다. color가 brown인 강아지만 찾을 수 있게 설계가 되어있기 때문입니다. 다양한 조건을 인자로 넣어 보도록 합시다.
const weightCheck = weight => dog => dog['weight'] < weight
function getDogs(dogs, filterFunc) {
return dogs.filter(filterFunc).map((dog) => dog["name"]);
}
const dogName = getDogs(dogs, weightCheck(50));
console.log(dogName); // ["max", "shy"]
weightCheck 함수를 커링을 사용해 만들어 봤습니다. 이 함수는 무게의 수치를 받아 무게보다 낮은 강아지를 필터합니다.
이번엔 무게말고 이름, 지역, 색상 등으로 이름을 찾기 위한 커링 함수를 만들어 보도록 합시다.
const check = (field) => (value) => (dog) => dog[field] === value;
function getDogs(dogs, filterFunc) {
return dogs.filter(filterFunc).map((dog) => dog["name"]);
}
const colorCheck = check("color");
const locationCheck = check("location");
const dogNameByColor = getDogs(dogs, colorCheck("black"));
const dogNameByLocation = getDogs(dogs, locationCheck("busan"));
console.log(dogNameByColor); // ["max", "big"]
console.log(dogNameByLocation); // ["shy"]
위의 예제들처럼, 매개변수를 달리하면 다양한 함수형 프로그래밍을 구현할 수 있습니다.
이상 함수형 프로그래밍에 대해 알아봤습니다!
함수가 값으로써 사용된다는 일급 객체의 특성을 십분 활용해 매개변수로 로직을 구현하는 예들은 실제 프로젝트에서도 유용하게 사용할 수 있을 것 같습니다!
출처
- 자바스크립트 코딩의 기술
- 인사이트 자바스크립트