웹 페이지는 원래 정적인 문서였습니다. 하지만 사용자 행동(버튼 클릭, 폼 입력, 탭 이동 등)에 따라 UI가 바뀌어야 했고, 그 변화의 기준이 되는 값들이 생겨났습니다,
예를 들어
이처럼, UI에 영향을 주는 값들을 컴포넌트 안에 기억해둘 필요가 생겼고, 그거를 리액트에서는 state라고 부르게 되었습니다.
상태(state)는 컴포넌트가 현재 어떤 상황인지를 기억하고 있는 값을 의미합니다.
사용자의 행동(버튼 클릭, 입력 등)에 따라 변할 수 있고, 이 상태가 바뀌면 React는 자동으로 UI를 다시 그려줍니다(리렌더링).
웹 페이지는 더 이상 정적인 정보만 보여주는 화면이 아닙니다.
오늘날의 UI는 사용자 행동에 따라 즉각 반응하고 변화해야 합니다.
예시
이처럼 상태는 UI의 기준이 되는 값입니다.
let count = 0;
function handleClick() {
count = count + 1;
}
위 코드는 변수 값이 바뀌긴 하지만, 리액트는 이 변경을 감지하지 못하고 화면을 다시 렌더링하지 않습니다.
리액트는 내부적으로 상태 값이 바뀌었는지 검사하고, 바뀌었다고 판단되면 그 컴포넌트만 다시 렌더링합니다.
그런데 일반 변수는 React가 추적할 수 없기 때문에, 상태는 반드시 useState 또는 this.state를 통해 선언해야 합니다.
리액트에서는 상태를 관리하기 위한 전용 기능을 제공합니다.
| 방식 | 사용되는 함수/문법 |
|---|---|
| 함수형 컴포넌트 | useState() |
| 클래스형 컴포넌트 | this.state, this.setState() |
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0); // 상태 초기값 0
const handleClick = () => {
setCount(count + 1); // 상태 변경 → UI 자동 리렌더링
}
}
리액트는 상태가 바뀌면 이 컴포넌트의 화면을 다시 그려야겠다고 판단합니다.
그 결과, 해당 컴포넌트의 render() 함수 또는 JSX 부분이 다시 실행되며 새로운 화면이 나옵니다.
이 구조 덕분에 개발자는 DOM 조작 없이도 "값만 바꾸면 UI가 알아서 바뀌는" 선언형 프로그래밍을 할 수 있게 되었습니다.
컴포넌트는 웹페이지 안에서 "나타나고", "변하고", "사라지는" 과정을 겪습니다.
예를 들어
즉, 컴포넌트가 존재하는 시점에 따라 해줘야 할 일이 다르기 때문에 리액트는 이 과정을 생명주기라고 나누고, 각 시점마다 특별한 함수(hook 또는 메서드)를 제공합니다.
생명주기란 컴포넌트가 탄생 → 변화 → 종료하는 일련의 흐름입니다.
개발자는 그 시점마다 적절한 작업(API 요청, 정리 등)을 넣을 수 있도록 도와주는 구조입니다.
| 시점 | 클래스형 메서드 | 함수형 Hook |
|---|---|---|
| 마운트됨 (처음 나타남) | componentDidMount() | useEffect(() => { ... }, []) |
| 업데이트됨 (상태/props 변화) | componentDidUpdate() | useEffect(() => { ... }) |
| 언마운트됨 (사라짐) | componentWillUnmount() | useEffect(() => { return () => { ... } }, []) |
| 개념 | 목적 | React 기능 |
|---|---|---|
| 상태관리 | UI에 영향을 주는 값들을 기억하고 변화에 따라 렌더링 | useState, useReducer, this.state |
| 생명주기 | 컴포넌트가 존재하는 시점별로 작업을 제어 | useEffect, componentDidMount 등 |