React 학습 순서 요약
React를 처음 공부한다면 개발환경 준비 → 컴포넌트·JSX → props → 이벤트·state·폼 → 상태 위치 → Effect → Context·Reducer → Zustand·서버 상태 순서로 진행하는 것이 좋습니다. 이 글은 각 기술을 깊게 설명하는 글이 아니라, 무엇을 먼저 배우고 어떤 실습으로 다음 단계에 넘어갈지 정하는 React 과정의 시작 페이지입니다.
0단계: React 전에 확인할 JavaScript
React를 시작하기 전에 JavaScript 전체를 끝낼 필요는 없습니다. 다만 함수, 객체·배열, 구조 분해, spread 문법, map·filter, import/export, Promise와 async/await 정도는 읽고 수정할 수 있어야 합니다. React 코드에서는 배열을 화면 목록으로 바꾸고, 객체를 복사해 일부 값을 갱신하고, 모듈을 파일별로 나누는 일이 반복되기 때문입니다.
기준은 문법 암기가 아니라 작은 기능을 만들 수 있는지입니다. 배열에서 특정 항목을 찾거나 필터링할 수 있고, 객체를 직접 수정하지 않고 새 객체로 바꾸며, 비동기 함수의 결과를 기다릴 수 있다면 React 기초를 시작해도 됩니다.
1단계: React 개발환경 만들기
처음 React를 공부할 때 가장 먼저 빠지기 쉬운 부분이 개발환경입니다. 코드 예제를 보기 전에 직접 프로젝트를 만들고 실행할 수 있어야 이후 예제를 그대로 따라갈 수 있습니다. 이 글에서는 Vite와 TypeScript를 기준으로 시작합니다.
Node.js와 npm 확인
node -v
npm -v
버전이 정상적으로 출력되면 Node.js와 npm이 설치된 상태입니다. Vite 8 기준으로는 Node.js 20.19 이상 또는 22.12 이상 환경을 사용합니다. 명령어 자체를 찾지 못한다면 React보다 먼저 Node.js 설치를 진행해야 합니다.
React·TypeScript 프로젝트 생성
npm create vite@latest my-react-app -- --template react-ts
cd my-react-app
npm install
npm run dev
npm create vite@latest는 프로젝트 골격을 만들고, npm install은 package.json에 정의된 의존성을 설치합니다. npm run dev를 실행하면 터미널에 Local 주소가 표시되고 브라우저에서 React 화면을 확인할 수 있습니다.
프로젝트 생성, 파일 구조, 개발 서버와 빌드까지 자세히 확인하려면 React Vite 사용법: Vite 8 프로젝트 생성·실행·빌드를 먼저 진행하세요. 이 글의 이후 단계는 React 프로젝트를 직접 실행할 수 있다는 전제로 이어집니다.
2단계: 컴포넌트와 JSX로 화면을 나눕니다
React의 첫 번째 핵심은 화면을 컴포넌트로 나누는 것입니다. 헤더, 검색 영역, 상품 카드, 버튼처럼 역할이 분명한 UI를 함수 단위로 만들고 JSX로 화면 구조를 표현합니다. 처음부터 파일을 많이 쪼개는 것이 목표가 아니라, 같은 UI를 다시 사용할 수 있는 단위를 찾는 것이 중요합니다.
function ProductCard() {
return (
<article>
<h3>무선 키보드</h3>
<p>49,000원</p>
</article>
);
}
완료 기준은 큰 화면 하나를 여러 컴포넌트로 나누고, 같은 컴포넌트를 두 번 이상 렌더링할 수 있는 것입니다. 컴포넌트의 기준이 아직 어렵다면 React 컴포넌트 개념 정리를 먼저 확인하세요.
3단계: props로 데이터를 전달합니다
컴포넌트를 재사용하려면 고정된 텍스트 대신 외부에서 값을 받아야 합니다. 부모 컴포넌트가 데이터를 가지고 자식 컴포넌트에 props로 전달하는 흐름을 익히면 목록 UI를 데이터 기반으로 바꿀 수 있습니다.
type Product = {
id: number;
name: string;
price: number;
};
function ProductCard({ product }: { product: Product }) {
return (
<article>
<h3>{product.name}</h3>
<p>{product.price.toLocaleString()}원</p>
</article>
);
}
여기서는 props를 읽기 전용 입력값으로 이해하면 됩니다. 부모가 데이터를 소유하고 자식은 전달받은 값으로 화면을 그립니다. 배열을 map으로 순회하고 안정적인 key를 지정할 수 있으면 다음 단계로 넘어갑니다.

4단계: 이벤트·state·폼으로 화면을 바꿉니다
정적인 화면과 props 전달이 익숙해졌다면 사용자의 행동에 따라 바뀌는 값을 state로 관리합니다. 버튼 클릭, 입력, 체크박스 선택처럼 사용자 행동이 발생하면 이벤트 핸들러가 state를 변경하고 React가 변경된 값을 기준으로 다시 렌더링합니다.
import { useState } from 'react';
function LikeButton() {
const [liked, setLiked] = useState(false);
return (
<button onClick={() => setLiked((previous) => !previous)}>
{liked ? '좋아요 취소' : '좋아요'}
</button>
);
}
객체나 배열 state는 기존 값을 직접 변경하지 않고 새로운 값으로 교체해야 합니다. 입력값과 화면 상태가 연결되는 방식은 React useState 사용법과 React 제어 폼과 state에서 이어서 연습할 수 있습니다.
5단계: 상태를 어디에 둘지 결정합니다
React를 어느 정도 사용하기 시작하면 useState 문법보다 상태의 위치가 더 중요해집니다. 한 컴포넌트에서만 사용하는 값은 그 컴포넌트에 두고, 여러 자식이 같은 값을 사용한다면 가장 가까운 공통 부모로 올립니다. props와 state로 계산할 수 있는 값은 별도 state로 다시 저장하지 않습니다.
예를 들어 검색어와 원본 목록이 있으면 검색 결과는 렌더링 중 계산할 수 있습니다. 검색 결과까지 state에 저장하면 검색어가 바뀔 때 두 값을 함께 맞춰야 하므로 서로 어긋날 가능성이 생깁니다.
const [keyword, setKeyword] = useState('');
const visibleProducts = products.filter((product) =>
product.name.toLowerCase().includes(keyword.toLowerCase()),
);
완료 기준은 “이 값의 원본은 어디인가?”, “두 컴포넌트가 공유해야 하는가?”, “기존 값에서 계산할 수 있는가?”를 설명할 수 있는 것입니다. 이 판단을 먼저 익혀야 Context나 Zustand를 사용할 때 모든 상태를 전역으로 옮기는 실수를 줄일 수 있습니다.
6단계: Effect는 외부 시스템과 동기화할 때 사용합니다
useEffect는 모든 후처리를 넣는 공간이 아닙니다. 브라우저 이벤트 구독, 타이머, 외부 위젯, 네트워크 연결처럼 React 바깥의 시스템과 상태를 맞출 때 사용합니다. props나 state로 계산할 수 있는 값을 Effect에서 다시 state로 복사하지 않습니다.
Effect를 작성할 때는 연결과 정리를 한 쌍으로 생각합니다. 이벤트를 등록했다면 cleanup에서 해제하고, 타이머를 만들었다면 제거합니다. DOM 자체를 직접 다뤄야 하는 예제는 React ref와 DOM 초점 실습에서 확인할 수 있습니다.

7단계: Context와 Reducer로 공유 범위를 이해합니다
props 전달 단계가 길어지거나 여러 하위 컴포넌트가 같은 값을 읽어야 한다면 Context를 검토할 수 있습니다. 상태 변경 규칙이 많아져 여러 setter 호출이 흩어진다면 reducer로 action과 변경 로직을 한 곳에 모을 수 있습니다.
중요한 점은 Context와 reducer를 Zustand의 전 단계로 외우는 것이 아니라 각 도구가 해결하는 문제가 무엇인지 구분하는 것입니다. reducer·Context를 직접 연결하는 과정은 React useReducer·Context 상태 실습에서 이어집니다.
8단계: Zustand와 서버 상태를 구분합니다
Zustand는 로컬 state를 모두 대체하는 도구가 아닙니다. 여러 화면이나 멀리 떨어진 컴포넌트가 같은 클라이언트 상태를 공유하고, props 전달이나 Provider 구조가 복잡해질 때 검토합니다. 입력 중인 검색어 하나나 단일 모달처럼 가까운 UI 상태는 여전히 useState가 더 단순할 수 있습니다.
새 프로젝트에 Zustand를 추가하는 명령은 다음과 같습니다.
npm install zustand
설치 후 바로 store 문법부터 외우기보다 먼저 React state vs Zustand에서 전역 상태가 필요한 기준을 확인하고, Zustand 학습 로드맵 → Zustand 설치와 기본 Store 순서로 진행하는 편이 좋습니다.
API에서 받은 상품·게시글·주문처럼 서버가 원본인 데이터는 성격이 다릅니다. 로딩, 오류, 캐시, 재요청 같은 서버 상태 문제는 TanStack Query와 같은 데이터 패칭 계층의 역할입니다. 차이는 TanStack Query vs Zustand에서 이어서 확인하세요.
시리즈 프로젝트: TaskFlow는 이렇게 완성됩니다
이 글의 상단 내용은 React 학습 순서를 이해하기 위한 독립 학습 영역입니다. 아래 TaskFlow는 1편부터 순서대로 학습하는 독자를 위한 선택 실습입니다. 실제 누적 구현은 다음 글인 Vite 글부터 시작합니다.
| 구간 | TaskFlow에서 달라지는 내용 |
|---|---|
| 1~6편 | Vite 베이스 → 컴포넌트 분리 → JSX 목록 → props 흐름 → useState 추가·토글·삭제 |
| 7~13편 | 불변 업데이트·key·제어 폼·ref·Effect·대표 오류를 실제 프로젝트에서 재현하고 수정 |
| 14~20편 | Reducer·Context·TypeScript 전환·커스텀 훅·검색 필터로 구조 확장 |
| 21~23편 | React Router와 shadcn/ui를 적용해 목록·상세·편집 흐름 완성 |
최소 개발환경 확인
node -v
npm -v
버전이 출력되면 다음 글에서 Vite 프로젝트를 만들 수 있습니다. 설치 명령과 Vite의 파일 구조·dev·build·preview는 다음 글에서 자세히 다루므로 여기서 반복하지 않습니다.
1단계 종료 시 만들 수 있어야 하는 것
- 작업을 새로 추가할 수 있습니다.
- 작업의 완료 상태를 토글할 수 있습니다.
- 작업을 삭제할 수 있습니다.
- 완료 개수는 별도 state가 아니라 작업 배열에서 계산합니다.
다음 글: React Vite 사용법: Vite 8 프로젝트 생성·실행·빌드에서 TaskFlow의 실제 베이스 프로젝트를 생성합니다.
다음 단계로 넘어갈 기준
- 개발환경: 새 Vite React·TypeScript 프로젝트를 만들고
npm run dev와npm run build를 실행할 수 있습니다. - 컴포넌트·props: 목록 UI를 컴포넌트로 나누고 부모 데이터를 자식에게 전달할 수 있습니다.
- state·이벤트: 입력, 클릭, 체크 상태를 변경하고 배열·객체를 불변 방식으로 갱신할 수 있습니다.
- 상태 설계: 로컬 state, 끌어올린 state, 계산 가능한 파생 값을 구분할 수 있습니다.
- Effect: 외부 시스템과 동기화할 때만 Effect가 필요한 이유를 설명할 수 있습니다.
- 공유 상태: Context·Reducer·Zustand를 언제 검토할지 설명할 수 있습니다.
- 서버 상태: API 데이터 캐시와 클라이언트 전역 상태를 같은 문제로 취급하지 않습니다.
이 기준을 만족하면 React 문법을 외운 상태를 넘어 실제 애플리케이션의 상태 흐름을 설계할 준비가 된 것입니다. 다음에는 React·TypeScript 검색 필터 실습처럼 여러 상태와 사용자 입력이 연결된 프로젝트를 만들고, 서버 데이터가 필요한 시점에 TanStack Query와 Next.js로 확장하면 됩니다.
공식 문서
이 글이 도움이 되었나요?
React 학습 순서
필수 19개 · 전체 23개
읽음 기록 관리
전체 과정 목차 (23개)
- 필수 길잡이 · React 학습 순서: 컴포넌트·props·state부터 상태관리까지 현재 글
- 필수 학습 · React Vite 사용법: Vite 8 프로젝트 생성·실행·빌드
- 필수 학습 · React 컴포넌트 개념 정리: UI 재사용 구조 잡기
- 필수 학습 · React JSX 문법 사용법: 조건부 렌더링과 리스트 처리
- 필수 학습 · React props 사용법: 부모에서 자식으로 데이터 전달하는 구조
- 필수 학습 · React useState 사용법: state와 객체 배열 업데이트 기준
- 선택 참고 · React state 업데이트 안됨 문제 해결
- 필수 선수 · React 리스트 key 경고 해결 기준: index key를 피해야 하는 이유
- 필수 학습 · React 제어 컴포넌트 폼과 상태 끌어올리기 첫 실습 가이드
- 필수 학습 · React useRef 실습: 입력 포커스와 state의 역할 나누기
- 필수 선수 · React useEffect 두 번 실행되는 이유: StrictMode·API 중복 해결
- 선택 참고 · React Maximum update depth exceeded 오류 해결: 무한 렌더링 원인 찾기
- 선택 참고 · React Cannot update 오류 해결: 렌더링 중 setState 원인
- 필수 학습 · React useReducer와 Context 실습: 작업 목록 상태를 여러 컴포넌트에서 공유하기
- 필수 학습 · React 컴포넌트 props 타입 지정하기: 부모와 자식 사이의 값 구조 잡기
- 선택 참고 · React Hook Form 에러 메시지 표시 문제 해결: validation이 안 보일 때 체크리스트
- 필수 길잡이 · React 라이브러리 조합 가이드: Zustand·TanStack Query·shadcn/ui 선택 기준
- 필수 학습 · Next.js 커스텀 훅 설계: 프론트엔드 상태 관리 구조 잡기
- 필수 학습 · React Compiler 기준: useMemo useCallback 언제 줄일까
- 필수 학습 · React·TypeScript 검색 필터 만들기: 상태와 결과 목록 연결
- 필수 학습 · React Router v7 실습: BrowserRouter부터 Layout·Outlet·상세 경로까지
- 필수 학습 · shadcn/ui 시작 실습: Vite 설정·components.json·입력 폼·Sonner
- 필수 학습 · shadcn/ui 복합 컴포넌트 실습: Dialog·Popover·Carousel과 접근성
새 글 받아보기
RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.