본문 바로가기
Front-End/React + Native

[React]React 16 버전에서의 주요 변화점과 동작 원리

by MS_developer 2024. 10. 13.

출처: Lifecycle methods in React 16 (링크 참조)

 

프론트엔드 개발자라면 리액트는 너무나도 친숙한 기술 스택이다.

 

언제부터 리액트는 이렇게 인기가 많아지게 되었을까? 그리고 웹 개발자들은 왜 리액트를 선호하게 되었을까?

 

리액트의 중요한 분기점이 되었을 16 버전의 주요 업데이트와 동작 원리, 그리고 역사를 간단히 알아보도록 하자.

 


Why use React? (왜 리액트를 쓰는가?)

출처: 2023년도 스택오버플로우 설문조사 (링크 참조)

 

2023년에 스택오버플로우에서 개발자들을 대상으로 진행한 설문에서 "웹 프레임워크 및 기술" 부문에서 위와 같은 결과가 집계되었다. 웹 개발, 특히 프론트엔드 분야에서는 현재 가장 많이 사용되는 기술 스택이라고 보아도 될 것이다.

 

하지만 의문이 든다.

 

왜 사람들은 리액트를 주요 기술 스택으로 채용하여 개발하게 되었을까?

 

 

그냥 너도나도 써서 리액트를 썼을리는 없는데, 무엇이 리액트를 이토록 성장하도록 이끌었을까?

 

많은 이유들이 있겠지만, React를 사용하는 가장 대표적인 이유 3가지를 개인적으로 꼽아보았다.

 

1. 컴포넌트 기반 아키택처

generated by Napkin AI

 

컴포넌트 기반 아키택처란 웹 개발에서 사용되는 개발 패턴으로, 애플리케이션에서 재사용이 가능한 컴포넌트 단위로 분리하여 개발하는 방식이다.

 

컴포넌트란 앞서 언급한대로 재사용이 가능한 UI를 구성하는 코드 조각들을 일컫는다.

 

간단한 예를 들어, 아날로그 시계를 만드는 공장을 예로 들 수 있다.

 

아날로그 시계의 내부는 굉장히 복잡하게 구성되어 있는데, 하나의 시계를 구현하기 위해 내부에 다양한 부품들이 맞물려 사용되고 있다. 만약 기존과 비슷한 다른 시계를 만든다고 했을 때, 비슷한 부품들을 미리 구성해 두었다면 새로운 시계를 만들 때 필요한 부품들을 다시 만들 필요가 없을 것이다.

 

여기서 각 부품들이 컴포넌트에 해당한다.

 

컴포넌트 기반 아키택처 패턴을 사용함으로써 재사용성을 높여 불필요한 반복 작업을 줄일 수 있다. 또한, 모듈화 된 코드들은 이후 유지보수에 용이하고 다른 사람이 사용하거나 참조할 수 있어 보다 효율적인 협업을 할 수 있다. 더불어 복잡한 애플리케이션을 체계적으로 관리할 수 있다.

 

2. 가상 DOM (Virtual DOM)

generated by Napkin AI

 

리액트의 주요 강점 중 하나인 가상 돔 (Virtual DOM)의 자세한 동작 원리까지 설명하지는 않겠다.

 

간단한 설명을 하자면, 가상 돔은 기존의 DOM (Document Object Model)과 다르게 페이지에 변경사항이 생겨도 해당 페이지 전체를 재렌더링하지 않고 변경된 부분만을 업데이트하여 재렌더링할 수 있는 기능이다.

 

이를 통해 성능을 최적화하고, 특히 대규모 애플리케이션에서 부드러운 UI 업데이트 빠른 반응성을 보장할 수 있게 된다.

 

3. 풍부한 생태계 및 커뮤니티

generated by Napkin AI

 

리액트는 (구) Facebook에서 개발한 오픈소스 프로젝트로 방대하고 활발한 생태계와 커뮤니티를 유지하고 있고, 덕분에 수많은 서드파티 라이브러리와 도구들을 손쉽게 사용할 수 있다.

 

특히 React Native와 Next.js 같은 확장 프레임워크를 통해 모바일 앱과 서버 사이드 렌더링까지 폭넓게 지원이 가능하다.

 

개인적으로 이 부분이 굉장히 큰 메리트라고 생각한다.

 

래퍼런스를 확인할 수 있는 다양한 코드와 사람들의 검증을 마친 우수한 라이브러리들이 있다는 점에서 쾌적한 개발 환경과 안정성을 보장받을 수 있기 때문이다. 특히 상세한 documentation과 수많은 사람들이 작성한 해당 라이브러리 깃헙의 issue는 비슷한 문제를 해결하거나 해당 라이브러리를 온전히 사용하는데 소모되는 리소스를 크게 줄일 수 있다.

 

특히나 S/I 분야에서는 이러한 수고들을 줄일 수 있다는 것이 엄청난 메리트로 다가온다.

 


Why React v16? (왜 리액트 16 버전이 중요한가?)

 

여기서 한 가지 의문이 더 든다.

 

그렇다면 리액트는 언제부터 이토록 우수한 생태계와 커뮤니티를 구성할 수 있었을까?

 

 

이에 대한 해답도 킹갓스택오버플로우에서 찾을 수 있다.

 

출처: 스택오버플로우 trend (링크 참조)

 

위 차트는 2010년(사실상 2012년)부터 스택오버플로우에서 집계된 각 기술 스택들의 질문 빈도를 %로 수치화한 것이다.

 

푸른색 선이 리액트의 지표인데, 2016년부터 가속화되어, 2017년 이후 관련 질문들이 폭발적으로 증가한 것이 보인다.

 

사람들이 차차 리액트의 우수성과 편의성을 알아가기 시작했던 시기이기도 했겠지만, 결정적으로 리액트 16 버전의 출시가 크다고 생각한다.

 

리액트 16.0 버전은 2017년 9월 26일에 출시되었는데, 이때를 기점으로 성능, 안정성, 확장성의 측면에서 리액트를 한 단계 끌어올린 중요한 버전이라고 부른다.

 


What has changed? (무엇이 바뀌었는가?)

 

그렇다면 리액트 16 버전에서는 무엇이 그토록 바뀌었길래 리액트의 수준을 한 단계 더 끌어올릴 수 있었을까?

 

좀 더 자세한 설명을 이어나가기 전에 간략하게 리액트의 동작 단계에 대해 확인할 필요가 있다.

 

 

먼저 초기 렌더링 단계에서 리액트 엘리먼트 트리를 생성하고, 이를 기반으로 props 또는 상태의 변경을 감지하여 새로 생성된 가상 DOM과 비교한다. 이후 Commit 단계에서 브라우저의 실제 DOM에 변경 사항을 반영하고 이 과정을 반복한다.

 

실제 과정은 좀 더 복잡한 원리와 절차가 있지만, 간략하게 설명하자면 위와 같다.

 

리액트 동작 단계를 기반으로 다음의 주요 변화 내용을 살펴보자.

 

1. 아키텍처 변화: Stack vs Fiber Reconciler

generated by Napkin AI

 

 

리액트 16 버전에서의 가장 커다란 변환점은 재조정자(Reconciler)의 변경이라 할 수 있다.

 

앞서 언급했듯, 리액트의 동작 단계에서는 재조정 단계를 거쳐 가상 DOM과 비교하여 변경된 부분을 실제 DOM에 반영한다.

 

이 과정에서 리액트 16버전 이전의 스택 재조정자는 몇 가지 문제점들이 있었다.

출처: Lin Clark - A Cartoon Intro to Fiber - React Conf 2017 (링크 참조)

 

React 16 이전:

  • 리액트의 재조정(reconciliation) 알고리즘은 스택 재조정자(Stack Reconciler)로 동기적으로 처리되었다. 이때 깊이 우선 탐색(DFS)을 통해 진행되어 한 번 시작된 탐색과 변경 처리는 중간에 나눠질 수 없기 때문에 UI 업데이트가 끝날 때까지 UI는 잠시 멈추어 있어야 한다. 이는 사용자의 눈에 화면이 버벅거리는 것처럼 보이게 된다.
  • 모든 상태 변화가 한 번에 처리되었기 때문에 비동기 렌더링이 불가능하고, 복잡한 UI나 대규모 애플리케이션에서는 성능 문제가 발생할 수 있었다.

React 16 이후 (Fiber 아키택처 도입):

  • 컴포넌트의 상태, 업데이트 정보, 위치 등을 가지고 있으며, 이 정보를 바탕으로 재조정 작업을 세밀하게 처리가 가능한 Fiber Node 기반의 파이버 재조정자(Fiber Reconciler)를 사용한다. 이때 작업을 여러 청크로 나눠서 처리함으로써 비동기 렌더링이 가능해졌고, 이로 인해 UI가 블로킹되지 않고 부드럽게 렌더링 된다.
  • 자연스럽게 성능이 대폭 향상되었으며, 특히 애니메이션이나 백그라운드 작업을 더 효과적으로 처리할 수 있게 되었다.

 

위 내용을 그림으로 단순화하면 다음과 같다.

 

출처: Lin Clark - A Cartoon Intro to Fiber - React Conf 2017 (링크 참조)

 

더 자세한 내용은 2017년에 발표한 리액트 컨퍼런스에서의 발표 영상을 참조하도록 하자. 매우 유익한 영상이니 기회가 된다면 꼭 시청하길 추천한다. 근데 이제 영어를 곁들인

 

2. 에러 경계(Error Boundary) 도입

또 하나의 주요 변화점은 에러 경계(또는 에러 바운더리)를 도입한 점이다.

 

React 16 이전:

  • React 16 이전에는 컴포넌트 내부에서 에러가 발생하면 트리 전체가 영향을 받아 앱 전체가 중단되는 문제가 발생했다. 이 때문에 에러를 특정하고 대처하기가 어려웠고, 이를 효과적으로 처리하는 방법이 제한적이었다.

React 16 이후 (Error Boundaries 도입):

  • 에러 경계는 하위 컴포넌트 트리의 어디에서든 자바스크립트 에러를 기록하고, 깨진 컴포넌트 트리 대신 설정해 둔 풀백 UI(대체 UI)를 보여주는 리액트 컴포넌트다. 
  • componentDidCatch 메서드로 에러를 처리하고, 에러 발생 시 대체 UI를 렌더링할 수 있기 때문에 대규모 애플리케이션에서의 안정성이 크게 향상되었다.

단, React는 공식적으로 함수형 컴포넌트에서 Error Boundary를 지원하지 않는다.

 

하지만 일부 서드파티 라이브러리나 커스텀 훅을 사용하여 함수형 컴포넌트에서도 유사한 기능을 구현할 수 있어react-error-boundary와 같은라이브러리를 사용해야 함수형 컴포넌트로도 구현할 수 있다. 앞서 언급했던 리액트의 넓은 생태계의 장점이 부각되는 순간이다.

3. Context API  개선

Context API란 props를 사용하지 않아도 특정 값이 필요한 컴포넌트끼리 쉽게 값을 공유할 수 있게 해주는 리액트의 내장 기능이다. 이를 기반으로 전역 상태 관리에 주로 사용된다.

 

React 16 이전:

  • 상태를 하위 컴포넌트로 전달하기 위해 childContextTypes getChildContext를 사용하여 복잡한 사용 방식을 거쳐야 했다.
  • 트리의 모든 컴포넌트를 무조건 리렌더링이 되었기 때문에 불필요한 성능 비용이 발생하는 성능 문제가 있었다.

React 16 이후 (Context API 도입):

  • Provider와 Consumer를 통해 Context 데이터를 쉽게 제공하고 소비하여 코드가 간략화되었다.
  • Provider에서 value가 변경되었을 때, 해당 Provider 하위의 Consumer들만 리렌더링 되어 불필요한 렌더링이 축소되었다.
  • 여러 Provider를 중첩하여 사용하여 특정 데이터만 필요한 부분에서 독립적으로 Context를 사용할 수 있게 되었다.

 

포스팅이 너무 길어지는 것 같아 추가적인 서술은 하지 않겠지만, 이 외에도 React Portals, React Fragment, 커스텀 돔 속성(Custom DOM Attributes) 지원 등 다양한 기능들이 16 버전을 추가되었다.

 

해당 버전에서의 업데이트는 안정성과 효율성 측면에서 크게 향상된 것을 알 수 있다. 대중화되어 가던 리액트에 날개를 달아준 셈이다.

 


What now? (리액트의 현재)

이후에도 점진적인 업데이트와 변화로 현재의 리액트 18 버전에 도달해 있다. 각 버전의 주요 업데이트를 요약하자면 다음과 같다.

 

 

 

 

더 자세한 설명은 이후 다른 포스팅에서 다룰 예정이라 전체적인 흐름만을 짚고 넘어가도록 하겠다.

 

중요한 건 2016년도부터 서서히 리액트가 웹 개발 분야에서 대중적으로 자리 잡게 되었고, 이러한 성공의 뒤에는 리액트의 기능을 효과적으로 보완하고 발전시킨 16 버전이 있었다는 점이다. 이후에도 지속적인 업데이트와 새로운 기능들을 도입하여 발전하고 있어 앞으로의 행보가 기대되는 기술 스택이라고 생각한다.


참조

 
 

댓글