💻 프로그래밍

Higher-Order Function

고차 함수

함수를 인자로 받거나 반환하는 함수. map, filter, reduce가 대표적.

📖 상세 설명

고차 함수(Higher-Order Function)는 함수를 인자로 받거나 함수를 반환하는 함수를 말합니다. 이 개념은 함수형 프로그래밍의 핵심 원리로, 함수를 일급 객체(First-Class Citizen)로 취급하는 언어에서 자연스럽게 구현됩니다. JavaScript, Python, Haskell 등 현대 프로그래밍 언어 대부분이 고차 함수를 지원합니다.

가장 대표적인 고차 함수로는 map, filter, reduce가 있습니다. map은 배열의 각 요소에 함수를 적용하여 새 배열을 만들고, filter는 조건을 만족하는 요소만 추출하며, reduce는 배열을 하나의 값으로 축약합니다. 이들은 for 루프를 대체하여 코드를 더 선언적이고 읽기 쉽게 만들어줍니다.

고차 함수의 핵심 장점은 추상화와 재사용성입니다. 반복되는 패턴을 함수로 추상화하면 코드 중복을 줄이고, 함수를 조합하여 복잡한 로직을 구성할 수 있습니다. 또한 부수 효과(Side Effect)를 줄여 테스트와 디버깅이 용이해집니다.

실무에서 고차 함수는 이벤트 핸들러 등록, 콜백 패턴, 미들웨어 구현, 데코레이터 패턴 등 다양한 곳에서 활용됩니다. React의 고차 컴포넌트(HOC), Redux의 미들웨어, Express의 라우터 체인 모두 고차 함수의 원리를 응용한 것입니다. 모던 프론트엔드 개발에서는 필수적으로 이해해야 하는 개념입니다.

💻 코드 예제

// 1. 기본 고차 함수: 함수를 인자로 받는 경우
const numbers = [1, 2, 3, 4, 5];

// map: 각 요소를 변환
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

// filter: 조건에 맞는 요소만 추출
const evens = numbers.filter(n => n % 2 === 0);
console.log(evens); // [2, 4]

// reduce: 배열을 하나의 값으로 축약
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(sum); // 15

// 2. 함수를 반환하는 고차 함수
function multiplier(factor) {
    return function(number) {
        return number * factor;
    };
}

const double = multiplier(2);
const triple = multiplier(3);

console.log(double(5));  // 10
console.log(triple(5));  // 15

// 3. 실용적인 예제: 커링(Currying)
const curry = (fn) => {
    return function curried(...args) {
        if (args.length >= fn.length) {
            return fn.apply(this, args);
        }
        return (...nextArgs) => curried(...args, ...nextArgs);
    };
};

const add = (a, b, c) => a + b + c;
const curriedAdd = curry(add);

console.log(curriedAdd(1)(2)(3));    // 6
console.log(curriedAdd(1, 2)(3));    // 6
console.log(curriedAdd(1)(2, 3));    // 6

// 4. 함수 합성(Composition)
const compose = (...fns) => (x) =>
    fns.reduceRight((acc, fn) => fn(acc), x);

const addOne = x => x + 1;
const square = x => x * x;
const toString = x => `Result: ${x}`;

const compute = compose(toString, square, addOne);
console.log(compute(4)); // "Result: 25" (4+1=5, 5^2=25)

🗣️ 실무에서 이렇게 말하세요

💬 회의에서
"이 데이터 변환 로직은 map과 filter를 체이닝해서 처리하면 될 것 같아요. for 루프보다 가독성도 좋고, 중간 결과를 확인하기도 편합니다. 성능이 중요한 부분은 reduce로 한 번에 처리하는 것도 고려해보죠."
💬 면접에서
"고차 함수는 함수를 인자로 받거나 반환하는 함수입니다. 대표적으로 Array의 map, filter, reduce가 있고요. 이를 활용하면 함수 합성이나 커링 같은 함수형 프로그래밍 패턴을 구현할 수 있습니다. React의 HOC도 고차 함수의 응용입니다."
💬 코드 리뷰에서
"여기 forEach에서 외부 변수를 수정하는 대신 reduce를 사용하면 어떨까요? 부수 효과 없이 결과를 만들 수 있어서 디버깅도 쉽고, 함수 단위로 테스트 작성하기도 좋습니다."

⚠️ 흔한 실수 & 주의사항

map/filter 혼동

map은 변환용, filter는 추출용입니다. map에서 undefined를 반환하면 배열 길이가 유지되고, filter에서 원소를 변환하면 의도치 않은 결과가 나옵니다. 목적에 맞는 메서드를 선택하세요.

불필요한 체이닝으로 성능 저하

map().filter().map() 처럼 여러 번 순회하면 대용량 데이터에서 성능 문제가 생깁니다. reduce로 한 번에 처리하거나, 꼭 필요한 경우만 체이닝하세요.

콜백에서 this 바인딩 문제

일반 함수를 콜백으로 전달하면 this가 달라집니다. 화살표 함수를 사용하거나, bind()로 명시적 바인딩하세요. 클래스 메서드를 콜백으로 넘길 때 특히 주의가 필요합니다.

작은 순수 함수로 분리하기

고차 함수에 전달하는 콜백은 작고 순수하게 만드세요. 재사용이 가능하고, 테스트하기 쉬우며, 함수 합성으로 복잡한 로직을 구성할 수 있습니다.

🔗 관련 용어

📚 더 배우기