본문 바로가기

JavaScript

[JavaScript] 함수형 프로그래밍 - 개요

들어가며 

함수형 프로그래밍에 대해서는 많이 알고있다. 

일급 함수, 불변성, 순수 함수 ... 등등

 

하지만 막상 이것들을 사용하려고 하니 과연 실제로 적용은 어떻게 해야할까?

아니 내가 제대로 이해하고 적용할 수 있는가? 

적용이 가능한가? 라는 생각들이 들었다. 

 

결국 내가 함수형 프로그래밍을 정확하게 이해를 한 것이 맞는가? 에 대한 의문으로 

이어졌다. 

 

이론은 아는데 그것을 사용하지 못한다면 정말 공부한 것이 맞을까? 

 

마침 인프런에 자바스크립트로 알아보는 함수형 프로그래밍이라는 무료 강의가 있어 이번에 공부해보려고 한다.

 

함수형 프로그래밍 정의 

함수형 프로그래밍은 부수적인 효과를 배제하고, 조합성을 강조하는 프로그래밍이다. 

 

부수 효과를 배제한다 => 순수 함수를 만든다. 

조합성을 강조한다.  => 모듈화 수준을 높인다. 

 

즉, 

순수함수를 만듬으로써 오류를 줄이고 안정성을 높이고

모듈화 수준을 높여생산성을 높이는 프로그래밍 패러다임이다. 

순수 함수 ? 

부수효과가 없는 함수

들어온 인자가 같으면 항상 동일한 결과를 리턴한다. 

함수가 받은 인자 외 다른 외부에 영향을 끼치지 않는 함수를 말한다.

또한 리턴값 외에는 외부와 소통이 없다. 

function pureFunc (number1, number2) {
    return number1 + number2
}

pureFunc(10, 20) // result = 30
pureFunc(10, 20) // result = 30
pureFunc(10, 20) // result = 30

pureFunc은 number1과 number2에 동일한 값을 넣으면 항상 동일한 결과를 리턴하는 순수 함수이다.

 

let number2 = 10;
function notPureFunc (number1) {
    return number1 + number2
}

notPureFunc(10) // result = 20

number2 = 30
notPureFunc(10) // result = 40

number2 = 50
notPureFunc(10) // result = 60

notPureFunc은 number2가 외부에 있어 다른 작업으로 number2의 값이 바뀌면

같은 number1의 값이라도 결과가 달라진다. 

 

const NUMBER2 = 10;

이때, 외부에 값이 있더라도 그 값이 변경되지 않는 상수라면 순수 함수가 된다. 

 

 

let number3 = 10;
function notPureFunc2 (number1) {
    number3 = 30;
    
    return number1 + 10;
}

console.log(number3) // 10

notPureFunc2(10) // result = 20
notPureFunc2(10) // result = 20
notPureFunc2(10) // result = 20

console.log(number3) // 30

notPureFunc2의 경우에도 number1의 값에 따라 결과는 항상 같지만, number3이라는

외부 값을 변경하는 부수 효과가 있으므로 순수 함수가 아니다. 

 

const obj = { val: 10 };

function notPureFunc3 (obj, number) {
    obj.val += number
}

console.log(obj);  // { val: 10 }
notPureFunc3(obj, 10); 
console.log(obj);  // { val: 20 }

notPureFunc3는 리턴이 없으며, 객체 obj를 직접 변경하는 함수이므로 순수 함수가 아니다. 

 

그렇다면 순수 함수는 객체를 변경할 수 없을까? 

const obj = { val: 10 };

function pureFunc2 (obj, number) {
    return { val: obj.val + number }
}

console.log(obj);  // { val: 10 }
pureFunc2(obj, 10);// { val: 20 }
console.log(obj);  // { val: 10 }

pureFunc2는 전달받은 obj의 값을 직접 변경하고 있지 않고 참조만 하고있다. 

그리고 외부 상태를 변경하고 있지 않고 리턴으로 새로운 객체를 만들어서 원하는 상태를 변경한다. 

 

즉, 원본 객체는 그대로 두고 복사본을 만들어서 새로운 객체를 만드는 방식으로 변경한다. 

 

notPureFunc과 notPureFunc2, notPureFunc3의 방식이 문제라는 것은 아니다. 

단, 세 함수는 순수 함수가 아니라는 것이다. 

 

함수 만들어보기 - add_maker

함수형 프로그래밍을 배울 때 많이 나오는 예제인 add_maker라는 함수를 만들면서 

함수형 프로그래밍을 이해해보자

 

function add_maker(a) {
    return function(b) {
        return a + b
    }
}

add_maker 함수란 함수는 함수를 리턴하는 함수이다. 

그리고 그 함수 안에서 a와 b를 더해주는 함수이다. 여기서 일급 함수의 개념을 사용한다. 

일급 함수 ? 

함수를 변수에 담을 수 있다. 

또는 함수를 인자로 넘길 수 있다. 그리고 함수를 리턴하는 함수를 말한다. 

const f1 = function(a) { return a * a };

f1 변수는 함수를 가지고 있는 변수이다. 

 

function f2(f) {
    return f();
}

f2(function() { return 10 })

f2 함수는 전달받은 함수를 실행해서 리턴하는 함수이다. 

즉, 리턴 10을 하는 함수를 전달받으면 f2 함수는 결과적으로 10을 리턴하는 함수가 된다. 

 

다시 add_maker 함수로 돌아가면 

const add10 = add_maker(10);

console.log(add10(20));  // 30

 add10 변수는 add_maker의 a 인자로 10을 넘겨주고 함수를 리턴 받았다. 

그리고 console.log에서 20을 b 인자로 넘겨줘서 결국 10 + 20, 30을 리턴 받았다.

 

정리하면 add_maker라는 함수는 일급 함수라는 개념과 클로져라는 개념이 함께 사용된 

함수이다. 

 

일급 함수에 대해서는 위에 이야기 했는데, 클로저는 무엇인가? 

클로저 ? 

함수의 호출할 때 넘겨준 인자가 호출이 끝난 시점에서도 인자에 접근할 수 있는 것을 말한다. 

function add_maker(a) {
    return function(b) {
        return a + b
    }
}

add_maker를 처음 호출할 때 add_maker(10) 과 같은 방식으로 a에 인자로 10을 넘겨줬고 

함수의 호출이 끝난다. 

 

하지만 뒤에 console.log에서 add10(20)으로 호출할 때도 함수에서는 a의 값에 접근해서

10 + 20을 실행한 결과인 30이라는 값을 얻었다. 

add_maker 총정리 

function add_maker(a) {
    return function(b) {
        return a + b
    }
}

add_maker라는 함수는 일급 함수, 클로저, 순수 함수의 개념이 모두 들어간 

함수형 프로그래밍의 집합체(?!) 라고 할 수 있다. 

 

함수가 함수를 리턴할 수 있다일급 함수의 개념과 

호출이 끝난 시점에도 a의 값에 접근해서 a + b의 결과를 리턴할 수 있다클로저

언제든 add10(20)을 실행해도 같은 결과인 30과 add10이란 함수는 외부에 영향을 미치지 않는다

점에서 순수 함수의 개념을 모두 가지고 있다. 

반응형