이미지09
Coding Story/REACT

[ React ] 리액트 함수형 프로그래밍

반응형

 

 

 

함수형 프로그래밍이란 함수를 함수로 넘기거나 함수가 함수를 결과로 내놓는 것이 가능한 프로그래밍을 뜻한다.

이는 함수가 다른 함수를 조작하고, 함수가 함수를 인자로 받거나 반환하는 것이 가능한 고차 함수 개념을 사용한다.

정수나 문자열 같은 일반적인 값을 1급 시민이라 하는데

 

JAVASCRIPT 는 함수를 1급 시민과 같이 취급하기 때문에 함수형 프로그래밍을 지원한다.

무슨말인가 하니 함수를 변수, 객체, 배열에 넣을 수 있고 이 함수를 다른 함수에 인자로 넘길 수 있고 반환 또한 가능하다.

함수형 프로그래밍의 다양한 예제를 보며 이해해보자.

보통 JAVASCRIPT 에서는 아래처럼 함수를 변수에 담아 사용할 수 있다.

var logMessage = function(message) {
    console.log(message);
}
logMessage("로그 찍기");
//result - 로그 찍기

 

 

ES6 에서는 화살표 함수를 사용해 아래와 같이 선언이 가능하다.

const logMessage = message => console.log(message)
logMessage("로그 찍기");
//result - 로그 찍기

 

 

또한 앞서 말했듯 객체에 함수를 넣어 아래처럼 사용할 수도 있고,

const obj = {
    message : "로그 찍기",
    logMessage(message) {
        console.log(message);
    }
}
obj.logMessage(obg.message);
//result - 로그 찍기

 

 

배열에 함수를 넣어 사용할 수도 있다.

const messages = [
    "첫 번째 로그 찍기", //messages[0]
    "두 번째 로그 찍기", //messages[1]
    logMessage => console.log(message) //messages[2]
]
messages[2](messages[0]); //result - 첫 번째 로그 찍기
messages[2](messages[1]); //result - 두 번째 로그 찍기

 

 

그리고 함수를 다른 함수에 인자로 넘길수 있고,

function numberPlusTen(val, fn) {
    return fn(10, val);
}
function numberSum(val1, val2) {
    return val1 + val2;
}
numberPlusTen(20, numberSum); //result - 30

 

 

함수가 함수를 return 할 수도 있다.

function logMessage(val) {
    return function() {
        return ( val + "로그 입니다" );
    }
}
logMessage("첫 번째"); //result - 첫 번째 로그 입니다.

 

 

이 때, 마지막 두 가지 예제 ( 함수를 다른 함수에 인자로 넘김, 함수가 함수를 return ) 함수를 고차 함수라고 부르는 것이다.

 

다음으로, 함수형 프로그래밍의 핵심 개념에 대해 알아보자.

함수형 프로그래밍의 핵심 개념으로는 불변성, 고차 함수, 재귀 함수, 순수 함수 등이 있는데 순서대로 살펴보자.

먼저 불변성(immutable)​ 은 말 그대로 데이터의 불변성을 뜻한다.

예를 들어, 우리의 출생 정보가 담겨 있는 출생증명서가 있고 이를 공개하고 싶다고 가정하자.

하지만 개인 정보 중 민감한 주소같은 경우 숨기거나 알아볼 수 없게 만들어 보여주고 싶은데

 

현실적으로 선택 가능한 방법은 두 가지다.

첫 번째 방법은 원본 출생증명서에서 주소 부분을 펜으로 마킹해 가리는 것이고,

두 번째 방법은 원본 출생증명서를 복사해 복사본의 출생증명서에 주소를 펜으로 마킹해 가리는 방법이다.

첫 번째 방법은 데이터의 불변성에 위배되고

 

두 번째 방법은 데이터의 불변성을 지킴과 동시에 개인 정보를 보호하며 출생증명서를 공개할 수 있다.

이것이 바로 불변성 데이터가 함수에서 작동하는 원리이다. 원본 데이터의 복사본을 만들고 그 중 일부를 사용하는 셈이다.

아래의 예를 보며 불변성에 대한 이해를 마치자.

//색의 이름이 들어있는 배열
let colorArray = [
    { color : "red" },
    { color : "blue" },
    { color : "black" }
]

const addColor = (color, array) => array.concat({color})
console.log(addColor("yellow", colorArray).length); // result - 4 ( red, blue, black, yellow 4 개 색상 )
console.log(colorArray.length); // result - 3 ( red, blue, black 3 개 색상 )

 

 

위 예제에서 Array 에 push 가 아닌 concat 을 이용해 새로운 색상을 추가했는데

이유가 push 함수는 원본 데이터에 새로운 값을 추가해 불변성에 위배 되기 때문.

concat 함수는 원본 데이터 배열을 복사한 후 원소를 추가하고

 

이를 조합해 새로운 배열을 return 해주기에 concat 을 사용한 것이다.

 

다음으로 고차 함수는 위에서 부분부분 설명했으니 넘어가고 재귀 함수에 대해 간략히 설명하면

재귀 함수자기 자신을 호출하는 함수를 만드는 기법인데, 재귀 함수는 워낙 인터넷에 설명글이 잘 되어있기도 하고

예제만 간단히 훑어봐도 이해가 될 것이므로 추가적인 설명은 스킵하겠다.

// 1부터 10까지 증가하는 재귀 함수
const countAdd = (value, fn) => {
    fn(value);
    return (value < 10) ? countAdd(value+1, fn) : value; // countAdd 함수가 countAdd 함수를 호출
}
countAdd(0, value => console.log(value));

 

 

마지막으로 순수 함수에 대해 살펴보자.

순수 함수parameter 에 의해서만 반환 값이 결정되어지는 함수를 뜻한다.

그렇기에 순수 함수는 반드시 하나 이상의 인자를 받아야 하며, 인자가 같으면 항상 같은 값이나 함수를 반환한다.

또한 순수 함수는 부수 효과 ( 외부의 상태를 변경하는 것 ) 가 없어야만 한다.

먼저 순수 함수의 간단한 예제인 함수 하나를 살펴보자.

function countAdd(val1, val2) {
    return val1 + val2;
}
console.log(countAdd(5, 10)); // result - 15
console.log(countAdd(5, 10)); // result - 15
console.log(countAdd(5, 10)); // result - 15
console.log(countAdd(10, 20)); // result - 30

 

 

위의 countAdd 함수는 순수 함수이다. 똑같은 인자 5 와 10 을 여러번 넘겨주면 항상 같은 값을 반환하며,

그 외의 어떤 값을 인자로 넘겨주더라도 외부 상태로부터의 제약이 없고 외부 상태를 변경하지도 않는

 

일정한 return 이 이루어지기 때문.

그럼 반대로 순수하지 않은 함수를 살펴보자.

var number = 1;
function countAdd2(val1, val2) {
    return val1 + val2 + number;
}
console.log(countAdd2(5, 10)); // result - 16
number = 10;
console.log(countAdd2(5, 10)); // result - 25

 

 

위의 countAdd2 함수는 순수하지 않은 함수이다.

외부 상태인 number 변수 값이 변하면 이를 참조하고 있는 함수 내의 결과값에 영향이 가기 때문이다.

그런데 만약 number 변수가 var 가 아닌 변하지 않는 const 형태의 변수라면 countAdd2 함수는 순수 함수가 된다.

외부 상태를 참조하더라도 동일한 상태를 참조하면 인자가 같은 값을 가져 일정한 return 이 이루어지기 때문이다.

이번엔 다른 순수하지 않은 함수를 하나 살펴보자.

var number = 1;
function countAdd3(val1, val2) {
    number = val1 + val2;
    return val1 + val2 + number;
}
console.log(countAdd3(5, 10));

 

 

위의 countAdd3 함수 또한 순수 함수가 아니다.

함수 내에서 외부 상태인 number 변수의 값을 변경해 부수 효과가 발생했기 때문이다.

이렇게 함수형 프로그래밍에 대해 알아보았다. 여기서 확실하게 짚고 넘어갈 부분이 있는데,

함수형 프로그래밍은 모듈화 수준이 높으면

 

재사용성이 높은 좋은 프로그래밍이라는 패러다임에 초점이 맞춰져 있을 뿐이다.

분명 함수형 프로그래밍에도 단점이 존재할 뿐더러,

위의 마지막 countAdd2, countAdd3 함수의 예제가 꼭 나쁜 프로그래밍인건 아니라는 걸 알아두고 넘어가자.

 

 

 

반응형