지난 글에서는 React UI 구축의 핵심 단위인 함수형 컴포넌트와 props를 통한 데이터 전달 방식에 대해 자세히 알아보았습니다. 이번 여정에서는 React 컴포넌트의 또 다른 중요한 형태인 클래스형 컴포넌트 (Class Component)에 대해 탐구해 보겠습니다. 클래스형 컴포넌트는 과거 React 개발에서 주로 사용되었으며, 상태 (state) 관리와 생명주기 메서드 (lifecycle methods)를 활용하여 더욱 복잡하고 동적인 UI 로직을 구현하는 데 중요한 역할을 합니다. 비록 Hooks의 등장으로 함수형 컴포넌트에서도 이러한 기능들을 사용할 수 있게 되었지만, 클래스형 컴포넌트의 기본 개념을 이해하는 것은 여전히 React 개발의 중요한 토대입니다.
클래스형 컴포넌트란 무엇일까요?
클래스형 컴포넌트는 JavaScript의 class 문법을 사용하여 정의되는 React 컴포넌트입니다. React.Component 클래스를 상속받아 만들어지며, render() 메서드를 필수적으로 포함해야 합니다. 이 render() 메서드 내에서 JSX를 반환하여 컴포넌트가 렌더링할 UI 구조를 정의합니다.
클래스형 컴포넌트의 주요 특징:
- JavaScript 클래스: ES6의 class 키워드를 사용하여 정의됩니다.
- React.Component 상속: React.Component 클래스를 상속받아 React 컴포넌트로서의 기능을 갖게 됩니다.
- render() 메서드 필수: UI를 렌더링하는 역할을 하는 render() 메서드를 반드시 구현해야 합니다. 이 메서드는 JSX 또는 null을 반환합니다.
- 상태 (State) 관리: 컴포넌트 내부에서 변화하는 데이터를 관리하기 위한 state 속성을 가질 수 있습니다. this.state를 통해 접근하고 this.setState() 메서드를 사용하여 업데이트합니다.
- 생명주기 메서드 (Lifecycle Methods): 컴포넌트가 생성, 업데이트, 소멸되는 특정 시점에 호출되는 메서드들을 제공합니다. 이를 통해 side effects (데이터 fetching, subscriptions, timers 등)를 관리할 수 있습니다.
클래스형 컴포넌트 정의 방법
클래스형 컴포넌트는 다음과 같은 기본적인 구조를 가집니다.
import React from 'react';
class MyComponent extends React.Component {
constructor(props) {
super(props);
// 초기 state 설정 (선택 사항)
this.state = {
// 초기 상태 값들
};
// 이벤트 핸들러 메서드 바인딩 (선택 사항)
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// 이벤트 처리 로직
console.log('Button clicked!');
this.setState({ /* 상태 업데이트 */ });
}
render() {
return (
<div>
{/* JSX를 사용하여 UI 렌더링 */}
<h1>Hello from Class Component!</h1>
<button onClick={this.handleClick}>Click Me</button>
<p>Current State: {this.state.someValue}</p>
</div>
);
}
}
export default MyComponent;
주요 요소:
- class MyComponent extends React.Component: MyComponent라는 이름의 클래스를 정의하고 React.Component를 상속받습니다.
- constructor(props): 컴포넌트가 생성될 때 호출되는 생성자 메서드입니다. super(props)를 반드시 호출해야 하며, 초기 state를 설정하거나 메서드를 바인딩하는 데 사용됩니다.
- this.state: 컴포넌트의 상태를 저장하는 JavaScript 객체입니다. 상태가 변경되면 React는 컴포넌트를 다시 렌더링하여 UI를 업데이트합니다.
- this.setState(updater, [callback]): state를 업데이트하는 데 사용되는 메서드입니다. 직접 this.state를 수정해서는 안 됩니다. updater는 새로운 상태 값 또는 이전 상태를 기반으로 새로운 상태를 반환하는 함수일 수 있습니다. callback 함수는 상태 업데이트가 완료된 후 실행됩니다 (선택 사항).
- render(): 컴포넌트가 렌더링할 UI를 JSX 형태로 반환하는 필수 메서드입니다.
- 이벤트 핸들러 (handleClick) 및 바인딩: 클래스 메서드를 이벤트 핸들러로 사용할 경우, 생성자 내에서 this 바인딩을 해줘야 합니다 (this.handleClick = this.handleClick.bind(this);). 화살표 함수를 사용하여 메서드를 정의하면 자동 바인딩이 됩니다.
상태 (State) 관리
클래스형 컴포넌트의 가장 중요한 특징 중 하나는 상태 (state)를 관리할 수 있다는 점입니다. 상태는 컴포넌트 내부에서 변화하는 데이터를 의미하며, 이 상태 변화에 따라 UI가 동적으로 업데이트됩니다.
상태 사용 예시:
import React from 'react';
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.increment = this.increment.bind(this);
}
increment() {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<h1>Count: {this.state.count}</h1>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
export default Counter;
위 Counter 컴포넌트는 constructor에서 초기 상태 count를 0으로 설정합니다. increment 메서드는 this.setState()를 사용하여 count 상태를 1씩 증가시킵니다. 상태가 업데이트될 때마다 render() 메서드가 다시 호출되어 변경된 count 값을 UI에 반영합니다.
생명주기 메서드 (Lifecycle Methods)
클래스형 컴포넌트는 컴포넌트가 생성되어 화면에 나타나고 (Mounting), 업데이트되고 (Updating), 화면에서 사라지는 (Unmounting) 일련의 과정에서 특정 시점에 자동으로 호출되는 생명주기 메서드 (Lifecycle Methods)를 제공합니다. 이러한 메서드를 사용하여 side effects를 처리하거나 컴포넌트의 동작을 제어할 수 있습니다.
주요 생명주기 메서드:
- Mounting: 컴포넌트가 DOM에 삽입될 때 호출되는 메서드
- constructor(): 컴포넌트가 생성될 때 가장 먼저 호출됩니다. 초기 state 설정 및 메서드 바인딩에 사용됩니다.
- static getDerivedStateFromProps(props, state): 렌더링 직전에 호출되며, props의 변화에 따라 state를 업데이트하는 데 사용됩니다 (자주 사용되지는 않습니다).
- render(): UI를 렌더링하는 메서드입니다.
- componentDidMount(): 컴포넌트가 DOM에 마운트된 직후에 호출됩니다. 데이터 fetching, subscriptions, timers 설정 등 side effects를 처리하는 데 주로 사용됩니다.
- Updating: 컴포넌트의 props나 state가 변경되어 다시 렌더링될 때 호출되는 메서드
- static getDerivedStateFromProps(props, state): 렌더링 직전에 호출됩니다.
- shouldComponentUpdate(nextProps, nextState): 컴포넌트가 리렌더링될지 여부를 결정하는 메서드입니다. 성능 최적화를 위해 사용될 수 있습니다. true 또는 false를 반환해야 합니다.
- render(): UI를 다시 렌더링하는 메서드입니다.
- getSnapshotBeforeUpdate(prevProps, prevState): DOM이 업데이트되기 직전에 호출되며, 업데이트 전의 DOM 정보를 저장하는 데 사용됩니다 (예: 스크롤 위치).
- componentDidUpdate(prevProps, prevState, snapshot): 업데이트가 완료된 직후에 호출됩니다. DOM 업데이트 후 side effects 처리 (예: 데이터 fetching)에 사용될 수 있습니다.
- Unmounting: 컴포넌트가 DOM에서 제거될 때 호출되는 메서드
- componentWillUnmount(): 컴포넌트가 언마운트되기 직전에 호출됩니다. subscriptions 해제, timers 제거 등 리소스 정리를 수행하는 데 사용됩니다.
생명주기 메서드 활용 예시 (데이터 Fetching):
import React from 'react';
class UserList extends React.Component {
constructor(props) {
super(props);
this.state = {
users: [],
loading: true,
error: null
};
}
componentDidMount() {
fetch('https://api.example.com/users')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
this.setState({ users: data, loading: false });
})
.catch(error => {
this.setState({ error: error.message, loading: false });
});
}
render() {
if (this.state.loading) {
return <p>Loading users...</p>;
}
if (this.state.error) {
return <p>Error fetching users: {this.state.error}</p>;
}
return (
<ul>
{this.state.users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
}
export default UserList;
위 예시에서 UserList 컴포넌트는 componentDidMount() 생명주기 메서드 내에서 API를 호출하여 사용자 데이터를 가져옵니다. 데이터 fetching이 진행 중일 때는 "Loading users..." 메시지를 표시하고, 에러가 발생하면 에러 메시지를 표시하며, 데이터를 성공적으로 가져오면 사용자 목록을 렌더링합니다.
함수형 컴포넌트와의 비교 및 Hooks의 등장
과거에는 상태 관리와 생명주기 메서드 사용이 클래스형 컴포넌트의 전유물이었기 때문에, 동적인 UI 로직을 구현해야 하는 경우 클래스형 컴포넌트를 사용하는 것이 일반적이었습니다. 하지만 React 16.8 버전에 도입된 Hooks라는 기능을 통해 함수형 컴포넌트에서도 상태 관리 (useState) 및 다양한 생명주기 관련 기능 (useEffect, useContext, useReducer 등)을 사용할 수 있게 되면서, 현대 React 개발에서는 함수형 컴포넌트가 더욱 선호되는 추세입니다.
Hooks는 함수형 컴포넌트 내에서 상태와 side effects를 "hook" 할 수 있도록 해주는 API입니다. Hooks를 사용하면 클래스 없이도 상태를 가진 컴포넌트를 작성하고, 생명주기 메서드와 유사한 동작을 구현할 수 있어 코드의 가독성과 재사용성을 높이는 데 기여합니다.
그럼에도 불구하고 클래스형 컴포넌트의 기본 개념과 생명주기 메서드를 이해하는 것은 여전히 중요합니다. 기존 코드베이스에서 클래스형 컴포넌트를 마주할 수 있으며, Hooks의 동작 방식을 더 깊이 이해하는 데 도움이 되기 때문입니다.
마무리하며
이번 글에서는 React 컴포넌트의 또 다른 중요한 형태인 클래스형 컴포넌트에 대해 자세히 알아보았습니다. 클래스형 컴포넌트의 정의 방법, 상태 관리 (state), 그리고 컴포넌트의 생명주기를 관리하는 생명주기 메서드 (componentDidMount, componentDidUpdate, componentWillUnmount 등)의 기본적인 개념과 사용법을 이해하셨으리라 생각합니다.
비록 현대 React 개발에서는 Hooks를 활용한 함수형 컴포넌트가 주를 이루지만, 클래스형 컴포넌트의 이해는 React 생태계를 폭넓게 이해하는 데 필수적인 부분입니다. 다음 블로그에서는 함수형 컴포넌트에서 상태를 관리하는 가장 기본적인 Hook인 useState에 대해 자세히 알아보는 시간을 갖도록 하겠습니다.
'IT Data 분석' 카테고리의 다른 글
Props 심화: 컴포넌트 간 효율적인 데이터 흐름 구축 (0) | 2025.05.10 |
---|---|
State 관리 기초 (useState 훅): 함수형 컴포넌트에 생명력을 불어넣다 (0) | 2025.05.08 |
React 컴포넌트 (함수형 컴포넌트): UI 구축의 기본 단위 (0) | 2025.05.04 |
JSX 이해: React UI 렌더링의 핵심에 대해 알아볼까요? (0) | 2025.05.04 |
React 시작하기: 웹 개발의 새로운 가능성을 열다 (0) | 2025.05.03 |