Pink Spider/About curring

Created Fri, 20 Jun 2025 14:11:00 +0900 Modified Mon, 08 Dec 2025 08:41:47 +0900
1002 Words 5 min

커링(Currying)은 여러 개의 인자를 받는 함수를 하나의 인자만 받는 함수들의 연속으로 변환하는 기법입니다. 수학자 하스켈 커리(Haskell Curry)의 이름에서 따온 용어입니다.

기본 개념

일반적인 함수:

function add(a, b, c) {
    return a + b + c;
}

add(1, 2, 3); // 6

커링된 함수:

function curriedAdd(a) {
    return function(b) {
        return function(c) {
            return a + b + c;
        };
    };
}

curriedAdd(1)(2)(3); // 6

화살표 함수로 간단하게

const curriedAdd = a => b => c => a + b + c;

const result = curriedAdd(1)(2)(3); // 6

부분 적용 (Partial Application)

커링의 가장 큰 장점은 부분 적용이 가능하다는 것입니다:

const curriedAdd = a => b => c => a + b + c;

// 부분 적용
const add5 = curriedAdd(5);
const add5And3 = add5(3);

console.log(add5And3(2)); // 10 (5 + 3 + 2)
console.log(add5(4)(1)); // 10 (5 + 4 + 1)

실용적인 예제들

1. 문자열 검사 함수

const hasSubstring = substring => str => str.includes(substring);

const hasReact = hasSubstring('React');
const hasVue = hasSubstring('Vue');

console.log(hasReact('React 개발자')); // true
console.log(hasVue('Vue.js 프레임워크')); // true

// 배열에서 활용
const frameworks = ['React', 'Angular', 'Vue', 'Svelte'];
const reactItems = frameworks.filter(hasReact);
console.log(reactItems); // ['React']

2. 수학 연산

const multiply = a => b => a * b;
const divide = a => b => a / b;

const double = multiply(2);
const triple = multiply(3);
const half = divide(1/2); // 또는 multiply(0.5)

console.log(double(5)); // 10
console.log(triple(4)); // 12

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(double);
console.log(doubled); // [2, 4, 6, 8, 10]

3. 이벤트 핸들러

const log = level => message => {
    console.log(`[${level}] ${message}`);
};

const logError = log('ERROR');
const logInfo = log('INFO');

logError('데이터베이스 연결 실패'); // [ERROR] 데이터베이스 연결 실패
logInfo('서버 시작됨'); // [INFO] 서버 시작됨

4. API 요청

const apiRequest = method => url => data => {
    return fetch(url, {
        method: method,
        headers: { 'Content-Type': 'application/json' },
        body: data ? JSON.stringify(data) : undefined
    });
};

const get = apiRequest('GET');
const post = apiRequest('POST');
const put = apiRequest('PUT');

// 사용
get('/api/users')();
post('/api/users')({ name: '김철수', email: 'kim@example.com' });

자동 커링 함수 만들기

function curry(fn) {
    return function curried(...args) {
        if (args.length >= fn.length) {
            return fn.apply(this, args);
        } else {
            return function(...nextArgs) {
                return curried.apply(this, args.concat(nextArgs));
            };
        }
    };
}

// 사용 예
function add(a, b, c) {
    return 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
console.log(curriedAdd(1, 2, 3)); // 6

라이브러리에서의 활용

Lodash

const _ = require('lodash');

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

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

Ramda

const R = require('ramda');

const users = [
    { name: '김철수', age: 25 },
    { name: '이영희', age: 30 },
    { name: '박민수', age: 35 }
];

const getProperty = R.curry((prop, obj) => obj[prop]);
const getName = getProperty('name');

const names = users.map(getName);
console.log(names); // ['김철수', '이영희', '박민수']

커링의 장점

  1. 재사용성: 특정 매개변수가 고정된 새로운 함수를 쉽게 생성
  2. 가독성: 함수의 의도가 더 명확해짐
  3. 함수 조합: 다른 고차 함수들과 조합하기 쉬움
  4. 부분 적용: 필요할 때 일부 인자만 먼저 적용 가능

주의사항

  1. 성능: 함수 호출이 중첩되므로 약간의 오버헤드 발생
  2. 디버깅: 스택 트레이스가 복잡해질 수 있음
  3. 가독성: 과도하게 사용하면 오히려 코드를 이해하기 어려워질 수 있음

커링은 함수형 프로그래밍의 핵심 개념 중 하나로, 코드의 재사용성과 모듈성을 크게 향상시킬 수 있는 강력한 기법입니다.