React.Component — 클래스 컴포넌트와 작동 방식

저자: IT Sectr 게시일: 2026-07-04 읽는 시간: 9 분

React.Component는 React에서 상속을 사용하여 컴포넌트를 생성하기 위한 기본 클래스입니다. 버전 16.8에서 훅이 도입되기 전에는 클래스 컴포넌트가 상태와 생명주기를 관리하는 유일한 방법이었습니다. React, 2024에 따르면, 클래스 컴포넌트는 여전히 지원되지만, 새 프로젝트에는 훅이 있는 함수형 컴포넌트가 권장됩니다.

핵심 사항

  • React.Component는 클래스 컴포넌트가 extends Component를 통해 상속받는 기본 클래스입니다.
  • 상태(State)는 this.state를 통해 관리되며 this.setState를 통해서만 업데이트됩니다 — 직접 변경은 금지됩니다.
  • 생명주기에는 componentDidMount, componentDidUpdate 및 componentWillUnmount 메서드가 포함됩니다.
  • this는 클래스 메서드에서 컨텍스트 바인딩이 필요합니다 — bind, 화살표 함수 또는 class fields를 통해.
  • 마이그레이션은 점진적으로 가능합니다: 훅과 클래스는 동일한 프로젝트에서 공존할 수 있습니다.

React.Component란?

React.Component는 상태, props 및 컴포넌트 생명주기 작업을 위한 내장 메서드를 제공하는 추상 클래스입니다. 클래스 컴포넌트를 만들려면 React.Component를 확장하는 클래스를 정의하고 render 메서드를 구현해야 합니다.

React.Component는 React의 첫 번째 버전(2013)에서 등장했으며, 5년 동안 컴포넌트를 만드는 주요 방식으로 남아 있었습니다. React 생태계는 클래스를 중심으로 구축되었습니다: 고차 컴포넌트(HOC), render props, 컨텍스트 — 이러한 모든 패턴은 클래스 구문을 사용하여 구현되었습니다.

2019년 React 16.8 출시와 함께 React 팀은 클래스의 대안으로 을 도입했습니다. 훅은 동일한 문제 — 상태, 효과, 컨텍스트 — 를 해결했지만, 상속과 복잡한 컨텍스트 바인딩 없이 해결했습니다. React.Component는 완전히 지원되지만, 새 프로젝트에는 함수형 접근 방식이 권장됩니다.

클래스 컴포넌트 만들기

최소한의 클래스 컴포넌트는 React 요소를 반환하는 단일 render 메서드를 가진 클래스입니다. render는 유일한 필수 메서드입니다. this.props와 this.state의 순수 함수여야 합니다: 동일한 props와 상태 세트는 동일한 결과를 생성합니다.

js
import React, { Component } from 'react';

class Welcome extends Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

생성자와 상태 초기화

생성자는 마운팅 전에 실행됩니다. 부모 클래스에 props를 전달하기 위해 super(props)를 호출하고 this.state를 초기화합니다. 생성자를 다른 목적 — 구독, API 호출 — 에 사용하는 것은 권장되지 않습니다. 이를 위한 componentDidMount가 있습니다.

js
class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  render() {
    return <p>Count: {this.state.count}</p>;
  }
}

this.state와 this.setState를 통한 상태 관리

this.state는 컴포넌트의 데이터를 포함하는 객체입니다. 직접 변경하는 것(this.state.count = 1)은 금지됩니다 — 리렌더링을 트리거하지 않으며 예측 가능성을 깨뜨립니다. 상태는 this.setState를 통해 업데이트되어야 하며, 새 상태 객체를 생성하고 리렌더링을 트리거합니다.

setState는 객체나 함수를 받을 수 있습니다. 새 상태가 이전 상태에 의존하는 경우 함수형이 선호됩니다: this.setState(prev => ({ count: prev.count + 1 })). React는 성능 최적화를 위해 여러 setState 호출을 하나의 배치로 그룹화할 수 있습니다.

js
class Toggle extends Component {
  constructor(props) {
    super(props);
    this.state = { isOn: false };
  }

  handleClick() {
    this.setState(prev => ({ isOn: !prev.isOn }));
  }

  render() {
    return (
      <button onClick={() => this.handleClick()}>
        {this.state.isOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

setState의 중요한 특성은 비동기라는 것입니다. setState를 호출한 후 상태가 즉시 업데이트되지 않습니다. 업데이트 후 작업을 수행해야 하는 경우 두 번째 인수로 콜백을 전달하세요: this.setState(newState, () => console.log(this.state)).

생명주기 메서드

클래스 컴포넌트에는 React가 특정 시점에 호출하는 미리 정의된 메서드가 있습니다. 마운팅 — constructor → render → componentDidMount. 업데이트 — render → componentDidUpdate. 언마운팅 — componentWillUnmount.

메서드단계목적
constructor마운팅상태 초기화 및 메서드 바인딩
render매번React 요소 반환 (필수)
componentDidMount마운팅 후API 요청, 구독, 타이머
componentDidUpdate업데이트 후props/상태 변경에 반응
componentWillUnmount제거 전구독, 타이머, 이벤트 리스너 정리

ComponentDidMount — 데이터 가져오기

componentDidMount는 첫 번째 렌더링 후 사이드 이펙트를 위한 주요 위치입니다. 여기서 HTTP 요청을 수행하고, WebSocket 연결을 설정하고, 타이머를 시작합니다. componentWillUnmount에서 구독을 정리하지 않으면 메모리 누수가 발생합니다.

js
class UserProfile extends Component {
  componentDidMount() {
    fetch(`/api/users/${this.props.userId}`)
      .then(res => res.json())
      .then(data => this.setState({ user: data }));
  }

  componentWillUnmount() {
    // Cancel request on unmount
  }

  render() {
    return <div>{this.state.user?.name}</div>;
  }
}

메서드에서 this 컨텍스트 바인딩

JavaScript에서 클래스 메서드는 기본적으로 인스턴스에 바인딩되지 않습니다. 메서드를 콜백으로 전달하면 — 이벤트 핸들러에, 타이머에 — this는 undefined(엄격 모드) 또는 window(비엄격 모드)가 됩니다. 바인딩이 없으면 this.setState가 오류를 발생시킵니다.

바인딩하는 세 가지 방법이 있습니다: 생성자에서 bind, 콜백에서 화살표 함수, 화살표 함수가 있는 class field. 첫 번째 방법이 React의 공식 권장 사항입니다: 생성자에서 한 번 바인딩하고, 렌더링마다 함수를 다시 만들지 않습니다.

js
// Method 1: bind in constructor (recommended)
class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState({ clicked: true });
  }

  render() {
    return <button onClick={this.handleClick}>Click</button>;
  }
}

Class fields — 자동 바인딩이 있는 현대적인 구문입니다. 클래스 속성의 화살표 함수는 생성자의 스코프에서 this를 캡처합니다. 단점은 메서드가 프로토타입이 아닌 각 인스턴스에서 생성되어, 동일한 유형의 수백 개 컴포넌트에서 메모리 사용량이 증가한다는 것입니다.

클래스 vs 함수형 컴포넌트

클래스와 함수 중 선택은 단순한 구문 문제가 아닙니다. 훅이 있는 함수형 컴포넌트는 클래스에 내재된 문제를 해결합니다: 다른 생명주기 메서드(componentDidMount + componentDidUpdate)에서의 로직 중복, this의 복잡성, 관련 로직을 재사용 가능한 블록으로 추출할 수 없는 점.

함수형 컴포넌트는 테스트하기 쉽습니다 — 내부 상태가 없고(훅 이전에는 클래스에서만 가능했습니다), 콜백 확인을 위해 DOM 마운팅이 필요하지 않습니다. React는 모든 새 프로젝트에 함수형 컴포넌트를 권장합니다. 문서와 예제도 함수형으로 작성됩니다.

클래스 컴포넌트는 레거시 코드 작업 시 최선의 선택으로 남아 있습니다. 프로젝트가 2019년 이전에 시작된 경우, 수천 개의 클래스 컴포넌트가 있을 가능성이 높습니다. 이를 모두 하나의 스프린트에서 훅으로 다시 작성하는 것은 위험합니다. React는 하위 호환성을 보장합니다: 클래스 컴포넌트는 제거되지 않습니다.

클래스에서 훅으로 마이그레이션 전략

점진적 마이그레이션은 컴포넌트 분석으로 시작됩니다. 상태가 없는 단순한 컴포넌트가 먼저 변환됩니다 — 함수로 쉽게 대체됩니다. 그 다음 — 하나 또는 두 개의 상태 필드가 있는 컴포넌트로, useState가 this.state와 this.setState를 직접 대체합니다.

여러 생명주기 메서드가 있는 복잡한 컴포넌트는 useEffect를 사용하여 변환됩니다. componentDidMount + componentDidUpdate의 로직은 다른 종속성을 가진 별도의 useEffect 호출로 분할됩니다. componentWillUnmount는 useEffect 내부의 반환 함수로 대체됩니다. 복잡한 상태 로직에는 useReducer를 사용하세요.

자동 마이그레이션 도구 — @phenomnomnominal/ts-react-class-to-hook 또는 codemod 스크립트 — 는 단순한 클래스를 자동으로 변환할 수 있습니다. 복잡한 경우에는 마이그레이션이 수동 작업으로 남아 있으며, 원본 컴포넌트의 로직을 이해해야 합니다.

자주 묻는 질문

생성자에서 super(props)를 호출해야 하나요?

네. super(props)는 부모 React.Component에 props를 전달합니다. 이 호출이 없으면 생성자 내에서 this.props가 undefined가 됩니다. render 및 생명주기 메서드에서는 super 없이도 props를 사용할 수 있지만, 이는 구현의 부수적 동작입니다.

setState가 비동기인 이유는 무엇인가요?

React는 불필요한 리렌더링을 줄이기 위해 여러 setState 호출을 하나의 배치로 그룹화합니다. setState가 동기식이었다면 각 호출이 즉시 렌더링을 트리거하여 대량 업데이트 중 성능이 저하됩니다.

클래스 컴포넌트 내에서 훅을 사용할 수 있나요?

아니요. 은 함수형 컴포넌트에서만 작동합니다. 클래스 컴포넌트가 있는 프로젝트에서는 모든 기존 패턴을 사용할 수 있습니다: render props, HOC 및 컨텍스트용 Consumer. 훅으로 마이그레이션하려면 클래스를 함수로 변환해야 합니다.

PureComponent란 무엇이며 Component와 어떻게 다른가요?

React.PureComponent는 props와 상태의 얕은 비교로 shouldComponentUpdate를 구현합니다. setState에서 항상 리렌더링하는 Component와 달리, PureComponent는 데이터가 변경되지 않은 경우 리렌더링을 건너뜁니다. 이는 복잡한 중첩이 없는 컴포넌트를 위한 최적화입니다.

클래스 컴포넌트에서 오류를 어떻게 처리하나요?

componentDidCatchgetDerivedStateFromError를 사용하세요. componentDidCatch(error, info)는 오류를 기록합니다. getDerivedStateFromError는 폴백 UI를 표시하기 위해 상태를 업데이트합니다. 이 메서드는 클래스 컴포넌트에서만 작동합니다 — 함수는 ErrorBoundary 래퍼 컴포넌트가 필요합니다.

요약

  • React.Component는 상속, 상태 및 생명주기 메서드를 가진 컴포넌트의 기본 클래스입니다.
  • this.state는 생성자에서 초기화되며 this.setState를 통해서만 업데이트됩니다 — 직접 변경은 금지됩니다.
  • componentDidMount는 첫 번째 렌더링 후 API 요청, 구독 및 타이머를 위한 주요 위치입니다.
  • componentWillUnmount는 메모리 누수를 방지하기 위한 구독 및 타이머의 필수 정리입니다.
  • this 바인딩은 필수입니다: 생성자에서의 bind가 콜백 메서드에 권장되는 방식입니다.
  • 은 새 프로젝트에서 클래스 컴포넌트를 대체했지만, 클래스는 완전히 지원됩니다.
  • 마이그레이션은 점진적으로 수행됩니다: 먼저 상태 없는 컴포넌트, 복잡한 것은 useReducer와 useEffect를 통해.

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기