HOWTO · React

React에서 for 루프 사용하기

안정적인 key와 컴포넌트 props를 사용해 .map() 또는 JavaScript for 루프로 React 목록을 렌더링하는 방법

이 페이지의 내용

배열에 제품, 사용자 또는 다른 레코드가 들어 있다면 React는 각 항목에 해당하는 요소나 컴포넌트를 렌더링할 수 있습니다. 보통은 일대일 변환에 .map()을 사용하고, 명시적인 단계로 처리하는 편이 더 명확할 때는 JavaScript for 루프를 선택합니다. 두 방법 모두 React가 렌더링할 수 있는 요소 배열을 만듭니다.

React에서 .map()으로 목록 렌더링하기

먼저 화면에 표시할 레코드를 준비합니다. 다음 독립 JavaScript 예제는 각 제품을 레이블로 바꿉니다. React를 사용하거나 컴포넌트를 마운트하지는 않습니다. 아래 출력은 이 JavaScript 예제에서 실제로 관찰된 결과입니다.

const products = [
  { id: "mug", name: "Ceramic mug", price: 12 },
  { id: "notebook", name: "Notebook", price: 8 },
];

const labels = products.map((product) => `${product.name}: $${product.price}`);
console.log(labels.join("\n"));
Ceramic mug: $12
Notebook: $8

JSX에서는 같은 데이터를 요소 배열로 변환할 수 있습니다. 예를 들어 products.map((product) => <li key={product.id}>{product.name}: ${product.price}</li>)처럼 작성합니다. 반환된 배열은 목록을 표시할 마크업 안에 넣으면 됩니다. 예를 들면 <ul>{products.map((product) => <li key={product.id}>{product.name}</li>)}</ul>과 같습니다. React는 배열을 직접 렌더링하므로 페이지 구조상 필요할 때만 래퍼를 추가하면 됩니다. 이 JSX 코드는 React 렌더링을 설명하는 예시이며, 앞의 JavaScript 런타임 증거로 실행을 확인한 것은 아닙니다.

각 레코드를 재사용 가능한 컴포넌트로 변환할 수도 있습니다. function ProductCard(props) { return <li>{props.name}: ${props.price}</li>; }로 컴포넌트를 정의한 다음 products.map((product) => <ProductCard key={product.id} name={product.name} price={product.price} />)로 렌더링합니다. 자식 컴포넌트는 name과 price를 props 객체로 받아 해당 값으로 화면에 표시할 내용을 만듭니다. 대신 product={product}처럼 레코드 전체를 전달하고 컴포넌트 안에서 props.product.name과 props.product.price를 읽을 수도 있습니다. 컴포넌트에 필요한 데이터가 무엇인지 잘 드러나는 인터페이스를 선택하세요.

.map()으로 만든 각 형제 요소에는 형제 사이에서 고유하고, 같은 레코드에 대해 계속 안정적으로 유지되는 key가 필요합니다. 보통 데이터에 포함된 ID를 사용합니다. 항목이 추가, 삭제 또는 재정렬될 수 있는 목록에서는 배열 인덱스를 사용하지 마세요. 목록이 바뀐 뒤 인덱스가 다른 레코드를 가리키면 React가 컴포넌트 상태를 잘못된 항목에 연결할 수 있습니다. React는 업데이트 과정에서 목록 요소를 서로 대응시키는 데 key를 사용하며, key를 자식 컴포넌트의 prop으로 전달하지는 않습니다. 키와 목록 렌더링에 관한 자세한 내용은 React의 목록 렌더링 가이드를 참고하세요.

JavaScript for 루프 사용하기

명시적인 단계를 거쳐 요소를 구성하려면 JavaScript for 루프를 사용할 수 있습니다. 컴포넌트에서 return 전에 배열을 초기화하고, 제품마다 key가 있는 요소를 하나씩 추가한 뒤, 반환할 마크업에 그 배열을 포함합니다. 아래는 앞에서 선언한 products 데이터를 사용하는 컴포넌트를 한 줄씩 나타낸 예시입니다.

function ProductList() {
const items = [];
for (let i = 0; i < products.length; i += 1) {
const product = products[i];
items.push(<li key={product.id}>{product.name}: ${product.price}</li>);
}
return <ul>{items}</ul>;
}

이 컴포넌트는 React/JSX를 설명하는 예시이며, 앞서 실행한 JavaScript 예제의 일부가 아닙니다. 컴포넌트가 반환할 결과를 준비하는 동안 루프가 실행됩니다. 문(statement)을 JSX 안에 바로 넣을 수는 없습니다. 간단한 일대일 변환이라면 .map()이 대체로 더 짧고, 각 레코드와 요소의 관계를 한눈에 파악하기 쉽습니다. 결과를 만들 때 여러 문장이나 조건 분기가 필요하다면 루프가 더 명확할 수 있습니다. 어느 방식을 쓰든 반환하는 요소에는 안정적인 key를 지정해야 합니다.

즉시 호출 함수 사용하기

즉시 호출 함수 표현식(IIFE)은 JSX 표현식 안에 문장을 넣을 수 있지만, 목록 렌더링에는 흔히 쓰이지 않는 방법입니다. 예를 들어 JSX 표현식 {(() => { const items = []; for (let i = 0; i < products.length; i += 1) { const product = products[i]; items.push(<li key={product.id}>{product.name}</li>); } return items; })()}은 배열을 만들어 즉시 반환합니다. 이는 구문을 보여 주는 예시이며 실행한 React 예제가 아닙니다. return과 반환할 값을 같은 줄에 두거나 값을 괄호로 감싸세요. return 바로 다음에 줄바꿈을 넣으면 JavaScript의 자동 세미콜론 삽입으로 인해 undefined가 반환될 수 있습니다. 일반적인 목록은 .map()을 사용하거나 컴포넌트의 return 앞에서 루프를 실행하는 편이 읽고 유지 관리하기 쉽습니다.