1. 커링(Currying)의 실제 활용
커링은 여러 인자를 받는 함수를 하나의 인자를 받는 함수들의 체인으로 변환하는 기법입니다. 코드 재사용성과 지연 실행(lazy evaluation)을 가능하게 합니다.
활용 1: 공통 파라미터 고정을 통한 API 클라이언트 생성
// 일반적인 fetch 함수
function request(baseUrl, path, query) {
const params = new URLSearchParams(query).toString();
return fetch(`${baseUrl}/${path}?${params}`);
}
// 커링을 적용한 API 클라이언트 팩토리
function apiClient(baseUrl) {
return (path) => (query) =>
fetch(`${baseUrl}/${path}?${new URLSearchParams(query)}`);
}
// GitHub API 전용 클라이언트 생성
const github = apiClient('https://api.github.com');
const fetchUser = github('users');
const fetchRepo = github('repos');
// 실제 호출
fetchUser({ username: 'torvalds' });
fetchRepo({ owner: 'facebook', repo: 'react' });
활용 2: 이벤트 핸들러에 동적 데이터 바인딩
// 커링을 사용한 이벤트 핸들러 생성
const itemClickHandler = (itemId) => (event) => {
console.log(`아이템 ${itemId} 클릭됨`, event.target);
};
// 리스트 아이템에 이벤트 등록
items.forEach((item) => {
const btn = document.getElementById(`btn-${item.id}`);
btn.addEventListener('click', itemClickHandler(item.id));
});
활용 3: 재사용 가능한 입력값 검증기
// 정규식 검증 함수 커링
const createValidator = (pattern) => (value) => pattern.test(value);
// 전용 검증기 생성
const checkEmail = createValidator(/^[\w.-]+@[\w.-]+\.\w+$/);
const checkPhone = createValidator(/^\d{2,3}-\d{3,4}-\d{4}$/);
// 활용
console.log(checkEmail('user@domain.com')); // true
console.log(checkPhone('010-1234-5678')); // true
2. 팩토리 함수(Factory Function)의 실제 활용
팩토리 함수는 객체 생성을 캡슐화하고, 반복적인 생성 로직을 간소화합니다. new 키워드 없이 객체를 반환합니다.
활용 1: 설정 기반 UI 위젯 생성
function buildButton(options) {
const el = document.createElement('button');
el.textContent = options.label || '확인';
el.style.cssText = `background: ${options.bgColor || '#ddd'}; color: ${options.textColor || '#000'};`;
if (options.action === 'submit') {
el.addEventListener('click', () => options.onSubmit?.());
} else if (options.action === 'reset') {
el.addEventListener('click', () => options.onReset?.());
}
return el;
}
// 다양한 버튼 인스턴스 생성
const saveBtn = buildButton({
label: '저장',
bgColor: '#4CAF50',
textColor: '#fff',
action: 'submit',
onSubmit: () => console.log('저장 완료'),
});
const clearBtn = buildButton({
label: '초기화',
bgColor: '#f44336',
textColor: '#fff',
action: 'reset',
onReset: () => console.log('초기화 완료'),
});
활용 2: 데이터 모델 객체 생성
function makeUser({ name, age, role = 'viewer' }) {
const created = new Date();
return {
displayName: () => name,
displayAge: () => age,
displayRole: () => role,
summary: () => `${name}(${age}세, ${role}) - 가입일: ${created.toLocaleDateString()}`,
};
}
const admin = makeUser({ name: '관리자', age: 28, role: 'admin' });
const guest = makeUser({ name: '게스트', age: 22 });
console.log(admin.summary()); // "관리자(28세, admin) - 가입일: ..."
console.log(guest.summary()); // "게스트(22세, viewer) - 가입일: ..."
활용 3: 캐싱 기능이 포함된 fetch 래퍼
function cachedFetcher() {
const store = new Map();
return async (url) => {
if (store.has(url)) {
console.log('[캐시 적중]', url);
return store.get(url);
}
const res = await fetch(url);
const data = await res.json();
store.set(url, data);
return data;
};
}
const getWithCache = cachedFetcher();
getWithCache('https://api.example.com/data');
getWithCache('https://api.example.com/data'); // 두 번째 호출은 캐시에서 반환
핵심 정리
- 커링: 인자를 부분적으로 고정하여 전용 함수 생성. API 요청, 이벤트 바인딩, 폼 검증 등에 적합.
- 팩토리 함수: 객체 생성을 위한 템플릿 역할. UI 컴포넌트, 데이터 모델, 캐시 시스템 구축에 유용.
두 패턴 모두 클로저(Closure)를 기반으로 동작하며, 코드의 모듈성과 유지보수성을 높여줍니다.