React는 사용자 인터페이스(UI)를 렌더링하기 위한 JavaScript 라이브러리입니다. UI는 버튼, 텍스트, 이미지와 같은 작은 단위로 구성됩니다. React를 사용하면 재사용 가능하고 중첩 가능한 컴포넌트로 결합할 수 있습니다. 웹 사이트부터 휴대폰 앱까지 화면의 모든 것을 컴포넌트로 분류할 수 있습니다. 이 장에서는 React 컴포넌트를 만들고, 사용자 정의하고, 조건부로 표시하는 방법을 배웁니다.
이 챕터에서 다룰 내용
첫 번째 컴포넌트
React 애플리케이션은 컴포넌트라고 불리는 분리된 UI 조각으로 구축됩니다. React 컴포넌트는 마크업으로 뿌릴 수 있는 JavaScript 함수입니다. 컴포넌트는 버튼처럼 작을 수도 있고 전체 페이지처럼 클 수도 있습니다. 다음은 세 개의 Profile 컴포넌트를 렌더링하는 Gallery 컴포넌트입니다.
function Profile() {
return (
<img
src="https://i.imgur.com/MK3eW3As.jpg"
alt="Katherine Johnson"
/>
);
}
export default function Gallery() {
return (
<section>
<h1>Amazing scientists</h1>
<Profile />
<Profile />
<Profile />
</section>
);
}
컴포넌트 import 및 export
하나의 파일에 여러 컴포넌트를 선언할 수 있지만 파일이 크면 탐색하기 어려울 수 있습니다. 이 문제를 해결하려면 컴포넌트를 자체 파일로 export(내보내기)한 다음 다른 파일에서 해당 컴포넌트를 import(가져오기)하면 됩니다:
// Gallery.js
import Profile from './Profile.js';
export default function Gallery() {
return (
<section>
<h1>Amazing scientists</h1>
<Profile />
<Profile />
<Profile />
</section>
);
}
// Profile.js
export default function Profile() {
return (
<img
src="https://i.imgur.com/QIrZWGIs.jpg"
alt="Alan L. Hart"
/>
);
}
JSX로 마크업 작성하기
각 React 컴포넌트는 React가 브라우저에 렌더링하는 일부 마크업을 포함할 수 있는 JavaScript 함수입니다.
React 컴포넌트는 JSX라는 구문 확장자를 사용해 해당 마크업을 표현합니다. JSX는 HTML과 매우 비슷해 보이지만 조금 더 엄격하고 동적 정보를 표시할 수 있습니다.
기존 HTML 마크업을 React 컴포넌트에 붙여넣으면 항상 작동하는 것은 아닙니다:
// App.js
export default function TodoList() {
return (
// This doesn't quite work!
<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>Rehearse a movie scene
<li>Improve spectrum technology
</ul>
);
}
이와 같은 기존 HTML이 있다면 converter를 사용하여 수정할 수 있습니다:
// App.js
export default function TodoList() {
return (
<>
<h1>Hedy Lamarr's Todos</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
className="photo"
/>
<ul>
<li>Invent new traffic lights</li>
<li>Rehearse a movie scene</li>
<li>Improve spectrum technology</li>
</ul>
</>
);
}
JSX에서 JavaScript 사용하기
JSX를 사용하면 JavaScript 파일 내에 HTML과 유사한 마크업을 작성하여 렌더링 로직과 콘텐츠를 같은 위치에 유지할 수 있습니다. 때로는 마크업 안에 약간의 JavaScript 로직을 추가하거나 동적 프로퍼티를 참조하고 싶을 때가 있습니다. 이 경우 JSX에서 중괄호를 사용하여 JavaScript로의 '창을 열' 수 있습니다:
// App.js
const person = {
name: 'Gregorio Y. Zara',
theme: {
backgroundColor: 'black',
color: 'pink'
}
};
export default function TodoList() {
return (
<div style={person.theme}>
<h1>{person.name}'s Todos</h1>
<img
className="avatar"
src="https://i.imgur.com/7vQD0fPs.jpg"
alt="Gregorio Y. Zara"
/>
<ul>
<li>Improve the videophone</li>
<li>Prepare aeronautics lectures</li>
<li>Work on the alcohol-fuelled engine</li>
</ul>
</div>
);
}
컴포넌트에 props 전달하기
React 컴포넌트는 서로 통신하기 위해 props를 사용합니다. 모든 부모 컴포넌트는 자식 컴포넌트에 props를 전달하여 일부 정보를 전달할 수 있습니다. props라고 하면 HTML 어트리뷰트를 떠올릴 수 있지만 객체, 배열, 함수, 심지어 JSX를 포함한 모든 JavaScript 값을 전달할 수 있습니다!
// App.js
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>
);
// utils.js
export function getImageUrl(person, size = 's') {
return (
'https://i.imgur.com/' +
person.imageId +
size +
'.jpg'
);
}
조건부 렌더링
컴포넌트는 여러 조건에 따라 다른 것을 표시해야 하는 경우가 많습니다. React에서는 if 문, &&, ? : 연산자 같은 JavaScript 구문을 사용해 조건부로 JSX를 렌더링할 수 있습니다.
이 예제에서는 JavaScript && 연산자를 사용하여 체크 표시를 조건부로 렌더링합니다:
// App.js
function Item({ name, isPacked }) {
return (
<li className="item">
{name} {isPacked && '✔'}
</li>
);
}
export default function PackingList() {
return (
<section>
<h1>Sally Ride's Packing List</h1>
<ul>
<Item
isPacked={true}
name="Space suit"
/>
<Item
isPacked={true}
name="Helmet with a golden leaf"
/>
<Item
isPacked={false}
name="Photo of Tam"
/>
</ul>
</section>
);
}
목록 렌더링
데이터 모음에서 유사한 컴포넌트를 여러 개 표시하고 싶을 때가 많습니다. React에서 JavaScript의 filter()와 map()을 사용해 데이터 배열을 필터링하고 컴포넌트 배열로 변환할 수 있습니다.
각 배열 항목마다 key를 지정해야 합니다. 보통 데이터베이스의 ID를 key로 사용하는 것이 좋습니다. 키를 사용하면 목록이 변경되더라도 React가 목록에서 각 항목의 위치를 추적할 수 있습니다.
// App.js
import { people } from './data.js';
import { getImageUrl } from './utils.js';
export default function List() {
const listItems = people.map(person =>
<li key={person.id}>
<img
src={getImageUrl(person)}
alt={person.name}
/>
<p>
<b>{person.name}:</b>
{' ' + person.profession + ' '}
known for {person.accomplishment}
</p>
</li>
);
return (
<article>
<h1>Scientists</h1>
<ul>{listItems}</ul>
</article>
);
}
// data.js
export const people = [{
id: 0,
name: 'Creola Katherine Johnson',
profession: 'mathematician',
accomplishment: 'spaceflight calculations',
imageId: 'MK3eW3A'
}, {
id: 1,
name: 'Mario José Molina-Pasquel Henríquez',
profession: 'chemist',
accomplishment: 'discovery of Arctic ozone hole',
imageId: 'mynHUSa'
}, {
id: 2,
name: 'Mohammad Abdus Salam',
profession: 'physicist',
accomplishment: 'electromagnetism theory',
imageId: 'bE7W1ji'
}, {
id: 3,
name: 'Percy Lavon Julian',
profession: 'chemist',
accomplishment: 'pioneering cortisone drugs, steroids and birth control pills',
imageId: 'IOjWm71'
}, {
id: 4,
name: 'Subrahmanyan Chandrasekhar',
profession: 'astrophysicist',
accomplishment: 'white dwarf star mass calculations',
imageId: 'lrWQx8l'
}];
// utils.js
export function getImageUrl(person) {
return (
'https://i.imgur.com/' +
person.imageId +
's.jpg'
);
}
컴포넌트 순수성 유지
일부 JavaScript 함수는 순수 함수입니다. 순수 함수는:
- 자신의 일만 처리합니다. 호출되기 전에 존재했던 객체나 변수를 변경하지 않습니다.
- 동일 입력, 동일 출력. 순수 함수는 동일한 입력이 주어지면 항상 동일한 결과를 반환해야 합니다.
컴포넌트를 순수 함수로만 엄격하게 작성하면 코드베이스가 커짐에 따라 당황스러운 버그와 예측할 수 없는 동작이 발생하는 것을 방지할 수 있습니다. 다음은 불순한 컴포넌트의 예시입니다:
// App.js
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 />
</>
);
}
기존 변수를 수정하는 대신 prop을 전달하여 이 컴포넌트를 순수하게 만들 수 있습니다:
// App.js
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} />
</>
);
}
'Dev > React' 카테고리의 다른 글
React 상태 관리: 깊이 있게 파헤치기 (0) | 2024.11.10 |
---|---|
React 19 RC 버전: 더욱 강력해진 React 개발 경험 (4) | 2024.11.09 |
[공식문서] React - React로 사고하기 (0) | 2023.09.17 |
[공식문서] React - 튜토리얼: Tic-Tac-Toe (0) | 2023.09.16 |
[공식문서] React - Quick Start (0) | 2023.09.16 |