함수형 프로그래밍(Functional Programming, FP)은 자바스크립트에서 점점 더 주목받고 있는 프로그래밍 패러다임입니다.
함수형 프로그래밍의 핵심 개념 중 하나는 바로 순수 함수(Pure Function)입니다. 순수 함수는 코드를 더 예측 가능하고 안정적으로 만들어주며, 디버깅과 테스트를 쉽게 할 수 있도록 돕습니다.
이번 글에서는 순수 함수란 무엇인지, 순수 함수의 특징과 장점, 그리고 자바스크립트에서 순수 함수를 작성하는 방법에 대해 알아보겠습니다.
1. 순수 함수(Pure Function)란?
순수 함수는 동일한 입력에 대해 항상 동일한 출력을 반환하며, 외부 상태를 변경하지 않는 함수를 말합니다.
쉽게 말해, 함수의 동작이 외부 요인에 의해 영향을 받지 않고, 함수 내부의 로직에만 의존하는 함수입니다.
순수 함수의 조건
1. 동일한 입력 → 동일한 출력
- 함수의 결과는 입력값에만 의존하며, 외부 상태나 전역 변수를 참조하지 않습니다.
2. 부수효과(Side Effect)가 없음
- 함수가 외부의 상태를 변경하거나, 외부와의 상호작용(예: DOM 조작, 파일 읽기/쓰기 등)을 하지 않습니다.
2. 순수 함수의 특징
예측 가능성
- 입력값이 같으면 항상 동일한 결과를 반환하므로, 함수의 동작을 쉽게 예측할 수 있습니다.
테스트 용이성
- 외부 상태에 의존하지 않기 때문에, 독립적으로 테스트하기 쉽습니다.
병렬 처리 가능
- 부수효과가 없으므로, 병렬 처리나 캐싱과 같은 최적화 작업에 유리합니다.
3. 순수 함수의 예와 비순수 함수의 비교
3.1 순수 함수의 예
// 순수 함수
function add(a, b) {
return a + b; // 입력값(a, b)에만 의존
}
console.log(add(2, 3)); // 5
console.log(add(2, 3)); // 5 (항상 동일한 출력)
3.2 비순수 함수의 예
let total = 0;
// 비순수 함수
function addToTotal(value) {
total += value; // 외부 상태(total)를 변경
return total;
}
console.log(addToTotal(5)); // 5
console.log(addToTotal(5)); // 10 (입력이 같아도 출력이 다름)
위의 addToTotal 함수는 외부 변수 total을 변경하므로, 순수 함수가 아닙니다.
이런 함수는 예측 가능성이 떨어지고, 디버깅이 어렵습니다.
4. 순수 함수의 장점
4.1 디버깅과 테스트가 쉬움
순수 함수는 외부 상태에 의존하지 않으므로, 특정 입력값에 대한 결과를 쉽게 테스트할 수 있습니다.
// 순수 함수
function multiply(a, b) {
return a * b;
}
// 테스트
console.assert(multiply(2, 3) === 6, 'Test failed');
console.assert(multiply(4, 5) === 20, 'Test failed');
4.2 코드의 예측 가능성 증가
함수의 동작이 입력값에만 의존하므로, 코드의 결과를 쉽게 예측할 수 있습니다.
4.3 병렬 처리와 캐싱 가능
순수 함수는 외부 상태를 변경하지 않으므로, 병렬 처리나 메모이제이션(Memoization) 같은 최적화 기법에 적합합니다.
5. 순수 함수로 작성된 코드 vs 비순수 함수 코드
5.1 비순수 함수 코드
let discount = 0.1;
function calculatePrice(price) {
return price - price * discount; // 외부 상태(discount)에 의존
}
console.log(calculatePrice(100)); // 90
discount = 0.2;
console.log(calculatePrice(100)); // 80 (외부 상태 변경으로 결과가 달라짐)
5.2 순수 함수 코드
function calculatePrice(price, discount) {
return price - price * discount; // 입력값에만 의존
}
console.log(calculatePrice(100, 0.1)); // 90
console.log(calculatePrice(100, 0.2)); // 80
순수 함수는 외부 상태에 의존하지 않고, 모든 값을 입력값으로 전달받기 때문에 더 예측 가능하고 안전합니다.
6. 순수 함수로 작성할 때 주의할 점
6.1 상태 변경을 피하기
함수 내부에서 외부 변수나 객체를 변경하지 않도록 주의합니다.
// 비순수 함수
function updateArray(arr, value) {
arr.push(value); // 원본 배열을 변경
return arr;
}
// 순수 함수
function addToArray(arr, value) {
return [...arr, value]; // 새로운 배열 반환
}
6.2 참조 투명성 유지
함수의 결과가 입력값에만 의존하도록 작성합니다.
// 비순수 함수
function getRandomNumber() {
return Math.random(); // 외부 상태(랜덤 값)에 의존
}
// 순수 함수
function add(a, b) {
return a + b; // 입력값에만 의존
}
7. 순수 함수로 작성된 실용적 예제
7.1 배열 처리
map, filter, reduce는 순수 함수의 대표적인 예입니다.
const numbers = [1, 2, 3, 4, 5];
// map: 각 요소를 제곱
const squares = numbers.map(num => num * num);
console.log(squares); // [1, 4, 9, 16, 25]
// filter: 짝수만 필터링
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4]
// reduce: 모든 요소의 합
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // 15
7.2 함수 조합
순수 함수는 다른 함수와 조합하기 쉽습니다.
const toUpperCase = str => str.toUpperCase();
const exclaim = str => str + '!';
const shout = str => exclaim(toUpperCase(str));
console.log(shout('hello')); // HELLO!
8. 순수 함수가 아닌 경우가 필요한 상황
순수 함수는 이상적이지만, 모든 상황에서 사용할 수 있는 것은 아닙니다.
- I/O 작업: 파일 읽기/쓰기, API 호출.
- DOM 조작: 사용자 인터페이스 업데이트.
이러한 경우, 부수효과를 최소화하고, 가능한 한 순수 함수와 분리하여 관리하는 것이 중요합니다.
'JavaScript' 카테고리의 다른 글
[JavaScript] 지연 평가(Lazy Evaluation) (0) | 2025.01.16 |
---|---|
[JavaScript] 모나드(Monad) (0) | 2025.01.09 |
[JavaScript] 커링(Currying) (2) | 2024.12.28 |
[JavaScript] 프로토타입으로 상속하기 (0) | 2024.12.25 |
[JavaScript] 클래스와 객체 생성 (0) | 2024.12.16 |