리액트(React)는 사용자 인터페이스를 구축하기 위한 JavaScript 라이브러리입니다. 리액트는 컴포넌트 기반 아키텍처를 채택하고 있으며, 이로 인해 개발자는 재사용 가능한 UI 구성 요소를 만들 수 있습니다. 본 강좌에서는 리액트의 핵심 개념인 ‘컴포넌트’와 ‘상태’에 대해 깊이 있게 다룰 것입니다.
1. 컴포넌트란?
컴포넌트는 리액트의 기본 빌딩 블록으로, UI를 구성하는 작은 조각입니다. 각 컴포넌트는 독립적으로 작동하며, 다른 컴포넌트와 결합하여 복잡한 사용자 인터페이스를 형성합니다.
1.1. 컴포넌트의 종류
리액트 컴포넌트는 크게 두 가지 종류로 분류됩니다.
- 클래스 컴포넌트: ES6 클래스를 사용하여 정의된 컴포넌트입니다. 상태(state)를 관리할 수 있습니다.
- 함수형 컴포넌트: JavaScript 함수로 정의된 컴포넌트입니다. 최근에는 훅(Hooks)이라는 기능을 도입하여 상태를 관리할 수 있게 되었습니다.
1.2. 컴포넌트 생성
리액트 컴포넌트는 다음과 같이 생성할 수 있습니다.
import React from 'react';
class MyComponent extends React.Component {
render() {
return <h1>안녕하세요, 리액트!</h1>;
}
}
위의 예제는 클래스를 선언하여 ‘MyComponent’라는 컴포넌트를 정의하고, 이를 사용하여 “안녕하세요, 리액트!”라는 텍스트를 화면에 렌더링하는 간단한 컴포넌트입니다.
2. 상태(state)란?
상태는 컴포넌트의 데이터나 값을 의미합니다. 컴포넌트의 상태는 내부적으로 저장되며, 상태가 변경될 경우 컴포넌트는 자동으로 다시 렌더링됩니다.
2.1. 상태의 사용
클래스 컴포넌트에서 상태를 사용하려면, constructor 메서드에서 초기 상태를 정의하고, `this.setState()` 메서드를 사용하여 상태를 업데이트합니다.
class MyStateComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<p>현재 카운트: {this.state.count}</p>
<button onClick={this.increment}>증가</button>
</div>
);
}
}
위의 예제에서 ‘MyStateComponent’는 카운트를 증가시키는 기능을 가진 컴포넌트입니다. `increment` 메서드를 호출하면 상태가 변경되고, 이로 인해 컴포넌트가 다시 렌더링됩니다.
2.2. 함수형 컴포넌트에서의 상태 관리
함수형 컴포넌트에서 상태를 관리하기 위해 React의 `useState` Hook을 사용합니다. 아래는 상태를 사용하는 함수형 컴포넌트의 예시입니다.
import React, { useState } from 'react';
const MyFunctionalComponent = () => {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
}
return (
<div>
<p>현재 카운트: {count}</p>
<button onClick={increment}>증가</button>
</div>
);
}
3. 상태가 컴포넌트에 미치는 영향
상태는 컴포넌트의 UI를 동적으로 변화시키는 중요한 요소입니다. 상태가 바뀌면 컴포넌트와 관련된 모든 부분이 다시 렌더링되며, 이로 인해 최신 상태를 반영한 UI가 제공합니다.
3.1. Props와 State의 차이점
컴포넌트 간에 데이터 전달 시 사용되는 ‘props’와, 컴포넌트 내부의 데이터를 관리하는 ‘state’는 서로 다른 개념입니다. props는 부모 컴포넌트에서 자식 컴포넌트로 전달되는 읽기 전용 데이터이며, state는 컴포넌트가 자체적으로 관리하는 데이터입니다.
4. 리액트에서 컴포넌트와 상태 관리하기
리액트 애플리케이션은 보통 여러 개의 컴포넌트로 구성되며, 이들 간의 데이터 흐름은 상위 컴포넌트에서 하위 컴포넌트로 이루어집니다. 아래에서는 컴포넌트와 상태를 어떻게 효과적으로 관리할 수 있는지에 대해 설명하겠습니다.
4.1. 상태 끌어올리기
부모 컴포넌트에서 상태를 관리하고, 자식 컴포넌트에 props로 전달하는 방법을 ‘상태 끌어올리기’라고 합니다. 이렇게 하면 여러 자식 컴포넌트가 동일한 상태를 공유하며, 이를 통해 더욱 일관된 UI를 구축할 수 있습니다.
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.state = { sharedState: 0 };
}
updateSharedState = (newValue) => {
this.setState({ sharedState: newValue });
}
render() {
return (
<div>
<ChildComponent sharedState={this.state.sharedState} updateSharedState={this.updateSharedState} />
</div>
);
}
}
4.2. 상태 관리 라이브러리
프로젝트가 커지면서 상태 관리가 복잡해지면, Redux, MobX와 같은 상태 관리 라이브러리를 사용하는 것이 좋습니다. 이러한 라이브러리는 전역 상태를 관리하는데 유용하며, 복잡한 애플리케이션에서 상태 관리를 쉽게 할 수 있게 도와줍니다.
예를 들어, Redux를 사용하는 경우 다음과 같은 방식으로 상태를 관리할 수 있습니다.
import { createStore } from 'redux';
const initialState = { count: 0 };
const reducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
default:
return state;
}
};
const store = createStore(reducer);
5. 리액트 컴포넌트의 라이프사이클
리액트 컴포넌트는 생성, 업데이트, 제거의 과정을 거치며, 이 각 단계에서 특정 메서드가 호출됩니다. 이를 ‘라이프사이클’이라고 합니다.
5.1. 라이프사이클 메서드
클래스 컴포넌트에서 사용할 수 있는 주요 라이프사이클 메서드로는 다음과 같은 것들이 있습니다.
- componentDidMount: 컴포넌트가 첫 렌더링을 끝낸 후 호출됩니다.
- componentDidUpdate: 컴포넌트가 업데이트된 후 호출됩니다.
- componentWillUnmount: 컴포넌트가 언마운트(제거)될 때 호출됩니다.
6. 결론
리액트에서 컴포넌트와 상태는 애플리케이션의 구조와 동작에 매우 중요한 역할을 합니다. 컴포넌트를 통해 UI를 구성하고, 상태를 통해 동적인 사용자 경험을 제공하여, 최종 사용자가 만족하는 애플리케이션을 개발할 수 있습니다. 본 강좌를 통해 리액트의 기본 개념을 이해하고, 다양한 컴포넌트를 만들며, 상태를 관리하는 방법을 익히기를 바랍니다.
7. 추가 자료
리액트 공식 문서와 다양한 온라인 강의들을 통해 더 많은 정보를 찾아보실 수 있습니다. 아래는 유용한 링크입니다: