[JavaScript] 커리 아니고 커링

jade·2025년 7월 22일
0
post-thumbnail

Javascript 디자인 패턴 : 커링패턴

여러개의 입력을 받는 함수를 한개의입력만 받는 여러개의 함수로 변환하는 것이다. 유연한 함수를 선언해 재사용성을 향상시킬 수 있지만, 성능이슈가 발생할 수 있다.

커링패턴은 함수영 프로그래밍에서 자주 사용되는 기법 중 하나인데 하스켈이나 스칼라 같은 함수형 프로그래밍 언어에는 기본적으로 내장되어 있다고 한다. 자바스크립트의 유연한 문법으로 이를 구현할 수 있다.

장점

  • 일부 매개변수를 미리 설정하고 나머지 매개변수에 대해서는 나중에 처리함으로써 함수의 재사용성이 높아짐
  • 크고 복잡한 함수를 작고 관리하기 쉬운 단위로 분할

단점

  • 매개 변수가 많아질 수록 추가적인 함수호출과 메모리할당을 발생시켜 성능이슈가 발생
  • 함수 호출 구조가 복잡해지고 여러단계로 나뉘어 있어서 추적이 더 어려워질 수 있음.

커링함수 예시

const applyDiscount = (할인율) => (가격) => 가격 - 가격 * 할인율

// 1. 변동성이 낮은 인자를 우선으로 받고, 높은 인자는 뒷순서로 받는 것이 좋다.
// 할인율이 0.1이라는 것을 기억하는 클로저
const tenPercentDiscount = applyDiscount(0.1)
// 두번째 인자를 나중에 전달하여 함수를 지연실행
const discountedPrice = tenPercentDiscount(1000)
console.log(discountedPrice)

// 2. 연속해서 호출 가능
const directlyDiscountedPrice = applyDiscount(0.1)(1000)
console.log(directlyDiscountedPrice)

활용하기

이벤트 핸들러 간소화

더 이상 onClick={(e) => handleItemClick(itemId)} 와 같이 선언하지 않아도 된다.

function Component() {

    const handleItemClick = itemId => (event) => {
        console.log(itemId, event.target.value)
    }

    return (
        <div>
            {['item1', 'item2', 'item3'].map(itemId => (
                <button key={itemId} onClick={handleItemClick(itemId)}>
                    Click {itemId}
                </button>
            ))}
        </div>
    )
}

api 호출처리

const createEndPoint = (base) => endpoint => params => {
    const query = new URLSearchParams(params).toString();
    return `${base}/${endpoint}?${query}`
}

// 기본 api url
const baseAPI = createEndPoint('https://example.com/api');

// 엔드포인트 확장
const fetchUser = baseAPI('users');
const fetchPost= baseAPI('posts');


const userAPIPath = fetchUser({id: 1, name: 'lee'});

고차 컴포넌트

// 커링 함수를 이용한 HOC 선언
function withLoading(WrappedComponent) {
    return function({ isLoading, ...rest }) {
        if (isLoading) {
            return <div>Loading...</div>;
        } else {
            return <WrappedComponent {...rest} />;
        }
    };
}

// 예시 컴포넌트 선언
function MyComponent({ data }) {
    return (
        <div>
            <h1>My Component</h1>
            <p>{data}</p>
        </div>
    );
}

// 사용 예시
const MyComponentWithLoading = withLoading(MyComponent);

function App() {
    // 데이터를 가져오는 상태 시뮬레이션
    const [loading, setLoading] = useState(true);
    const [data, setData] = useState(null);


    return (
        <MyComponentWithLoading isLoading={loading} data={data} />
    );
}

팩토리 패턴

// 커링 함수를 사용한 컴포넌트 생성 함수
const createComponent = (Component) => (properties) => {
    return <Component {...properties} />;
};

// 커링 함수 사용하여 특정 컴포넌트 생성 함수 만들기
const createButton = createComponent("button"); // HTML button 요소
const createLabel = createComponent("label"); // HTML label 요소

// 개별 컴포넌트 생성
const BlueButton = () =>
    createButton({ style: { color: "blue" }, children: "Click me" });
const LargeLabel = () =>
    createLabel({ style: { fontSize: "large" }, children: "Label text" });

// 사용 예시
function App() {
    return (
        <div>
            <BlueButton />
            <LargeLabel />
        </div>
    );
}
profile
keep on pushing

0개의 댓글