Learn React 1장 / UI 구성하기
신현호
React Docs
목차
1장 / UI 구성하기
#첫 번째 컴포넌트
#React 애플리케이션은 컴포넌트라고 불리는 분리된 UI 조각으로 구축됩니다. React 컴포넌트는 마크업으로 뿌릴 수 있는 JS 함수입니다.
컴포넌트는 버튼처럼 작을 수도 있고 전체 페이지처럼 클 수도 있습니다. 다음은 그 예시입니다.
우리는 웹에서 HTML의 다양한 태그를 통해 풍부한 구조의 문서를 만들 수 있습니다.
html
<article>
<h1>My First Component</h1>
<ol>
<li>Components: UI Building Blocks</li>
<li>Defining a Component</li>
<li>Using a Component</li>
</ol>
</article>
이 마크업은 아티클을 article 태그로, 제목을 h1 태그로, 목차를 ol태그로 나타내고 있습니다.
이와같은 마크업은 스타일을 위한 CSS, 상호작용을 위한 JS와 결합되어 웹에서 볼 수 있는 모든 사이드바, 아바타, 모달, 드롭다운 등 모든 UI의 기반이 됩니다.
React를 사용하면 마크업, CSS, JS를 앱의 재사용 가능한 UI 요소인 컴포넌트로 결합할 수 있습니다.
그 예시로 React를 사용하면 위의 HTML태그를 간단하게 <TableOfContents /> 로 사용할 수 있습니다.
jsx
export default function TableOfContents() {
return (
<article>
<h1>My First Component</h1>
<ol>
<li>Components: UI Building Blocks</li>
<li>Defining a Component</li>
<li>Using a Component</li>
</ol>
</article>
)
}
컴포넌트를 생성할 때는 export default 접두사를 사용하면 됩니다. 이 접두사를 사용하면 나중에 다른 파일에서 해당 컴포넌트를 로드할 수 있습니다.
React 컴포넌트는 반드시 대문자로 시작해야합니다. 대문자로 시작하지 않으면 작동하지 않습니다. (JSX 문법을 사용하는 React 컴포넌트 한정입니다.)
jsx
// bad
export default function profile() {
...
}
// good
export default function Profile() {
...
}
마크업을 추가하기 위해 다음과 같이 로직을 작성할 수 있습니다.
jsx
return <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
한 줄의 경우 다음과 같이 작성할 수 있지만, 여러줄을 return해야하는 경우 괄호로 묶어야 합니다.
jsx
return (
<div>
<img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
</div>
)
컴포넌트 import 및 export
#하나의 파일에 여러 컴포넌트를 선언할 수 있지만 파일이 커지면 탐색하기가 어려워집니다.
따라서 이 문제를 해결하기 위해 컴포넌트들을 분리하여 export(내보내기) 한 다음 다른 파일에서 해당 컴포넌트를 import(가져오기) 해야합니다.
앞서 말했던 것 처럼, 컴포넌트를 내보내기 / 가져오기 하기 위해서는 import, export를 사용하면 됩니다. 사용 방법도 간단합니다.
- 컴포넌트를 넣을 JS파일을 생성합니다.
- 새로 만든 파일에서 함수 컴포넌트를 export합니다. (default 또는 name export 방식을 사용합니다.)
- 컴포넌트를 사용할 파일에서 import합니다. (default 또는 named export에 대응하는 방식으로 import합니다.)
JSX로 마크업 작성하기
#웹은 HTML, CSS, JS를 기반으로 만들어져왔고, 수년 동안 웹 개발자들은 컨텐츠는 HTML, 디자인은 CSS, 로직은 JS로 작성해왔습니다.
이전까지는 분리된 파일로 관리를 해왔으나 웹이 인터랙티브 해지면서 로직이 컨텐츠를 결정하는 경우가 많아졌습니다.
그래서 JS가 HTML을 담당하게 되었고, 이것이 React에서 렌더링, 마크업 로직이 같은 위치에 존재하는 이유입니다.
만약 버튼을 React 컴포넌트로 만든다고 생각해봅시다. 버튼의 렌더링 로직과 마크업 로직이 함께 존재한다면 모든 편집에서 동기화 상태를 유지할 수 있을 것입니다.
반대로, 버튼의 마크업과 사이드바의 마크업처럼 서로 관련이 없는 항목들은 서로 분리되어있기 때문에 각각 개별적으로 변경하는 것이 안전합니다.
html
<h1>Hedy Lamarr's Todos</h1>
<img src="https://i.imgur.com/yXOvdOSs.jpg" alt="Hedy Lamarr" class="photo" />
<ul>
<li>Invent new traffic lights</li>
<li>Rehearse a movie scene</li>
<li>Improve the spectrum technology</li>
</ul>
위와 같은 html 로직이 있습니다. 이걸 React 컴포넌트로 그대로 변환한다고 해서 React가 렌더링 할 수 있을까요?
정답은 안된다입니다. 왜냐하면 JSX는 HTML보다 더 염격하고 몇 가지 규칙이 더 존재하기 때문입니다.
해당 오류를 해결하기 위해서는 단일 엘리먼트만을 반환해야합니다. 아래의 예 처럼요.
jsx
<div>
<h1>Hedy Lamarr's Todos</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
...
</ul>
</div>
<div>말고도 <>와 </>를 사용해서 나타낼 수도 있습니다. 이런 빈 태그를 Fragment라고 합니다.
Fragment는 브라우저상의 HTML 트리 구조에서 흔적을 남기지 않고 그룹화해줍니다.
jsx
<>
<h1>Hedy Lamarr's Todos</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
...
</ul>
</>
JSX에서는 태그를 명시적으로 닫아야합니다. <img>와 같이 자체적으로 닫는 태그도 마찬가지입니다.
<li>와 같은 래핑 태그 역시도 반드시 닫아줘야합니다.
jsx
<>
<img src="https://i.imgur.com/yXOvdOSs.jpg" alt="Hedy Lamarr" class="photo" />
<ul>
<li>Invent new traffic lights</li>
<li>Rehearse a movie scene</li>
<li>Improve the spectrum technology</li>
</ul>
</>
JSX는 JS로 바뀌고 JSX로 작성된 어트리뷰트는 JS 객체의 키가 됩니다.
컴포넌트 안에서 어트리뷰트를 변경하고 싶을 때가 있을 것입니다. 하지만 JS 변수명에는 제한이 있습니다. 예를들어 class같은 이름들 말입니다.
이것이 React에서 많은 HTML과 SVG 어트리뷰트들이 카멜 케이스로 작성되는 이유입니다. 예를 들어 SVG의 stroke-width 대신 strokeWidth를 사용하는 것 처럼요
JSX에서 JS 이용하기
#JSX에 문자열 속성을 전달하려면, 작은 따옴표 또는 큰 따옴표로 묶습니다. (백틱 ` 도 가능합니다)
jsx
export default function Avatar() {
return (
<img
className="avatar"
src="https://i.imgur.com/7vQD0fPs.jpg"
alt="Gregorio Y. Zara"
/>
)
}
근데 src나 alt에 동적으로 값을 지정하고싶으면 어떻게 해야할까요? 이럴 때는 큰 따옴표를 중괄호로 대체하여 JS의 값을 사용할 수 있습니다.
jsx
export default function Avatar() {
const avatar = 'https://i.imgur.com/7vQD0fPs.jpg'
const description = 'Gregorio Y. Zara'
return <img className="avatar" src={avatar} alt={description} />
}
JSX는 JS를 작성하는 특별한 방법입니다. 그것은 즉, 중괄호 안에서 JS를 사용할 수 있다는 의미입니다.
아래의 로직에서 name값을 변경하면 투두리스트의 제목 또한 변경됩니다.
jsx
export default function TodoList() {
const name = 'Gregorio Y. Zara'
return <h1>{name}'s To Do List</h1>
}
중괄호 사이에는 모든 JS 표현식이 작동합니다.
jsx
const today = new Date()
function formatDate(date) {
return new Intl.DateTimeFormat('en-US', { weekday: 'long' }).format(date)
}
export default function TodoList() {
return <h1>To Do List for {formatDate(today)}</h1>
}
JSX 내부에서는 중괄호를 두 가지 방법으로만 사용할 수 있습니다.
- JSX 태그 안에 직접 텍스트로 사용하기 : ex) <h1>{name}</h1>
- = 기호 바로 뒤에 오는 속성 : ex) src={avatar}
문자열, 숫자 및 기타 JS 표현식 외에도 JSX로 객체를 전달할 수도 있습니다. 객체는 중괄호로 표시할 수 있습니다.
따라서 JSX에서 JS 객체를 전달하려면 다른 중괄호 쌍으로 객체를 감싸야합니다.
JSX의 인라인 CSS스타일에서 이것을 볼 수 있습니다. (사실 React에서는 딱히 인라인 스타일을 사용할 필요가 없습니다.)
하지만 필요한 경우 다음과 같이 객체를 전달할 수 있습니다.
jsx
export default function TodoList() {
return (
<ul
style={{
backgroundColor: 'black',
color: 'pink',
}}>
<li>Improve the videophone</li>
<li>Prepare aeronautics lectures</li>
<li>Work on the alcohol-fuelled engine</li>
</ul>
)
}
컴포넌트에 props 전달하기
#React 컴포넌트는 서로 통신하기 위해 props를 사용합니다. 모든 부모 컴포넌트는 자식 컴포넌트에 props를 전달할 수 있습니다.
props라고 하면 HTML 어트리뷰트를 떠올릴 수 있지만 객체, 배열, 함수, 심지어 JSX를 포함한 모든 JS값을 전달할 수 있습니다.
다음 예제에서는 Card 컴포넌트가 props로 children을 받고있습니다.
jsx
import { getImageUrl } from './utils.js'
export default function Profile() {
return (
<Card>
<Avatar
size={100}
person={{
name: 'Katsuko Saruhashi',
imageId: 'YfeOqp2',
}}
/>
</Card>
)
}
function Avatar({ person, size }) {
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
)
}
function Card({ children }) {
return <div className="card">{children}</div>
}
children 말고 다른 일반적인 props를 전달하고 싶다면 다음과 같이 사용하면 됩니다.
jsx
export default function Profile() {
return (
<Avatar person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }} size={100} />
)
}
이제 Avatar 컴포넌트 내부에서는 person을 조회하여 name과 imageId 값을, size를 통해 100이라는 값을 참조할 수 있습니다.
자식 컴포넌트에서는 다음과 같이 사용하면 됩니다.
jsx
function Avatar({ person, size }) {
// person and size are available here
}
props에 기본값을 지정하는 방법도 있습니다.
jsx
function Avatar({ person, size = 100 }) {
// ...
}
때때로 전달되는 props들은 반복적입니다. 이럴때는 spread 구문을 통해 간결하게 나타낼 수 있습니다.
jsx
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
)
}
단, 전개구문은 제한적으로 사용되어야 합니다. 다른 모든 컴포넌트에 이 구문이 적용되어있다면 문제가 있는 것입니다.
이는 종종 컴포넌트를 분할하여 자식을 JSX로 전달해야 함을 나타냅니다.
props는 항상 고정되어 있지 않습니다. 부모 컴포넌트로부터 받게되는 데이터가 변경되면 props는 그때마다 변경된 데이터를 반영합니다.
그러나 props는 불변으로, 컴퓨터 과학에서 변경할 수 없다는 뜻의 용어입니다.
컴포넌트가 props를 변경해야 하는 경우 부모 컴포넌트에 다른 props, 즉 새로운 객체를 전달하도록 요청해야합니다.
그렇게 되면 이전의 props는 버려지고, JS 엔진은 기존 props가 차지했던 메모리를 회수(가비지 콜렉팅) 하게 됩니다.
props 변경을 시도하지 마세요 사용자 입력에 따라 props가 변경되어야 하는 경우에는 후에 나올 set state가 필요할 것입니다.
조건부 렌더링
#상품이 포장되었는지 여부를 표시할 수 있는 여러개의 Item을 렌더링하는 PackingList 컴포넌트가 있다고 가정해봅시다.
일부 Item 컴포넌트의 isPacked prop이 false가 아닌 true로 설정되어 있는 것을 확인할 수 있습니다.
이 경우, true 항목에 대해서 체크 표시를 추가하고 싶습니다. 그렇다면 어떤식으로 이를 구현할 수 있을까요?
if/else 문으로 해당 기능을 구현할 수 있습니다.
어떤 상황에서는 아무것도 렌더링하고 싶지 않을수도 있습니다. 예를들어, 포장된 아이템을 전혀 표시하고 싶지 않다고 가정해보겠습니다.
컴포넌트는 무언가를 반환해야만 합니다. 이런 경우에는 null을 반환하면 됩니다.
실제로 컴포넌트에서 null을 반환하는 것은 렌더링하려는 개발자를 놀라게 할 수 있기 때문에 일반적이지 않습니다.
부모 컴포넌트의 JSX에 컴포넌트를 조건부로 포함하거나 제외하는 경우가 더 많습니다. 이러한 방법은 다음에서 설명하도록 하겠습니다.
이전 예제에서는 컴포넌트가 반환할 JSX 트리가 있는 경우를 제어했습니다. 그런데, 해당 렌더링 출력을 가만히 보다보면 중복을 발견할 수 있습니다.
jsx
<li className="item">{name} ✔</li>
jsx
<li className="item">{name}</li>
위와 아래는 매우 유사합니다. 이러한 중복은 해롭지는 않지만 코드를 유지 관리하기 어렵게 만들 수 있습니다.
className을 변경하려면 어떻게 해야할까요? 코드의 두 곳 모두에서 변경해야 할 것입니다.
이런 상황에서는 조건부로 약간의 JSX를 포함시켜 코드를 더 DRY하게 만들 수 있습니다.
삼항 연산자를 사용하면 이를 간결하게 나타낼 수 있습니다.
jsx
// bad
if (isPacked) {
return <li className="item">{name} ✔</li>
}
return <li className="item">{name}</li>
// good
return <li className="item">{isPacked ? name + ' ✔' : name}</li>
또 다른 단축표현으로는 논리 AND 연산자 (&&) 가 있습니다.
React 컴포넌트 내에서 조건이 참일 때 일부 JSX를 렌더링하거나 아무것도 렌더링하지 않으려 할 때 자주 사용됩니다.
jsx
return (
<li className="item">
{name} {isPacked && '✔'}
</li>
)
JS && 표현식은 왼쪽(조건)이 참이면 오른쪽의 값을 반환합니다.
하지만 조건이 거짓이라면 전체가 false가 되어 아무것도 렌더링하지 않습니다.
아래는 위의 단축표현을 사용하여 구현한 예제입니다.
단축키가 일반 코드를 작성하는데 방해가 된다면 if문과 변수를 사용해 보세요. let으로 정의된 변수는 재할당할 수 있습니다!
jsx
let itemContent = name
if문을 사용하여 isPacked가 true면 JSX 표현식을 itemContent에 재할당합니다.
jsx
if (isPacked) {
itemContent = name + ' ✔'
}
이 다음 반환된 변수를 JSX 트리에 삽입하여 이전에 계산된 표현식을 JSX 안에 중첩시킵니다.
jsx
<li className="item">{itemContent}</li>
아래는 이를 사용한 예제입니다.
목록 렌더링
#jsx
<ul>
<li>Creola Katherine Johnson: mathematician</li>
<li>Mario José Molina-Pasquel Henríquez: chemist</li>
<li>Mohammad Abdus Salam: physicist</li>
<li>Percy Lavon Julian: chemist</li>
<li>Subrahmanyan Chandrasekhar: astrophysicist</li>
</ul>
위와 같은 콘텐츠 목록이 있다고 가정해보겠습니다.
이러한 목록을 React에서 어떻게 효과적으로 렌더링할 수 있을까요?
다음은 배열에서 항목 목록을 생성하는 방법에 대한 간단한 예시입니다.
- 데이터를 배열로 이동시킵니다.
js
const people = [
'Creola Katherine Johnson: mathematician',
'Mario José Molina-Pasquel Henríquez: chemist',
'Mohammad Abdus Salam: physicist',
'Percy Lavon Julian: chemist',
'Subrahmanyan Chandrasekhar: astrophysicist',
]
- people 요소들을 JSX 노드 배열에 매핑합니다.
jsx
const listItems = people.map((person) => <li>{person}</li>)
- 컴포넌트에서 ul로 감싼 listItems를 반환합니다.
jsx
return <ul>{listItems}</ul>
만약 항목 배열을 필터링 하고싶다면 이 또한 간단합니다. JS의 배열 함수인 Array.filter() 를 사용하여 위의 과정을 수행하면 됩니다.
매핑된 항목들에 key가 존재하지 않을 때 해당 오류가 발생합니다. 이 오류에 주목해봅시다.
React에서 각 배열 항목에는 해당 배열의 항목들 사이에서 고유하게 식별할 수 있는 문자열 또는 숫자인 key를 부여해야합니다.
key는 다음 규칙을 따라야 합니다.
- key는 형제간에 고유해야 합니다.
- key는 변경되지 않아야 합니다.
그럼 이러한 key들은 어디에서 얻을 수 있을까요?
- 데이터베이스의 데이터의 경우 데이터베이서의 key/ID를 사용할 수 있습니다.
- 로컬에서 생성된 데이터의 경우 uuid와 같은 패키지를 사용하면 됩니다.
컴포넌트 순수성 유지
#순수 함수란 다음과 같은 특징을 가진 함수입니다.
- 자신의 일에만 신경씁니다. 호출되기 전에 존재했던 객체나 변수를 변경하지 않습니다.
- 동일 입력, 동일 출력. 동일한 입력이 주어지면 항상 동일한 결과를 반환 해야합니다.
아래와 같은 함수가 JS에서 순수함수라고 할 수 있습니다.
js
function double(number) {
return 2 * number
}
React는 이 개념을 중심으로 설계되었습니다. React는 우리가 작성하는 모든 컴포넌트가 순수 함수라고 가정합니다.
우리가 작성하는 React컴포넌트는 동일한 입력이 주어졌을 때 항상 동일한 JSX를 반환해야합니다.
컴포넌트를 레시피라고 생각할 수 있습니다. 레시피를 따르고 요리 과정에서 새로운 재료를 넣지 않으면 매번 같은 요리를 얻을 수 있습니다.
React에서 그 요리는 컴포넌트가 렌더링에 반응하기 위해 제공하는 JSX입니다.
React의 렌더링 프로세스는 항상 순수해야 합니다. 컴포넌트는 오직 JSX만을 반환해야하며, 렌더링 전에 존재했던 객체나 변수를 변경해서는 안됩니다.
jsx
let guest = 0
function Cup() {
// Bad: changing a preexisting variable!
// 나쁨: 기존 변수를 변경합니다!
guest = guest + 1
return <h2>Tea cup for guest #{guest}</h2>
}
export default function TeaSet() {
return (
<>
<Cup />
<Cup />
<Cup />
</>
)
}
이 컴포넌트는 다음과 같은 문제를 야기합니다.
- 외부에서 선언된 guest 변수 때문에 호출할 때마다 다른 JSX가 생성됩니다.
- 다른 컴포넌트가 guest를 읽으면 렌더링된 시점에 따라 JSX도 다르게 생성됩니다.
우리는 guest를 props로 전달함으로써 이러한 사이드이펙트를 방지할 수 있습니다.
jsx
function Cup({ guest }) {
return <h2>Tea cup for guest #{guest}</h2>
}
export default function TeaSet() {
return (
<>
<Cup guest={1} />
<Cup guest={2} />
<Cup guest={3} />
</>
)
}
이제 컴포넌트가 반환하는 JSX는 guest props에만 의존하므로 순수하다고 할 수 있습니다.
일반적으로 컴포넌트가 특정 순서로 렌더링될 것이라고 기대해서는 안됩니다.
예를들어 y = 2x라는 수식을 y = 5x앞에 호출하든 뒤에 호출하든요. 두 수식은 서로 독립적으로 해결됩니다.
마찬가지로 각 컴포넌트는 렌더링 중에 다른 컴포넌트와 조율하거나 의존하지 말고 스스로 생각하게 해야 합니다.
위의 예시에서는 컴포넌트가 렌더링하는동안 기존 변수를 변경하는 것이 문제였습니다.
하지만 React에서 렌더링하는동안 '방금' 생성한 변수와 객체를 변경하는 것은 완전히 괜찮습니다. 아래는 그 예시입니다.
jsx
function Cup({ guest }) {
return <h2>Tea cup for guest #{guest}</h2>
}
export default function TeaGathering() {
let cups = []
for (let i = 1; i <= 12; i++) {
cups.push(<Cup key={i} guest={i} />)
}
return cups
}
함수형 프로그래밍은 순수성에 크게 의존하지만, 언젠가는 어딘가에서 '무언가'는 바뀌어야 합니다 그리고 이것이 바로 프로그래밍의 핵심입니다.
화면 업데이트, 애니메이션 시작, 데이터 변경과 같은 이러한 변경을 사이드 이펙트라고 하며, 렌더링중에 일어나는 것이 아니라 부수적으로 일어나는 일입니다.
React에서 사이드 이펙트는 보통 이벤트 핸들러에 속합니다. 이벤트 핸들러는 사용자가 어떤 동작을 수행할 때 React가 실행하는 함수입니다.
이벤트 핸들러가 컴포넌트 내부에 정의되어 있긴 하지만 렌더링중에는 실행되지 않습니다. 따라서 이벤트 핸들러는 순수할 필요가 없습니다
다른 모든 옵션을 다 사용했는데도 사이드 이펙트게 적합한 이벤트 핸들러를 찾을 수 없다면, 컴포넌트에서 useEffect호출을 통해 반환된 JSX에 이벤트 핸들러를 첨부할 수 있습니다.
하지만 이 방법은 최후의 수단으로 사용되어야 합니다.
트리로서의 UI
#트리는 아이템 간의 관계 모델이며 UI는 트리 구조를 사용하여 표현되는 경우가 많습니다.
예를 들어 브라우저는 트리 구조를 통해 HTML(DOM) 및 CSS(CSSOM)를 모델링합니다. 모바일 플랫폼 또한 트리를 사용하여 뷰 계층 구조를 나타냅니다.
React역시 마찬가지입니다.
- React는 모듈과 컴포넌트 사이의 관계를 트리 형태로 구성합니다.
- React의 렌더 트리는 컴포넌트간의 부모와 자식관계를 나타낼 수 있습니다.
렌더 트리는 렌더 패스마다 다를 수 있지만 일반적으로 이러한 트리는 React 앱의 최상위 컴포넌트와 리프 컴포넌트가 무엇인지 식별하는데 도움이 됩니다.
최상위 컴포넌트의 경우 그 아래에 있는 모든 컴포넌트의 렌더링 성능에 영향을 미치며 종종 가장 복잡한 컴포넌트를 포함합니다.
리프 컴포넌트는 트리 하단에 있으며 하위 컴포넌트가 없고 자주 리렌더링 됩니다.
트리로 모델링 할 수 있는 React 앱의 또 다른 관계는 앱의 모듈 종속성입니다. 컴포넌트와 로직을 별도의 파일로 분리하면서 컴포넌트, 함수 또는 상수를 내보낼 수 있는 JS 모듈을 만듭니다.
- 모듈 종속성 트리의 각 노드는 모듈이고 각 분기는 해당 모듈의 import 문을 나타냅니다.
- 이전 Inspirations 앱을 사용하면 모듈 종속성 트리, 줄여서 종속성 트리를 구축할 수 있습니다.
트리의 루트 노드는 entrypoint 파일이라고도 알려진 루트 모듈입니다. 루트 컴포넌트를 포함하는 모듈인 경우가 많습니다.
위의 렌더 트리와 비교해보면 구조는 비슷하지만 몇 가지 차이점이 있습니다.
- 트리를 구성하는 노드는 컴포넌트가 아닌 모듈입니다.
- Inspirations.js와 같은 컴포넌트가 아닌 모듈도 트리에 표시됩니다. 반면에 렌더 트리는 컴포넌트만 트리로 캡슐화합니다.
- Copyright.js는 App.js의 하위 노드로 나타나지만 렌더트리에서 Copyright 컴포넌트는 InspirationGenerator의 하위 컴포넌트로 나타납니다.
- 이는 JSX를 ChildProp으로 전달하여 자식 컴포넌트로 렌더링하지만 모듈을 가져오지는 않기 때문입니다.
종속성 트리는 React 앱을 실행하는 데 필요한 모듈들을 결정하는 데 유용합니다. 프로덕션용 React 앱을 빌드할 때 일반적으로 클라이언트에 제공하는 데 필요한 모든 JS를 번들로 묶는 빌드 단계가 있습니다.
이를 담당하는 도구를 번들러라고 하며, 번들러는 종속성 트리를 사용하여 어떤 모듈을 포함할지 결정합니다.
앱이 성장함에 따라 번들 크기도 커지는 경우가 많습니다. 큰 번들 크기는 다운로드 / 실행하는데 비용이 많이 듭니다.
번들 크기가 크면 UI가 그려지는 시간이 지연될 수 있습니다. 앱의 종속성 트리를 이해하면 이러한 문제를 디버깅하는데 도움이 될 수 있습니다.
참고
#신현호
Frontend Developer
프론트엔드 개발자를 꿈꾸고 있는 대학생입니다. 끊임없이 배우고 성장하는 개발자가 되기 위해 노력하고 있습니다.
React Docs
총 5개의 포스트가 존재합니다.