리액트 공식문서 번역
* 스터디 공부용으로 리액트 공식문서 한글번역 을 병행 합니다.
* DeepL 번역기를 적극 사용하였고, 가독성을 위해 수정 혹은 의역한 부분이 있습니다.
* 도전과제는 일부 생략한 부분이 있습니다.
* React docs beta 원문 링크는 https://beta.reactjs.org/ 입니다.
* 공유하던 깃북을 닫았습니다.
* 최근 리액트 베타가 공식문서로 전환되었습니다. https://react.dev/
이 사이트는 무엇인가요?
우리는 몇 가지 차이점을 가지고 React 문서를 다시 작성하고 있습니다:
- 모든 설명은 클래스가 아닌 Hook을 사용하여 작성되었습니다.
- 대화형 예제와 시각적 다이어그램을 추가했습니다.
- 가이드에는 이해도를 확인할 수 있는 챌린지(솔루션 포함!)가 포함되어 있습니다.
- 이 베타 웹사이트에는 새 문서의 현재 초안이 포함되어 있습니다.
얼마나 많은 콘텐츠가 준비되었나요?
React 배우기: ~99% 완료.
API 참조: 100% 완료.
피드백을 제공하려면 어떻게 해야 하나요?
높은 수준의 피드백을 원하시면 이 GitHub 이슈 또는 이 익명 양식을 사용해 주세요. 이해가 되지 않는 부분을 발견하면 알려주세요! 또한 각 페이지의 모서리에 좋아요/나빠요 버튼이 있습니다.
이 사이트가 메인 사이트를 대체하나요?
기존 React 문서와 콘텐츠 동등성에 도달하면 이 사이트를 메인 사이트로 전환하는 것을 목표로 하고 있습니다. 이전 React 웹사이트는 하위 도메인에 보관되므로 계속 액세스할 수 있습니다. 오래된 콘텐츠 링크는 아카이브된 하위 도메인으로 리디렉션되며, 이 하위 도메인에는 오래된 콘텐츠에 대한 알림이 표시됩니다.
Quick Start 빠른 시작
React 문서에 오신 것을 환영합니다! 이 페이지에서는 여러분이 매일 사용하게 될 React 개념의 80%를 소개합니다.
학습 내용
- 컴포넌트 생성 및 중첩하는 방법
- 마크업과 스타일을 추가하는 방법
- 데이터를 표시하는 방법
- 조건과 목록을 렌더링하는 방법
- 이벤트에 응답하고 화면을 업데이트하는 방법
- 컴포넌트 간에 데이터를 공유하는 방법
컴포넌트 생성 및 중첩
React 앱은 컴포넌트로 만들어집니다. 컴포넌트는 고유한 로직과 모양을 가진 UI(사용자 인터페이스)의 일부입니다.
컴포넌트는 버튼만큼 작을 수도 있고 전체 페이지만큼 클 수도 있습니다.
React 컴포넌트는 마크업을 반환하는 JavaScript 함수입니다:
function MyButton() {
return (
<button>I'm a button</button>
);
}
이제 MyButton을 선언했으므로 다른 컴포넌트에 중첩할 수 있습니다:
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}
<MyButton />이 대문자로 시작하는 것을 주목하세요. 이것이 React 컴포넌트라는 것을 알 수 있는 방법입니다.
React 컴포넌트 이름은 항상 대문자로 시작해야 하고 HTML 태그는 소문자로 시작해야 합니다.
결과를 살펴보세요:
function MyButton() {
return (
<button>
I'm a button
</button>
);
}
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}
export default 키워드는 파일의 주요 구성 요소를 지정합니다.
자바스크립트 구문에 익숙하지 않다면 MDN과 javascript.info를 참조하세요
JSX로 마크업 작성.
위에서 본 마크업 구문을 JSX라고 합니다. 선택 사항이지만 대부분의 React 프로젝트는 편의성을 위해 JSX를 사용합니다.
로컬 개발에 권장하는 모든 도구는 JSX를 기본적으로 지원합니다.
JSX는 HTML보다 더 엄격합니다.
<br /> 태그처럼 모든 태그를 닫아줘야 합니다. 컴포넌트는 여러 개의 JSX 태그를 반환할 수도 없습니다.
따라서 공유 부모로 감싸줘야합니다. <div>...</div> 혹은 비어있는 <> … </> 태그로 감싸줘야 합니다.
function AboutPage() {
return (
<>
<h1>About</h1>
<p>Hello there.<br />How do you do?</p>
</>
);
}
JSX로 포팅할 HTML이 많은 경우 온라인 변환기를 사용할 수 있습니다.
스타일 추가하기
React에서는 className으로 CSS 클래스를 지정합니다. HTML 클래스 어트리뷰트와 같은 방식으로 작동합니다:
<img className="avatar" />
그런 다음 별도의 CSS 파일에 해당 CSS 규칙을 작성합니다:
/* In your CSS */
.avatar {
border-radius: 50%;
}
React는 CSS 파일을 추가하는 방법을 규정하지 않습니다. 가장 간단한 방법은 HTML에 <link> 태그를 추가하는 것입니다.
빌드 도구나 프레임워크를 사용하는 경우 해당 문서를 참조하여 프로젝트에 CSS 파일을 추가하는 방법을 알아보세요.
데이터 보여주기
JSX를 사용하면 자바스크립트에 마크업을 넣을 수 있습니다.
중괄호{} 를 사용하면 자바스크립트에서 "escape back" 할 수 있습니다. 코드에 변수를 삽입하여 사용자에게 보여줄 수 있습니다.
예를 들어, 이렇게 user.name을 표시합니다:
return (
<h1>
{user.name}
</h1>
);
JSX 어트리뷰트(속성)에서 "자바스크립트로 이스케이프"할 수도 있지만 따옴표 대신 중괄호를 사용해야 합니다.
예를 들어 className="avatar"는 "avatar" 문자열을 CSS 클래스로 전달하지만,
src={user.imageUrl}은 JavaScript user.imageUrl 변수 값을 읽은 다음 해당 값을 src 어트리뷰트로 전달합니다:
return (
<img
className="avatar"
src={user.imageUrl}
/>
);
JSX 중괄호 안에 문자열 연결과 같이 더 복잡한 표현식을 넣을 수도 있습니다:
const user = {
name: 'Hedy Lamarr',
imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
imageSize: 90,
};
export default function Profile() {
return (
<>
<h1>{user.name}</h1>
<img
className="avatar"
src={user.imageUrl}
alt={'Photo of ' + user.name}
style={{
width: user.imageSize,
height: user.imageSize
}}
/>
</>
);
}
위의 예에서 style={{}}은 특별한 구문이 아니라 style={ } JSX 중괄호 안에 있는 일반 {} 객체입니다.
스타일이 자바스크립트 변수에 의존할 때 스타일 속성을 사용할 수 있습니다.
조건부 렌더링
React에서는 조건을 작성하기 위한 특별한 문법이 없습니다. 대신 일반 자바스크립트 코드를 작성할 때 사용하는 것과 동일한 기법을 사용하면 됩니다. 예를 들어, if 문을 사용하여 조건부로 JSX를 포함할 수 있습니다:
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);
보다 간결한 코드를 선호하는 경우 조건부 ? 연산자를 사용할 수 있습니다(삼항연산자). ? 연산자는 if와 달리 JSX 내부에서 작동합니다:
<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>
else 분기가 필요하지 않은 경우 더 짧은 논리 && 구문을 사용할 수도 있습니다:
<div>
{isLoggedIn && <AdminPanel />}
</div>
이 모든 접근 방식은 조건부로 속성을 지정할 때도 작동합니다.
이러한 자바스크립트 구문에 익숙하지 않다면 항상 if...else를 사용하는 것으로 시작할 수 있습니다.
목록 렌더링
컴포넌트 목록을 렌더링하기 위해 for 루프 및 배열 map() 함수와 같은 자바스크립트 기능을 사용하게 됩니다. 예를 들어 products 배열이 있다고 가정해 보겠습니다:
const products = [
{ title: 'Cabbage', id: 1 },
{ title: 'Garlic', id: 2 },
{ title: 'Apple', id: 3 },
];
컴포넌트 내에서 map() 함수를 사용하여 products 배열을 <li> 항목 배열로 변환합니다:
const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);
<li>에 키 속성이 있는 것을 주목하세요. 목록의 각 항목에 대해 형제 항목 중에서 해당 항목을 고유하게 식별하는 문자열 또는 숫자를 전달해야 합니다. 일반적으로 키는 데이터베이스 ID와 같은 데이터에서 가져와야 합니다. React는 나중에 항목을 삽입, 삭제 또는 재정렬할 때 어떤 일이 일어났는지 이해하기 위해 키를 사용합니다.
const products = [
{ title: 'Cabbage', isFruit: false, id: 1 },
{ title: 'Garlic', isFruit: false, id: 2 },
{ title: 'Apple', isFruit: true, id: 3 },
];
export default function ShoppingList() {
const listItems = products.map(product =>
<li
key={product.id}
style={{
color: product.isFruit ? 'magenta' : 'darkgreen'
}}
>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);
}
이벤트에 응답하기
컴포넌트 내부에 이벤트 핸들러 함수를 선언하여 이벤트에 응답할 수 있습니다.
function MyButton() {
function handleClick() {
alert('You clicked me!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}
onClick={handleClick} 끝에 괄호가 없는 것을 주목하세요!
이벤트 핸들러 함수를 호출하지 말고 전달만 하면 됩니다. React는 사용자가 버튼을 클릭할 때 이벤트 핸들러를 호출합니다.
화면 업데이트
컴포넌트가 특정 정보를 '기억'하여 표시하기를 원하는 경우가 종종 있습니다. 예를 들어 버튼이 클릭된 횟수를 세고 싶을 수 있습니다. 이렇게 하려면 컴포넌트에 state를 추가하세요.
먼저 React에서 useState를 가져옵니다:
import { useState } from 'react';
이제 컴포넌트 내에서 상태 변수를 선언할 수 있습니다:
function MyButton() {
const [count, setCount] = useState(0);
useState에서 두 가지를 얻을 수 있습니다: 현재 상태(count)와 이를 업데이트할 수 있는 함수(setCount).
어떤 이름이라도 붙일 수 있지만 [something, setSomething]과 같이 부르는 것이 관례입니다.
버튼이 처음 표시될 때는 useState()에 0을 전달했기 때문에 카운트가 0이 됩니다.
상태를 변경하려면 setCount()를 호출하고 새 값을 전달합니다. 이 버튼을 클릭하면 카운터가 증가합니다:
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
React가 컴포넌트 함수를 다시 호출합니다. 이번에는 카운트가 1이 될 것입니다. 그 다음에는 2가 됩니다. 이런 식으로요.
동일한 컴포넌트를 여러 번 렌더링하면 각각 고유한 상태를 갖게 됩니다. 각 버튼을 개별적으로 클릭해 보세요:
import { useState } from 'react';
export default function MyApp() {
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
각 버튼이 자체 카운트 상태를 '기억'하고 다른 버튼에 영향을 주지 않는 방식에 주목하세요.
Hooks 사용하기
‘use’로 시작하는 함수를 Hook이라고 합니다. useState는 React에서 제공하는 내장 Hook입니다. 다른 내장 Hook은 React API 레퍼런스에서 찾을 수 있습니다. 기존의 Hook을 조합하여 자신만의 Hook을 작성할 수도 있습니다.
Hook은 일반 함수보다 더 제한적입니다. 컴포넌트(또는 다른 Hook)의 최상위 레벨에서만 Hook을 호출할 수 있습니다. 조건이나 루프에서 useState를 사용하려면 새 컴포넌트를 추출하여 거기에 넣으세요.
컴포넌트 간 데이터 공유
이전 예제에서는 각 MyButton에 독립적인 카운트가 있었고, 각 버튼을 클릭하면 클릭한 버튼의 카운트만 변경되었습니다:
하지만 데이터를 공유하고 항상 함께 업데이트하는 컴포넌트가 필요한 경우가 많습니다.
두 MyButton 컴포넌트가 동일한 카운트를 표시하고 함께 업데이트되도록 하려면, 개별 버튼에서 모든 버튼이 포함된 가장 가까운 컴포넌트로 상태를 "위쪽"으로 이동해야 합니다.
이 예제에서는 MyApp입니다:
이제 두 버튼 중 하나를 클릭하면 MyApp의 카운트가 변경되고, 이에 따라 MyButton의 카운트도 모두 변경됩니다. 이를 코드로 표현하는 방법은 다음과 같습니다.
먼저 상태를 MyButton에서 MyApp으로 이동합니다:
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
// ... we're moving code from here ...
}
그런 다음 공유하고있는 클릭 핸들러와 함께 MyApp에서 각 MyButton으로 상태를 전달합니다.
이전에 <img>와 같은 기본 제공 태그를 사용했던 것처럼 JSX 중괄호를 사용하여 MyButton에 정보를 전달할 수 있습니다.
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
이렇게 전달한 정보를 props라고 합니다. 이제 MyApp 컴포넌트는 count 상태와 handleClick 이벤트 핸들러를 포함하며, 이 두 가지를 각 버튼에 props로 전달합니다.
마지막으로, 부모 컴포넌트에서 전달한 props를 읽도록 MyButton을 변경합니다:
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}
버튼을 클릭하면 onClick 핸들러가 실행됩니다. 각 버튼의 onClick prop은 MyApp 내부의 handleClick 함수로 설정되었으므로 그 안에 있는 코드가 실행됩니다. 이 코드는 setCount(count + 1)를 호출하여 카운트 상태 변수를 증가시킵니다. 새로운 카운트 값은 각 버튼에 prop으로 전달되므로 모든 버튼에 새로운 값이 표시됩니다.
이를 "상태 올리기"라고 합니다. 상태를 위로 이동함으로써 컴포넌트 간에 상태를 공유했습니다.
import { useState } from 'react';
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}
다음 스텝
이제 React 코드를 작성하는 방법의 기본을 알았습니다!
튜토리얼을 확인하여 실습하고 React로 첫 번째 미니 앱을 만들어 보세요.