본문 바로가기
Language/React

[React 공식 Doc 가이드 #9] Lists and Keys

by ocwokocw 2021. 2. 11.

- 이 글은 React 공식 홈페이지 Docs v16.8.3 (https://reactjs.org/docs) 에 기반하여 작성한 글입니다.

- Lists and Keys

우선 Javascript 와 관련된 예제를 한번 보자.

위의 예제는 map function 을 이용하여 numbers 에 저장된 배열값들의 2배의 값 목록을 doubled 변수에 저장 후 log 로 출력하였다. React 에서는 배열을 element 의 list 로 변환할 때 위와 같은 방식을 많이 사용 한다.


- Rendering Multiple Components

JSX 안에서 collection 들을 {} 을 이용하여 build 할 수 있다. 

위의 예제에서 JavaScript 의 map() function 을 사용해서 numbers 배열에 대해 <li> 목록을 만들었다. 그리고 그 element 를 listItems 에 할당하였다.


- Basic List Component

일반적으로 component 안에서 list 를 rendering 하는 경우가 많다. 앞의 예제를 수정해서 props 로 배열을 받아서 element list 를 출력하는 Component 를 만들어보자.

이 코드를 돌리고 난 뒤 개발자 도구를 켜보면 list items 에 key 가 할당되어야 한다는 warning 메시지가 뜰것이다.

"key" 는 list element 를 만들 때 할당해야 하는 특별한 attribute 이다. 왜 이게 중요한지는 다음 section 에서 논의해보도록 하자. 일단 정말로 list element에 "key" attribute 를 할당하면 되는지 확인해보자.

 

key attribute에 number 를 할당했더니 정말 warning 이 사라졌다.


- Keys

React 가 어떤 item 들이 삽입, 삭제, 변경되었는지 알고자 할 때 key 를 사용할 수 있다. key 를 할당할 때에는 다른 형제 레벨들의 item 과는 구분될 수 있도록 하는 것이 중요하다. 실용적인 프로젝트에서는 DB로 부터 조회해온 id 값을 할당할 것이다.

아마 위와같은 형태가 될 것이다.

 

만약 마땅히 고려할 key 값이 없다면, 순차적으로 늘어나는 단순 index 값을 할당할 수도 있다.

사실 단순 index 를 할당하는건 좋은 방법이 아니다. 그 index 라는게 그 아이템이라는걸 기술적으로는 구분할 수 있겠지만, 비즈니스적인 로직 관점에서 구분을 할 수가 없다. 더군다나 todo 앱 같은 경우 순서까지 변경할 수 있는 기능이 없다면 전혀 쓸모없는 기능이다.

 

그리고 공식 문서에서는 performance 에 나쁜 영향을 준다고 까지 설명하고 있다.

index 를 key 로 썼을 때 미치는 부정적인 영향 : https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318

 

key 를 할당하지 않는다면 React 에서도 마땅한 방법은 없기 때문에 index로서 Default로 key를 할당한다.


- Extracting Components with Keys

key 는 array 내에서만 의미를 가진다. 사실 무슨소리인지 좀 헷갈릴 것이다. 만약에 ListItem component 를 number 를 출력했던 예제에서 <li> 부분을 ListItem component로 추출해보자.

ListItem 이라는 Component 를 만들어서 그대로 li 를 옮겼는데 warning 이 떴다. 아마 이 예제를 봤다면 이해가 갈 것이다. 

 

아까는 <li>부분이 array context(numbers )였기 때문에 key 를 할당하면 warning 이 없어졌었지만, 이제는 ListItem 이 array context 기 때문에 ListItem에 key 를 할당해야 한다.

context 니 나발이니 헷갈린다면 map() 함수안에서 쓰는 element에 key를 할당한다고 생각하면 될 것이다.


- Keys Must Only Be Unique Among Siblings

소제목이 좀 이상하게 느껴질 것이다. 너무 당연한 소리지 않은가? key 가 유니크 해야 key 지 그럼 뭐란말인가?

이 소제목에는 다른 뜻이 숨어있다. 형제레벨에서는 unique 해야 하지만, 전역적으로는 unique 할 필요가 없다는 소리이다. 

 

function Blog(props){
	
	const sidebar = (
		<ul>
			{props.posts.map((post) => {
				return (
					<li key={post.id}>
						{post.title}
					</li>);
			})}
		</ul>
	);
	
	const content = (
		<ul>
			{props.posts.map((post) => {
				return (
					<li key={post.id}>
						<h3>{post.title}</h3>
						<p>{post.content}</p>
					</li>
				);
			})}
		</ul>
	);
	
	return (
		<div>
			{sidebar}
			<hr />
			{content}
		</div>
	);
	
}

const posts = [
	{id: 1, title: 'Hello world', content: 'Welcome to learning React!'},
	{id: 1, title: 'Installation', content: 'You can install React from npm.'}
];

ReactDOM.render(
	<Blog posts={posts}/>, 
	document.getElementById('root')
);

Key 는 React 에게 hint를 제공하지만, Component 에게는 전달하지 않는다. 만약 key 를 참조해야할 필요가 있다면 명시적으로 선언해서 넘기면 된다.

위 예제에서는 props.id 로 참조하는게 가능하지만 props.key 로는 참조할 수 없다.


- Embedding map() in JSX

위에서 listItems 에 변수를 담은다음 {listItems} 와 같이 jsx 안에서 표현을 했다. 

JSX 는 위와같이 numbers.map 과 같은 복잡한 형태의 부분도 inline 형태로 쓸 수 있다.

 

inline 형태로 쓰는게 간단할 수도 있지만, 실제 Project 코드는 위와같이 짧지가 않기 때문에 잘못쓰면 가독성을 더 헤칠수도 있다. 변수로 추출한 다음에 변수를 JSX 안에서 참조할 것인지 inline 형태로 쓸 것인지는 상황이나 프로젝트에 맞게 선택하여 쓰면 된다. 

 

map() 의 함수가 너무 복잡하다면 Component 로 빼야하는 좋은 후보군이 될 수도 있다.

댓글