FE/BOOK

[함수형코딩]WEEK6 일급함수, 너 뭐 돼?

<zinny/> 2025. 4. 15. 20:38
728x90

 

지난 주차에는 계층형 설계에 대해서 이야기 나눴다.

이번 주는 책의 흐름이 한번 바뀌는 파트로 일급 함수에 대해서 이야기하도록 하겠다.

 

일급 함수(First-Class-Function)

함수형 프로그래밍에 대해서 공부하다 보면 계속 등장하는 단어가 있다.

바로 일급 함수(First-Class-Function)

 

자바스크립트에서 "함수는 값이다"라는 말은,  
함수를 숫자나 문자열처럼 변수에 담고, 전달하고, 리턴할 수 있다는 것이다.  
이렇게 다룰 수 있는 함수는 일급 함수라고 부른다.

 

뭔말인지 모르겠으니 예시를 만들어보았다.

 

📌 예시

// 값으로 다룰 수 있다. 
const add1 = a => a + 2;

// 변수에 담을 수 있다
const greet = () => console.log("hi");

// 함수의 인자로 전달될 수 있다
setTimeout(greet, 1000);

// 함수의 리턴값으로 사용될 수 있다
const makeLogger = () => () => console.log("logged");
const logger = makeLogger();
logger();

 

한 문장으로 정리해 보면 함수는 변수에 담고, 전달하고, 리턴할 수 있는 값이라는 뜻이다. 

 


 

코드 냄새: 함수 이름에 있는 암묵적 인자

이게 무슨 뜻이냐면

함수 이름이 너무 구체적이라 특정 조건을 이미 내포하고 있는 경우가 있다

 

이건 함수 이름에 암묵적 인자가 들어있는 것과 같다.

 

📌 예시

function printIfUserIsAdmin(user) {
  if (user.role === "admin") {
    console.log(user.name);
  }
}

 

함수 이름을 보면 '만약 유저가 어드민이면 출력한다' 라고 바로 알 수 있는데

 

- 조건이 다르지만 같은 역할을 하는 비슷한 함수가 있다면?

- 조건이 하드코딩 되어있고, 다른 조건으로 재사용성이 힘든 상황이라면?

 

➡ 이름이 너무 구체적이라 코드가 유연하지 못하고 중복이 생기기 쉬워진다. 

 

 

🔷냄새나는 코드를 일급 함수로 리팩터링하는 방법

🔧 리팩터링 방법 1: 암묵적 인자를 드러내기

이건 무슨 뜻이냐면

조건을 하드코딩 하지 말고, 함수 인자로 분리해서 외부에서 주입하자

 

📌 예시

function printIf(user, predicateFn) {
  if (predicateFn(user)) {
    console.log(user.name);
  }
}

printIf(user, u => u.role === "admin");
printIf(user, u => u.age > 30);

 

➡ printIfUserIsAdmin() 같은 조건 고정형 함수 대신에

조건을 인자로 받아서 재사용 가능한 구조로 바꾸자는 것이다.

 

🔧 리팩터링 방법 2: 함수 본문을 콜백으로 바꾸기

이건 무슨 뜻이냐면

실제 실행할 작업 자체도 함수로 분리해 유연하게 바꾸자 

 

📌 예시

function when(predicateFn, actionFn) {
  return (value) => {
    if (predicateFn(value)) {
      actionFn(value);
    }
  };
}

const logIfAdmin = when(
  u => u.role === "admin",
  u => console.log(`관리자: ${u.name}`)
);

logIfAdmin({ name: "철수", role: "admin" });

 

➡ 조건에 더해 로직까지 동적으로 주입하도록 바꾸자는 것이다. 

 

 

💡 그런데 그게 실무에서 왜 중요할까?

다양한 예시를 통해서 한번 알아보도록 하자!

 

📌 예시 : 이벤트 핸들러

// addEventListener는 함수를 인자로 받는 함수 (고차함수), 넘기는 화살표 함수는 일급 함수!
button.addEventListener("click", () => {
  console.log("클릭됨!");
});

 

📌 예시 : 배열 데이터 가공

// filter, map은 함수를 인자로 받는 함수(고차함수), 넘기는 화살표 함수는 일급 함수!
users
  .filter(user => user.isActive)
  .map(user => user.email);

 

예시를 보면 이해는 가겠지만..

진짜 진짜 중요한 이유는

 

1️⃣ 동작을 바꿔야 할때, 함수를 고치지 않고 외부에서 함수만 바꿔서 주입하면 되기 때문에

동작을 유연하게 바꿀수 있다는 장점이 있다.

function runTwice(fn) {
  fn();
  fn();
}

runTwice(() => console.log("hello"));

 

2️⃣ 반복되는 흐름을 재사용가능한 유틸로 만들 수 있다는 장점이 있다. 

// 원하는 함수에서 래핑해서 사용 가능
function withLogging(fn) {
  return (...args) => {
    console.log("Before");
    const result = fn(...args);
    console.log("After");
    return result;
  };
}

 

3️⃣ 작은 함수들을 조합해 큰 조건을 만들거나, 기능단위로 관리할 수 있게 되면서

기능 조합과 확장이 쉬워진다는 장점이 있다. 

const isAdmin = user => user.role === "admin";
const isAdult = user => user.age >= 18;

const canAccess = user => isAdmin(user) || isAdult(user);

 

그 외에도

 

콜백 전달을 통해 비동기 흐름에서 동작제어가 가능하고, 

외부에서 함수 주입이 가능함으로 테스트 대역 사용이 쉽다는 점에서도 일급 함수를 사용해야 하는 이유가 차고 넘친다.


💡

실무에서 일급 함수는 단지 “함수를 변수에 담을 수 있다”는 걸 넘어서,
함수의 동작 자체를 유연하게 주입, 조합, 교체할 수 있는 구조적 무기가 된다.

함수를 쓰는 것도 일급이라는 속성을 이해할때 비로소 강력한 힘을 가진다고 생각한다. 

 

 

 

728x90