[React] 배열 렌더링하기

2021. 4. 19. 18:33Front-end/React

728x90
반응형

🍧 이번 시간에는 리액트에서 배열을 렌더링하는 방법을 알아보겠다.

const users = [
  {
    id: 1,
    username: 'velopert',
    email: 'public.velopert@gmail.com'
  },
  {
    id: 2,
    username: 'tester',
    email: 'tester@example.com'
  },
  {
    id: 3,
    username: 'liz',
    email: 'liz@example.com'
  }
];

예를 들어 이런 배열이 있다고 가정한다.

배열 안에 3개의 객체가 있고, 이것을 각각 렌더링해주어야 하는데 어떻게 할까?

 

UserList.js를 만들고 작업한다.

 

🍧 비효율적인 방법

function UserList(){

    const users = [

        {

          id: 1,

          username: 'velopert',

          email: 'public.velopert@gmail.com'

        },

        {

          id: 2,

          username: 'tester',

          email: 'tester@example.com'

        },

        {

          id: 3,

          username: 'liz',

          email: 'liz@example.com'

        }

      ];      

    return (

        <div>

            <div>

                <b>{users[0].username}</b> <span>({users[0].email})</span>

            </div>

            <div>

                <b>{users[1].username}</b> <span>({users[1].email})</span>

            </div>

            <div>

                <b>{users[2].username}</b> <span>({users[2].email})</span>

            </div>

        </div>

    )

}

이렇게 그냥 노가다로 작성하고 App 컴포넌트에서 렌더링한다.(좋지 않은 방법!)

 

조금 더 고쳐보자.

 

function User({user}){

    return (

        <div>

            <b>{user.username}</b> <span>({user.email})</span>

        </div>

    )

}

UserList.js에 User라는 컴포넌트를 하나 더 만든다. User 컴포넌트는 user를 받아와서 다음과 같이 리턴한다.

 

return (

        <div>

            <User user={users[0]}/>

            <User user={users[1]}/>

            <User user={users[2]}/>

        </div>

    )

그리고 UserList 컴포넌트에서 다음과 같이 작성한다.

 

배열이 고정적이라면 이렇게 해도 되겠지만, 배열의 내용이 고정적이지 않다면? 동적일 때는 어떻게 해주어야 할까?

 

🍧 효율적인 방법 - map 사용하기

이럴때 자바스크립트의 map이라는 함수를 사용한다.

map은 자바스크립트의 배열에 있는 요소들에 어떤 작업을 하여 그 결과를 배열로 리턴해주는 함수이다.

return (

        <div>

            {users.map((user) => {

                return (<User user={user}/>)

            })}

        </div>

    )

UserList 컴포넌트에서 위와 같이 작성하면 된다. users라는 배열의 각 요소들을 가지고 User 컴포넌트로 반환해주는 것이다. 그리고 반환한 User 컴포넌트는 props로 users 배열의 각 요소들을 전달하게 되고, 이것이 User 컴포넌트 안에서 name과 email을 렌더링해주게 된다.

 

🍧 잊지 않고 key값을 props로 꼭 넣어주기 ⭐⭐⭐

여기서 끝이 아니다! 여기 까지만 하면 브라우저 콘솔에서 경고가 나타나게 된다.

경고 내용을 보면, 배열의 각 요소들에는 key라는 prop이 있어야 한다는 오류가 있다.

key라는 prop이 하는 역할은 각 원소들마다 고유 값을 줌으로써 리렌더링 성능을 최적화하게 해주는 것이다.

 

return (

        <div>

            {users.map((user) => {

                return (<User key={user.id} user={user}/>)

            })}

        </div>

    )

따라서 다음과 같이 수정하면 된다. key로 user의 id를 준 것이다.

만약 key값으로 사용할 요소가 없다면 map의 콜백함수의 두번째 인자인 index를 넣어주어도 되기는 된다. 그러나 key로 index를 넣어주는 것은 단순히 경고창만 없애주는 것이지 성능적으로 좋아진다거나 그런 것은 아니기 때문에 왠만하면 key에 index를 넣어주는 것은 지양하는 것이 좋다. (map 콜백함수의 첫번째 인자는 배열의 각 element, 두번째 인자는 index가 되겠다)

 

 

🍧 key의 역할

 

const array = ['a','b','c','d'];

 

array.map((item) => <div>{item}</div>);

 

위와 같은 array가 있고, 그 array를 map 함수를 사용해서 div 엘리먼트들로 변환해준다고 가정해보자.

 

이런 상황에서 b와 c 사이에 z를 넣는다고 생각해보자.

['a','b','z','c','d']

 

⊙ key가 없다면?

 

a b z d

일단 c가 z로 바뀐다

a b z c

d가 c로 바뀐다

a b z c d

그리고 새로운 d가 생긴다

 

좀 이상하고 효율적이지 않다. 사실 z가 사이에 들어온다는 것은 기존의 것은 그대로 두고 그 사이에 z만 들어와야 하는 것인데 말이다.

이러한 문제는 각 배열의 원소가 어떤 것을 렌더링하고 있는지 모르기 때문에 발생한다.

 

key가 있다면!

 

하지만 객체에  key 로 사용 할 수 있는 고유 값이 있고 다음과 같이 렌더링이 된다면

 

array.map(item => <div key={item.id}>{item.text}</div>);

 

배열이 업데이트 될 때 key 가 없을 때 처럼 비효율적으로 업데이트 하는 것이 아니라, 수정되지 않는 기존의 값은 그대로 두고 원하는 곳에 내용을 삽입하거나 삭제한다.

 

때문에, 배열을 렌더링 할 때에는 고유한 key 값이 있는것이 중요하며, 만약에 배열안에 중복되는 key 가 있을 때에는 렌더링시에 오류메시지가 콘솔에 나타나게 되며, 업데이트가 제대로 이루어지지 않게 된다.

 

 

 

728x90
반응형