[Javascript] 클로저와 커링

Urther·2022년 7월 20일
0

JavaScript

목록 보기
8/8

정재남 개발자님의 코어 자바스크립트의 '클로저' 파트를 보고 정리한 글입니다.

모던 자바스크립트에는 커링에 대한 부분이 나오지 않았었던 것 같은데 코어 자바에서 있었다.. !! 자바스크립트는 알면 알수록.. 더 알아야하는 언어임을 깨닫게 되었다.

커링 함수를 보고 들었던 생각은 맥도날드의 컬리후라이였다. 최애 후라이인데 모양도 비슷하다.

커링 함수란 ?

커링 함수란, 위와 같은 형태로 여러개의 인자를 받는 함수다.
그리고 순서대로 호출될 수 있도록 체인 형태로 구성된 것을 의미한다.

부분 적용 함수와 달리, 커링 함수는 인자에 딱 하나만 , 전달할 수 있게끔 한다.

let curry3 = function (func) {
  return function (a) {
    return function (b) {
      return func(a, b);
    };
  };
};

위와 같은 함수가 커링 함수다. 사실, 어떤 방식으로 동작하는지 return return 문으로 연결되어있어서 굉장히 어렵게 느껴진다.

이 함수를 통해 인자를 여러개 사용하여 Math.max 를 구하는 방법이 있다.

let getMaxWith10 = curry3(Math.max)(10)(25);
console.log(getMaxWith10); //25

이렇게 여러개의 인자를 전달하며, 1번째 인자 func 에는 Math.max 라는 함수가 담기고, 첫 번째 리턴 문에서 a 인자는 10이 들어온다. 그리고 두번째 b에는 25라는 숫자가 들어오게 되면서 Math.max(10, 25)를 비교하게 되는 것이다.

재귀를 처음 배울 때 처럼 어렵게 느껴진다.

let curry3 = function (func) {
  return function (a) {
    return function (b) {
      return function (c) {
        return function (d) {
          return function (e) {
            return function (f) {
              return func(a, b, c, d, e, f);
            };
          };
        };
      };
    };
  };
};

그리고 여러개 사용할 때는 위와 같이 가독성이 떨어진다는 단점이 있다.
다행히, ES6 문법을 통해 다음과 같이 한줄로 쓸 수 있게 되었다.

let curry3=func=>a=>b=>c=>d=>e=>f=>func(a,b,c,d,e);

각 단계에서 받은 인자들은 모두 마지막 단계인 func(a,b,c,d,e)에서 참조하므로, 가비지 컬렉터의 대상이 되지 않고, 마지막 호출 실행 컨텍스트가 종료된 이후에 비로서 한번에 가비지 컬렉터 대상이 된다.

커링 함수의 장점

원하는 시점까지 지연시켰다가 실행하는 것이 요긴한 상황에 커링함수는 적합하게 쓰일 수 있다. 데이터를 fetch 받아야 하는 상황이 생긴다. 그때, baseUrl은 동일 할 수 있다. (ex . http://localhost:3000) 그때, path 나 id는 달라질 수 있다.

그 때,

const getInfo=baseUrl=>path=>id=>fetch(baseUrl+path+'/'+id);

처럼 사용하게 된다면 개발의 효율성이나 가독성 측면에서 더 좋을 수 있다.

커링 함수의 활용

Fluc 아키텍처의 구현체 중 하나인 Redux의 미들웨어의 예로 들 수 있다.

Redux의 미들웨어는 무엇일까

Reference | 벨로퍼트 리덕스 미들웨어

액션이 dispatch 된 다음, 리듀서에서 해당하는 액션을 받아와서 업데이트하기전에 미들웨어에서 추가적인 작업을 가능하게끔 한다.

  • 특정 조건에 따라 action이 무시되게 만들 수 있다.
  • 특정 action 이 발생했을 때 특정 자바스크립트 함수를 실행시킬 수 있다.

사실, 미들웨어를 사용하는 주된 용도는 비동기 작업을 처리하기 위해서이다. 리액트 앱에서 만약 백엔드 API를 연결해야한다면 리덕스 미들웨어를 사용하여 처리한다.

Redux-logger

커링으로 구현한 logger는 리듀서가 실행되기 전과 실행된 후를 log로 비교하기 어려웠던 점을 redux-logger을 이용하여 편리하게 비교할 수 있다.

const logger=store=>next=>action=>{
  console.log('dispatching',action);
  console.log('next state',state.getState());
  
  return next(action);

}

logger라는 미들웨어는 store를 받고, next를 받고, action 을 받는다. store란, 프로젝트 내에서 한번 생성 된 이후로는 바뀌지 않는 속성이고, dispatch의 의미를 가지는 next 또한 마찬가지다. 그러나, action의 경우 매번 달라진다. 그래서 redux에서는 먼저 store와 next 를 먼저 받고 action만 받아서 처리할 수 있게끔 해주는 것이다.

커링의 응용 문제

처음 면접에서 이 문제를 받았을 때 오타난 줄 알았다. rest 문법을 사용해서 sum(...rest) 로 작성하려 했었는데 rest 문법은 사용할 수 없다고 하셨다. 그래서 힌트로 주신 것이 '커링'이라는 것이었는데, 그 때 당시에 모던 자바스크립트를 읽고 있었음에도 커링이라는 것을 처음 들어봤다.

그리고 코어 자바스크립트라는 책에서 발견할 수 있었다. 상세하게 기초부터 다지기 좋은 것은 모던이고, 어떻게 활용될 수 있는지는 코어자바스크립트가 괜찮다고 생각이 든다.

각설하고, 위에서 커링 함수를 작성하는 방법에 대해서 배웠다. 위와 같은 문제는 몇 개의 인자가 들어올지 모르는 함수다. (인자가 최대 몇개까지 들어오냐에 대한 질문은 하지 못했다. 임시적으로 최대 4개라고 하겠다.)

들어오는 인자가 있는지 확인하고, 없다면 현재 전까지 들어오는 인자를 있다면 자신을 포함한 인자를 리턴해주는 방식이다. 조금 더 컴팩트하게 짤 수 있을 것 같은데 마땅히 방법이 생각이 안난다.

profile
이전해요 ☘️ https://mei-zy.tistory.com

0개의 댓글