• 2021. 12. 29.

    by. 문익점

    반응형

    리액트에 대하여

    https://reactjs.org/

    리액트란?

    공식페이지에 들어가보면 리액트는 UI(User Interface)를 위한 Javascript Library라고 설명한다. 데이터(state)를 가지는 간단한 뷰를 설계하면 데이터 변할때 마다 효율적으로 뷰를 업데이트하는 interactive ui를 만들어준다. 리액트는 이 뷰를 component라고 부른다. 좀 더 복잡한 UI를 만들기 위해 각각의 데이터(state)를 가진 component를 구성한다. 하나하나의 component들이 모여 application을 구성한다.

    virtual dom

    virtual DOM은 이상적인 혹은 가상(an ideal, or “virtual”) UI의 표현이 메모리에 유지, 리액트DOM과 같은 라이브러리에 의해 실제 DOM과 동기화되는 프로그래밍 개념이다. 이러한 과정을 재조정(Reconciliation)이라고 부른다.

    기존 방식은 DOM 트리에 변화가 생기면 DOM 트리에 변화가 생긴 부분을 위해 전부 다시 그린다. 이는 큰 비용이 든다. 그래서 리액트는 메모리에 virtual DOM 이라는 가상의 돔 트리를 이용하여 변경시킬 일부 부분만을 리렌더링하게끔 하는 방식을 이용한다.

    Reconciliation

    기존의 VDOM과 변경사항이 생긴 VDOM 의 비교작업 재조정(Reconciliation) 과정을 거친다. render() 함수는 React 엘리먼트 트리를 만든다. 또한 state나 props가 갱신되면 새로운 엘리먼트 트리가 반환된다. 이때 React는 방금 만들어진 트리에 맞게 가장 효과적으로 UI를 갱신해야 한다. 단순하게 n개의 엘리먼트가 있는 트리를 비교한다고 가정하면 n^3 만큼의 연산이 발생한다. 이는 1000개의 엘리먼트를 그리기 위해 10억 번의 비교 연산을 수행해야 한다. 리액트는 이러한 문제를 해결하기 위해 2가지 가정을 통한 비교 알고리즘을 사용한다

    1. 서로 다른 타입의 두 엘리먼트는 서로 다른 트리를 만들어낸다.
    2. 개발자가 key prop을 통해, 여러 렌더링 사이에서 어떤 자식 엘리먼트가 변경되지 않아야 할지 표시해 줄 수 있다.

    비교 알고리즘 (Diffing Algorithm)

    두 개의 트리를 비교할 때, React는 두 엘리먼트의 루트(root) 엘리먼트부터 비교한다.

    엘리먼트 타입이 다른 경우

    <div>
      <Counter />
    </div>
    
    <span>
      <Counter />
    </span>

    위와 같이 두 엘리멘트 트리(위와 아래)를 비교 할 때, 최상단 엘리먼트가 <div><span>으로 변경 되었다. 두 루트 엘리먼트의 타입이 다르면, React는 이전 트리를 버리고 완전히 새로운 트리를 구축합니다. 즉 루트 엘리먼트 아래의 모든 컴포넌트도 언마운트되고 그 state도 사라진다. 이 비교에선 Counter는 사라졌다가, 새로 다시 마운트가 된다.

    엘리먼트의 타입이 같은 경우

    <div className="before" title="stuff" style={{color: 'red', fontWeight: 'bold'}} />
    
    <div className="after" title="stuff" style={{color: 'green', fontWeight: 'bold'}} />

    같은 타입의 두 React DOM 엘리먼트(위와 아래)를 비교할 때, React는 두 엘리먼트의 속성을 확인하여, 동일한 내역은 유지하고 변경된 속성들만 갱신한다.. 위와 같은 경우는 classNamecolor 속성 만을 수정한다.

    자식에 대한 재귀적 처리

    <ul>
      <li>first</li>
      <li>second</li>
    </ul>
    
    <ul>
      <li>first</li>
      <li>second</li>
      <li>third</li>
    </ul>

    자식들을 재귀적으로 처리할 때, 기본적으로 동시에 두 리스트를 순회하고 차이점이 있으면 변경을 생성한다. 두 트리에서 <li>first</li>가 일치하는 것을 확인하고, <li>second</li>가 일치하는 것을 확인한다. 그리고 마지막으로 <li>third</li>를 트리에 추가한다.

    여기서 주의 할 점은 자식들 중 맨 처음 엘리먼트가 같은지를 판단하기 때문에 자식요소를 앞에서 부터 추가한다면 성능이 좋지 않다. 매번 모든 자식들을 변경해야 하기 때문이다. 이와 같은 문제를 해결해주는 것이 key 속성이다.

    key

    <ul>
      <li key="2015">Duke</li>
      <li key="2016">Villanova</li>
    </ul>
    
    <ul>
      <li key="2014">Connecticut</li>
      <li key="2015">Duke</li>
      <li key="2016">Villanova</li>
    </ul>

    key 속성을 이용하게 된다면 key를 통해 기존 트리와 이후 트리의 자식들이 일치하는지 확인합니다. key 속성을 통하여 고유하게 지정이 가능한다.

    <li key={item.id}>{item.name}</li>

    다만 위와 같이 꼭 고유한 값으로 지정해야 된다. 배열의 인덱스 값과 같이 요소가 변경 될 때마다 변경 될 여지가 있는 값으로 key 속성을 지정하게 된다면 의도하지 않은 방식으로 바뀔 수도 있다.

    리액트는

    현대 웹에서는 보여줘야 할 정보가 많기 때문에 매번 페이지를 갱신하는 MPA 방식으론 사용자 경험에 한계가 있다. 페이지를 이동할 때마다, 사용자 인터렉션이 발생할 때마다 갱신되는 페이지는 UX에 악영향을 미친다. 이를 개선하기 위해선 SPA 방식을 채택해야 된다. SPA는 사용자와 인터렉션이 발생한 곳만 갱신되고 필요한 리소스만 부분적으로 로딩하기 때문에 랜더링 속도 또한 MPA 보다 빠르다. SPA는 많은 정보를 보여줘야하는 현대 웹에서 딱딱하고 끊기는 느낌이 아닌 빠른 응답으로 UX에 더 적합하다.

    React는 SPA를 구현하기 위해서 탁월한 라이브러리이다. 상태(state)를 가지는 컴포넌트 기반으로 전체적인 Application을 구상하며 잘 설계된 컴포넌트는 재사용이 가능하여 전체적인 생산성이 높아진다. 또한 웹에서는 수많은 인터렉션이 발생한다. 이는 DOM tree를 변경할 경우가 많다는 걸 의미한다. React는 웹에서 Virutal DOM을 사용하므로 인터렉션에 의한 DOM tree 변경 대응에 좀 더 성능적으로 뛰어나다.

    반응형

    '코딩' 카테고리의 다른 글

    프로그래머스 - 고양이 사진첩 애플리케이션  (0) 2022.01.12
    Javascript 엔진  (0) 2022.01.04
    리팩터링 2판 리뷰 - 5장 6.5장  (0) 2021.12.28
    리팩터링 2판 리뷰 - 4장  (0) 2021.12.24
    리팩터링 2판 리뷰 - 3장  (0) 2021.12.22