카테고리 없음

JavaScript 함수형 프로그래밍의 이해: 순수 함수, 고차 함수, 그리고 불변성

ghkdtprhf5 2024. 11. 8. 21:22

JavaScript는 객체 지향 프로그래밍과 함수형 프로그래밍을 모두 지원하는 언어로, 다양한 스타일의 코딩이 가능합니다. 특히 함수형 프로그래밍은 코드의 가독성을 높이고, 예측 가능한 동작을 만들어 내는 데 유용합니다. 이번 글에서는 함수형 프로그래밍의 기본 개념인 순수 함수(Pure Function), 고차 함수(Higher-Order Function), 그리고 **불변성(Immutability)**에 대해 알아보겠습니다.

1. 함수형 프로그래밍이란?

함수형 프로그래밍은 상태와 부수 효과를 줄이고, 데이터 처리 과정을 함수로만 이루어지게 하여 코드를 작성하는 스타일입니다. 함수형 프로그래밍을 통해 코드의 예측 가능성을 높이고, 모듈화를 쉽게 할 수 있습니다. 이 방식은 특히 복잡한 애플리케이션이나 대규모 데이터 처리가 필요한 환경에서 유용합니다.

2. 순수 함수(Pure Function)

순수 함수는 함수형 프로그래밍의 핵심 개념 중 하나로, 같은 입력이 주어지면 항상 같은 출력을 반환하는 함수를 의미합니다. 순수 함수는 외부 상태를 변경하지 않으며, 부수 효과가 없습니다.

// 순수 함수의 예시
function add(a, b) {
  return a + b;
}

console.log(add(2, 3)); // 항상 5를 반환

위의 add 함수는 주어진 두 숫자를 더한 결과를 반환하며, 외부 상태나 전역 변수를 변경하지 않습니다. 이러한 순수 함수는 예측 가능성이 높고, 테스트가 용이합니다.

순수 함수가 아닌 예시

let count = 0;

function increment() {
  count++;
  return count;
}

console.log(increment()); // 호출할 때마다 다른 결과 반환

위 예제의 increment 함수는 외부 변수 count를 변경하므로 순수 함수가 아닙니다. 이처럼 외부 상태를 변경하는 함수는 부수 효과가 발생할 가능성이 있어 예측 가능성이 떨어집니다.

3. 고차 함수(Higher-Order Function)

고차 함수는 다른 함수를 인자로 받거나, 함수를 반환하는 함수를 의미합니다. 고차 함수는 JavaScript에서 자주 사용되는 중요한 개념으로, 특히 배열과 같은 데이터 구조를 다룰 때 유용합니다.

  • map(): 배열의 각 요소에 함수를 적용하여 새로운 배열을 반환합니다.
  • filter(): 배열의 각 요소에 함수를 적용하여 조건에 맞는 요소만을 추출합니다.
  • reduce(): 배열을 순회하며 누적된 결과를 하나의 값으로 반환합니다.
// map()을 사용한 예시
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);

console.log(doubled); // [2, 4, 6, 8, 10]

// filter()를 사용한 예시
const evenNumbers = numbers.filter(num => num % 2 === 0);

console.log(evenNumbers); // [2, 4]

// reduce()를 사용한 예시
const sum = numbers.reduce((total, num) => total + num, 0);

console.log(sum); // 15

고차 함수를 사용하면 데이터를 간결하고 직관적으로 처리할 수 있습니다. 특히 배열이나 리스트와 같은 반복적인 데이터 처리 작업을 고차 함수를 통해 쉽게 구현할 수 있습니다.

4. 불변성(Immutability)

불변성은 객체나 배열과 같은 데이터 구조를 변경하지 않고, 항상 새로운 값을 생성하는 것을 의미합니다. JavaScript에서는 기본 데이터 타입(String, Number 등)은 불변성을 가지지만, 배열이나 객체는 기본적으로 가변적입니다. 함수형 프로그래밍에서는 불변성을 유지하기 위해 새로운 값을 반환하고, 기존 값을 변경하지 않도록 합니다.

const numbers = [1, 2, 3, 4];

// 새로운 배열을 생성하여 변경
const newNumbers = [...numbers, 5];

console.log(numbers); // [1, 2, 3, 4] - 원본 배열은 그대로 유지
console.log(newNumbers); // [1, 2, 3, 4, 5]

위 예제에서 newNumbers는 원본 배열 numbers를 변경하지 않고 새로운 배열을 생성합니다. 이처럼 불변성을 유지하면 데이터가 예상치 못하게 변경되는 문제를 방지할 수 있어, 코드의 안정성과 유지보수성이 높아집니다.

5. 함수형 프로그래밍의 장점과 단점

장점단점

예측 가능성과 테스트 용이성 증가 복잡한 로직에서는 가독성 저하 가능
코드 재사용성과 모듈화 용이 JavaScript에서 함수형 패러다임에 익숙해지기 어려움
부수 효과 감소로 인한 안정성 증가 불변성을 유지하기 위한 메모리 사용 증가

함수형 프로그래밍을 통해 코드를 간결하게 유지하고 예측 가능성을 높일 수 있지만, 모든 상황에 적합한 것은 아닙니다. 함수형 프로그래밍의 장점과 단점을 이해하고, 프로젝트의 요구 사항에 따라 적절히 활용하는 것이 중요합니다.

6. 함수형 프로그래밍의 실제 사용 예

함수형 프로그래밍은 특히 데이터 처리와 관련된 작업에 강력합니다. 예를 들어, 배열에서 특정 조건에 맞는 요소만 추출하거나, 데이터를 필터링하는 작업에서 유용합니다.

다음은 여러 단계의 필터링을 거쳐 데이터를 처리하는 예제입니다.

const products = [
  { name: "Laptop", price: 1000 },
  { name: "Phone", price: 500 },
  { name: "Tablet", price: 700 },
];

const affordableProducts = products
  .filter(product => product.price < 800)
  .map(product => product.name);

console.log(affordableProducts); // ['Phone', 'Tablet']

이 예제에서는 filter와 map을 조합하여 가격이 800 이하인 제품들의 이름만 추출했습니다. 고차 함수의 활용으로 간결하고 직관적인 코드를 작성할 수 있습니다.

마치며

함수형 프로그래밍은 JavaScript 개발에서 가독성과 유지보수성을 높이는 데 매우 유용한 패러다임입니다. 순수 함수, 고차 함수, 불변성을 이해하고 적용하면 더 효율적이고 예측 가능한 코드를 작성할 수 있습니다. 함수형 프로그래밍은 처음에는 다소 생소할 수 있지만, 반복적으로 사용하다 보면 큰 장점을 느낄 수 있을 것입니다. 이번 글이 함수형 프로그래밍에 대한 이해를 높이는 데 도움이 되었기를 바랍니다.