프론트엔드 첫걸음

익명함수와 클로저, 커링 본문

개발 공부/Javascript

익명함수와 클로저, 커링

차정 2024. 12. 23. 08:52

 

익명함수의 기능을 제대로 모르고 사용하는 경우가 많습니다.
익명함수의 기능을 제대로 짚고 , 커링함수 라는 것도 알아봅시다.

 

익명 함수란?

익명 함수는 이름이 없는 함수로, 주로 특정 문맥에서 단일 작업을 수행하기 위해 사용됩니다. 리액트에서 익명 함수는 화살표 함수 형태로 많이 사용됩니다. 예를 들어:

() => console.log("This is an anonymous function");​

익명 함수는 다음과 같은 특징을 가집니다:

  1. 이름이 없다: 특정 작업에만 사용되며 재사용되지 않습니다.
  2. 클로저로 상위 스코프의 변수 접근: 익명 함수 내부에서 상위 스코프의 변수에 접근 가능합니다.
  3. 주로 즉시 실행하거나 이벤트 핸들러로 전달: 한 번만 사용되기 때문에 이벤트 핸들러나 일회성 로직에서 유용합니다.

 

 

리액트에서 익명 함수의 역할

리액트에서 익명 함수는 컴포넌트의 이벤트 핸들러에서 특정 값을 전달하거나 상태를 고정하기 위해 주로 사용됩니다.

예시: 익명 함수로 handleAction 호출

아래 코드를 보면, onClick에 직접 handleAction을 넣는 대신, 익명 함수를 사용하고 있습니다.

const Example = () => {
  const index = 1;

  const handleAction = (index: number, message: string) => {
    console.log(`Index: ${index}, Message: ${message}`);
  };

  return (
    <button onClick={() => handleAction(index, "Clicked!")}>
      Click Me
    </button>
  );
};

 

왜 익명 함수를 사용하는가?

onClick 이벤트 핸들러는 리액트가 자동으로 MouseEvent를 넘기도록 설계되어 있습니다. 따라서 아래처럼 함수만 넣으면 MouseEvent가 기본 전달됩니다:

<button onClick={handleAction}>Click Me</button>;

하지만 handleAction은 (index: number, message: string) 타입의 매개변수를 요구하므로, 바로 넣을 수 없습니다. 이 문제를 해결하려면 익명 함수를 사용해 적절한 값을 전달합니다:

<button onClick={() => handleAction(index, "Clicked!")}>Click Me</button>;

익명 함수가 하는 일:

  1. MouseEvent를 무시: 기본적으로 전달되는 MouseEvent를 처리하지 않습니다.
  2. 상위 스코프의 변수(index)를 클로저로 기억: index 값을 함수가 생성될 때 고정합니다.
  3. 추가 매개변수 전달 가능: 익명 함수 내부에서 handleAction 호출 시 매개변수를 조합하여 전달합니다.
 

익명 함수와 클로저의 관계

익명 함수는 클로저의 중요한 특성을 활용합니다:

  • 클로저: 함수가 생성된 시점의 상위 스코프의 변수를 기억하는 특성입니다.
  • 위 코드에서 index는 익명 함수가 생성될 때 상위 스코프의 값으로 고정됩니다.
 
어떤 버튼컴포넌트가 있습니다.
이 버튼컴포넌트는 클릭할 때 날짜를 만들어서 onClick함수에 넘깁니다.
import React from 'react';

interface ButtonProps {
  onClick: (date: Date) => void; // date만 받는 핸들러
}

const Button: React.FC<ButtonProps> = ({ onClick }) => {
  const handleClick = () => {
    const today = new Date(); // 클릭 시 날짜 생성
    onClick(today);
  };

  return <button onClick={handleClick}>Click Me</button>;
};

export default Button;

 


그리고 버튼 컴포넌트를 사용하는 부모 컴포넌트는 인덱스와 날짜를 같이 출력하는 함수를 Button컴포넌트에 넘깁니다.
import React from 'react';
import Button from './Button';

const ParentComponent = () => {
  const index = 1; // 상위 스코프에서 관리되는 값

  const handleAction = (index: number, date: Date) => {
    console.log(`Index: ${index}, Date: ${date}`);
  };

  return (
    <Button onClick={(date) => handleAction(index, date)} />
  );
};

export default ParentComponent;

 

  1. 버튼 컴포넌트:
    • onClick으로 date => void 타입의 함수를 받습니다.
    • 버튼 클릭 시 handleClick이 실행되고, new Date() 값을 onClick으로 전달합니다.
  2. 부모 컴포넌트:
    • 부모 컴포넌트의 handleAction은 (index: number, date: Date) => void 타입입니다.
    • Button의 onClick은 date => void 타입이므로, 익명 함수 (date) => handleAction(index, date)를 전달합니다.
  3. 익명 함수의 역할:
    • 버튼에서 전달한 date를 받습니다.
    • index는 상위 스코프에서 클로저로 기억되어, handleAction(index, date)에 전달됩니다.
    • 익명함수는 상위스코프의 index를 기억하는 클로저 역할을 합니다.

익명 함수와 매개변수 개수의 연결

  • 익명 함수는 상위 스코프의 변수(index)와 이벤트 핸들러의 매개변수(date)를 조합하여 함수 호출을 가능하게 합니다.
  • date => void 타입과 (index, date) => void 타입의 함수 사이를 연결하는 다리 역할을 합니다.
  • 익명 함수는 매개변수를 고정하거나 새로운 매개변수를 추가하는 역할을 합니다.
onClick={(date) => handleAction(index, date)}
 
위 코드는 익명 함수 (date) => {...}가 다음과 같은 역할을 합니다:
  1. date를 전달받습니다.
  2. index는 익명 함수가 정의된 시점에 이미 고정된 값입니다.
  3. handleChangeEndDate에 index와 date를 전달합니다.
 

 

 

 

 

익명 함수는 유연하지만 매번 새로운 함수를 생성해야 하므로 성능에 영향을 줄 수 있습니다.
커링을 활용하면 이 문제를 해결하면서 코드의 재사용성과 가독성을 높일 수 있습니다.
 

커링으로 변환

const createActionHandler = (index: number) => {
  return (message: string) => {
    console.log(`Index: ${index}, Message: ${message}`);
  };
};

const Example = () => {
  const index = 1;

  const handleAction = createActionHandler(index); // 커링된 함수 생성

  return (
    <button onClick={() => handleAction("Clicked!")}>
      Click Me
    </button>
  );
};
 
 

 

동작 과정

  1. createActionHandler를 호출:
    • index = 1을 고정한 새로운 함수 생성.
    • 반환된 함수는 (message: string) => void 타입.
  2. 버튼 클릭:
    • 반환된 함수가 실행되며, message = "Clicked!"가 전달됩니다.
 

커링 방식의 장점

  1.  매개변수 고정: createActionHandler 호출 시 index가 고정됩니다.
  2. 재사용성 증가: 고정된 index를 가진 핸들러를 여러 곳에서 재사용 가능합니다.
  3. 동적 생성 가능: 다른 상황에서도 새로운 매개변수 조합을 동적으로 생성할 수 있습니다.
 
 

결론

  • 익명 함수는 특정 변수 고정매개변수 전달을 위해 리액트에서 매우 유용하게 사용됩니다.
  • 클로저를 활용해 상위 스코프의 변수를 기억하며, 이벤트 핸들러의 제한을 우회합니다.
  • 반복적 사용이나 성능 최적화가 필요한 경우, 커링을 통해 익명 함수의 역할을 대체할 수 있습니다.

익명 함수는 간단한 이벤트 핸들링에 적합하지만, 복잡한 로직이 필요한 경우에는 커링을 사용하는 것이 더 좋은 선택이 될 수 있습니다.