함수형 프로그래밍이란?
정의
데이터를 함수로 연결하고 계산하는 것을 중시하는 프로그래밍 패러다임
특징
1. 순수함수
- 동일한 입력에는 항상 동일한 값을 반환해야 한다.
- 함수 내부에서 전달받은 인자의 값을 변경하거나,
외부의 값을 변경하는 Side Effect가 없어야 한다.
// 비순수함수
let num = 10;
function multiply(a) {
return a * num;
}
전역 변수인 num의 값이 바뀌면 리턴값이 달라지므로, 순수함수라고 할 수 없다.
// 순수함수
function multiply(a, b) {
return a * b;
}
함수의 실행이 외부의 값에 영향을 미치지 않고,
동일한 입력에 대하여 동일한 리턴값을 가지므로 순수함수라고 할 수 있다.
2. 불변성
- 데이터는 변하지 않는 불변성을 유지해야 한다.
- 데이터의 변경이 필요한 경우, 원본 데이터의 복사본을 만들어 사용한다.
// Bad
const user = { name: "gihong", level: 1 };
function increaseLevel(user) {
user.level += 1;
return user;
}
user 객체의 속성이 변경되었다. 불변성을 지키지 못한 사례다.
// Good
const user = { name: "gihong", level: 1 };
function increaseLevel(user) {
return { ...user, level: user.level + 1 };
}
원본 데이터의 복사본을 만들어 사용한다. 불변성을 만족하였다.
3. 일급 객체
함수는 일급 객체이어야 한다. 이는 다음과 같은 의미다.
- 함수를 변수 또는 객체와 같은 자료구조에 저장할 수 있다.
- 함수의 매개변수에 전달할 수 있다. (고차함수)
- 함수의 리턴값으로 사용할 수 있다. (고차함수)
// 일급 객체로서의 함수
const add = (num) => num + 2;
const multiply = (num) => num * 2;
const transform = (numbers) => numbers.map(add).map(multiply);
console.log(transform([0, 1, 2, 3])); // [4, 6, 8, 10]
4. 선언형 프로그래밍
명령형 프로그래밍은 무엇을 어떻게 할 것인가에 주목하고,
선언형 프로그래밍은 무엇을 할 것인가에 주목한다.
// 명령형 프로그래밍
const numbers = [0, 1, 2];
function addFive(numbers) {
for (let i = 0; i < numbers.length; i++) {
numbers[i] = numbes[i] + 5;
}
}
이와는 다르게
선언형 프로그래밍에서는 if, for, switch 등이 아닌 함수형 코드를 사용해야 한다.
// 선언형 프로그래밍
function addFive(number) {
return number.map((num) => num + 5);
}
장점
- 높은 수준의 추상화
- 함수 단위의 코드 재사용
- 불변성을 지향하므로 동작을 예측하기 쉬워짐
단점
- 순수함수 구현 시 코드의 가독성이 나빠질 수 있음
- 여러 개의 순수함수를 조합하는 것이 어려움