실행하며 배우는 React 튜토리얼
React 19 무료 튜토리얼입니다. 컴포넌트, JSX, props, state, 훅, 성능까지 다룹니다. 모든 예제가 페이지에서 바로 실행되므로 코드를 고치면 컴포넌트와 콘솔이 즉시 바뀌는 것을 볼 수 있습니다.
React 가이드 학습 시작하기시작하기
- React란React는 컴포넌트로 사용자 인터페이스를 만드는 자바스크립트 라이브러리입니다. 현재 데이터에 맞게 화면이 어떻게 보여야 하는지 설명하면, 데이터가 바뀔 때 React가 페이지를 그에 맞게 유지합니다.
- 리액트 설치Vite로 프로젝트를 만들어 React를 설치합니다. Node.js를 확인하고, 생성 명령 하나를 실행하고, 의존성을 설치한 뒤 개발 서버를 시작합니다. 생성된 파일, 프로덕션 빌드, Create React App이 지원 중단된 이유도 다룹니다.
- JSXJSX는 React 컴포넌트 안에 HTML 같은 마크업을 작성하게 해 주는 자바스크립트 문법 확장입니다. 하나의 루트 요소, 닫힌 태그, className, camelCase 속성, 중괄호, 인라인 스타일, 주석, 그리고 JSX가 무엇으로 컴파일되는지 배웁니다.
- 컴포넌트React 컴포넌트는 JSX를 반환하는 자바스크립트 함수입니다. 함수 컴포넌트를 작성하고 이름 짓는 법, 트리로 조합하는 법, 여러 파일로 나누는 법, 순수하게 유지하는 법, 그리고 컴포넌트와 요소의 차이를 배웁니다.
- Propsprops는 React 컴포넌트의 입력값으로, 부모가 JSX 속성으로 자식에게 넘기는 값입니다. props를 전달하고 구조 분해하는 법, 기본값 설정, 함수 전달, props 전개, 그리고 props가 읽기 전용인 이유를 배웁니다.
- Childrenchildren은 컴포넌트의 여는 태그와 닫는 태그 사이에 넣은 내용을 담는 prop입니다. 이를 이용해 래퍼와 레이아웃 컴포넌트를 만드는 법, 여러 슬롯을 이름 있는 props로 넘기는 법, children을 함수로 쓰는 법, 그리고 Children API가 맞지 않는 경우를 배웁니다.
- FragmentReact Fragment는 페이지에 노드를 추가하지 않고 여러 요소를 하나의 반환값으로 묶습니다. 짧은 문법 <>...</>, <Fragment key>가 필요한 경우, 그리고 테이블과 목록 안에서 프래그먼트가 중요한 이유를 배웁니다.
- 조건부 렌더링React의 조건부 렌더링은 평범한 자바스크립트입니다. if 문, 삼항 연산자, &&가 컴포넌트가 반환할 JSX를 결정합니다. 각 패턴, &&가 출력할 수 있는 엉뚱한 0, null 반환, 그리고 컴포넌트를 숨기는 것과 렌더링하지 않는 것이 다른 이유를 배웁니다.
- 리스트와 keyReact에서 목록을 렌더링하려면 배열에 map()을 호출해 항목마다 JSX를 반환하고, 모든 항목에 key prop을 줍니다. filter 후 map, key를 어디서 가져와야 하는지, 그리고 목록이 바뀔 때 배열 인덱스 key가 항목을 뒤섞는 이유를 배웁니다.
- 이벤트 처리React 이벤트는 onClick, onChange처럼 함수를 받는 props이며, 사용자가 행동하면 React가 이벤트 객체와 함께 그 함수를 호출합니다. 핸들러를 호출하지 않고 넘기는 법, 인자 전달, e.target.value와 e.key 읽기, 폼 새로고침 막기, 버블링 중단을 배웁니다.
- 리액트 CSSReact 컴포넌트는 className과 일반 CSS, 자바스크립트로 계산한 값을 위한 style prop, 범위가 지정된 클래스 이름을 위한 CSS Modules, 또는 Tailwind 유틸리티 클래스로 스타일을 줍니다. 각 방법, 조건부 클래스, 그리고 언제 무엇을 쓸지 배웁니다.
state와 폼
- useStateuseState는 리렌더링 사이에도 유지되는 값과, 값이 바뀌면 화면을 다시 그리는 setter를 컴포넌트에 제공합니다. 문법, 업데이터 함수, 상태 안의 객체와 배열, 그리고 값을 설정한 직후에 이전 값이 보이는 이유를 배웁니다.
- 배열과 객체 업데이트React state의 배열이나 객체를 바꾸려면 새로 만들어 setter에 넘깁니다. 항목 추가, 제거, 교체, 삽입, 정렬, 중첩 객체 업데이트, 그리고 state를 직접 변경하면 화면이 그대로인 이유를 배웁니다.
- 리액트 폼제어 입력으로 React 폼을 만듭니다. 텍스트 필드, textarea, select, 체크박스와 라디오 버튼, 여러 필드를 하나의 state 객체로 관리하기, onSubmit으로 제출하기, 유효성 검사 오류 표시, 그리고 React 19 폼 액션을 다룹니다.
- 제어 컴포넌트 비제어 컴포넌트제어 input은 React state에서 값을 받고 onChange로만 바뀝니다. 비제어 input은 자기 값을 DOM에 보관하며, ref나 FormData로 읽습니다. 차이점, 자주 보는 경고, 그리고 각각을 언제 쓸지 배웁니다.
- 상태 끌어올리기상태 끌어올리기는 두 컴포넌트의 state를 가장 가까운 공통 부모로 옮기고, 부모가 값과 setter를 props로 다시 내려 주는 것입니다. 언제 끌어올릴지, 세 단계로 끌어올리는 방법, 그리고 state를 지역에 남겨야 하는 경우를 배웁니다.
- useReduceruseReducer는 state를 저장하고 모든 업데이트를 하나의 리듀서 함수로 옮깁니다. 액션을 dispatch하면 리듀서가 다음 state를 반환합니다. 문법, 순수한 리듀서 작성법, 할 일 목록 예제, 지연 초기화, 그리고 useState 대신 고를 때를 배웁니다.
이펙트와 ref
- useEffectuseEffect는 React가 화면을 업데이트한 뒤에 코드를 실행하므로, 컴포넌트가 타이머, 구독, 이벤트 리스너처럼 React 바깥의 무언가와 동기화할 수 있습니다. 의존성 배열의 세 가지 형태, 클린업, 무한 루프, 그리고 이펙트가 아예 필요 없는 경우를 배웁니다.
- 리액트 데이터 가져오기React에서는 useEffect에서 요청을 시작하고, 로딩, 오류, 데이터를 state에 보관하고, 입력이 바뀐 뒤에 도착한 응답은 무시하는 방식으로 데이터를 가져옵니다. 이펙트 안의 async/await, AbortController, 경쟁 상태, 그리고 라이브러리를 써야 할 때를 다룹니다.
- useRefuseRef는 컴포넌트에 `{ current }`라는 상자를 줍니다. 렌더링 사이에도 내용이 유지되고, 바꿔도 렌더링이 일어나지 않습니다. DOM 노드에 접근하거나(포커스, 스크롤, 측정) 타이머 id처럼 화면에 보이지 않는 값을 저장할 때 사용합니다.
- forwardRefforwardRef를 쓰면 컴포넌트가 부모에게서 ref를 받아 안쪽의 DOM 노드에 붙일 수 있습니다. React 19에서는 함수 컴포넌트가 `ref`를 일반 prop으로 받으므로 새 코드에는 forwardRef가 더 이상 필요 없습니다. 두 버전을 실행해 보고 useImperativeHandle과 TypeScript 타입도 살펴봅니다.
- useLayoutEffectuseLayoutEffect는 useEffect처럼 동작하지만, React가 DOM을 업데이트한 직후 브라우저가 그리기 전에 실행됩니다. 눈에 보이는 깜빡임 없이 요소를 측정하고 레이아웃을 조정할 때 쓰고, 그 밖의 모든 것에는 useEffect를 쓰세요.
훅과 컨텍스트
- 리액트 훅훅은 이름이 use로 시작하는 함수로, 컴포넌트가 state, 컨텍스트, ref, 이펙트 같은 React 기능을 쓸 수 있게 해 줍니다. 목적별로 묶은 모든 내장 훅, 모든 훅이 따르는 두 가지 규칙, 그리고 직접 훅을 만드는 방법을 살펴봅니다.
- useContextuseContext는 부모 컴포넌트가 제공하는 값을 읽으므로, 깊이 중첩된 컴포넌트가 중간의 모든 컴포넌트가 prop으로 넘겨 주지 않아도 그 값을 받을 수 있습니다. createContext, Provider, 자식에서 컨텍스트 업데이트하기, 그리고 컨텍스트가 리렌더링에 주는 영향을 배웁니다.
- Prop Drillingprop drilling은 prop을 쓰지 않는 컴포넌트들을 거쳐, 더 아래의 컴포넌트가 쓸 수 있도록 prop을 넘기는 것입니다. 실행 가능한 예제로 직접 보고, 앱이 커질수록 왜 문제가 되는지, 그리고 시도할 순서대로 해결책을 살펴봅니다. 컴포지션, 컨텍스트, 그다음 상태 관리 라이브러리입니다.
- 커스텀 훅커스텀 훅은 이름이 use로 시작하고 다른 훅을 호출하는 함수로, 여러 컴포넌트가 같은 상태 로직을 재사용할 수 있게 해 줍니다. useToggle, useLocalStorage, useDebounce, useWindowWidth를 만들어 보고, 호출마다 자기만의 state를 받는 이유를 배웁니다.
- 훅의 규칙훅에는 두 가지 규칙이 있습니다. 컴포넌트의 최상위에서 호출하고 조건문, 반복문, 중첩 함수 안에서는 호출하지 않을 것, 그리고 함수 컴포넌트나 커스텀 훅에서만 호출할 것입니다. React가 렌더링마다 같은 호출 순서를 필요로 하는 이유와, 순서가 바뀔 때 나는 오류를 고치는 방법을 배웁니다.
- useIduseId는 컴포넌트 인스턴스마다 고유하고 안정적인 id를 반환하므로, 컴포넌트가 여러 번 나타나도 라벨, input, aria-describedby 힌트가 서로를 가리킬 수 있습니다. Math.random과 카운터가 서버 렌더링에서 깨지는 이유, 그리고 useId를 목록 key로 쓰면 안 되는 이유를 배웁니다.
- useSyncExternalStoreuseSyncExternalStore는 작은 스토어 모듈이나 navigator.onLine 같은 브라우저 API처럼 React 바깥에 있는 데이터를 컴포넌트가 구독하게 하고, 그 데이터가 바뀔 때마다 다시 렌더링합니다. subscribe와 getSnapshot, 스냅샷을 캐시해야 하는 이유, getServerSnapshot을 배웁니다.
렌더링과 성능
- 리액트 렌더링React 컴포넌트는 state가 바뀔 때, 부모가 렌더링될 때, 또는 읽는 컨텍스트가 바뀔 때 다시 렌더링됩니다. 렌더링과 커밋의 차이, 가상 DOM이 실제로 뜻하는 것, 필요 없는 렌더링을 멈추는 방법을 배웁니다.
- useMemouseMemo는 렌더링 사이에 계산 결과를 캐시하고, 의존성이 바뀔 때만 다시 계산합니다. 문법, memo 자식을 위해 객체를 안정적으로 유지하는 법, 그리고 useMemo가 쓸 가치가 없는 경우를 배웁니다.
- useCallbackuseCallback은 의존성이 바뀔 때까지 렌더링 사이에 같은 함수를 반환합니다. 그 함수를 memo 자식에 넘기거나 이펙트 의존성으로 쓸 때만 도움이 됩니다. 문법, useMemo와의 차이, 피해야 할 실수를 배웁니다.
- React.memomemo는 컴포넌트를 감싸서, props가 지난번과 얕은 비교로 같으면 React가 리렌더링을 건너뛰게 합니다. 언제 도움이 되는지, props의 새 객체와 함수가 왜 memo를 무력화하는지, 그리고 memo가 막지 못하는 것을 배웁니다.
- useTransitionuseTransition은 state 업데이트를 긴급하지 않은 것으로 표시해서, React가 느린 부분을 백그라운드에서 렌더링하는 동안 페이지가 반응성을 유지하게 합니다. isPending, startTransition, React 19의 비동기 트랜지션, 그리고 디바운스와 다른 이유를 배웁니다.
- useDeferredValueuseDeferredValue는 무거운 렌더링 중에 뒤처져도 되는 값의 사본을 주므로, 느린 목록이 따라잡는 동안에도 input이 반응성을 유지합니다. 동작 방식, React 19의 초기값, 그리고 useTransition 및 디바운스와의 비교를 배웁니다.
- Suspense와 lazySuspense는 안의 컴포넌트가 준비되지 않은 동안 대체 UI를 보여 주고, React.lazy는 컴포넌트가 처음 렌더링될 때만 그 코드를 불러옵니다. 코드 분할, 중첩된 경계, React 19의 use()와 Suspense, 오류 처리를 배웁니다.
React 19와 고급 주제
- React 19React 19는 액션, useActionState, useOptimistic, use, prop으로서의 ref, 문서 메타데이터를 추가했고, 19.2는 Activity와 useEffectEvent를 추가했습니다. 각 기능을 실행해 보고, 무엇이 제거되었는지, 어떻게 업그레이드하는지 살펴봅니다.
- useActionStateuseActionState는 async 액션을 감싸고, 액션이 마지막으로 반환한 값을 보관하며, 아직 실행 중인지 알려 줍니다. 시그니처, 폼 액션, 유효성 검사 오류 반환, 폼 바깥에서 호출하기를 배웁니다.
- useOptimisticuseOptimistic은 async 액션이 아직 실행 중인 동안 예상되는 결과를 보여 주고, 끝나면 실제 state로 돌아가므로 실패한 요청은 스스로 되돌려집니다. 문법, 리듀서 형태, 그리고 액션 안에서 실행해야 하는 이유를 배웁니다.
- use 훅use는 렌더링 중에 프로미스나 컨텍스트의 값을 읽습니다. 프로미스라면 데이터가 도착할 때까지 일시 중단하고 가장 가까운 Suspense의 대체 UI를 보여 줍니다. 다른 훅과 달리 if 문과 반복문 안에서도 실행할 수 있습니다.
- 에러 바운더리에러 바운더리는 안쪽 컴포넌트가 렌더링 중에 던진 오류를 잡아서 빈 화면 대신 대체 UI를 보여 주는 컴포넌트입니다. 무엇을 잡는지, 클래스로 작성하는 법, 초기화하는 법, 그리고 react-error-boundary 라이브러리를 배웁니다.
- 리액트 포털createPortal은 컴포넌트의 일부를 document.body 같은 다른 DOM 노드에 렌더링하면서도, React 트리에서는 같은 자리에 둡니다. overflow hidden과 z-index 쌓임 맥락에서 벗어나야 하는 모달, 툴팁, 메뉴에 사용하세요.
- Strict ModeStrictMode는 개발 환경에서만 동작하는 래퍼로, 컴포넌트를 두 번 렌더링하고, 마운트 시 이펙트를 setup, cleanup, setup 순으로 실행하며, 지원 중단된 API를 경고해서 순수하지 않은 렌더링과 빠진 클린업을 일찍 드러냅니다. 프로덕션에서는 아무것도 하지 않습니다.
- 리액트 생명주기모든 React 컴포넌트는 마운트되고(나타나고), 업데이트되고(다시 렌더링되고), 언마운트됩니다(제거됩니다). 각 단계가 useEffect에 어떻게 대응하는지, 클래스 생명주기 메서드와 그에 대응하는 훅, 그리고 렌더링 단계와 커밋 단계를 배웁니다.
- 클래스 컴포넌트클래스 컴포넌트는 React.Component를 상속하고 render 메서드에서 JSX를 반환하는 자바스크립트 클래스입니다. this.props, this.state와 setState, 이벤트 핸들러 바인딩, 생명주기 메서드, PureComponent, 그리고 클래스를 함수 컴포넌트로 바꾸는 방법을 배웁니다.
비교와 면접
- 리액트 면접 질문초급부터 고급까지 약 30개의 리액트 면접 질문을 면접관이 받아들일 짧은 답변과 함께 정리했습니다. 읽는 것보다 보는 것이 쉬운 질문에는 실행 가능한 코드가 있습니다.
- React vs AngularReact는 다른 도구와 조합해서 쓰는 UI 라이브러리이고, Angular는 라우팅, 폼, HTTP, 의존성 주입이 내장된 완전한 프레임워크입니다. 두 방식으로 작성한 같은 컴포넌트를 나란히 비교합니다.
- React vs VueReact와 Vue는 모두 컴포넌트로 사용자 인터페이스를 만드는 자바스크립트 도구입니다. 마크업(JSX와 템플릿), 변경에 반응하는 방식(불변 state와 리렌더링, 변경 가능한 반응형 ref), 그리고 생태계에서 공식 도구가 차지하는 비중이 다릅니다.
- 리액트 타입스크립트TypeScript로 React 앱에 타입을 지정하는 방법입니다. props와 children, 유니온과 null을 쓰는 useState, DOM 요소를 위한 useRef, 이벤트 핸들러, 컨텍스트, 제네릭 컴포넌트, 네이티브 요소 props를 다룹니다.