코드 품질을 높여주는 유용한 자바스크립트 함수 - (2)

JeBread·2024년 4월 3일
0

WEB

목록 보기
5/10
post-thumbnail

자바스크립트는 강력하고 다재다능한 프로그래밍 언어이며 보다 효율적이고, 유지 보수가 용이하며, 가독성이 높은 코드를 작성하는 데 도움이 되는 기능들을 많이 내장하고 있습니다.

이 글에서는, 내장된 기능을 사용해 성능을 향상하고 코드를 더 멋지게 보이도록 하는 아주 강력한 함수들을 만드는 방법을 설명하려고 합니다. 이는 자바스크립트 작업을 더욱 즐겁고 효율적으로 만들어 줍니다. 자바스크립트 개발자로서 코드 품질을 최적화하기 위해 유틸리티 파일/클래스에 저장할 수 있는 Debounce, Throttle, Once, Memoize, Curry, Partial, Pipe, Compose, Pick, Omit, 그리고 Zip까지 다뤄보겠습니다.

Memoize

Memoize는 자바스크립트 함수로, 동일한 인수로 연산 비용이 많이 드는 루틴을 여러 번 호출하는 것을 방지하기 위해 특정 함수의 결과를 캐싱하는 용도로 사용됩니다.

function memoize(func) {
  const cache = new Map();
  return function() {
    const key = JSON.stringify(arguments);
    if (cache.has(key)) {
        return cache.get(key);
    }
    const result = func.apply(this, arguments);
    cache.set(key, result);
    return result;
  };
}

memoize() 함수는 주어진 함수의 결과를 캐싱하고 동일한 인수로 다시 호출될 때 그 결과 값을 가져오기 위해 인수를 키로 사용합니다.

입력 변수를 기반으로 복잡한 계산을 수행하는 함수가 있다면, 결과 값을 캐싱하고 동일한 입력값으로 여러 번 호출될 때 즉시 값을 가져올 수 있도록 memoize() 함수를 사용할 수 있습니다.

memoize() 함수의 이점을 보기 위해, 피보나치수열을 계산하는 데에 사용할 수 있습니다.

// 계산을 수행하는 함수 정의
function fibonacci(n) {
    if (n < 2)
        return 1;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

// 메모화된 함수 생성
const memoizedFibonacci = memoize(fibonacci);

// 여러 입력 값으로 메모화된 함수 호출
console.time('total')
console.time('sub1')
const result1 = memoizedFibonacci(30);
console.timeEnd('sub1')
console.time('sub2')
const result2 = memoizedFibonacci(29);
console.timeEnd('sub2')
console.time('sub3')
const result3 = memoizedFibonacci(30);
console.timeEnd('sub3')
console.timeEnd('total')

이 예제에서, finbonacci() 함수는 memoizedFibonacci 함수로 변환될 겁니다. 그 후 memoized() 함수가 호출되고 실행 시간이 콘솔에 나타납니다.

결과는 다음과 같습니다.

두 번째 호출은 29에 대한 피보나치 수를 계산함에도 불구하고, 30에 대한 피보나치 수를 계산하는 세 번째 호출보다 더 오래 걸렸습니다. 세 번째 호출은 memoize() 함수에 의해 캐싱된 값을 사용했기 때문입니다.

Curry

Curry(커링 이라고도 알려진) 함수는 일부 인수를 "미리 채움"으로써 이미 존재하는 함수에서 새로운 함수를 만드는 데 사용되는 고급 자바스크립트 함수입니다. 커링은 여러 인수를 받는 함수로 작업할 때 자주 사용되는데, 항상 같을 인수들을 제외한 나머지 인수만을 받는 함수로 변환합니다.

Curry 함수는 여러 장점이 있습니다.

  • 동일한 변수를 반복해서 사용하는 것을 방지하는 데 도움이 됩니다
  • 코드의 가독성을 높여줍니다
  • 함수를 여러 작은 함수들로 나누는데 이 함수들은 하나의 책임만을 가집니다
function curry(func, arity = func.length) {
  return function curried(...args) {
    if (args.length >= arity) return func(...args);
    return function(...moreArgs) {
      return curried(...args, ...moreArgs);
    };
  };
}

Curry 함수는 다른 함수(func)를 인수로 받고 func의 인수의 길이를 기본값으로 가지는 arity 인수를 선택적으로 가집니다. 함수는 arity 수만큼의 인수와 함께 호출되는 새로운 함수(curried) 함수를 반환합니다. 모든 인수가 제공되지 않은 경우, 필요한 인수가 모두 주어질 때까지 더 많은 인수로 호출할 수 있는 새로운 함수를 반환합니다. 모든 인수가 주어지면, 원래 함수(func)가 호출되고, 이 함수의 결과 값이 반환됩니다.

Curry 함수의 이점을 이해하기 위해, 한 면에 있는 두 점의 거리를 계산하는 메서드를 가정해 볼 수 있습니다. Curry 함수를 이용하면, 여러 점들 중 한 점만 필요한 함수를 만들 수 있어 더욱 쉬워집니다.

다음 스니펫은 이전에 정의된 curry 함수가 어떻게 구현의 가독성을 최적화하는지를 보여줍니다.

// 두 점 간의 거리를 계산하는 함수 정의
function distance(x1, y1, x2, y2) {
  return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
}

// 한 점만 필요로 하게끔 함수를 curry된 버전으로 생성
const distanceFromOrigin = curry(distance, 3)(0, 0);

// 다른 점을 인수로 하여 curry된 함수를 호출
const d1 = distanceFromOrigin(1, 1);
const d2 = distanceFromOrigin(2, 2);

이 예제에서, distance 함수는 curry 함수에 첫 번째 인수로 넘겨지고 두 번째 인수(arity)로 3을 함께 넘겨 커리된 함수(distanceFromOrigin)로 생성되었습니다. 또한, 커리된 함수와 함께 0, 0 두 인수를 전달하여 호출합니다.

결과적으로 생성된 distanceFromOrigin 함수는 두 개의 인수만을 필요로 하는 새로운 함수가 되었고, 첫 번째 점으로 항상 0, 0을 사용하게 됩니다.

Partial

자바스크립트에서 Partial 함수는 Curry 함수와 유사합니다. 하지만 Curry 함수는 커링 체인에서 다른 함수를 반환하고, Partial 함수는 결과를 즉시 반환한다는 큰 차이가 있습니다.

function partial(func, ...args) {
  return function partiallyApplied(...moreArgs) {
    return func(...args, ...moreArgs);
  }
}

자바스크립트에서 partial 함수는 일반적으로 함수와 하나 이상의 입력 인수를 받고, 새로운 함수가 호출될 때 인수로 받은 함수에 추가로 받은 인수들을 전달하여 호출하는 새로운 함수를 반환합니다.

다음 경우에서, calculate 함수에 처음 두 개의 인수를 미리 채우고 더 가독성 있는 이름을 가지는 새로운 함수를 생성합니다.

// 계산하는 함수 정의
function calculate(x, y, z) {
  return (x + y) * z
}

// 마지막 인수(z)만 필요로 하도록 parital이 적용된 함수 버전으로 생성
const multiply10By = partial(calculate, 8, 2);

// 반복 횟수 값을 전달하여 partial이 적용된 함수를 호출
const result = multiply10By(5);

이 예제에서, 일반 calculate 함수를 부분적으로 적용하고 미리 8과 2라는 첫 두 개의 인수를 미리 채우는 방식으로 multiply10By 함수를 생성합니다. 이렇게 생성된 multiply10By 함수는 10을 얼마나 곱할지를 정하는 하나의 인수만을 필요로 합니다. 또한, 이 방식을 통해 코드의 가독성과 이해도를 더 향상할 수 있습니다.

오늘은 여기까지 알아보고 다음 시간에는 Pipe 부터 알아보겠습니다.

0개의 댓글

관련 채용 정보