[JavaScript] First-Class Function

2025. 11. 5. 17:31JavaScript

이 글에서는 JavaScript의 일급 함수(First-Class Function)와 고차 함수 생성 및 동작 원리 등에 대해 학습한 내용을 정리하고 공유합니다.

  • 일급 함수(First-Class Function)
  • 일급 시민(First class citizen)
  • 사용 방법
  • 정리
  • 회고

일급 함수(First-Class Function)

일급 시민(First-Class Citizen)으로 취급되어, 변수처럼 사용할 수 있는 함수

JS의 함수는 일급 시민으로 취급되며 변수처럼 사용할 수 있습니다.

const run = () => console.log("run!"); // 함수를 값으로 할당

run(); // 값으로 할당된 함수 실행

이는 아래와 같은 이점이 있습니다.

  • 재사용성 향상 & 유연한 함수 처리
    : 함수를 변수에 저장하며, 중복 코드 감소 및 일관성 유지가 가능합니다.
  • 고차 함수 사용(Higher-order functions)
    : 함수를 다른 함수의 인자로 전달해, 함수의 동작을 위임할 수 있습니다.
  • 추상화와 캡술화 용이
    : 복잡한 로직은 숨기고, 함수 호출로 간단하게 실행할 수 있습니다.

함수의 실행 시점을 제어하고, 동작 위임이 가능해 Callback, Closure, Promise 등과 같은 비동기 처리가 가능합니다.


일급 시민 (First class citizen)

모든 연산과 기능을 자유롭게 사용할 수 있는 엔티티

일급 시민으로 취급되는 엔티티는 아래와 같이 사용될 수 있습니다.

  • 변수에 저장
  • 인자로 전달
  • 반환값으로 사용
  • 런타임 중 동적 생성 및 조작 등

사용 방법

[ 함수의 변수 할당과, 전달 ]

다음과 같이 함수를 변수에 할당하거나, 인자로 전달해 동작을 위임할 수 있습니다.

const numbers = [1,2,3,4];
const double = (x) => x * 2; // 함수를 변수에 할당

const doubledNumbers = numbers.map(double); // 변수에 할당된 함수를 전달 해 동작 위임
// numbers.map((x) => x * 2); 와 동일하다.

 

 

[ 캡슐화 / 클로저 예시 ]

상태와 상태를 조작하는 함수를 하나로 묶어 캡슐화를 구현하고, 상태를 변경하는 함수만 반환할 수 있다.

캡슐화로 사용된 함수의 호출이 끝나더라도, Closure에 의해 상태 변경 함수로 상태를 변경할 수 있다.

function createCounter() {
    let count = 0;

    return function() {
        count++;
        console.log(count);	
    };
}

const counter1 = createCounter(); // createCounter 실행은 끝났지만 반환된 익명함수 자체는 count변수를 기억한다.
counter1(); // 1
counter1(); // 2

const counter2 = createCounter();
counter2(); // 1

 

 

[ 고차 함수를 사용한 컴포지션 ]

설정값을 받아, 특화된 함수를 반환하는 함수를 생성하는, Function Factory 패턴이 가능합니다.

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

const double = multiplyBy(2); // 설정값에 맞는 특화된 함수를 반환한다.
console.log(double(5)); // 10 출력

정리

  • JS의 함수는 일급 함수/시민으로 취급되어 변수에 할당해 사용할 수 있다.
  • 이를 기반으로 고차 함수 생성 및 다양한 비동기 처리가 가능하다.
  • 함수는 합성(Composition)과 위임(Delegation)이 모두 가능한 설계 재료다

회고

이번 학습에서 JavaScript의 함수가 완전히 값처럼 다뤄지는 언어 설계의 유연성을 직접 체감한 점이 특히 흥미로웠다.

이전에는 “좋은 함수란 순수하고 결정적이며 부수 효과가 없어야 한다”는 함수의 품질 관점에서 이해하고 있었다면, 이번 학습은 함수 자체를 어떻게 설계 재료로 유통시키고 코드 흐름을 구성하는가에 대한 관점으로 확장된 경험이었다.

특히 함수를 코드 레벨에서 이동하고, 확장하고, 실행 시점을 위임할 수 있는 구조적 특성을 구체적인 예시와 패턴으로 탐색하면서, Callback·Closure·Promise, 그리고 React 훅에서의 의존성 및 실행 흐름 제어 같은 개념들이 결국 함수값의 시민권에서 출발한 확장 패턴이라는 점이 더 선명하게 느껴졌다.

또한 함수를 인자로 전달하는 모습이, Java의 Integer::parseInt 같은 메서드 참조와 표현 형태에서는 비슷하게 보였던 이유도 이해하게 되었다.

하지만 메서드를 함수형 인터페이스 타입으로 래핑해야 하는 Java와 달리, JavaScript는 어떤 추상 타입이나 래핑 없이 함수 자체를 그대로 넘기는 것이 허용되는 언어이며, 이것이 바로 함수가 언어 차원에서 일급 시민으로 설계되었기 때문에 가능한 차이임을 깨달았다.

결국 두 방식의 유사성은 “함수 참조를 전달한다”는 표현의 유사성에 있었고, 실제 차이는 정적 타입 기반 위임 vs 런타임 값 기반 위임이라는 실행 모델과 설계 철학의 차이에 있었다는 점이 인상 깊었다.

앞으로는 단순히 함수가 좋고 나쁜지를 따지는 것을 넘어, 어디까지 위임하고, 어떻게 호출 흐름과 컨텍스트를 통제할 것인지를 먼저 고민하는 방식으로 설계 사고를 넓혀가야겠다는 생각이 들었다.

'JavaScript' 카테고리의 다른 글

[JavaScript] Callback Function  (0) 2025.11.06
[JavaScript] 블로킹 논블로킹, 동기 비동기  (0) 2025.11.06
[JavaScript] Pure Function  (0) 2025.11.05
[JavaScript] Function  (0) 2025.11.05
[JavaScript] namespace  (0) 2025.11.03