이 글에서 정리하는 내용
React를 처음 배울 때 가장 어려운 지점은 문법 자체보다 순서입니다. 컴포넌트, JSX, props, state, useEffect, Zustand가 한꺼번에 보이면 무엇을 먼저 잡아야 하는지 흐려집니다. 이 글은 React 입문자가 블로그 안의 기초 글을 어떤 순서로 이어 보면 좋은지 정리하는 로드맵입니다.
- React를 처음 배울 때 막히는 이유
- 컴포넌트와 JSX를 먼저 잡기
- props로 데이터를 내려보내는 흐름 이해하기
- useState로 화면 변화를 만들기
- useEffect는 필요한 순간에 보고, Zustand는 상태가 커질 때 본다
- 이 순서대로 같이 읽으면 좋은 글
React를 처음 배울 때 막히는 이유

React 입문 글을 하나씩 보면 각각은 어렵지 않은데, 프로젝트를 만들려고 하면 갑자기 복잡해집니다. JSX 문법을 봤는데 컴포넌트 분리가 헷갈리고, props를 이해한 것 같은데 state가 들어오면 데이터가 어디서 바뀌는지 놓치기 쉽습니다. 여기에 useEffect와 전역 상태 관리까지 같이 검색하면 순서가 뒤섞입니다.
그래서 처음에는 “React 기능을 전부 아는 것”보다 “화면이 만들어지고 바뀌는 흐름”을 먼저 잡는 편이 좋습니다. 화면을 작은 조각으로 나누고, 그 조각에 데이터를 내려보내고, 사용자의 행동에 따라 화면을 다시 그리는 순서입니다. 이 흐름이 잡히면 React 컴포넌트 개념 정리나 React JSX 문법 사용법 같은 글도 따로 떨어진 문법이 아니라 하나의 작업 흐름으로 읽힙니다.
컴포넌트와 JSX를 먼저 잡기
React의 출발점은 컴포넌트입니다. 버튼, 카드, 헤더, 목록 같은 UI를 하나의 함수 단위로 나누고, 그 함수가 화면에 보여줄 구조를 반환합니다. 이때 사용하는 문법이 JSX입니다. JSX는 HTML과 비슷해 보이지만 JavaScript 안에서 UI 구조를 표현하는 문법이기 때문에 class 대신 className을 쓰고, 조건부 렌더링이나 리스트 렌더링도 JavaScript 표현식으로 처리합니다.
입문 단계에서는 컴포넌트를 “재사용 가능한 UI 조각”으로만 외우기보다, 어떤 기준으로 나눌지를 같이 봐야 합니다. 같은 카드가 여러 번 반복된다면 카드 컴포넌트로 나누고, 페이지마다 공통으로 쓰는 버튼이라면 버튼 컴포넌트로 분리합니다. JSX는 이 컴포넌트가 실제로 어떤 태그와 조건을 갖는지 표현하는 도구입니다.
function ProductCard({ name, price }) {
return (
<article className="rounded-xl border p-4">
<h3>{name}</h3>
<p>{price.toLocaleString()}원</p>
</article>
);
}
이 예시에서 먼저 봐야 할 것은 코드 길이가 아니라 역할입니다. ProductCard는 하나의 카드 모양을 담당하고, JSX는 카드 안에 제목과 가격을 배치합니다. 이 기준을 잡으면 다음 단계인 props가 자연스럽게 이어집니다.
props로 데이터를 내려보내는 흐름 이해하기
props는 부모 컴포넌트가 자식 컴포넌트에게 전달하는 값입니다. 처음에는 “매개변수 같은 것”이라고 이해해도 괜찮지만, 실무에서는 데이터 흐름을 보는 기준으로 쓰는 편이 더 중요합니다. 목록 페이지가 상품 데이터를 가지고 있고, 각각의 카드 컴포넌트가 그중 하나의 상품만 받는 구조를 떠올리면 됩니다.
React props 사용법을 볼 때도 props 자체의 문법보다 “누가 데이터를 가지고 있고, 누가 화면만 그리는가”를 같이 봐야 합니다. 부모가 배열을 가지고 있고 자식은 받은 값만 보여주면 구조가 단순해집니다. 반대로 자식이 너무 많은 데이터를 직접 만들거나 수정하려고 하면 컴포넌트 사이의 책임이 흐려집니다.
function ProductList({ products }) {
return products.map((product) => (
<ProductCard key={product.id} name={product.name} price={product.price} />
));
}
여기에서 key도 같이 등장합니다. 처음에는 무시하기 쉽지만, 리스트를 렌더링할 때 React가 각 항목을 구분하는 기준입니다. key 경고는 단순 콘솔 메시지가 아니라 화면 업데이트가 어긋날 수 있다는 신호에 가깝습니다.
useState로 화면 변화를 만들기
props까지 이해했다면 다음은 state입니다. props가 부모에게서 내려온 값이라면, state는 컴포넌트가 스스로 기억하고 바꾸는 값입니다. 좋아요 버튼의 눌림 여부, 모달 열림 상태, 입력 폼의 현재 값처럼 사용자의 행동에 따라 화면이 바뀌는 부분이 state로 연결됩니다.
React useState 사용법을 볼 때는 setState가 값을 즉시 바꾸는 명령이 아니라 “다음 렌더링에 사용할 값을 예약한다”는 느낌으로 이해하면 좋습니다. 특히 객체나 배열을 직접 수정하지 않고 새 값으로 만들어 넘겨야 화면 갱신 흐름이 안전합니다.
function LikeButton() {
const [liked, setLiked] = useState(false);
return (
<button onClick={() => setLiked((prev) => !prev)}>
{liked ? '좋아요 취소' : '좋아요'}
</button>
);
}
이 단계에서 중요한 것은 “state가 어디에 있어야 하는가”입니다. 버튼 하나만 바뀌면 버튼 컴포넌트 안에 두면 됩니다. 여러 컴포넌트가 같은 값을 함께 봐야 한다면 공통 부모로 올리는 방식을 먼저 생각합니다. 전역 상태 도구는 그다음 선택지입니다.
useEffect는 필요한 순간에 보고, Zustand는 상태가 커질 때 본다

useEffect는 React 입문 초반에 너무 빨리 깊게 들어가면 오히려 헷갈립니다. 화면을 그리는 것과 외부 작업을 연결해야 할 때 등장한다고 보는 편이 안전합니다. 예를 들어 컴포넌트가 보인 뒤 API를 호출하거나, 브라우저 이벤트를 등록하고 해제하거나, 외부 라이브러리와 동기화할 때입니다. Strict Mode에서 두 번 실행되는 현상처럼 헷갈리는 부분은 React useEffect 두 번 실행 문제 해결을 따로 이어 보면 좋습니다.
Zustand도 마찬가지입니다. React를 배우자마자 모든 state를 Zustand로 옮길 필요는 없습니다. 로그인 사용자, 테마, 장바구니, 여러 화면에서 공유하는 필터처럼 “컴포넌트 트리를 넘어서 같이 쓰는 상태”가 생겼을 때 검토하면 됩니다. 이 기준은 React state vs Zustand나 Zustand 사용 기준으로 이어서 보면 흐름이 자연스럽습니다.
이 순서대로 같이 읽으면 좋은 글
처음에는 React 컴포넌트 개념 정리로 화면을 나누는 기준을 잡고, 이어서 React JSX 문법 사용법으로 조건부 렌더링과 리스트 처리를 익히면 좋습니다. 그다음 React props 사용법으로 데이터 전달 흐름을 보고, React useState 사용법으로 화면 변화까지 연결합니다.
이후에는 상황에 따라 갈라집니다. 리스트가 이상하게 갱신되거나 key 경고가 보이면 key 관련 글을 보고, 렌더링 이후 외부 작업이 필요하면 useEffect를 봅니다. 상태가 여러 컴포넌트에 퍼지기 시작하면 그때 Zustand 로드맵으로 넘어가면 됩니다. 이렇게 보면 React 학습은 기능 목록 암기가 아니라 화면 구조에서 상태 관리로 넓어지는 흐름이 됩니다.
“React 처음 배우는 순서: 컴포넌트부터 state, Zustand까지”에 대한 13개의 생각