Describing the UI
1. Your first component
- React를 사용하면 앱에 재사용 가능한 UI 요소인 컴포넌트를 만들 수 있음
- React 앱에서는 모든 UI가 컴포넌트
- React 컴포넌트는 일반적인 자바스크립트 함수
- 컴포넌트의 이름은 항상 대문자로 시작
- JSX 마크업을 반환
2. Importing and Exporting Components
The root component file
- 루트 컴포넌트는 보통 App.js 파일에 있지만, 설정에 따라 루트 컴포넌트가 다른 파일에 있을 수도 있음.
- Next.js와 같이 파일 기반 라우팅이 있는 프레임워크를 사용하는 경우 루트 컴포넌트는 페이지마다 달라짐.
Exporting and importing a component
컴포넌트를 export 하고 import하는 방법
1. 컴포넌트를 넣을 새 JS 파일 생성
2. 해당 파일에서 함수 컴포넌트를 export(default export or named export).
3. 컴포넌트를 사용할 파일로 컴포넌트를 import(export 방식에 맞는 import 방식 사용).
Exporting and importing multiple components from the same file
하나의 파일은 최대 하나의 default export만 가질 수 있지만, named export는 여려 개 가질 수 있음.

3. Writing Markup with JSX
JSX: Putting markup into JavaScript
- 각 React 컴포넌트는 React가 브라우저에 렌더링하는 마크업을 포함하는 JavaScript 함수.
- React 컴포넌트는 JSX라는 구문 확장자를 사용해 해당 마크업을 표현
- JSX는 HTML과 매우 비슷해 보이지만 조금 더 엄격하고 동적 정보를 표시할 수 있음
The Rules of JSX
- 컴포넌트에서 여러 element를 반환하려면 하나의 부모 tag로 감싸야 함(ex. 빈 태그인 Fragment)
- Fragment: 브라우저 HTML 트리에 영향을 주지 않고 element들을 묶어줌
- 모든 태그는 닫혀야 함
- self-closing tag:
<img/>
- wrapping tag:
<div></div>
- JSX가 자바스크립트로 바뀌면 JSX로 작성된 attribute는 자바스크립트 객체의 키가 됨. 이 attribute들을 변수로 읽는 경우가 많이 생기는데, 자바스크립트에는 변수 이름에 제한이 있으므로(변수 이름에는 대시를 포함하거나 클래스 같은 예약어를 사용할 수 없음) React에서는 대부분의 HTML과 SVG attribute를 camelCase로 작성.
- class는 자바스크립트에서 예약어이므로 className으로 대체
4. JavaScript in JSX with Curly Braces
Passing strings with quotes
JSX에서 attribute에 문자열을 전달하고 싶을 때는 쌍따옴표("") 사용
Using curly braces: A window into the JavaScript world
JSX 안에서 중괄호({})를 사용하여 JavaScript를 사용가능
- 함수 호출도 가능
- tag 이름으로는 사용 불가
Using “double curlies”: CSS and other objects in JSX
JSX에서 JavaScript 객체를 전달하고 싶은 경우 중괄호 안에 객체가 들어가므로, 중괄호 두 개안에 객체의 property들이 나열된 것처럼 보임. (person={{ name: "Hedy Lamarr", inventions: 5 }}.
5. Passing Props to a Component
- 모든 부모 컴포넌트는 자식 컴포넌트에 property를 전달하여 정보를 전달
- 객체, 배열, 함수를 포함한 모든 자바스크립트 값을 프로퍼티를 통해 전달 가능
Familiar props
<img>와 같은 predefined tag에 전달할 수 있는 property는 미리 정해져 있지만, 사용자가 정의하는 컴포넌트는 커스텀 가능
- 프로퍼티는 함수의 인자와 같은 역할
- 프로퍼티는 컴포넌트에 대한 유일한 인자! React 컴포넌트 함수는 하나의 argument, props 객체를 받음
6. Conditional Rendering
Conditionally returning JSX
컴포넌트는 조건에 따라 다른 것을 렌더링해야 하는 경우가 많음. React에서는 if 문, &&, ? 연산자 같은 자바스크립트 구문을 사용해 조건부로 JSX를 렌더링할 수 있음
Conditionally returning nothing with null
- 특정 조건에서 아무것도 렌더링하고 싶지 않을 때는 컴포넌트가 null을 반환하도록 하면 됨
- 하지만 실제로는 컴포넌트에서 null을 반환하는 대신 부모 컴포넌트의 JSX에서 조건부로 컴포넌트를 렌더링하는 경우가 더 많음
Conditional (ternary) operator (? :)
JavaScript의 조건부 연산자(삼항 연산자)를 사용하면 간결하게 조건부 표현식을 작성할 수 있음
Logical AND operator (&&)
7. Rendering Lists
서로 다른 데이터를 사용해서 유사한 컴포넌트를 여러 개 렌더링하고 싶을 때, JavaScript의 fiter(), map() 등의 배열 메서드를 사용해서 배열을 조작하고, 컴포넌트 배열로 변환할 수 있음
Rendering data from arrays
JavaScript의 map() 메서드는 배열의 각 항목을 같은 규칙으로 변환한 항목으로 구성된 새로운 배열을 반환하므로, 데이터를 컴포넌트 배열로 변환할 수 있음
Filtering arrays of items
JavaScript의 filter() 메서드는 배열에서 특정 조건을 만족하는 항목으로 구성된 새로운 배열을 반환하므로, 이를 이용해 렌더링하고싶은 데이터만 추출할 수 있음
Keeping list items in order with key
컴포넌트 배열의 각 컴포넌트에는 고유한 문자열이나 숫자를 key로 지정해야함. key는 각 컴포넌트가 어떤 배열 항목에 해당하는지 React에 알려주고, 배열의 항목이 삽입, 삭제되거나 순서가 변경될 때 DOM 트리를 올바르고 효율적으로 업데이트할 수 있도록 함
Displaying several DOM nodes for each list item
배열의 각 항목이 하나가 아닌 여러 개의 DOM Node로 렌더링되어야 하는 경우 <>...</> 구문에는 key를 전달할 수 없으므로 하나의 <div>로 묶거나, <Fragment> 구문을 사용해야 함
Where to get your key
- 데이터베이스에서 데이터를 가져오는 공유 공유한 데이터베이스 key나 id값을 사용
- 로컬에서 생성된 데이터의 경우 고유한 문자열을 생성해주는 uuid와 같은 패키지 사용
Rules of keys
- key는 형제 컴포넌트에 한해 고유해야하지만, 다른 배열의 JSX 노드에는 동일한 key를 사용해도 됨
- 배열에서 항목의 인덱스를 key로 사용하면 안됨. key를 지정하지 않으면 React는 항목의 인덱스를 key로 사용하지만, 항목이 삽입/삭제되거나 배열의 순서가 바뀔 경우 버그가 발생할 수 있음(참고: https://robinpokorny.com/blog/index-as-a-key-is-an-anti-pattern/)
- key는 변경되어서는 안되므로 렌더링 중에는 key값을 생성하면 안됨.
key={Math.random()}처럼 렌더링 단계에서 매번 다른 key값이 할당될 경우 모든 컴포넌트가 다시 생성되어 성능이 저하되고, 항목 내부의 사용자 입력도 손실될 수 있음.
- key를 전달해도 React가 내부적으로 사용할 뿐 컴포넌트가 이 값을 prop으로 받는 것은 아님. 컴포넌트 내부에서 고유한 id값이 필요할 경우 key와 별개의 prop으로 따로 전달해야 함.
8. Keeping Components Pure
- 순수 함수: 계산만 수행하는 함수
- 순수 함수로 컴포넌트를 작성하면 버그와 예측불가능한 동작을 피할 수 있음
- 순수함수의 특성
- 자신의 일만 신경씀: 자신이 호출되기 전에 존재했던 객체나 변수를 변경하지 않음
- 리액트는 모든 컴포넌트가 순수함수라고 가정. 즉, 모든 React 컴포넌트는 같은 Input이 주어질 때 같은 JSX를 반환해야 함
Side Effects: (un)intended consequences
- 컴포넌트에서 외부에서 선언된 변수를 변경하면, 컴포넌트가 렌더링되는 시점마다 다른 JSX를 반환하므로 결과를 예측할 수 없음
- Strict Mode에서는 개발단계에서 각 컴포넌트의 함수를 두 번씩 호출한 후, 두 결과값이 같은지 확인함으로써 순수함수가 아닌 컴포넌트를 찾아냄
- Strict 모드를 사용하려면 루트 컴포넌트를 <React.StrictMode>로 감싸면 되고, 일부 프레임워크는 기본적으로 Strict 모드를 제공
Local mutation: Your component’s little secret
리액트의 컴포넌트가 자신이 호출되기 전에 존재했던 객체나 변수를 변경해서는 안되지만, 렌더링하는동안 컴포넌트 내부에서 생성한 객체나 변수를 변경하는 것은 괜찮음
Why does React care about purity?
리액트에서 순수함수가 중요한 이유
- 동일한 입력에 대해 항상 동일한 결과를 반환하므로 하나의 컴포넌트가 많은 사용자 요청을 처리할 수 있게 됨 -> 컴포넌트를 서버와 같은 환경에서도 사용할 수 있음
- 동일한 입력에 대해 항상 동일한 결과를 반환하므로 입력값이 바뀌지 않은 컴포넌트의 렌더링을 생략하여 성능을 향상시킬 수 있음
- 순수함수는 언제든 계산을 중단해도 다른 컴포넌트에 영향을 미치지 않으므로, 깊은 컴포넌트 트리를 렌더링하는 도중에 일부 데이터가 변경되는 경우 즉시 렌더링을 중단하고 새로운 렌더링을 시작해서 성능을 향상시킬 수 있음
9. Your UI as a Tree
React는 트리 구조를 사용하여 React 앱에서 컴포넌트 간의 관계를 관리하고 모델링
- 트리 구조는 React 앱에서 데이터가 흐르는 방식, 렌더링, 앱 크기를 최적화하는 방법을 이해하는 데 유용
The Render Tree

- React 앱에서 컴포넌트간의 관계는 렌더 트리로 모델링 가능
- React 렌더 트리의 각 노드는 React 컴포넌트
- 렌더 트리는 React 컴포넌트로만 구성됨(HTML 태그 등은 포함되지 X)
- UI 프레임워크인 React가 플랫폼에 구애받지 않도록 함
- React 렌더 트리의 루트 노드는 앱의 루트 컴포넌트(React가 렌더링하는 첫 번째 컴포넌트)
- 조건부 렌더링을 통해 부모 컴포넌트는 전달받은 데이터에 따라 다른 자식 컴포넌트를 렌더링
The Module Dependency Tree
- React 앱에서 모듈간의 관계는 모듈 종속성 트리로 모델링 가능
- React 모듈 종속성 트리의 각 노드는 모듈
- React 모듈 종속성 트리의 루트 노드는 루트 노드(엔트리포인트 파일, 대부분 루트 컴포넌트를 포함)
- 빌드 단계에서 번들러는 모듈 종속성 트리를 활용해서 포함시킬 모듈을 결정 -> 앱의 다운로드, 실행 속도 향상