위클리 페이퍼 (6)

깨진알·2023년 12월 30일

Weekly-Paper

목록 보기
8/14

6주차 위클리 페이퍼

Q1) 리액트에서 Virtual DOM이 무엇인지, 이를 사용하는 이유는 무엇인지 설명해 주세요.

많은 개발자들이 리액트를 사용하는 이유 중 하나는 빠른 속도를 제공하기 때문이다. 리액트는 가상 돔(Virtual DOM)을 사용해 보다 효율적으로 원하는 페이지를 브라우저에 빠르게 그려준다. Virtual DOM에 대해 이해하기 전에 간단히 DOM에 대해 설명하도록 하겠다.

(1) DOM (Doucment Object Model)

DOM이란 HTML 요소들을 tree 형태로 표현한 것을 의미한다. 하나하나의 HTML 요소들을 담고 있는 웹페이지를 Document라고 하는데, 이를 브라우저는 분석해 페이지를 띄워주게 된다.

DOM tree 안에는 각각의 요소에 상응하는 노드가 들어있다. 개발자들은 DOM이 제공하는 API를 통해 DOM 구조에 접근을 하고, 원하는 요소를 조작할 수 있게 된다. 이를 DOM 조작이라고 부르기도 한다.흔히 getElementById, querySelector과 같은 API를 통해 DOM 구조안의 요소에 접근해 원하는 내용, 스타일, 레이아웃 등을 수정한다.

(2) Virtual DOM

웹의 복잡도가 증가하며, DOM 조작도 이에 맞춰 점점 빈번하게 일어나게 되었다. DOM 조작이 많이 발생할 경우, 상당히 비효율적이다. Virtual DOM은 이러한 상황을 해결하기 위해 나타난 개념이다.

Virtual DOM은 하나의 가상 레이어이다. Virtual DOM에 적용하는 변경사항은 DOM에 바로 반영되지 않는다. 다만 그 변경사항들을 모아두고, 한번에 DOM한테 보내게 된다. 그러면 DOM은 업데이트를 한 번만 하게 되고, 렌더도 한 번만 실행하면 되는 것이다.

  1. 렌더링 이전 화면 구조를 나타내는 Virtual DOM
  2. 렌더링 이후에 보이게 될 화면 구조를 나타내는 Virtual DOM

리액트는 항상 위 2개의 Virtual DOM 객체를 가지고 있다. 리액트는 State가 변경될 때마다 재렌더링이 일어난다. 이 시점마다 새로운 내용이 담긴 Virtual DOM을 생성하게 된다.

Diffing은 효율적인 알고리즘을 사용하여 진행되기 때문에 어떤 요소에 차이가 있는지를 매우 신속하게 파악할 수 있게 된다. 리액트는 이를 통해 차이가 발생한 부분만을 실제 DOM에 적용하게 된다. 이 과정을 Reconciliation(재조정)이라고 한다. 이 과정이 매우 효율적인 이유는 Batch Update 때문이다. 모든 요소들을 집단화시켜 이를 한번에 실제 DOM에 적용하는 방식이다.

DOM 조작에 비용이 가장 많이 발생하는 지점은 브라우저에 화면을 그려주는 작업인 만큼 Batch Update는 변경된 요소들을 별개로 그려주는 것이 아니라, 변경된 내용을 한 번에 받아와 이를 실제 DOM에 한번에 적용시켜준다는 점이 매우 효율적이다.


Q2) 리액트에서 배열을 렌더링할 때 key를 써야 하는 이유에 대해 설명해 주세요.

리액트에서 map으로 컴포넌트를 반복 렌더링 할 경우 주의 문구를 확인할 수 있다. 리액트가 setState를 할때, 비동기로 동작하고 연속적으로 호출했을 때 배치 처리를 했는데, 그 이유는 리액트는 효율적으로 DOM을 업데이트하기 위해서였다. 리액트 입장에서는 컴포넌트를 반복해서 렌더링하는 일은 비효율적이다.

이러한 문제를 해결하기 위해 존재하는 것이 key 속성이다. 자식들이 key를 가지고 있다면, 리액트는 key를 통해 기존 트리와 이후 트리의 자식들이 일치하는지 캐치할 수 있고 효율적으로 렌더링 할수 있게 된다. 또한 요소들의 순서가 바뀔 때 엉뚱한 곳에 렌더링될 수 있기 때문에 key 속성을 지정해 주어야 한다.

(1) Map에서의 key 사용

export default function ListItem({
  onClickTitle,
  badges,
}) {
  return (
    <ListItemLayout>
      <div>
        <div role="button" onClick={onClickTitle} className={styles.title}>
          Issue Example
          {badges &&
            badges.map((badgeProps, idx) => (
              <Badge key={idx} {...badgeProps} />
            ))}
        </div>
        <div className={styles.description}># Description</div>
      </div>
    </ListItemLayout>
  )
}

map 함수 인자로 전달되는 함수 내부에서 key를 컴포넌트 props를 설정하는 것과 같이 작성하면 된다. keys는 요소의 교유한 값을 사용해야 하며, 배열 요소의 고유한 값을 사용하거나 index로 사용한다. 단, 항목의 순서가 바뀔 수 있는 경우, 순서가 바뀌면 index도 바뀌기 때문에 권장하지는 않는다.

(2) key 주의점

  • key는 반드시 변하지 않고, 예상 가능하며, 고유한 값이어야 한다.
  • key 형제 노드에서만 고유하면 된다. 즉, 전역에서 고유할 필요는 없고 해당 배열 안에서만 고유하면 된다.
  • 배열의 인덱스를 key로 사용할 수 있다. 항목들이 재배열되지 않는다면 잘 동작하지만, 만약 재배열되는 경우에는 컴포넌트의 state와 관련된 문제가 발생할 수 있다.
profile
프론트엔드 지식으로 가득찰 때까지

0개의 댓글