관리 메뉴

거니의 velog

(15) 컴포넌트 반복 1 본문

React_리액트 시작

(15) 컴포넌트 반복 1

Unlimited00 2023. 12. 1. 13:41

* 웹 애플리케이션을 만들다 보면 다음과 같이 반복되는 코드를 작성할 때가 있다. src 디렉터리에 IterationSample.js라는 파일을 작성해 다음 코드를 따라 한번 적어보자.

import React from 'react';

const IterationSample = () => {
  return (
    <ul>
      <li>눈사람</li>
      <li>얼음</li>
      <li>눈</li>
      <li>바람</li>
    </ul>
  );
};

export default IterationSample;

* 코드에서 다음 형태가 반복되는 것을 볼 수 있다.

<li>...</li>

* 지금은 li 태그 하나 뿐이라 그렇게 문제가 되지는 않을 것 같다. 하지만 코드가 좀 더 복잡하다면 어떨까? 코드양은 더더욱 늘어날 것이며, 파일 용량도 쓸데없이 증가할 것이다. 이는 낭비다. 또 보여 주어야 할 데이터가 유동적이라면 이런 코드로는 절대 관리하지 못한다.

* 이 장에서는 리액트 프로젝트에서 반복적인 내용을 효율적으로 보여 주고 관리하는 방법을 알아 보겠다.


1. 자바스크립트 배열의 map() 함수

* 자바스크립트 배열 객체의 내장 함수인 map 함수를 사용하여 반복되는 컴포넌트를 렌더링할 수 있다. map 함수는 파라미터로 전달된 함수를 사용해서 배열 내 각 요소를 원하는 규칙에 따라 변환한 후 그 결과로 새로운 배열을 생성한다.


(1) 문법

arr.map(callback, [thisArg])

* 이 함수의 파라미터는 다음과 같다.

* callback : 새로운 배열의 요소를 생성하는 함수로 파라미터는 다음 세 가지 이다.
    - currentValue : 현재 처리하고 있는 요소
    - index : 현재 처리하고 있는 요소의 index 값
    - array : 현재 처리하고 있는 원본 배열

* thisArg(선택 항목) : callback 함수 내부에서 사용할 this 레퍼런스

(2) 예제

* map 함수를 사용하여 배열 [1,2,3,4,5] 의 각 요소를 제곱해서 새로운 배열을 생성하겠다.

var numbers = [1, 2, 3, 4, 5];

var processed = numbers.map(function(num){
    return num * num;
});

console.log(processed);

* 크롬 개발자 도구[F12]를 열어 이 코드를 콘솔에 입력해 보자.

* 이처럼 map 함수는 기존 배열로 새로운 배열을 만드는 역할을 한다. 이 코드를 ES6 문법으로 작성해 보자.

var numbers = [1, 2, 3, 4, 5];
var result = numbers.map(num => num * num);
console.log(result);

* var 키워드 대신 const를 사용했고, function(...){...} 대신 화살표 함수를 사용했다.


2. 데이터 배열을 컴포넌트 배열로 변환하기

* 이전 절에서는 기존 배열에 있는 값들을 제곱하여 새로운 배열을 생성했다. 똑같은 원리로 기존 배열로 컴포넌트로 구성된 배열을 생성할 수도 있다.


(1) 컴포넌트 수정하기

* 조금 전에 만들었던 IterationSample 컴포넌트를 다음과 같이 수정해 보자.

import React from 'react';

const IterationSample = () => {
  const names = ['눈사람', '얼음', '눈', '바람'];
  const nameList = names.map((name) => <li>{name}</li>);
  return <ul>{nameList}</ul>;
};

export default IterationSample;

* 문자열로 구성된 배열을 선언한다. 그 배열 값을 사용하여 <li>...</li> JSX 코드로 된 배열을 새로 생성한 후 nameList에 담는다.

* map 함수에서 JSX를 작성할 때는 앞서 다룬 예제처럼 DOM 요소를 작성해도 되고, 컴포넌트를 사용해도 된다.


(2) App 컴포넌트에서 예제 컴포넌트 렌더링

* App 컴포넌트에서 기존 코드를 지우고, IterationSample 컴포넌트를 불러와 렌더링해 보자.

import React, { Component } from 'react';
import IterationSample from './IterationSample';

class App extends Component {
  render() {
    return <IterationSample />;
  }
}

export default App;

* 코드를 저장하고, 웹 브라우저를 체크해 보자.

* 원하는 대로 렌더링이 되었다. 하지만 완벽하지는 않다. 크롬 개발자 도구의 콘솔을 한번 열어보자.

* "key" prop이 없다는 경고 메시지를 표시했다. key 란 무엇일까?


3. key

* 리액트에서 key는 컴포넌트 배열을 렌더링했을 때 어떤 원소에 변동이 있었는지 알아내려고 사용한다. 예를 들어 유동적인 데이터를 다룰 때는 원소를 새로 생성할 수도, 제거할 수도, 수정할 수도 있다. key가 없을 때는 Virtual DOM을 비교하는 과정에서 리스트를 순차적으로 비교하면서 변화를 감지한다. 하지만 key가 있다면 이 값을 사용하여 어떤 변화가 일어났는지 더욱 빠르게 알아낼 수 있다.


(1) key 설정

* key 값을 설정할 때는 map 함수의 인자로 전달되는 함수 내부에서 컴포넌트 props를 설정하듯이 설정하면 된다. key 값은 언제나 유일해야 한다. 따라서 데이터가 가진 고윳값을 key 값으로 설정해야 한다.

* 예를 들어 다음과 같이 게시판의 게시물을 렌더링한다면 게시물 번호를 key 값으로 설정해야 한다.

const articleList = articles.map(article => {
	<Article
    	title={article.title}
        writer={article.writer}
        key={article.id}
    />
});

* 하지만 앞서 만들었던 예제 컴포넌트에는 이런 고유 번호가 없다. 이때는 map 함수에 전달되는 콜백 함수의 인수인 index 값을 사용하면 된다.

* 예제 컴포넌트를 다음과 같이 수정해 보자.

import React from 'react';

const IterationSample = () => {
  const names = ['눈사람', '얼음', '눈', '바람'];
  const nameList = names.map((name, index) => <li key={index}>{name}</li>);
  return <ul>{nameList}</ul>;
};

export default IterationSample;

* 이제 개발자 도구에서 더 이상 경고 메시지를 표시하지 않는다.

* 고유한 값이 없을 때만 index 값을 key로 사용해야 한다 index를 key로 사용하면 배열이 변경될 때 효율적으로 리렌더링하지 못한다.

'React_리액트 시작' 카테고리의 다른 글

(17) 컴포넌트의 라이프사이클 메서드 1  (0) 2023.12.04
(16) 컴포넌트 반복 2  (1) 2023.12.01
(14) ref:DOM 에 이름 달기 2  (0) 2023.11.30
(13) ref:DOM 에 이름 달기 1  (0) 2023.11.30
(12) 이벤트 핸들링 2  (0) 2023.11.30