자바스크립트를 처음 배우는 사람들에게 함수는 단순히 어떤 동작을 실행하기 위해 코드 블록을 묶는 도구로 느껴지기 쉽습니다. 보통은 특정 기능을 함수로 만들어두고, 필요할 때 호출해서 사용하죠. 하지만 자바스크립트에서 함수는 단순한 코드의 묶음 그 이상입니다. 자바스크립트는 함수 자체를 값으로 다룰 수 있는 ‘일급 객체(first-class citizen)’로 취급하는 언어입니다.
이 말은 함수를 변수에 저장할 수 있고, 다른 함수의 인자로 전달하거나, 심지어 함수의 반환 값으로도 사용할 수 있다는 뜻인데요. 이러한 특성 덕분에 자바스크립트는 함수형 프로그래밍(Functional Programming, FP)을 자연스럽게 사용할 수 있는 환경을 가지고 있습니다.
많은 초급 개발자들이 함수형 프로그래밍이라고 하면 어렵고 학문적인 느낌을 받아 부담스러워하지만, 사실 함수형 프로그래밍은 우리가 이미 사용하고 있는 많은 기능에 자연스럽게 녹아 있습니다. map이나 filter 같은 배열 메서드만 잘 활용해도 이미 함수형 프로그래밍의 철학을 실천하고 있는 것이죠. 이번 글에서는 함수형 프로그래밍이란 무엇인지, 자바스크립트에서 어떻게 활용되는지, 그리고 왜 이것이 중요하고 어떤 장점이 있는지 차근차근 살펴볼게요.
프로그래밍 패러다임은 시대에 따라 진화해 왔습니다. 기계어와 어셈블리 언어로 시작된 프로그래밍은 구조적 방식으로 발전했고, 이후 객체지향이 등장하며 코드를 더 유연하게 구성할 수 있게 되었습니다. 그리고 최근에는 함수형 프로그래밍이 다시 주목받고 있습니다.

함수형 프로그래밍은 데이터의 변경보다는 계산을 통해 새로운 값을 만들어내는 프로그래밍 패러다임입니다. 이 방식은 상태를 직접 수정하거나 공유하지 않고, 함수 호출을 통해 항상 예측 가능한 새로운 데이터를 만들어냅니다. 자바스크립트에서도 이러한 패러다임은 이미 다양한 곳에서 적용되고 있으며, 코드를 더 간결하고 안정적으로 만들 수 있게 해줍니다.
함수형 프로그래밍을 이해하기 위해서는 몇 가지 핵심 개념들을 정확하게 짚고 넘어가는 것이 중요합니다. 이제부터 차근차근 살펴보겠습니다.
순수 함수란 동일한 입력값에 대해서는 항상 동일한 결과를 반환하는 함수입니다. 또한 외부 상태를 변경하지 않고, 외부 변수에 의존하지 않는 것이 특징입니다. 예를 들어, 다음과 같은 함수는 순수 함수입니다.
function add(a, b) {
  return a + b;
}
이 함수는 a와 b라는 입력값만으로 결과가 결정되며, 함수 외부에 영향을 주지도 않습니다. 반면 아래의 함수는 순수하지 않습니다.
let count = 0;
function increment() {
  count++;
  return count;
}
이 함수는 외부 상태인 count를 변경하므로 호출할 때마다 결과가 달라집니다. 순수 함수는 코드의 예측 가능성과 테스트 용이성을 높여줍니다. 언제, 어디서 호출되더라도 같은 결과를 보장하므로 버그를 줄이고 안정적인 코드를 작성할 수 있게 해줍니다.
불변성이란 데이터를 변경하지 않고, 변경이 필요한 경우 복사본을 만들어 새로운 값을 만들어내는 것을 의미합니다. 예를 들어 객체의 속성 하나만 바꾸고 싶은 경우, 원본 객체를 수정하는 대신 새로운 객체를 만들어야 합니다.
const user = { name: "홍길동", age: 26 };
const updatedUser = { ...user, age: 27 };
이렇게 하면 원본 user 객체는 변경되지 않고, 변경된 값이 반영된 새로운 updatedUser 객체만 생성됩니다. 자바스크립트에서는 객체나 배열 같은 참조 타입 데이터를 직접 수정하게 되면, 그 데이터가 참조되고 있는 다른 곳에서도 값이 바뀌어 버릴 수 있습니다. 이런 상황은 예상치 못한 사이드 이펙트를 일으키고, 디버깅을 매우 어렵게 만들 수 있습니다.
반면 불변성을 유지하면 데이터의 변경 이력을 명확하게 추적할 수 있고, 이전 상태와 이후 상태를 쉽게 비교할 수 있습니다. 덕분에 상태 변경 감지가 쉬워지며, 특히 React처럼 상태 기반으로 UI를 그리는 라이브러리에서 매우 중요한 역할을 합니다.
또한 불변성을 지키는 방식은 버그 발생 확률을 줄이고, 예측 가능한 코드를 작성할 수 있게 해줍니다. 개발자가 의도하지 않은 상태 변경을 방지하고, 협업 시에도 상태 공유로 인한 충돌을 줄일 수 있기 때문에 유지보수 관점에서도 매우 유리합니다.
고차 함수는 함수를 인자로 받거나 함수를 반환하는 함수입니다. 자바스크립트에서는 map, filter, reduce와 같은 배열 메서드가 대표적인 고차 함수입니다. 예를 들어, 다음과 같은 코드를 보겠습니다. 예를 들어 다음과 같은 코드를 보겠습니다.
function greet(name) {
  return `안녕하세요, ${name}님`;
}
function processUser(name, callback) {
  return callback(name);
}
console.log(processUser("홍길동", greet)); // "안녕하세요, 홍길동님"
여기서 processUser는 인자로 받은 함수 greet을 호출합니다.

이처럼 고차 함수는 코드의 추상화를 가능하게 하고, 재사용성과 확장성을 높여줍니다. 나중에 greet 함수 대신 다른 동작을 하는 함수를 넣으면 전혀 다른 로직을 실행할 수 있게 되죠.
자바스크립트에서는 함수형 프로그래밍을 할 수 있는 도구들이 이미 표준으로 제공되고 있습니다. 그 중 가장 자주 사용되는 것이 바로 map, filter, reduce입니다. 이 메서드들은 배열을 다룰 때 사용되며, 모두 고차 함수로 동작합니다.
map은 배열의 각 요소에 함수를 적용해서 새로운 배열을 반환합니다. 원본 배열은 변경되지 않고, 새로운 결과 배열이 만들어지는 것이 특징입니다.
const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);
// doubled: [2, 4, 6]
map을 사용하는 이유는 반복문보다 코드가 더 간결하고 의도가 명확하기 때문입니다. 무엇을 ‘한다라’는 것이 코드에 잘 드러나므로 가독성도 좋습니다.
filter는 조건을 만족하는 요소만 남겨 새로운 배열을 만드는 함수입니다. 조건을 표현하는 콜백 함수는 true 또는 false를 반환해야 하며, true인 요소만 결과 배열에 포함됩니다.
const words = ["hi", "hello", "apple", "car"];
const longWords = words.filter(word => word.length > 3);
// longWords: ["hello", "apple"]
filter는 특히 검색, 필터링, 조건 기반 데이터 추출에 유용하며, 원본 배열을 변경하지 않기 때문에 안전하게 사용할 수 있습니다.
reduce는 배열의 모든 요소를 하나의 값으로 줄여주는 함수입니다. 합계를 구하거나, 평균, 최댓값, 객체 변환 등 다양한 목적으로 활용됩니다.
const scores = [10, 20, 30];
const total = scores.reduce((acc, curr) => acc + curr, 0);
// total: 60
reduce는 다소 복잡해 보일 수 있지만, 사용법에 익숙해지면 매우 강력한 도구가 됩니다. 특히 상태를 누적하거나 데이터를 정리해야 할 때 큰 도움이 됩니다.
 
함수형 프로그래밍은 단순히 새로운 문법이 아니라, 소프트웨어를 바라보는 사고방식 자체를 바꾸는 접근입니다. 자바스크립트를 비롯한 다양한 현대적인 개발 도구들은 이 함수형 프로그래밍의 개념을 적극적으로 받아들이고 있으며, 실제로 많은 이점이 있습니다.
복잡한 웹 애플리케이션에서는 상태(state)가 많아지고, 이 상태가 어디서 바뀌었는지를 추적하는 일이 점점 어려워집니다. 이런 상황에서 함수형 프로그래밍은 상태 변경을 피하고, 예측 가능한 결과를 유지하게 해줍니다. 예를 들어, React에서는 상태를 직접 수정하는 것을 금지하고, 항상 새로운 상태를 만들어서 전달하게 합니다. 이는 함수형 프로그래밍의 핵심 철학인 불변성과 순수 함수를 기반으로 합니다.
또한 테스트가 쉬워집니다. 순수 함수는 항상 같은 입력에 대해 같은 결과를 주기 때문에 테스트할 때 외부 환경의 영향을 걱정하지 않아도 됩니다. 즉, 사이드 이펙트가 줄어들고, 로직을 더 쉽게 검증할 수 있습니다.
가장 큰 장점은 코드의 예측 가능성과 안정성입니다. 부작용이 없고, 상태를 직접 건드리지 않기 때문에 디버깅이 훨씬 수월합니다. 또 코드가 간결하고 선언적입니다. 반복문보다 map, filter를 쓰면 목적이 명확하고 읽기 쉬운 코드가 만들어집니다. 추상화를 통해 공동 로직을 재사용하기도 쉬워지며, 팀 협업에서도 유지보수가 수월해집니다.

물론 단점도 존재합니다. 첫 번째는 학습 난이도입니다. 특히 reduce, compose, curry 같은 개념은 익숙하지 않다면 이해하기 어렵습니다. 두 번째는 가독성의 저하 가능성입니다. 고차 함수나 중첩 함수가 많아지면 오히려 코드를 읽기 어렵게 만들 수 있습니다. 세 번째는 성능 문제입니다. 너무 많은 복사와 새 객체 생성이 일어나면 메모리 사용량이 늘어나고, 성능이 저하될 수도 있습니다. 따라서 함수형 프로그래밍은 맹목적으로 사용하는 것이 아니라, 필요에 따라 유연하게 적용해야 합니다.
자바스크립트에서 함수형 프로그래밍은 어려운 이론이 아닙니다. 오히려 우리가 이미 사용하고 있는 배열 메서드들과 함수의 일급 객체 개념이 함수형 사고를 자연스럽게 익히는 데 도움을 줍니다. map, filter, reduce를 사용하고, 순수 함수와 불변성을 지키는 것만으로도 함수형 프로그래밍의 기반을 충분히 다질 수 있습니다.
처음에는 다소 어렵게 느껴질 수 있지만, 함수형 프로그래밍은 코드의 품질을 높이고, 안정성을 확보하며, 팀 프로젝트에서도 협업을 수월하게 만들어주죠. 프론트엔드 개발자라면 React, Redux와 같은 라이브러리 구조 속에서, 이 패러다임을 더욱 깊이 체감하게 될 것입니다.
©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.