함수형 프로그래밍에 대해 이해하기 위해서 다음과 같은 개념을 알아야 한다.
- 불변성
- 순수 함수
- 참조 투명성
- 1급 객체
- 1급 함수
불변성
불변성이란 값이나 상태를 변경할 수 없는 것을 의미한다.
한 번 생성된 데이터의 값이나 상태를 변경하지 않고 새로운 값을 할당하는 것을 의미한다.
자바스크립트를 기준으로 불변성에 대해 자세히 알아보자.
구체적으로는 ”메모리 힙 영역의 값이 변하지 않는다”라고 해석할 수 있다.
원시 타입과 참조 타입을 기준으로 불변성에 대해 알아보자.
자바스크립트 기준으로 원시 타입은 다음 종류들이 있다.
- Boolean,
- String
- Number
- Null
- undefined
- Symbol
자바스크립트 기준으로 참조 타입은 다음 종류들이 있다.
- Object
- Array
- Function
- Date
- Map
- Set
원시 타입은 call stack에 바로 할당된다.
원시 타입인 Number에 해당하는 값을 변수에 할당하고 새로운 값으로 재할당 할 때 메모리에 새로운 값을 할당하게 된다.
변수 a의 값이 바뀌었기 때문에 불변성이 보장되지 않는다고 할 수 없다.
Number 타입은 원시 타입으로 메모리 힙에 값을 할당하지 않고 콜 스택에 할당한다.
그래서 항상 새로운 메모리가 할당되고 메모리 힙의 값이 변경될 일이 없기 때문에 불변성을 가진다고 할 수 있다.
그렇다면 Mutable 타입인 객체 내부 값을 변경할 때를 확인하자.
새로운 메모리가 할당되지 않았고 메모리 힙 영역의 값이 변경되었다.
이 경우를 불변성이 지켜지지 않았다고 하는 것이다.
위와 같은 경우에서 불변성을 지키려면 새로운 메모리를 할당하고 메모리 힙 영역의 값을 변경하지 않으면 된다.
객체의 경우 새로운 객체를 만들면 된다
이제 새로운 메모리가 할당되었고 메모리 힙 영역의 값이 변경되지 않았기 때문에 불변성을 지킨 것이 된다.
그래서 객체의 값을 변경할 때는 전개 연산자를 사용해서 새로운 객체를 만들면 불변성을 유지할 수 있다.
let obj = {
a: 1,
b: 1
}
obj = {...obj, b:1}
순수 함수
순수 함수는 외부의 상태를 변경하지 않는 함수를 의미한다.
외부 상태를 변경하지 않기 때문에 부수 효과(side effect)가 발생하지 않는다.
부수 효과라는 것은 함수의 원래 목적과 다른 예상치 못 한 부작용이다.
부수 효과가 발생할 수 있는 함수를 예시로 들어보자.
- 인자의 값을 직접 변경한다. => 변경된 인자의 값이 다른 함수에 영향을 미친다.
- 입력 값을 받는다. => 입력에 따라 출력이 달라진다.
부수효과가 없는 순수 함수는 다음과 같은 장점이 있다.
- 입력이 동일하다면 출력이 동일하기 때문에 함수의 동작을 예측하기가 쉽다.
- 단위 테스트 코드 작성에 용이하다.
- thread에 안전하기 때문에 별도의 동기화 없이 병렬 처리를 할 수 있다.
1급 함수
1급 함수란 1급 객체 특성을 가지고 있는 함수이다.
1급 함수는 다음과 같은 특성을 가지고 있다.
1. 변수에 함수 할당
const foo = () => {
console.log("foobar");
};
foo(); // 변수를 사용해 호출
// foobar
2. 함수에 인자로 전달
function sayHello() {
return "Hello, ";
}
function greeting(helloMessage, name) {
console.log(helloMessage() + name);
}
// `sayHello`를 전달인자로 `greeting` 함수에 전달
greeting(sayHello, "JavaScript!");
// Hello, JavaScript!
3. 함수 반환
function sayHello() {
return () => {
console.log("Hello!");
};
}
1급 함수는 일반 변수와 비슷하게 다루어지는 것을 확인할 수 있다.
참조 투명성
동일한 입력 값에 대해 항상 동일한 출력 값을 보장하는 특성.
이 특성을 유지하기 위해서는 외부 변수에 의존해서는 안 된다.
다음 코드는 참조 투명성을 지키지 못 했다고 할 수 있다.
const a = 1;
function add(b, c){
return a + b + c;
}
외부 변수 a 값이 변하면 입력 값이 같아도 출력 값이 달라질 수 있기 때문이다.
위 코드를 참조 투명성을 지키도록 바꾸면 아래와 같다.
function add(a, b, c){
return a + b + c;
}
그렇다면 불변성과 참조 투명성을 지키는 코드를 작성해보자.
만들 함수는 obj.b의 value를 변경하는 함수이다.
function change(prev, value){
return {...prev, b: value};
}
let obj = {
a: 1,
b: 1
}
obj = change(obj, 3);
change 함수는 외부 변수를 참조하지 않고 불변성을 지키고 있으며 참조 투명성도 지키고 있다.
이러한 함수를 순수 함수라고 한다.
이러한 순수 함수는 외부에 영향을 받지 않고 side-effect가 없기 때문에 Thread 안정성을 보장받는다.
출처
https://developer.mozilla.org/ko/docs/Glossary/First-class_Function
https://maxkim-j.github.io/posts/js-pure-function/
https://www.youtube.com/watch?v=LRlooA5sYhU&t=221s
댓글