본문 바로가기

개발공부/기술면접준비

[React]Class Component와 Function Component의 차이점

Class Component에 대해서

클래스 컴포넌트는 자바스크립트 및 웹 개발 컨텍스트에서 주로 리액트와 같은 프론트엔드 프레임워크 및 라이브러리에서 사용되는 개념이다.
리액트는 사용자 인터페이스를 구축하기 위한 인기 있는 자바스크립트 라이브러리이며, 컴포넌트를 만드는 두가지 주요 방법(함수 컴포넌트, 클래스 컴포넌트)을 제공한다.

Class Components에 관련된 주요 특징과 개념

  1. 클래스 문법
import React, { Component } from 'react';

class MyComponent extends Component {
  render() {
    return <div>Hello, World!</div>;
  }
}

클래스 컴포넌트는 ES6 클래스 문법을 사용하여 정의된다.
리액트의 'Component' 클래스를 확장하는 클래스를 만들고 메서드 내에서 컴포넌트의 동작을 정의한다.

  1. 상태관리
class Counter extends Component {
  constructor() {
    super();
    this.state = { count: 0 };
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

클래스 컴포넌트는 'this.state' 객체를 사용하여 로컬 컴포넌트 상태를 관리할 수 있다.
상태는 시간이 지남에 따라 변경될 수 있는 데이터를 저장하고 업데이트하며, 상태의 변경은 컴포넌트를 다시 렌더링한다.

  1. 라이프사이클 메서드
    클래스 컴포넌트는 'componentDidMount', 'componentDidUpdate', 'componentWillUnmount'와 같은 다양한 라이프사이클 메서드에 접근할 수 있다.
    이러한 메서드를 사용하여 컴포넌트의 수명 주기의 다양한 단계에서 컴포넌트의 동작을 제어할 수 있다.
  2. 복잡한 로직
    클래스 컴포넌트는 복잡한 로직, Side Effect, 고급 기능이 필요한 컴포넌트에 적합하다.
    클래스는 UI 렌더링과 동작을 동일한 클래스 내에서 캡슐화 할 수 있다.

클래스형 컴포넌트에는 이러한 특징들이 존재하지만, 함수형 컴포넌트가 더 간단하고 간결하며, 'useState'와 'useEffect'와 같은 훅을 사용하여 상태와 Side Effect를 관리할 수 있기 때문에 클래스형 컴포넌트 대신 함수형 컴포넌트를 사용하는것이 많은 개발자에게 권장되고 있다.

새로운 프로젝트를 시작하거나 기존 프로젝트를 리팩토링할 때는 클래스형 컴포넌트 대신 함수형 컴포넌트를 고려하는 것이 좋다.

Function Component

함수형 컴포넌트는 리액트에서 사용되는 컴포넌트의 유형 중 하나로, 사용자 인터페이스를 구성하고 정의하기 위한 자바스크립트 함수이다.
리액트의 함수 컴포넌트는 ES6의 화살표 함수나 일반 함수를 사용하여 작성할 수 있다.

Function Component의 특징

  1. 단순성과 간결성
import React from 'react';

const MyComponent = () => {
  return <div>Hello, World!</div>;
};

위 코드는 예제코드로, 함수 컴포넌트는 간단하고 직관적으로 작성할 수 있음을 보여준다.
클래스 컴포넌트보다 코드가 더 간결하며, 컴포넌트를 정의하는데 필요한 코드양이 적다.

  1. 상태관리
import React, { useState } from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

위 코드는 예제코드로, React 16.8부터 도입된 훅(Hook)을 사용하여 함수 컴포넌트에서도 상태를 관리할 수 있다.
'useState' 훅을 통해 상태를 추가하고 업데이트할 수 있다.

  1. Side Effect관리
import React, { useState, useEffect } from 'react';

const ExampleComponent = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    // 데이터 가져오기 등의 사이드 이펙트 처리
    // ...

    // 컴포넌트가 언마운트될 때 정리하는 함수
    return () => {
      // 정리 작업 수행
      // ...
    };
  }, []); // 빈 배열은 컴포넌트가 마운트될 때만 실행

  return <div>{data}</div>;
};

위 코드는 예제코드로, 'useEffect'훅을 사용하여 함수 컴포넌트 안에서 사이드 이펙트(ex. 데이터 가져오기, 구독 설정)를 관리할 수 있다.

함수 컴포넌트와 훅을 함께 사용하면 클래스 컴포넌트보다 코드를 더 간결하게 작성할 수 있으며, 상태와 사이드 이펙트를 효과적으로 관리할 수 있다.
함수 컴포넌트와 훅은 React 애프리케이션 개발에서 널리 사용되고 권장되는 패턴이다.

Class Component와 Function Component의 차이점?

  1. 클래스 컴포넌트
  • 문법
    • ES6의 클래스 문법을 사용하여 정의된다.
    • 'React.Component'클래스를 확장하여 컴포넌트를 만든다.
  • 상태관리
    • 'this.state'를 사용하여 컴포넌트의 상태(state)를 관리한다.
    • 'this.setState()'를 호출하여 상태를 업데이트하고, 상태 변경에 따라 컴포넌트가 다시 렌더링된다.
  • 생명주기 메서드
    • 'componentDidMount', 'componentDidUpdate', 'componentWillUnmount'등과 같은 생명주기 메서드를 활용하여 컴포넌트의 생명주기를 관리한다.
  • 복잡한 로직
    • 복잡한 로직, 사이드 이펙트, 상태 관리등을 처리하기에 적합하다.
  • 렌더링
    • 'render()'메서드를 사용하여 컴포넌트의 UI를 반환한다.
  1. 함수 컴포넌트
  • 문법
    • ES6의 함수 문법을 사용하여 정의된다.
    • 함수의 인자로 'props'를 받아와서 컴포넌트를 정의한다.
  • 상태관리
    • 'useState'훅을 사용하여 상태를 관리한다. 각 상태는 독립적으로 관리된다.
    • 'useState'를 호출하여 상태를 업데이트 하고, 상태 변경에 따라 컴포넌트가 다시 렌더링된다.
  • 생명주기 메서드
    • 함수 컴포넌트에서는 생명주기 메서드를 사용할 수 없다. 대신에 'useEffect'훅을 사용하여 사이드 이펙트를 관리한다.
  • 단순성과 간결성
    • 코드가 간결하고 직관적으로 작성된다. 클래스 컴포넌트보다 코드 양이 적다.
  • 렌더링
    • 함수의 반환값으로 컴포넌트의 UI를 정의한다.

어떤 상황에서 어떤 컴포넌트를 사용해야할까?

  • 클래스 컴포넌트
    • 복잡한 상태 또는 라이프사이클 관리가 필요한 경우
    • 클래스 기반의 라이브러리와 통합할 때(Redux, MobX 등)
  • 함수 컴포넌트
    • 간단한 컴포넌트 구현이나 단순한 UI를 만들때
    • 상태나 사이드 이펙트를 관리하기 위해 Hooks를 사용할때
    • 함수형 프로그래밍 패러다임을 선호하는 경우

리액트의 최신 버전에서는 함수 컴포넌트와 훅을 활용하는것이 권장되며, 함수 컴포넌트를 활용하면 코드가 간결하고 유지보수가 용이해지는 등 많은 이점을 얻을 수 있다.

Q. 사이드 이펙트 관리 : 클래스 컴포넌트 vs 함수 컴포넌트

  1. 클래스 컴포넌트로 사이드 이펙트 관리
  • 라이프사이클 메서드 사용 : 클래스 컴포넌트의 라이프사이클 메서드를 사용하여 사이드 이펙트를 관리하게 되면, 컴포넌트의 생명주기동안 호출되며, 특정 시점에서 사이드 이펙트를 실행하는 데 유용하다.
  • 상태 관리 및 메서드 : 클래스 컴포넌트 내에서 컴포넌트 상태와 메서드를 사용하여 상태 변경과 사이드 이펙트를 관리하면, 컴포넌트 내에 상태와 관련 메서드가 함께 존재하게 된다.
  1. 함수 컴포넌트로 useEffect훅을 사용하여 사이드 이펙트를 관리
  • useEffect 훅 사용 : 함수 컴포넌트에서 useEffect훅을 사용하여 사이드 이펙트를 관리하면, useEffect는 컴포넌트가 렌더링될 때, 업데이트될 때, 언마운트될 때 등 특정 시점에서 사이드 이펙트를 실행할 수 있도록 한다.
  • 함수형 접근 : 함수 컴포넌트는 함수의 형태로 정의되며, 상태 및 사이드이펙트 처리는 함수 내에서 이루어진다. 이로 인해 코드가 간결해지고, 상태관리와 UI렌더링이 분리된다.

주요 차이와 장점에 대해서도 살펴보자

  • 간결성 : 함수 컴포넌트와 'useEffect'를 사용하면 코드가 더 간결하고 읽기 쉬워진다.
  • 분리된 관심사 : 함수 컴포넌트에서 'useEffect'를 사용하면 상태 관리와 사이드 이펙트 처리가 분리되므로 컴포넌트의 관심사를 분리할 수 있다.
  • 라이프사이클 감소 : 함수 컴포넌트에서는 라이프사이클 메서드가 없기 때문에 라이프사이클 관련 복잡성이 줄어든다.
  • 유연성 : 'useEffect'를 사용하면 여러개의 사이드이펙트를 다루거나, 조건부로 사이드 이펙트를 실행하는 등의 유연성을 가질 수 있다.
  • 성능 최적화 : 'useEffect'를 사용하여 최적화에 필요한 작업을 수행할 수 있으며, 의존성 배열을 활용하여 불필요한 렌더링을 방지할 수 있다.

정리하자면, 함수 컴포넌트와 'useEffect'를 사용하는 것이 일반적으로 더 간결하고 유연한 접근방식이며, 리액트에서 함수형 프로그래밍 패러다임과 더 잘 어울린다. 클래스형 컴포넌트는 여전히 사용 가능하지만, 최신 리액트 코드에서는 함수 컴포넌트와 'useEffect'를 선호하는 경향이 있다.

Q. 상태 관리 : 클래스 컴포넌트(this.state) vs 함수 컴포넌트(useState)

  1. 클래스 컴포넌트에서 'this.state'사용
  • 클래스 문법(Class Syntax)
class Counter extends React.Component {
  constructor() {
    super();
    this.state = { count: 0 };
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

클래스 컴포넌트에서 'this.state'를 사용하여 상태를 관리할 때, ES6의 클래스 문법을 사용한다.

  • 상태 업데이트 : 상태를 업데이트 할 때, 'this.setState'메서드를 호출하여 새로운 상태를 설정한다. 이때, 현재 상태를 이용하여 상태를 업데이트한다.
  1. 함수 컴포넌트에서 'useState'훅 사용
  • 함수 문법(Function Syntax)
import React, { useState } from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

함수 컴포넌트에서 'useState'훅을 사용하여 상태를 관리할 때, 함수의 형태로 컴포넌트를 정의한다.

  • 상태업데이트 : 'useState'훅을 호출하여 현재 상태와 상태를 업데이트하는 함수를 반환받는다. 이 함수를 호출하여 새로운 상태를 설정한다.

주요 차이점에 대해서도 알아보자

  • 문법적인 차이 : 클래스 컴포넌트에서는 클래스 문법을 사용하고, 함수 컴포넌트에서는 함수 문법을 사용한다.
  • 상태 업데이트 방식 : 클래스 컴포넌트에서는 'this.setState'를 사용하여 상태를 업데이트하고, 함수 컴포넌트에서는 반환된 업데이트 함수를 사용하여 상태를 업데이트한다.
  • 단일상태 vs 각각의 상태 : 클래스 컴포넌트에서는 단일 객체 형태의 상태를 사용하고, 함수 컴포넌트에서는 'useState'훅을 사용하여 여러 개의 독립적인 상태를 사용할 수 있다.
  • 상태 병합(State Merging) : 'this.setState'를 사용할 때, 클래스 컴포넌트에서는 업데이트할 상태의 일부만 업데이트할 수 있다. 'useState'를 사용할 때, 함수 컴포넌트에서는 새로운 상태를 전체적으로 설정하므로 이전 상태를 고려하지 않는다.
  • Functional vs Class Component Paradigm(함수형 vs 클래스형 컴포넌트 패러다임) : 함수 컴포넌트와 'useState'훅은 함수형 프로그래밍 패러다임에 더 적합하며, 더 간결하고 유연한 코드를 작성할 수 있게 해준다. 클래스 컴포넌트는 기조느이 클래스 기반 프로그래밍에 익숙한 개발자들에게 친숙하며 복잡한 상태와 라이프사이클 관리에 적합나다.

결론적으로 리액트의 최신 버전에서는 함수 컴포넌트와 'useState'훅을 사용하여 상태를 관리하고, 더 간결하고 관리하기 쉬운 코드를 작성하는 것이 권장된다.

Q. Props 사용 : 클래스 컴포넌트 vs 함수 컴포넌트

  1. 클래스 컴포넌트에서의 Props사용
  • props속성
class MyComponent extends React.Component {
  render() {
    return <div>Hello, {this.props.name}!</div>;
  }
}

클래스 컴포넌트에서는 'this.props'를 통해 props에 접근한다.

  • 기본값 설정
MyComponent.defaultProps = {
  name: 'Guest'
};

클래스 컴포넌트에서는 'defaultProps'를 사용하여 props의 기본값을 설정할 수 있다.

  • propTypes 설정
MyComponent.propTypes = {
  name: PropTypes.string
};

'propTypes'를 사용하여 props의 데이터 타입을 지정할 수 있다.

  1. 함수 컴포넌트에서의 props 사용
  • 매개변수로 받기
const MyComponent = (props) => {
  return <div>Hello, {props.name}!</div>;
};

함수 컴포넌트에서는 함수의 매개변수로 props를 받아 사용한다.

const MyComponent = ({ name }) => {
  return <div>Hello, {name}!</div>;
};

또는 위 코드와 같이 ES6의 구조분해를 사용하여 특정 props만 추출할 수 있다.

  • 기본값 설정
const MyComponent = ({ name }) => {
  const displayName = name || 'Guest';
  return <div>Hello, {displayName}!</div>;
};

함수 컴포넌트에서는 함수 내에서 조건부 로직을 사용하여 기본값을 설정한다.

const MyComponent = ({ name = 'Guest' }) => {
  return <div>Hello, {name}!</div>;
};

또는 위 코드와 같이 ES6의 구조분해와 기본값을 설정할 수 있다.

  • PropTypes설정
import PropTypes from 'prop-types';

const MyComponent = ({ name }) => {
  return <div>Hello, {name}!</div>;
};

MyComponent.propTypes = {
  name: PropTypes.string
};

함수 컴포넌트에서는 'prop-types'라이브러리를 사용하여 props의 데이터 타입을 지정한다.

리액트의 최신버전에서는 함수 컴포넌트를 권장한다.
'useState'훅을 사용하여 상태를 관리하고, 매개변수로 props를 받아 사용하는 방식으로 간단하게 props를 다룰 수 있다.
'defaultProps'와 'propTypes'는 여전히 사용가능하지만, 함수 컴포넌트에서는 보통 조건부 로직과 ES6의 구조 분해를 활용하여 기본값을 설정하고 필요한 경우에 PropTypes를 사용하여 타입을 검증한다.

Q. 라이프사이클 : 클래스 컴포넌트 vs 함수 컴포넌트

  1. 클래스 컴포넌트의 주요 라이프 사이클 메서드
  • componentDidMount : 컴포넌트가 화면에 표시된 후(렌더링 이후) 호출된다. 주로 초기 데이터 가져오기, 구독설정, 타이머 시작과 같은 초기화 작업에 사용된다.
  • componentDidUpdate : 컴포넌트가 업데이트된 후 호출된다. 업데이트 이후의 작업을 수행할때 유용하며, 이전 props, state와 현재 props, state를 비교할 수 있다.
  • componentWillUnmount : 컴포넌트가 화면에서 제거되기 전 호출된다. 주로 구독을 해지하거나 타이머를 정리하는데 사용된다.
  • shouldComponentUpdate : 컴포넌트가 업데이트되기 전 호출되며, 업데이트 여부를 결정할 수 있다. 일반적으로 성능 최적화를 위해 사용된다.
  1. 함수 컴포넌트에서 라이프사이클과 비슷한 역할을 하는 훅
  • useEffect : 함수 컴포넌트에서 사이드 이펙트를 관리하는데 사용된다. 'useEffect'는 컴포넌트가 렌더링된 후, 업데이트된 후, 언마운트되기 전 등의 시점에서 콜백함수를 실행할 수 있다. 'componentDidMount', 'componentDidUpdate', 'componentWillUnmount'와 비슷한 역할을 한다.
  • useLayoutEffect : 'useEffect'와 비슷하지만 동기적으로 실행되며 레이아웃의 변화 전후에 작업을 수행할 때 사용된다.
  • useRef : DOM요소에 직접 접근하거나 컴포넌트의 인스턴스 변수를 만들 때 사용된다.
  • useState : 컴포넌트의 상태를 관리할 때 사용된다.

함수 컴포넌트에서는 클래스 컴포넌트와 달리 라이프사이클 메서드 대신 훅을 사용하여 컴포넌트의 생명주기를 관리한다. 'useEffect'는 여러 다양한 상황에 대응할 수 있으며, 함수 컴포넌트를 간결하게 작성할 수 있는 장점을 제공한다.

리액트 팀은 함수 컴포넌트와 훅을 라이프 사이클 메서드 대신 사용하도록 권장하고 있으며, 미래버전에서 클래스 컴포넌트의 일부 라이프사이클 메서드가 사라질 가능성이 있다......

Q. 라이프사이클 vs 라이프사이클 API?

  1. 라이프사이클
  • 라이프사이클은 리액트 컴포넌트의 생명주기 동안 발생하는 이벤트와 메서드를 가리킨다. 이러한 라이프사이클 이벤트와 메서드는 컴포넌트가 생성되고 업데이트되며 화면에 표시되고 제거될때의 단계를 나타낸다.
  • 예를들어, 'componentDidMount', 'componentDidUpdate', 'componentWillUnmount', 'shouldComponentUpdate'와 같은 라이프사이클 메서드가 있으며, 이러한 메서드를 통해 컴포넌트의 동작을 제어하고 관리할 수 있다.
  • 라이프사이클 메서드를 클래스 컴포넌트 내에서 사용하여 컴포넌트의 동작을 제어한다.
  1. 라이프사이클 API
  • 라이프사이클 API는 리액트 컴포넌트의 라이프사이클 이벤트와 메서드를 활용하여 컴포넌트의 동작을 제어하고 관리할 수 있는 일련의 API함수 및 도구이다.
  • 주요 라이프사이클 API로는 'componentDidMount', 'componentDidUpdate', 'componentWillUnmount', 'shouldComponentUpdate' 그리고 React 16.3 이후에 도입된 'getDerivedStateFromProps', 'getSnapshotBeforeUpdate' 등이 있다.
  • 라이프사이클 API를 사용하여 특정 라이프사이클 단계에서 원하는 작업을 수행하거나, 컴포넌트 업데이트를 제어하고 데이터를 처리할 수 잇다.

라이프사이클은 리액트 컴포넌트의 생명주기를 설명하는 개념이며, 라이프사이클 API는 이러한 라이프사이클 단계에서 수행되는 작업을 구체화하고 컴포넌트의 동작을 제어하기 위한 도구 및 API함수의 집합이다.
이러한 API는 클래스 컴포넌트에서 주로 사용되며, 함수 컴포넌트에서는 'useEffect'훅 등을 사용하여 비슷한 기능을 수행한다.