Contents

React 함수 컴포넌트와 클래스 컴포넌트

리액트에서는 클래스 컴포넌트와, 함수 컴포넌트를 둘 다 사용할 수 있다.

다만 요즘에는 함수 컴포넌트가 많이 선호되는 추세이고, 클래스 컴포넌트는 거의 사용하지 않는 것 같았다.

둘이 어떤 차이가 있으며, 왜 함수 컴포넌트가 대세로 사용되고 있는지 궁금해서 찾아봤다.

문법

함수 컴포넌트와 클래스 컴포넌트 간 가장 큰 차이점은 문법이다.

  • 함수 컴포넌트는 prop들을 인자로 받아서 React element를 리턴하는 단순한 자바스크립트 함수이다.
  • 클래스 컴포넌트는 React.Component를 상속하는 것이 요구되며
    • render() 함수를 통해 React element를 리턴한다.
    • 이 방법은 더 많은 코드를 작성해야 하지만 뒤에 설명할 몇 가지 이점도 존재한다.

Babel을 통해 트랜스파일된 코드를 보게 된다면 몇 가지 차이점을 알 수 있다.

function Welcome(props) {
return _react2.default.createElement(
	'h1',
	null,
	'Hello, ',
	props.name
	);
}

함수 컴포넌트는 위와 같이 트랜스파일되고

var Welcome = function (_React$Component) {
	_inherits(Welcome, _React$Component);

	function Welcome() {
		__classCallCheck(this, Welcome);
		return _possibleConstructorReturn(this, (Welcome.__proto__ || Object.getPrototypeOf(Welcome)).apply(this, arguments));
	}

	_createClass(Welcome, [{
		key: 'render',
		value: function render() {
			return _react2.default.createElement(
				'h1',
				null,
				'Hello, ',
				this.props.name
			);
		}
	}]);

	return Welcome;
}(_react2.default.Component);

클래스 컴포넌트는 위와 같이 트랜스 파일된다.

상태의 사용 / 라이프사이클 훅

함수 컴포넌트는 단순한 자바스크립트 함수이기 때문에, 컴포넌트 내부에서 setState()를 할 수 없었다. (리액트 16.8 버전에서 훅스가 업데이트 되면서 함수 컴포넌트 내부에서 useState 할 수 있도록 변경되긴 했다)

그러니까 예전에는.. 함수 컴포넌트를 stateless 컴포넌트라고 정의할 수 있었다. 비슷한 맥락에는 컴포넌트 내부에 상태가 필요할 경우 클래스 컴포넌트를 사용하거나, 부모 컴포넌트에 대신 상태를 만들어서 props로 내려줘야 했었다. (언급했지만 지금은 틀린 말이 되었다 - 기저에 깔린 철학과는 달리 사용은 할 수 있다)

마찬가지로 예전에 함수 컴포넌트는 라이프사이클 훅을 사용할 수 없었지만, 리액트 버전이 업데이트 된 이후부터는 이것도 지원하게 되었기 때문에 틀린 말이 되었다.

함수 컴포넌트가 사랑 받는 이유

함수 컴포넌트를 사용하지 않고 클래스 컴포넌트만 사용해서 개발하여도 아무 상관 없다.

하지만 리액트에서 함수 컴포넌트를 사용했을 때의 이점으로는 다음이 있다.

  1. 함수 컴포넌트는 코드를 읽고 테스트하기 훨씬 쉽다.
    1. plain한 자바스크립트 함수이기 때문이다.
  2. 코드를 적게 쓴다.
  3. 구조를 개선하기 쉽다.
    1. 컴포넌트의 상태에 대해 더 많이 생각해야 하기 때문에 컨테이너와 표현 계층의 컴포넌트를 분리하기 쉬워진다.
  4. 리액트 팀이 함수 컴포넌트에 대한 지원을 늘리고 있기 떄문에, 미래에는 클래스 컴포넌트와 비교하여 성능적인 이점이 더 생길 수도 있다.

앞서 언급했던 리액트 16.8 버전 업데이트부터는 함수 컴포넌트에 대해 훅스 지원이 추가되었다.

예전처럼 함수 컴포넌트 내부에서 useState를 사용하지 못하는 것도 아니고, 다양한 라이프사이클 훅도 사용할 수 있게 되었다.

클래스 컴포넌트는 React.Component를 상속 받기 때문에,

  • 상태와 라이프사이클 메서드들을 React.Component와 같이 연관지어 사용한다.
  • 이 것들은 상속 시점에 이미 존재하기 때문에 라이프사이클 이벤트들이 어떻게 일어나고 상태를 관리하기 위해 어떻게 응답해야 하는지를 더 이해하기 쉬운 면이 있다.
  • 한편 클래스 컴포넌트는 데이터를 위해 API 호출을 할 때 생성자를 통한 추가 셋업 과정이 필요하다.
  • 서로 다른 클래스 객체 간에 디자인 패턴의 적용 없이는 공유되는 로직을 구현하기는 매우 어렵다.
    • 이것 때문에 어플리케이션이 크고 복잡해졌을 때 클래스 컴포넌트는 유지보수 하기 어려운 코드가 되는 경우가 많다.

또, 함수 컴포넌트는 Composition을 사용하는 반면 클래스 컴포넌트는 Inheritance를 사용한다는 차이가 있다.