본문 바로가기
개발공부일지/React

React - List & Key 사용하기

by Hynn1429 2023. 3. 6.
반응형

안녕하세요.

Hynn 입니다.

 

이번 포스팅에서는 React 에서 배열(Array) 를 사용하여 List, Key 를 사용하는 방법을 알아보도록 하겠습니다.

기존의 포스팅에서는 객체(Object) 위주로의 작성이 이루어졌다면, 이제 Array 를 이용해 List 를 만들고 각 항목에 그에 맞는 Key 를 사용하는 방법을 알아보도록 하겠습니다.

 

===========

===========

 

 

먼저 이를 위해서는 JavaScript 의 map method를 잘 이용해야 합니다.

map method 를 사용하면 결과값을 배열로 반환할 수 있기 때문에, 이를 이용하면 쉽게 Array 배열을 만들 수 있습니다.

즉, Map method 는 항상 결과 값을 배열로 반환하기 때문에, 기존의 JavaScript 에서도 배열을 이용한 리스트 출력에 도움이 되었습니다.

 

이를 이용해 React 에서도 Map 을 이용해 리스트로 변환하고, 그를 이용해 엘리먼트를 리스트로 출력해보는 작업을 시도해보겠습니다.

이를 이용하기 위해서 먼저 JavaScript 에서 간단한 숫자로 이루어진 배열을 생성하고, 이 배열을 이용해서 작업을 해보도록 하겠습니다.

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
    <div id="root"></div>
    <script type="text/babel">
        const numbers = [1,2,3,4,5,6,7,8,9,10]
        const numbers2 = [11,12,13,14,15,16,17,18,19,20]
        const arrayNumber = numbers.map((number)=> number*1)
        const arrayNumber2 = numbers2.map((number)=> number*1)
        const totalArray = arrayNumber.concat(arrayNumber2)
    </script>
</body>
</html>

이제 위 배열을 가지고 List 와 Key 를 다루는 React 기본 문법을 알아보도록 하겠습니다.

먼저, 위 totalArray 는 20개의 배열을 담고 있는 변수입니다. 이 변수를 map 함수를 이용해서, li로 변환하고, ul element 안에 담아 배열을 완성해보도록 하겠습니다.

 

const listItems = totalArray.map((numbers)=> <li>{numbers}</li>)
        
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(<ul>{listItems}</ul>)

 

map함수의 기능인 Array type 의 데이터의 각 요소를 반복하여 각 숫자의 값을 가진 요소를 <li></li> 요소를 포함하여 listItems 라는 새로운 배열을 생성합니다.

그리고 난 뒤, root.render 를 이용해 랜더하기만 하면 완성됩니다.

실제 "listItems" 의 console.log 는 아래와 같이 출력됩니다.

 

배열들에 담긴 정보를 보면, "Key", "Ref", "Props" 라는 React 에서 중요하게 다룰 요소들이 보입니다.

이제 이 요소들에서 중요한 것 중 하나인 Key 에 대해서 다루도록 해보겠습니다. Props 는 이전 포스팅에서도 몇차례 다룬 바 있으니, 이번 포스팅에서는 Key 를 위주로 다루어보도록 하겠습니다.

 

 

먼저 간단하게 Key 를 배열 각 요소에 설정해보도록 하겠습니다.

Key 는 HTML 에서 흔히 사용했던 ID, Class 와 같은 속성으로 이해하고 작성하시면 보다 쉽게 이해가 가능합니다.

즉 HTML 기준으로는 <Li> Element 에 작성해야 합니다.

아래와 같이 작성하여, Key 를 부여해보도록 하겠습니다.

 

const listItems = totalArray.map((numbers)=> <li key={numbers.toString()}>{numbers}</li>)

이제 console.log 에서 각 배열의 요소에 key 값이 부여된 것을 확인할 수 있습니다.

React 에서 Key 속성은 아주 중요한 요소입니다.

바로, React 에서 어떤 항목을 변경하거나, 추가, 삭제를 하기 위해 특정 Element 를 식별하기 위해 부여합니다. 즉 HTML 에서 ID,Class Attributed 와 같이 특정 Element 를 지정하기 위한 속성이라고 이해하시면 이해하기 쉽습니다.

 

이 Key는 일반적으로 HTML 의 ID, Class 처럼 지정한 항목을 고유하게 식별할 수 있는 문자열을 사용합니다. 대부분의 경우 데이터의 ID를 설정하지만, 작성자가 일정한 규칙을 가지고 있다면, 이 규칙에 맞는 Key 를 부여해도 관계는 없습니다. 

단, 주의해야 할 점은, Key 에 정말 입력할 것이 없다면 Index를 넣을 수도 있지만, 이는 권장되지 않습니다.

 

바로 항목의 순서가 바뀔 수 있는 경우가 발생할 경우 이는 성능에 영향을 미치거나, Component State, Props 와 같은 곳에서도 문제를 발생시키는 요인이 될 수 있기 때문입니다. 이로인해, React 에서는 작성자가 명시적으로 key 를 지정하지 않는 경우 Index 를 key 로 지정하기는 하지만, 가급적 식별이 가능한 고유한 문자열로 지정을 해야 합니다. 

 

 

Key 를 설정할때는, 어느위치에 설정하는지가 중요합니다.

이를 간단하게 이해하기 위해서는, Component 에 설정을 해야 합니다.

즉 위의 예제는 사실 좋지 않은 Key 를 설정한 것입니다.

 

        const numbers = [1,2,3,4,5,6,7,8,9,10]
        const numbers2 = [11,12,13,14,15,16,17,18,19,20]
        const arrayNumber = numbers.map((number)=> number*1)
        const arrayNumber2 = numbers2.map((number)=> number*1)
        const totalArray = arrayNumber.concat(arrayNumber2)
        const listItems = totalArray.map((numbers)=> <li key={numbers.toString()}>{numbers}</li>)
        console.log(listItems)
        
        const root = ReactDOM.createRoot(document.getElementById("root"))
        root.render(<ul>{listItems}</ul>)

 

위의 코드에서는 "listItems" 라는 컴포넌트 내의 "<li>" 내에 key 를 부여했습니다.

이는 올바른 사용법이 될 수 없습니다.

key 를 지정하기 위한 올바른 위치는 바로 Component 에 지정하는 것이지, "Component" 내의 <li>에 지정하는 것이 아닙니다.

 

즉 Key 의 올바른 예시와, 잘못된 예시는 아래와 같이 정리가 가능합니다.

이를 세부적으로 설명해보도록 하겠습니다.

 

class MyComponent extends React.Component {
  render() {
    return (
      <ul>
        {this.props.items.map(item => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    )
  }
}
class MyComponent extends React.Component {
  render() {
    return (
      <ul>
        {this.props.items.map(item => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    )
  }
}

 

위 두개의 예시중, 위의 설명을 대입한다면 첫번째 Key 사용은 예측할수 없는 동작을 발생시키는 가능성이 존재합니다.

첫번째 예시의 경우, key가 "Item" 로 지정이 되어있습니다. 이러한 경우, Item 은 가변적인 속성이 될 수 밖에 없습니다.  

React 의 Key 속성에서 "Item" 이라는 것은 랜더링되는 목록의 값이기 때문에, 상황에 따라 가변적으로 값이 바뀔 수 있습니다.

이로 인해 전체 페이지 랜더에서 예상할수 없는 동작이 발생할 수 있는 이유는, 기존에 작성자가 특정 Key 에 부여한 값이 고유한 값이 아닌 경우, 그 값에 부여한 여러가지 동작들이 올바르게 동작하지 않게 됩니다.

그러한 경우, 문제가 발생될 수 있는 근본적 구조를 안고 있기 때문에, 항상 Key 는 두번째 예시처럼 "Item.id"와 같이 고유한 식별자로 사용되는 속성들을 지정해야 합니다. 

 

 

 

말 그대로, HTML 에서 Class, ID 와 같이 중복이 되지 않아야 합니다.

하지만 이는 "배열" 내에서를 뜻합니다. 예시를 먼저 살펴보도록 하겠습니다.

 

<ul>
  <li key="1">항목 1</li>
  <li key="2">항목 2</li>
  <li key="3">항목 3</li>
  <li key="2">항목 4</li>
</ul>
<ul>
  <li key="1">항목 1</li>
  <li key="2">항목 2</li>
  <li key="3">항목 3</li>
  <li key="4">항목 4</li>
</ul>

위의 예시를 본다면, 각각의 배열로 되어 있는 첫번째 UL, 두번째 UL은 문제가 발생하지 않습니다. Key가 겹치는 값이 명백하게 존재함에도 말입니다.

즉 공식문서에서 말하는 "형제 사이에서만 고유한 값" 이라고 하는 것은, 같은 배열내에 존재한다면, Key 값은 각각 중복되는 요소가 없어야 합니다. 배열이 다른 경우에는 중복되도 아무런 영향을 미치지 않지만, 같은 배열 내에서는 중복되는 경우에 올바르지 않은 동작이 발생될 수 있기 때문입니다. 

 

다음 포스팅에서는 이제 HTML에서 많이 사용되는 "Form" 을 React 에서 어떻게 다루는지 알아보도록 하겠습니다.

 

감사합니다.

 

반응형

댓글