본문 바로가기
Front-End/React

React 컴포넌트 구현 방식 비교: 화살표 함수 vs 일반 함수

by jakejeong 2025. 2. 7.

React 컴포넌트를 작성할 때 우리는 크게 두 가지 함수 선언 방식을 사용할 수 있습니다: 화살표 함수(Arrow Function)와 일반 함수 선언(Function Declaration). 이 두 방식의 차이점과 각각의 장단점을 자세히 살펴보겠습니다.

1. 문법적 차이

일반 함수 선언 방식

function Greeting(props) {
  return <h1>안녕하세요, {props.name}님!</h1>;
}

// 또는 함수 표현식으로도 가능
const Greeting = function(props) {
  return <h1>안녕하세요, {props.name}님!</h1>;
};

화살표 함수 방식

const Greeting = (props) => {
  return <h1>안녕하세요, {props.name}님!</h1>;
};

// 더 간단한 형태로도 가능
const Greeting = props => <h1>안녕하세요, {props.name}님!</h1>;

2. this 바인딩의 차이

이것은 두 방식의 가장 큰 차이점 중 하나입니다.

일반 함수의 this

function UserProfile() {
  this.state = { name: '김철수' };

  function handleClick() {
    console.log(this.state); // undefined - this가 올바르게 바인딩되지 않음
  }

  // 해결방법 1: bind 사용
  const handleClickBound = handleClick.bind(this);

  // 해결방법 2: 화살표 함수로 래핑
  const handleClickWrapper = () => {
    handleClick();
  };
}

화살표 함수의 this

function UserProfile() {
  this.state = { name: '김철수' };

  // 화살표 함수는 렉시컬 스코프의 this를 유지
  const handleClick = () => {
    console.log(this.state); // { name: '김철수' } - 정상 작동
  };
}

3. 사용 사례별 비교

간단한 프레젠테이션 컴포넌트

// 화살표 함수 - 간결하고 읽기 쉬움
const Button = ({ onClick, children }) => (
  <button onClick={onClick}>{children}</button>
);

// 일반 함수 - 더 전통적인 형태
function Button({ onClick, children }) {
  return (
    <button onClick={onClick}>{children}</button>
  );
}

복잡한 로직을 포함한 컴포넌트

// 화살표 함수
const ComplexComponent = () => {
  const [count, setCount] = useState(0);
  const [name, setName] = useState('');

  const handleIncrement = () => {
    setCount(prev => prev + 1);
  };

  const handleNameChange = (e) => {
    setName(e.target.value);
  };

  return (
    <div>
      <p>카운트: {count}</p>
      <button onClick={handleIncrement}>증가</button>
      <input value={name} onChange={handleNameChange} />
    </div>
  );
};

// 일반 함수
function ComplexComponent() {
  const [count, setCount] = useState(0);
  const [name, setName] = useState('');

  function handleIncrement() {
    setCount(prev => prev + 1);
  }

  function handleNameChange(e) {
    setName(e.target.value);
  }

  return (
    <div>
      <p>카운트: {count}</p>
      <button onClick={handleIncrement}>증가</button>
      <input value={name} onChange={handleNameChange} />
    </div>
  );
}

4. 장단점 분석

화살표 함수의 장점

  1. 간결한 문법으로 코드가 더 깔끔해짐
  2. this 바인딩 문제를 자동으로 해결
  3. 암시적 반환(implicit return)을 사용하여 한 줄로 컴포넌트 작성 가능
  4. 모던 자바스크립트의 트렌드와 일치

화살표 함수의 단점

  1. prototype 속성이 없어 메서드를 추가할 수 없음
  2. constructor를 사용할 수 없음
  3. 가독성이 떨어질 수 있는 경우가 있음 (특히 복잡한 로직의 경우)

일반 함수의 장점

  1. 더 전통적이고 익숙한 문법
  2. 프로토타입 메서드 추가 가능
  3. constructor 사용 가능
  4. 호이스팅으로 인한 유연성

일반 함수의 단점

  1. this 바인딩을 수동으로 처리해야 하는 경우가 있음
  2. 상대적으로 더 장황한 문법
  3. 화살표 함수에 비해 모던하지 않은 느낌

5. 권장 사용 패턴

화살표 함수를 사용하기 좋은 경우

// 1. 간단한 프레젠테이션 컴포넌트
const Header = ({ title }) => <h1>{title}</h1>;

// 2. 콜백 함수
const List = () => {
  const items = ['사과', '바나나', '오렌지'];
  return (
    <ul>
      {items.map(item => <li key={item}>{item}</li>)}
    </ul>
  );
};

// 3. 이벤트 핸들러
const Form = () => {
  const handleSubmit = (e) => {
    e.preventDefault();
    // 처리 로직
  };

  return <form onSubmit={handleSubmit}>...</form>;
};

일반 함수를 사용하기 좋은 경우

// 1. 복잡한 클래스 컴포넌트 대체
function ComplexComponent() {
  // 여러 메서드와 생명주기 관련 로직
  useEffect(function setupComponent() {
    // 명확한 함수명으로 인한 가독성 향상
  }, []);

  function handleComplexLogic() {
    // 복잡한 비즈니스 로직
  }

  return <div>...</div>;
}

// 2. 재사용 가능한 고차 컴포넌트
function withAuth(WrappedComponent) {
  return function AuthWrapper(props) {
    const isAuthenticated = useAuth();

    if (!isAuthenticated) {
      return <Navigate to="/login" />;
    }

    return <WrappedComponent {...props} />;
  };
}

결론

  1. 간단한 컴포넌트나 이벤트 핸들러의 경우 → 화살표 함수
  2. 복잡한 로직이나 명확한 이름이 필요한 경우 → 일반 함수
  3. 팀의 컨벤션을 따르는 것이 가장 중요

중요한 것은 일관성 있는 코드 스타일을 유지하는 것입니다. 팀 프로젝트의 경우 팀원들과 합의된 방식을 사용하는 것이 좋습니다.

반응형