본문 바로가기
Web/javascript

javascript로 보는 함수형 프로그래밍

by EricJeong 2020. 6. 27.

함수형 프로그래밍의 콘셉트

  1. 모든 객체, 상태, 값은 불변(Immutable)이어야 한다
  2. 함수를 값처럼 사용한다. 변수에 함수를 저장하거나 리턴 값으로 함수를 반환할 수 있다.

사전 개념 정리

순수 함수 (pure function)

함수를 실행시켰을 때 부작용(side-effect)이 없는 상태를 말합니다. 함수를 실행시켜도 외부의 상태, 값에는 전혀 영향을 끼치지 않아야 합니다. 순수하게 함수 내부에서만 모든 작업이 이루어지기 때문에 함수가 어떤 역할을 하는지 파악하기도 쉽고, 다른 사이드 이펙트를 걱정할 필요도 없습니다.

사이드 이펙트가 없다면? => 스레드 안전하므로 병렬 처리를 안전하게 할 수 있습니다.

var number = 10;

// 외부 상태를 변경시키지 않는 순수함수
function pureFunction(a, b) {
    return a + b;
}

// 외부 상태(number)를 변경시키니 순수함수가 아니다
function notPureFunction(a, b) {
    number = a + b;
    return number;
}

순수 함수인 pureFunction은 외부 상태에 전혀 영향을 주지 않습니다. 하지만 순수 함수가 아닌 notPureFunction은 외부 number값을 변경시킵니다.

 

익명 함수 (anonymous function)

이름이 없는 함수를 생성합니다. 해당 함수는 호출할 수 있는 이름이 정해지지 않았기 때문에 1회성으로 사용하거나, 변수에 저장한 후 사용합니다.

 

예를 들어, 두 매개변수를 입력받아 더한 후 반환하는 sum 함수는 아래와 같이 만들 수 있습니다.

var sum = function(a, b) {return a + b;}

 

위 함수에 람다식을 적용하면 더욱 간결하게 만들 수 있습니다.

var sum = (a, b) => a + b;

 

1급 객체, 1급 함수

1급 객체란, type 안에 저장할 수 있고 이를 매개변수나 리턴 값으로 주고받을 수 있는 객체를 뜻합니다. javascript에서 사용하는 모든 값과 함수는 변수에 저장할 수 있으므로 1급 객체에 해당합니다. 조금 더 상세한 조건은 아래와 같습니다.

  • 변수에 담을 수 있다.
  • 파라미터로 전달할 수 있다.
  • 리턴 값으로 사용할 수 있다.

javascript에서는 함수를 변수에 저장할 수 있습니다, 그러므로 이를 javascript에서는 이를 1급 함수라고 부릅니다. 그리고 이러한 함수를 매개변수로 전달받거나, 리턴 값을 함수로 반환할 경우 이를 고차 함수(high order function)이라고 부릅니다.

 

 

불변성 (Immutable)

함수형 프로그래밍은 모든 상태는 변하지 않는다는 가정을 하고 있습니다. 하지만  javascript에서는 변수에 값을 할당한 후, 이를 다른 값으로 변경시킬 수 있습니다. 그러므로 개발자가 이 불변성을 지키기 위하여 유의하며 코드를 작성해야 합니다. let이나 const변수를 할당하는 것은 불변성을 지키는데 도움을 주지만, 불변성을 보장해주지는 않습니다. 객체나 배열에 let, const를 사용해도 그 내부 상태의 변경까지 막아주지는 못하기 때문입니다.

const person = {name:"eric", phone: "010-1234-1234"}
console.log(person); // {name: "eric", phone: "010-1234-1234"}

person.phone = "010-9999-9999";
console.log(person); // {name: "eric", phone: "010-9999-9999"}

 

js에서 제공하는 object.freeze를 사용하면 이러한 불변성을 지키는데 도움을 받을 수 있습니다.

 

예제

var customPlus = function(func1, func2) {
    return function(a, b) {
        return func1(a, b) + func2(a, b);
    }
}

var plus = (a, b) => a + b;
var minus = (a, b) => a - b;

var plusAndPlus = customPlus(plus, plus);
var plusAndMinus = customPlus(plus, minus);

console.log(plusAndPlus(1, 2)); // (1 + 2) + (1 + 2)
console.log(plusAndMinus(1, 2)); // (1 + 2) + (1 - 2)

함수 두 개를 받아서 두 함수를 더한 결과값을 반환하는 customPlus함수를 만들었습니다. 매개변수로 입력받는 것은 일급 함수인 func1, func2입니다. 리턴 값으로는 새로 만들어진 익명 함수를 반환합니다.

 

customPlus는 실제 매개변수로 일급 함수가 들어오기 전까지는 어떤 행위를 할지, 어떤 결과값을 반환할지 정확하게 알 수 없습니다. 이 함수를 사용하는 곳에서 입력한 매개변수(일차함수)에 따라서 그 동작이 달라지기 때문입니다. plusAndPlus와 plusAndMinus는 같은 customPlus함수를 사용하고 있지만, 서로 다른 동작을 하고 있습니다.

 

함수형 프로그래밍을 만족하는 대표 함수들

흔히 사용하는 filter과 같은 함수가 바로 이런 함수형 프로그래밍 패러다임을 따른 함수들입니다. 일급 함수를 매개변수로 받거나, 일급함수를 반환하는 몇몇 함수에 대해 알아보겠습니다. 아래 filter, map 함수는 원본을 변경하거나 외부 상태를 변경시키는 사이드 이펙트가 없고, 함수를 매개변수로 받거나 함수를 반환하는 함수형 프로그래밍 법칙을 만족하는 대표적인 함수입니다.

 

filter

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var biggerThenFive = arr.filter(number => number > 5);
console.log(biggerThenFive); // Array(5) [6, 7, 8, 9, 10]

배열이나 객체에서 원하는 값들을 필터링할 때 흔히 filter함수를 사용합니다. filter함수는 원본 arr에 전혀 영향을 끼치지 않으면서 새로운 값을 생성하여 필터에 적합한 값을 반환합니다. 

 

map

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var mappedArr = arr.map(number => number * 100);
console.log(mappedArr); // Array(10) [100, 200, 300, 400, 500, 600, 700, 800, …]

 

함수형 프로그래밍의 장점

장점

  • 사이드 이펙트가 없다
  • 스레드 안전하다
  • 코드의 재사용성이 높아진다.
  • 함수는 입력과 출력만 신경 쓰면 되므로, 테스트가 쉬워진다

댓글