자바스크립트에서 카레 함수를 활용하면 코드베이스 내에서 가독성과 표현력을 모두 향상시킬 수 있습니다. 이 접근 방식에는 복잡한 논리 연산을 다루기 쉬운 모듈식 독립 구성 요소로 분해하는 것이 포함됩니다.

자바스크립트 프로그래밍 언어의 맥락에서 커리 함수를 포괄적으로 이해하고, 단일 함수를 개별적으로 또는 집합적으로 사용할 수 있는 여러 특수 함수로 변환하는 함수 커리 과정을 통해 그 유용성을 알아보세요. 또한 원래 함수의 매개변수 중 일부만 제공된 경우인 커링된 함수와 부분적으로 적용된 함수의 실제 응용 사례를 살펴봅니다.

카레란 무엇인가요?

유명한 수학자 하스켈 B. 커리의 연구에 뿌리를 둔 커링 프로세스는 람다 미적분학 영역에서 유래했습니다. 다중 매개변수 함수를 단일 매개변수 단항 함수의 시퀀스로 변환하는 것을 포함합니다. 기본적으로 함수가 커링을 거치면 주어진 순간에 하나의 입력 변수만 받아들일 수 있습니다.

커링의 기본 예

커링 함수는 다음과 같이 정의할 수 있습니다: “`python def add(x, y): 반환 x + y add_two = add(2) print(add_two(3)) # 출력: 5 “` 이 예제에서 `add`는 두 개의 인수를 받아 그 합을 반환합니다. add`의 두 번째 인수를 “커링”하여 하나의 인자(이 경우 2)만 필요로 하는 `add_two`라는 새 함수를 만들었습니다. add_two(3)`를 호출하면 2와 결합하면 3이 5가 되므로 5라는 출력이 생성됩니다.

 function buildSandwich(ingredient1) {
  return (ingredient2) => {
    return (ingredient3) => {
      return `${ingredient1},${ingredient2},${ingredient3}`
    }
  }
}

`buildSandwich()` 함수는 중첩된 함수 시퀀스를 생성하며, 각 함수는 연속적인 입력을 받아 궁극적으로 문자열 조작을 위한 템플릿 리터럴을 산출합니다.

이 구현은 연속적인 함수가 재귀적으로 호출되어 가장 안쪽 함수에서 정점에 이르는 반복 절차로 구성됩니다. 빌드샌드위치()` 메서드가 단독 인수로 호출되면 해당 범위 내에서 실현되지 않은 매개변수를 반환합니다.

 console.log(buildSandwich("Bacon"))

출력 결과 `buildSandwich` 함수가 함수를 결과물로 산출하는 것을 알 수 있습니다.

함수 호출을 성공적으로 실행하려면 호출되는 특정 함수에 필요한 세 가지 매개 변수를 모두 제공해야 합니다.

 buildSandwich("Bacon")("Lettuce")("Tomato")

앞서 설명한 프로그램은 초기 연산에 “베이컨”이라는 문자열을 전달하고, 후속 프로세스에 “양상추”를 디스패치하며, 마지막 절차에 “토마토”를 배포하는 방식으로 실행됩니다. 기본적으로 빌드샌드위치() 메서드는 세 개의 개별 연산으로 나뉘며, 각 하위 연산은 단일 입력 변수를 받습니다.

카레를 만들기 위해 기존 함수를 활용하는 것은 전적으로 허용되지만, 더 깊이 파고들수록 중첩이 점점 더 매력적이지 않게 됩니다. 대안으로 화살표 함수를 사용하면 보다 간소화된 구문을 활용할 수 있습니다:

 const buildMeal = ingred1 => ingred2 => ingred3 =>
`${ingred1}, ${ingred2}. ${ingred3}`;

개정판은 표준 함수와 달리 화살표 함수를 사용할 때 상당한 이점을 제공하는 간결성을 보여줍니다. 함수 호출 절차는 변경되지 않으며 이전 버전과 동일하게 실행할 수 있습니다:

 buildMeal("Bacon")("Lettuce")("Tomato")

부분적으로 적용된 커리 함수

커리는 종종 함수를 부분적으로 적용하는 데 활용됩니다. 이 접근 방식은 필요한 모든 인수를 미리 제공하는 대신 호출할 때마다 인수를 점진적으로 제공합니다. 필요한 모든 매개변수를 갖춘 상태에서 함수를 호출하는 행위를 “적용”이라고 합니다.

이 글도 확인해 보세요:  녹 매크로: 매크로를 사용하여 코드를 개선하는 방법

설명용으로 가상의 시나리오를 예로 들어 다음과 같은 경우를 살펴보겠습니다.

 const multiply = (x, y) => x * y;

제공된 코드 스니펫은 두 숫자를 곱하는 커리 함수를 나타내며, ‘multiply’ 함수는 하나의 인수를 받고 원래 두 값의 곱을 계산하는 추가 인수를 받는 다른 함수를 반환합니다. 이 접근 방식을 사용하면 첫 번째 매개변수만 전달하여 곱셈에 필요한 두 번째 값을 나타내는 단일 매개변수를 가진 새로운 함수를 생성함으로써 `multiply` 함수를 부분적으로 적용할 수 있습니다.

 const curriedMultiply = x => y => x * y;

`curriedMultiply()` 함수는 두 개의 인수를 받는데, 첫 번째 인수의 값은 첫 번째 함수에 입력으로 전달되고, 두 번째 인수의 값은 두 번째 함수에 입력으로 전달됩니다. 그런 다음 함수는 이러한 입력에 곱셈을 수행합니다.

처음 부분적으로 적용된 함수를 생성하기 위해 첫 번째 인수를 제공하고 이후 결과 함수를 변수에 저장하여 `curriedMultiple()` 메서드를 호출할 수 있습니다.

 const timesTen = curriedMultiply(10)

이 코드는 부분 적용을 통해 이미 실행되고 있는 호출된 함수 내에서 10의 자동 곱셈이 발생하면서 timesTen() 메서드를 호출할 때 단독 입력만 필요하도록 curriedMultiply() 함수를 효과적으로 활용하고 있습니다.

 console.log(timesTen(8)) // 80

이 접근법을 활용하면 하나의 복잡한 함수에서 파생된 수많은 특수 함수를 개발할 수 있으며, 각 함수는 그 안에 미리 결정되고 보호되는 고유한 기능을 보유합니다.

실제 웹 개발 관행에 더 부합하는 시나리오를 고려해 보세요. 제공된 코드 스니펫은 초기 호출 시 요소 식별자를 받은 다음 후속 호출 시 원하는 텍스트 콘텐츠를 받는 `updateElemText()` 함수를 보여줍니다. 이 함수는 이후 제공된 식별자 및 콘텐츠 정보에 따라 지정된 요소를 수정합니다.

 const updateElemText = id = content
   => document.querySelector(`#${id}`).textContent = content

// Lock the element's id into the function:
const updateHeaderText = updateElemText('header')

// Update the header text
updateHeaderText("Hello World!")

커링 함수를 사용한 함수 구성

커링은 작은 함수를 순차적으로 호출하여 통합된 더 복잡한 함수로 통합할 수 있는 함수 구성에도 활용할 수 있습니다.

이 글도 확인해 보세요:  웹 개발을 위한 가장 인기 있는 8가지 백엔드 프레임워크

1. **제품 조회** – 사용자 입력 또는 검색 쿼리를 기반으로 데이터베이스에서 제품 정보를 검색합니다. 여기에는 이름, 가격, 재고 여부 등과 같은 세부 정보가 포함될 수 있습니다. 2. **주문 처리** – 고객이 원하는 상품을 선택하면 결제 정보를 처리하고 주문 확인서를 생성하는 기능입니다. 또한 판매자와 고객 모두에게 주문 알림을 전송할 수도 있습니다. 3. **배송 및 배송** – 주문이 처리된 후 이 기능은 배송비를 계산하고 적절한 배송업체를 통해 배송 일정을 예약합니다. 그러면 패키지가 배송 중일 때 고객에게 알림이 전송됩니다.

 const addCustomer = fn => (...args) => {
  console.log("Saving customer info")
  return fn(...args)
}

const processOrder = fn => (...args) => {
  console.log(`processing order #${args[0]}`)
  return fn(...args);
}

let completeOrder = (...args) => {
  console.log(`Order #${[...args].toString()} completed.`);
}

실제로 현재 코드 내에서 “let” 키워드를 사용하면 “completeOrder()” 함수를 설명하는 데 사용됩니다. 이를 통해 지정된 변수에 새 값을 할당할 수 있으며, 이는 자바스크립트에서 범위의 범위에 속합니다.

제공된 코드를 올바르게 실행하려면 추가 작업을 진행하기 전에 고객을 추가할 수 있도록 다른 메서드 내에 중첩된 메서드부터 시작하여 가장 바깥쪽에 있는 메서드까지 역순으로 메서드를 호출해야 합니다.

 completeOrder = (processOrder(completeOrder));
completeOrder = (addCustomer(completeOrder));
completeOrder("1000")

네, 기꺼이 도와드리겠습니다! 질문이 무엇인가요?

이 구절은 현실의 본질, 자아, 의식 및 기타 철학적 주제를 탐구하는 일련의 질문과 답변을 제시합니다. 저자는 생각과 감정의 관계, 감정이 순전히 주관적인 것인지 객관적으로 측정할 수 있는지, ‘나’를 구성하는 것은 무엇인지, 외부 세계에 대한 지식 주장을 검증하는 것이 어떻게 가능한지에 대한 질문을 던집니다. 이러한 질문은 인식론, 형이상학, 현상학 등 철학의 다양한 분야와 관련이 있습니다.

이 논문에서는 그래핀 기반 소재가 반도체 응용 분야에서 실리콘을 대체할 수 있는 잠재력에 대해 논의하며, 그래핀의 우수한 열 전도성과 소자 성능을 향상시킬 수 있는 기타 고유한 특성에 중점을 두고 있습니다. 저자는 특히 일부 그래핀 기반 시스템에서 포논이 열전도의 유일한 관련 모드가 아닐 수 있다는 최근 연구에 비추어 나노 스케일에서 열전도를 지배하는 복잡한 메커니즘을 이해하는 것이 중요하다고 강조합니다. 이러한 현상을 규명함으로써 연구자들은 미래의 전자 장치에 그래핀의 잠재력을 최대한 활용하고 나노 기술 분야의 발전에 기여할 수 있습니다.

이 글도 확인해 보세요:  내부에서 REST API 호출을 수행하는 방법 VS 코드

앞서 언급한 기능들은 다음과 같이 보다 정교하게 표현할 수 있습니다:

 function addCustomer(...args) {
  return function processOrder(...args) {
    return function completeOrder(...args) {
      // end
    }
  }
}

추가고객() 함수의 컨텍스트 내에서 제공된 입력 파라미터를 활용하여 내부 지점에서 시작하여 함수의 최상위 레벨을 향해 체계적인 순회가 진행됩니다.

커리 함수를 사용하여 일반 함수를 커리 함수로 변환

프로그래밍 작업에서 커리 함수를 자주 사용하는 경우 지원 보조 함수를 활용하여 워크플로우를 최적화할 수 있습니다.

제공된 함수는 무한한 수의 매개 변수를 수용하기 위해 재귀 기술을 활용하여 일반 함수를 카레 변형으로 변환합니다.

 const curry = (fn) => {
  return curried = (...args) => {
    if (fn.length !== args.length) {
      return curried.bind(null, ...args)
    }

    return fn(...args);
  }
}

여러 입력 인수를 허용하는 표준 함수가 주어지면 해당 함수의 커리 변형을 반환합니다. 예를 들어 더하기 연산을 수행하기 위해 세 개의 매개변수가 필요한 함수를 생각해 보겠습니다.

 const total = (x, y, z) => x + y + z

이 함수를 적용하려면 curry() 메서드를 호출하고 매개변수로 total 값을 제공해야 합니다.

 const curriedTotal = curry(total)

함수를 실행하고 필요한 모든 입력을 제공하려면 모든 필수 인수를 함수에 전달하기만 하면 됩니다.

 console.log(curriedTotal(10)(20)(30)) // 60

자바스크립트 함수에 대한 추가 정보

자바스크립트는 함수에 대한 광범위한 기능을 제공하며, 그 중 하나는 커리 함수 기능을 포함합니다. 그러나 이는 자바스크립트가 제공하는 전반적인 유연성의 일부에 불과합니다. 화살표 함수, 생성자 함수, 익명 함수와 같은 다른 유형의 함수도 존재하며 각각 고유한 특성과 용도를 가지고 있습니다. 자바스크립트에 능숙해지려면 이러한 다양한 함수 유형과 그 구성 요소에 대해 숙지하는 것이 필수적입니다.

By 김민수

안드로이드, 서버 개발을 시작으로 여러 분야를 넘나들고 있는 풀스택(Full-stack) 개발자입니다. 오픈소스 기술과 혁신에 큰 관심을 가지고 있고, 보다 많은 사람이 기술을 통해 꿈꾸던 일을 실현하도록 돕기를 희망하고 있습니다.