Partial Application
부분 적용은 기존 함수의 인자 일부를 미리 채워 두고, 나머지 인자만 받는 새 함수를 만드는 기법입니다. 예를 들어 (locale, currency, amount)를 받는 함수를 (amount)만 받는 통화 포맷터로 줄이는 식입니다.
핵심은 함수를 완전히 다른 모양으로 바꾸는 것이 아니라, 자주 반복되는 공통 인자를 앞단에서 고정해 호출부를 더 간결하고 목적에 맞게 만드는 데 있습니다.
▶아키텍처 다이어그램
🔄 프로세스 다이어그램점선 애니메이션은 데이터 또는 요청의 흐름 방향을 나타냅니다
같은 함수를 여러 곳에서 호출하는데 locale, prefix, 인증 헤더, 세율 같은 설정값은 항상 같고 실제 데이터만 달라지는 경우가 많습니다. 이때마다 공통 인자를 반복해서 넘기면 호출부가 지저분해지고, 어느 값이 진짜로 상황마다 달라지는 값인지 드러나지 않습니다. 그래서 결국 formatKrw, logApi, fetchWithAuth 같은 작은 래퍼를 여기저기 만들게 되는데, 구조를 보면 거의 다 '몇 개 인자를 미리 넣고 나머지만 받는 함수'입니다. 이 패턴을 이름 있는 개념으로 잡아 두면 래퍼가 우연한 편법이 아니라 의도된 설계 도구가 됩니다.
부분 적용은 함수형 언어에만 있는 기술이 아니라, 함수가 일급 값인 언어라면 거의 어디서나 나타나는 실무 패턴입니다. JavaScript의 Function.prototype.bind, Python의 functools.partial, C#의 람다 래퍼가 모두 같은 발상 위에 있습니다. 함수형 프로그래밍이 주류 개발 문화에 영향을 주면서, 개발자들은 이 패턴을 단순 편의가 아니라 API 설계 수단으로 보기 시작했습니다. 설정과 실제 입력을 분리해 다루면 재사용과 테스트가 쉬워지기 때문입니다.
부분 적용은 보통 세 단계로 이해하면 됩니다. 첫째, 원래 함수가 여러 인자를 받습니다. 둘째, 그중 일부를 지금 시점에 고정한 새 함수를 만듭니다. 셋째, 나중에 남은 인자가 들어오면 새 함수가 미리 기억해 둔 인자와 함께 원래 함수를 호출합니다. 이때 미리 고정한 인자를 보존하는 메커니즘은 보통 클로저입니다. formatPrice("ko-KR", "KRW", amount)를 formatKrw(amount)로 바꾸면, locale과 currency는 클로저 안에 남아 있고 amount만 호출 시점에 새로 들어옵니다. 함수 시그니처를 실제 사용 맥락에 맞게 좁히는 과정이라고 볼 수 있습니다.
공통 설정을 먼저 고정하기
function formatPrice(locale, currency, amount) {
return new Intl.NumberFormat(locale, {
style: "currency",
currency,
}).format(amount);
}
const formatKrw = (amount) => formatPrice("ko-KR", "KRW", amount);
formatKrw(12000); // "₩12,000"formatPrice는 세 인자를 받지만, 실무에서는 locale과 currency가 고정된 경우가 많습니다. formatKrw는 그 두 값을 미리 채워 두고 amount만 받는 더 목적지향적인 함수가 됩니다.
부분 적용과 커링은 자주 혼동되지만 다릅니다. 커링은 함수 전체를 단항 함수의 연쇄로 바꾸는 기계적 변환입니다. 부분 적용은 꼭 단항 체인일 필요 없이, 함수 인자 중 일부를 먼저 넣어 특정 상황에 맞는 새 함수를 만드는 사용 패턴입니다. 커링된 함수는 부분 적용이 쉬운 형태이지만, 커링되지 않은 함수도 래퍼나 bind를 써서 부분 적용할 수 있습니다. 즉 커링은 구조를 바꾸고, 부분 적용은 그 구조를 포함한 함수 사용 방식을 다룹니다.
Gain 공통 설정을 호출부에서 제거해 코드가 짧아지고, 함수 이름만으로 의도가 더 분명해집니다. 테스트에서도 고정값을 가진 전용 함수를 바로 검증할 수 있습니다. Cost 어떤 인자가 이미 고정됐는지 호출부만 보고는 바로 보이지 않을 수 있습니다. 함수 인자 순서가 사용성을 강하게 좌우하므로, 자주 고정되는 인자가 뒤쪽에 있으면 부분 적용이 어색해집니다. Decision Scale 같은 공통 인자가 반복 전달되고, 그 고정값이 의미 있는 이름을 가진 전용 함수로 드러날 가치가 있으면 부분 적용이 적합합니다. 반대로 한두 번만 쓰는 얇은 래퍼라면 굳이 개념적으로 일반화하지 않아도 됩니다.
부분 적용은 지역화 포맷터, 권한이 묶인 API 클라이언트, 공통 prefix를 가진 로거, 폼 검증기처럼 설정과 실제 입력이 분리되는 자리에서 특히 유용합니다. React 이벤트 핸들러에서 id를 먼저 고정해 두고 실제 이벤트 객체만 나중에 받는 패턴도 같은 발상입니다. 실무에서는 '반복되는 인자를 없애는 것' 자체보다, 그 결과로 만들어지는 함수가 더 좋은 이름과 더 좁은 책임을 가지는지가 중요합니다.