본문 바로가기

카테고리 없음

React Class Component vs Function Component 설명 및 비교

더보기

요약(Summary): React 에서 Class Component와 Function Component의 차이점에 대해 설명하였습니다. 결론적으로 React 버전 16.8 이후로는 기능상의 차이점은 거의 없다고 할 수 있으며 Function Component가 아주 미세하게 Class Component보다 메모리 효율적이라고 할 수 있습니다.

리액트 네이티브를 이용해서 개인 프로젝트인 사진 공유 어플리케이션을 만들던 중 React를 이용해 컴포넌트를 생성할 때에 **클래스(Class)**를 이용해서 컨포넌트를 생성하는 방법과 **함수(Function)**를 이용해서 컴포넌트를 생성하는 방법을 알게 되었습니다. 그래서 어플리케이션 내에서 이 둘 중 어느 것을 사용하는 게 더 좋은 지에 대해서 고민을 하게 되었고, 이 둘의 차이점을 글로 정리해서 남기기로 하였습니다. 그리고 이 방법의 차이점을 비교하고 원하는 기능에 따라서 어떠한 방법을 사용하는 것이 적합한지 정리해두면 개발자 분들에게 도움이 되었으면 합니다.

 

먼저 React에서 컴포넌트란 각종 UI들을 독립적이고, 재사용 할 수 있는 단위로서 개발을 편리하게 만들어 주는 도구입니다. 가령 모바일 어플리케이션을 생각했을 때에, 어플리케이션이 한 화면으로 구성되어 있는 경우는 매우 드문데 이를 하나의 UI 단위를 통해서 구현을 한다면 개발자의 입장에서 가독성이나 관리가 무척 어려울 것입니다. 그래서 컴포넌트를 사용하면 어플리케이션의 화면(로그인 화면, 메인 화면)을 구분하여 각각의 컴포넌트로 정의를 하므로써 중요한 기능을 담당하게 되는 것입니다.

 

그렇다면 클래스형 컴포넌트와 함수형 컴포넌트는 결국 앞서 정의한 같은 목적을 위해서 있는 것인데 어떤 점에서 차이가 있는 것일까요?

Class Component


클래스형 컴포넌트와 함수형 컴포넌트가 같은 목적을 지니지만, 클래스형 컴포넌트는 함수형 컴포넌트보다 더 편리하게 사용할 수 있는 기능들을 포함하고 있습니다. 가령 State를 통해서 컴포넌트 내의 로컬 변수를 나타내거나, Component Lifecycle의 메서드를 이용해서 컴포넌트가 특정 상황에서 특정한 동작을 하게 만들 수 있습니다.

 

class Welcome extends React.Component {
  render() {
    return <h1>Hello, world!</h1>;
  }
}

 

 

위 코드는 클래스형 컴포넌트를 사용하는 기초적인 예시라고 할 수 있습니다. 단순히 위 코드가 가지고 있는 기능만을 원한다면 함수형 컴포넌트와 동일하다고 할 수 있지만, 클래스형 컴포넌트는 아래와 같이 State를 이용해서 컴포넌트 내의 로컬 변수를 지정할 수 있습니다.

 

class Welcome extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
    }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
		);
	}
}

 

이러한 방식으로 Date()를 클래스형 컴포넌트의 State로 지정하므로서 컴포넌트 내에서 해당 변수를 사용할 수 있게 되는 것입니다. 또한 클래스형 컴포넌트는 Component Lifecycle을 이용해서 특정한 상황에서 특정한 기능이 동작하도록 할 수 있습니다. 예를 들어서 componentDidMount()를 이용해서 컴포넌트의 아웃풋이 렌더링 된 후에 특정 동작을 하게 할 수도 있고, componentWillUnmount() 컴포넌트의 라이프사이클이 종료되었을 때에 특정 동작이 실행되도록 할 수도 있습니다.

 

React documentation: 리액트 컴포넌트 라이프사이클

 

React Lifecycle Methods diagram

Fully interactive and accessible React Lifecycle Methods diagram.

projects.wojtekmaj.pl

반면 함수형 컴포넌트는 이러한 복잡한 작업을 하는게 불가능... 했었습니다. 하지만 React 버전 16.8에 새롭게 Hook이 추가되면서 이러한 작업들이 가능하게 되었습니다.

Function Component


React 버전 16.8이 나오기 전까지의 함수형 컴포넌트는 클래스형 컴포넌트에 비해서 제한된 작업들을 하는 데에만 사용되었습니다. 이는 클래스형 컴포넌트에서 사용하던 State나 Component Lifecycle에 정의된 메소드들을 사용하지 못했기 때문입니다. 이는 이후 추가된 Hook이라는 기능을 통해서 해결되었는데, 이 기능이 없는 상태에서 함수형 컴포넌트의 기본형을 살펴보겠습니다.

 

function Welcome(props) {
  return <h1>Hello, world</h1>;
}

 

 

위의 함수형 컴포넌트는 앞서 살펴보았던 클래스형 컴포넌트의 기본형과 동일한 기능을 담당합니다. 보시면 형태가 비슷한 듯 하면서 다른 것을 관찰하실 수 있습니다. 그렇다면 React 버전 16.8 이후에 나온 Hook을 추가하면서 함수형 컴포넌트 내에서도 State와 Component Lifecycle을 사용할 수 있다고 하였는데 Hook을 어떻게 하면 사용할 수 있는 지 알아보겠습니다.

 

import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"  
	const [count, setCount] = useState(0);

	return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
	);
}

 

위 코드는 함수형 컴포넌트 내에서 State를 사용하는 방법입니다. 이는 useState 함수를 react로 부터 불러오고 이를 이용해서 상태를 정의, 변경하는 방식으로 사용되게 됩니다. 위의 예시처럼 [count, setCount] = useState(0)을 이용한다면 1) count라는 State를 만들고, 2) count를 변경할 수 있는 함수인 **setCount()**를 만들고, 3) 0 이라는 값으로 count를 초기화 하게 됩니다. 코드를 이해하시면 이 컴포넌트가 버튼을 클릭할 때마다 클릭한 총 횟수를 보여주는 것이라는 것을 알 수 있습니다.

 

다음은 함수형 컴포넌트 내에서 LifeCycle을 사용하는 방법입니다.

 

import React, { useEffect } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"  
	const [count, setCount] = useState(0);

	useEffect(() => {
    return () => {
	  };
	});

	return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
	);

 

위의 코드와 같이 함수형 컴포넌트 내부에 useEffect를 정의해주면 앞서 클래스형 컴포넌트의 componentDidMount()나 componentWillUnmount()와 같은 케이스에 어떤 동작을 할 지 지정해 줄 수 있습니다.

 

useEffect(
    function() {
      // componentDidMount의 경우의 동작 수행
      return function() {
        // componentWillUnMount의 경우의 동작 수행
      };
    },
    []
  );
 
  useEffect(
    function() {
			// number의 값이 변했을 때 동작 수행
      return function() {
				// number의 값이 변했을 때 동작 수행
      };
    },
    [number]
  );

 

가령 useEffect의 두 번째 인자에 빈 배열 []를 주었을 떄는 componentDidMount(), componentWillUnMount()의 동작이 수행하도록 할 수 있고, 배열 내부에 값을 지정해주면 값이 변했을 때에 특정한 동작을 하도록 구현할 수 있습니다.

Class Component VS Function Component

기본적으로 함수형 컴포넌트는 클래스형 컴포넌트보다 메모리를 덜 사용하는 장점이 있지만 State나 Component LifeCycle을 사용하지 못하는 단점이 있었습니다. 하지만 Hook의 등장 이후 함수형 컴포넌트 내에서도 이러한 복잡한 기능들을 수행할 수 있게 되면서 이러한 단점이 사라졌다고 할 수 있습니다. 그리고 함수형 컴포넌트의 경우에는 선언이나 사용하기도 편리하기 때문에 둘 중 하나를 사용한다면 함수형 컴포넌트를 사용하는 것이 좋다는 느낌을 받았습니다.

하지만 현재의 많은 코드 내에서 클래스형 컴포넌트가 사용되고 있기 때문에 기존 코드의 유지 보수 등을 위해서는 클래스형 컴포넌트의 개념은 아는 게 좋을 것 같다는 생각이 들었습니다.

 

한 가지 더 첨언을 하자면 함수형 컴포넌트가 클래스형 컴포넌트에 비해서 더 메모리에 효율적으로 사용할 수 있지만 그 둘의 차이는 크지 않습니다. 오히려 코드가 어떤 식으로 구성되어 있느냐가 더 큰 영향을 주기 때문에 결론적으로는 둘 중 어느것을 사용하든지 상관은 없지만, 함수형 컴포넌트가 더 우세적인 사실은 틀리지 않다고 말씀드릴 수 있겠습니다.

Reference

https://reactjs.org/docs/components-and-props.html

https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

https://reactjs.org/docs/hooks-intro.html