본문 바로가기

Programming/JAVASCRIPT

자바스크립트 커링패턴(Currying Pattern)

 

커링패턴은 함수를 작성 시, 인자 전체를 넘겨서 바로 호출할수 있지만 일부 인자는 처음에 먼저 입력해두고 나머지만 입력할 수 있도록 새로운 함수를 만드는 패턴을 말한다.

 

ES6


const sum = x => y => x + y;
console.log(sum(2)(1)); // returns the number 3
console.log(sum(2)); // returns a function y => 2 + y

ES5


"use strict";

var sum = function sum(x) {
  return function (y) {
    return x + y;
  };
}; 

console.log(sum(2)(1)); // returns the number 3
console.log(sum(2)); // returns a function y => 2 + y

ES5의 결과에 보면 처음 function sum(x) 인자에 x값을 담아놓고, 그 다음 return function(y)를 호출해서 최종 x + y가 리턴된다.
여기까지는 커링패턴의 필요성에 대해서 느끼지 못할 수 있다.
처음부터 모든 인자를 다 넘겨서 리턴 값을 받는 쪽에서 한번에 처리하면 되는것이지 왜 이런 패턴을 구현하지라고 생각 할 수 있다.

 

 

다음 예시를 보자.

import { Resolvers } from '../../../types/resolvers';
import privateResolver from '../../../utils/privateResolver';

const resolvers: Resolvers = {
    Query: {
        GetMyProfile: privateResolver(async (_, __, { req }) => {
            const { user } = req;
            return {
                ok: true,
                error: null,
                user
            };
        })
    }
};

export default resolvers;

 

 

위 코드에서 privateResolver 함수를 호출을 하자고한다.
아래의 privateResolver는 커링패턴으로 구현되어 있다.

 

 


const privateResolver = resolverFunction => async (
    parent,
    args,
    context,
    info
) => {
    if (!context.req.user) {
        throw new Error('No JWT. Refuse to proceed');
    }
    const resolved = await resolverFunction(parent, args, context, info);
    return resolved;
};

export default privateResolver;

privateResolver()가 호출시 resolverFunction 함수를 준비 후, async(parent, args, context, info)의 context의 req객체에서 유저가 존재하지 않으면 에러 객체를 반환한다.
이처럼 커링패턴을 통해 미들웨어 시스템처럼 중간에 요청을 가로채서 검증 후 다음 행위를 할 수 있는 것을 구현하였다.

 

정리

  1. privateResolver() 함수를 호출한다.
  2. privateResolver() 함수는 resolverFunction() 함수를 준비 후, 다음 인자들을 준비한다.
  3. 인자들이 준비가 끝나면 context의 req 객체에서 유저가 존재하지 않으면 예외처리를 하며, 존재시 다음 4번으로 넘어간다.
  4. 비동기로 실행되는 커링함수가 검증 성공 후, await하여 최종 resolverFunction(parent, args, context, info)를 리턴한다.

 

결론

커링패턴으로 privateResolver는 일종의 preResolver처럼 모든 resolver에 대해 먼저 실행되어야 할 로직을 관리한다고 볼 수 있다.

(함수 준비) => (인자들을 준비함) => (인자들의 검증이 성공했는가 === true ? 함수와 인자들을 통으로 던짐 : 예외처리)