지난 주차에는 계층형 설계에 대해서 이야기 나눴다.
이번 주는 책의 흐름이 한번 바뀌는 파트로 일급 함수에 대해서 이야기하도록 하겠다.
일급 함수(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);
그 외에도
콜백 전달을 통해 비동기 흐름에서 동작제어가 가능하고,
외부에서 함수 주입이 가능함으로 테스트 대역 사용이 쉽다는 점에서도 일급 함수를 사용해야 하는 이유가 차고 넘친다.
💡
실무에서 일급 함수는 단지 “함수를 변수에 담을 수 있다”는 걸 넘어서,
함수의 동작 자체를 유연하게 주입, 조합, 교체할 수 있는 구조적 무기가 된다.
함수를 쓰는 것도 일급이라는 속성을 이해할때 비로소 강력한 힘을 가진다고 생각한다.
'FE > BOOK' 카테고리의 다른 글
[함수형코딩]WEEK5 계층형 설계- 추상화의 벽, 작은 인터페이스, 편리한 계층 (0) | 2025.04.08 |
---|---|
[함수형코딩]WEEK4 계층형 설계- 직접 구현 (0) | 2025.04.03 |
[함수형코딩]WEEK3 불변성 이야기 (2) | 2025.03.29 |
[함수형코딩]WEEK2 함수형 사고: 더 좋은 액션 만들기 (1) | 2025.03.19 |
[함수형 코딩] WEEK1 액션, 계산, 데이터 (2) | 2025.03.12 |