Dev-Tino

Dev-Tino 8주차(3):: map 함수를 사용할 때 key를 사용해야 하는 이유

react key 속성, map() 함수,

본 게시글은 위 문서를 참고하였다::

map과 함께 사용하는 key props

react에서는 list를 렌더링하기 위해 map 메소드를 함께 사용한다. 리턴하는 가장 바깥쪽 JSX props로 key 값을 입력하지 않으면 ‘Warning': Each child in a list should have a unique “key” props’ 경고를 반환한다. key를 작성하지 않으면 index를 key로 활용하기 때문이다. (key 없이도 페이지는 문제 없이 작동되나, key 값을 요구하는 이유는 고유의 key 값을 주어야만 ‘수정’, ‘삭제’ 등을 할 때 어떤 요소를 의미하는지를 컴퓨터가 확인하기 어렵기 때문이다. 고유의 key 값을 주는 것이 중요.)

리스트 렌더링에서의 key의 목적

각 컴포넌트가 어떤 배열 항목에 해당하는지 react가 식별할 수 있도록 한다. 배열의 요소 삽입, 삭제, 정렬로 인한 이동시에 React는 key 값을 통해 변화를 추론하고 DOM 트리를 업데이트 하는 데에 도움이 된다.

index를 값으로 활용할 때의 문제점

그러나 index를 key로 활용하면 배열에 변경이 일어날 때에 문제가 일어날 수 있다. 실제 컴포넌트를 따라가지 않거나 예상치 않은 문제가 나타날 수 있는 것. unique key를 이용하면 이런 문제를 예방할 수 있다. key를 index로 입력한다고 하여 무조건 에러를 발생시키지는 않지만, 예상치 못한 문제 등의 이유로 unique한 key를 권장한다. 유니크한 키를 위해 Math.random()으로 key를 생성하는 경우도 있는데, 이는 렌더링간의 key 불일치가 발생해 모든 컴포넌트와 DOM이 매번 다시 생성되는 문제를 가져올 수도 있으므로 조심하여야 한다.

key로는 어떤 것을 사용해야 할까?

key:: 데이터 베이스에서 조건에 만족하는 튜플을 찾거나 순서대로 정렬할 때 기준이 되는 속성. 중복이 되지 않아, 이상 현상이 일어날 일을 막기 위해 이 키를 이용한다. 주어진 릴레이션에서 모든 인스턴스 가운데 유일함을 보장해주는 하나 이상의 속성의 집합이라고도 한다.
이런 key로는 데이터 베이스의 데이터(데이터 베이스의 경우, 포함된 id나 key가 존재할 가능성이 높다.)를 쓰는 것이 좋다. 로컬에서 생성된 데이터일 경우 crypto.randomUUID() (*crypto는 기본적인 암호화 기법을 제공하는 객터이다. crypto.randomUUID 메소드를 이용하면 uuid 라이브러리를 사용하지 않고도 uuid를 생성할 수 있다.)와 같은 패키지를 이용해 키를 만들 수도 있다.

각 키는 형제간(특정 배열 렌더링을 위한 컴포넌트들 사이에서) 고유해야 한다. 하지만 다른 배열과 JSX 노드에 동일한 key를 사용해도 된다. 이 key는 변경되어서는 안된다.


map() 함수란?

자바스크립트 배열의 내장 함수로 반복되는 컴포넌트를 렌더링하기 위해 사용되는 이 함수는, 파라미터로 전달된 함수를 사용하여 배열 내 각 요소를 원하는 규칙에 따라 변환한 후 새로운 배열 혹은 리스트를 생성한다. 상황에 따라 for문이나 다른 반복문을 대체하여 사용한다면 코드가 간편해진다.

다음은 for문, map() 함수를 이용해 numbers 배열의 값을 두 배로 만드는 예시이다.

map() 함수를 이용해 numbers 배열의 값을 두 배로 만들고, map()에서 반환하는 새 배열을 square 변수에 할당했다. map()을 사용했을 때 코드가 더 간결해지고 편리해지는 것을 볼 수 있다.

React에서의 map() 함수는 JS의 map() 함수와 유사하다. 기본적인 문법은 아래와 같다::

-array: 원본 배열

-element: 현재 요소

-index: 현재 요소의 인덱스(생략 가능하다.)

-함수 안에서는 새로운 배열을 반환하는 로직을 정의한다.

위 문법을 사용해 새로운 배열을 반환하는 로직을 작성할 수 있다. React에서는 이를 주로 사용하여 배열 요소들을 JSX로 변환하고, 이를 화면에 렌더링한다.

위 함수(li 요소가 5번 반복된다.) map() 함수를 이용하면 이 코드를 다음과 같이 간략화할 수 있다::

이는 array 배열의 각 요소를 반복하고, 각 요소를 <li> 태그로 래핑하여 새로운 listItems를 만든다. 또한 listItems 배열을 렌더링해 <ul> 리스트를 생성한다.


리액트의 Key 속성

요소 트리

리액트는 컴포넌트의 상태와 속성(props)가 변할 때마다 render() 함수를 호출한다. render() 함수는 새로운 리액트 요소 트리를 반환하고 이를 기존의 요소 트리와 비교해 새로운 변경점에 대해서만 재렌더링을 수행한다. 예를 들어, 기존 코드에 <ul>…</ul> 코드가 추가되면 리액트는 변경점만을 새로 렌더링한다. 이처럼 기존 요소들의 끝에 요소를 추가할 때에는 별다른 문제가 일어나지 않는다.

문제가 일어나는 것은 ‘기존 요소의 앞에 무언가를 추가하여 렌더링 순서가 달라질 때’이다. 이 경우, 리액트는 맨 첫 부분만 재렌더링하는 것이 아닌 모든 부분을 재렌더링한다.

키 설정을 하지 않아 키를 인덱스로 받는다. 덕분에 모든 요소가 리렌더링된다.

그러나 key 속성을 부여하면 리액트는 key를 토대로 효율적인 렌더링을 시도한다.

때때로 key 대신 index를 key로 사용하는 경우가 있는데, 요소의 순서가 변할 수도 있는 상황이라면 이 경우 key를 인덱스로 설정해서는 안된다.

이는 위 코드의……. 소스코드이다…

[참고 자료]

-https://mxx-kor.github.io/blog/react-key-props

-https://ko.legacy.reactjs.org/docs/lists-and-keys.html

-https://goddaehee.tistory.com/303

-https://velog.io/@seola1ne/React-map-%ED%95%A8%EC%88%98%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%82%AC%EC%9A%A9

-https://merrily-code.tistory.com/187

카테고리
#기타

댓글 0



추천 포스트