출처: https://uxgjs.tistory.com/102 [UX 공작소]
스퀘어랩 기술블로그 로고
Engineering

React Conf 감상기

이종완|Jun 3, 2024

React Conf 2024가 한국시간으로 지난 5월 16일, 17일 이틀간 진행되었습니다. 새벽 1시~9시에 진행되는 바람에 실시간 시청을 포기하고, 이후 올라온 유튜브 링크로 짬짬이 시청했는데요. React Conf 전체 세션을 모두 본 적은 처음인데 흥미로운 내용이 많이 있었네요. 인상 깊었던 세션 몇 가지를 간단히 소개해 봅니다.

React Conf 1일차

  • React Conf - What’s new in React 19
    • 한 달 전쯤에 React 블로그에 React 19가 임박했다는 글이 올라왔는데요. 전반적으로 어떤 기능이 추가되고 변경되었는지를 소개합니다.
  • React Conf - Vanilla React
    • Remix는 React Route 팀이 만든 React 프레임워크로 알고 있는데요. Remix가 React Router와 합쳐진다고 합니다. 즉, Remix의 다음 버전은 Remix v3가 아니라 React Router v7으로 배포될 예정입니다.
    • React는 UI 계층을 위한 라이브러리로 시작했지만, React 기반으로 완성된 앱을 만들기 위해서는 code splitting, routing, data fetching, server rendering 등 UI 외에도 신경 써야 할 것들이 많은데요. 이와 같은 요구사항을 제대로 구현하는 것이 쉽지 않다 보니, 이를 도와주는 프레임워크들이 생겼고, React 팀에서도 프레임워크의 사용을 적극 권장하고 있습니다. 그리고 React Server Component와 같이 React 라이브러리만으로는 구현이 어려울 만한 기능들을 프레임워크의 사용을 전제로 프레임워크 개발팀과 긴밀히 협업하면서 도입하고 있습니다.
    • 세션 제목인 Vanilla React는 이런 프레임워크 없이, 한땀 한땀 필요한 라이브러리를 별도로 붙이거나 직접 구현해 가며 만든 React 프로젝트를 말하는 것으로 보입니다. React 초창기에 시작한 프로젝트 중 이미 수많은 코드를 담고 있어서 프레임워크로 넘어가지 못하고 Vanilla React로 남아 있는 프로젝트들이 많다고 합니다. 많은 Vanilla React 프로젝트가 routing을 위해 React Router를 사용하고 있는데요. 이런 프로젝트들에 “Modern React”의 맛을 보여주기 위해 최대한 마이그레이션 비용을 줄여서 프레임워크로 넘어올 수 있도록 새로운 Remix/React Router 버전을 준비 중이라고 합니다.
    • 서버가 없어도 어느 정도 Remix가 제공하는 장점을 누릴 수 있다고 하는 것 같으니, 굳이 SSR을 적용할 필요가 없고, React Router를 사용하고 있는 프로젝트들은 이걸 적용해 보는 것도 괜찮을 것 같습니다. 스퀘어랩에서도 Vanilla React로 남아있는 프로젝트가 많고, 일부는 NextJS로 넘어가는 것을 고려하고 있는데요. React Router v7의 마이그레이션 비용이 충분히 작다면, 이쪽으로 넘어가는 것도 시도해볼 수 있을 것 같습니다.
  • React Conf - React for Two Computers
    • React 관련 공부를 하다 보면 자주 접하게 되는 Dan Abramov의 세션입니다. React Server Component를 만들게 된 의식의 흐름과 개념을 데모와 함께 설명합니다. 아주 간단한 서버 코드를 통해 React Server Component가 어떤 느낌인지를 엿볼 수 있었습니다. Dan Abramov의 세션과 비슷한 제목의 블로그 포스트(The Two Reacts)도 쓴 적이 있습니다.
  • React Conf - Forget About Memo
    • useMemo, useCallback을 버릴 수 있게 해주는 React Compiler를 소개합니다.
    • 빌드 과정에 React의 코드를 제대로 이해하는 컴파일러를 추가해서 useMemo, useCallback React.memo 등의 API를 이용해 수동으로 해야 했던 렌더 최적화를 컴파일러가 자동으로 해줍니다.
    • Rules of React라는 규칙을 지키는 컴포넌트와 hook만 컴파일러가 최적화할 수 있다고 합니다. 컴포넌트 렌더는 동일한 props, state, context가 주어지면 결과가 동일해야 하고, 사이드 이펙트는 렌더 바깥에서(useEffect, 이벤트 콜백 등) 일어나야 한다는 등의 내용입니다.
    • 컴파일러는 useMemo, useCallback로 감싸는 것과 비슷한 효과가 있지만, 다른 방식으로 코드를 변환합니다. React 코드를 컴파일러가 어떻게 변환하는지 테스트해 볼 수 있는 Playground 사이트가 있습니다.
    • 현재는 컴파일러로 렌더를 최적화하는 기능만 추가하지만, 이번에 React 코드를 잘 이해하는 컴파일러를 만들었기 때문에 앞으로 더 다양한 기능을 추가할 수 있는 발판이 마련된 것이라고 합니다.
    • 저희 팀에서도 렌더 최적화를 위해 모든 이벤트 콜백 함수를 useCallback으로 감쌀지, 가독성을 위해, 실제 동작상 문제가 일어날 경우에만 useCallback으로 감쌀지에 대해 논의한 적이 있었는데요. React Compiler의 자동 렌더 최적화 기능을 사용하면, 가독성과 최적화를 둘 다 잡을 수 있게 되어서 기대가 됩니다.
  • React Conf - Introducing Universal React Server Components in Expo Router
    • React Native에서 React Server Component를 활용하는 모습을 보여줍니다. 웹 쪽에서는 NextJS, Remix 등의 프레임워크를 이용해 Modern React의 기능을 사용할 수 있는데, 모바일 쪽에서는 Expo가 이런 프레임워크의 역할을 하는 것 같습니다.
    • Netflix, Reddit 등의 앱은 모바일 네이티브 앱에서도 Server-Driven UI를 사용한다고 합니다. UI를 나타내는 JSON 형식의 데이터 구조를 정의하고, 서버로부터 이 형식의 UI 데이터를 받아서 UI를 그리는 방식인 것 같습니다. 이런 아키텍처를 처음부터 만드는 것은 쉽지 않을 수 있습니다.
    • Expo에서는 React Server Component를 이용해서 Server-Driven UI를 구현할 수 있도록 준비하고 있습니다. 데모로 ChatGPT와 비슷한 AI 채팅 앱을 구현한 것을 보여 주는데요. 서버의 응답 메시지로 단순 텍스트나 마크다운이 아니라, 네이티브 UI 컴포넌트 자체를 내려줘서, 응답 메시지 내에서 사용자와의 상호작용을 통해 모달 UI를 띄운다거나 캘린더 API를 써서 일정을 등록하는 등, 좀 더 기능이 풍부한 메시지를 만드는 모습을 보여주었습니다. Expo와 React Server Component 기능을 이용하면, Server-Driven UI 아키텍처를 직접 구현하지 않아도 이런 기능을 누릴 수 있을 것이라고 합니다.

React Conf 2일차

  • React Conf - Demystifying accessibility in React apps
    • 저같이 accessibility 기능에 대해 개념이 안 잡힌 사람이 기초적인 개념을 잡는 데 도움이 될 만한 영상이었습니다.
    • 브라우저는 HTML을 읽어서 DOM tree뿐 아니라 accessibility tree라는 것을 만드는데, 이는 스크린 리더와 같은 assistive technology에서 참조하여 페이지를 탐색할 수 있게 합니다.
    • Accessibility tree의 각 node에는 role, name 등의 속성들이 있는데, 예를 들어, 스크린 리더에게는 눈에 보이는 페이지가 아니라 accessibility tree의 node만이 페이지의 구성 요소이고, 그 node의 속성으로 그게 무엇인지 파악합니다. accessibility tree에 의미 있는 node와 속성들이 탐색하기 좋은 방식으로 설정되도록 하는 것이 Accessibility 지원의 기본으로 느껴졌습니다.
    • 요즈음의 HTML 페이지들에는 의미 있는 요소뿐 아니라 보기 좋게 하기 위한 꾸밈 요소들도 많이 들어 있습니다. ARIA의 수많은 속성은 accessibility tree에 불필요한 꾸밈 요소들은 제외하고, 의미 있는 요소에 의미 있는 속성이 들어갈 수 있도록 돕기 위해 사용됩니다.
  • React Conf - Pigment CSS, CSS in the Server component age
    • MUI 컴포넌트 라이브러리를 만들고, 운영 중인 Olivier Tassinari가 MUI 팀에서 React Server Component를 지원하기 위해 고민한 내용과 그 결과물인 Pigment CSS를 소개합니다.
    • MUI 최신 버전(v5)에서는 스타일 엔진으로 emotion과 styled component 라이브러리를 사용합니다. 이는 Javascript 코드로 CSS 스타일을 정의하는 CSS-in-JS 방식을 사용하는데, Javascript로 정의한 CSS 스타일을 실행 시점(runtime)에 <style> 태그로 만들어서 <head> 영역에 추가하는 식으로 동작합니다.
    • React Server Component는 기존의 emotion이나 styled component로는 현재 지원이 불가능한데, 가장 큰 이유가 Server Component에서는 React Context를 사용할 수 없기 때문이라고 합니다. Server Component에서 React Context와 같이 컴포넌트 간에 상태를 공유하는 메커니즘이 없는 것은 구조상 제약 때문으로 보이는데, React 팀에서도 Context와 같은 것을 현재 missing feature로 여기는 것 같습니다. 이를 극복할 방법을 찾을지는 기약이 없습니다.
    • Meta에서 내놓은 stylex은 React Server Component를 지원하는 스타일 라이브러리입니다. 그러나 MUI에서는 기존의 styled component 방식의 API를 더 선호하고, MUI를 사용하고 있는 사용자들이 너무 큰 마이그레이션 수고를 겪는 것을 원치 않기 때문에 기존 방식과 비슷하게 쓸 수 있는 다른 방법을 고민하고 있습니다.
    • Context 없이 기존과 비슷한 API를 사용하면서 React Server Component를 지원하기 위해 빌드 툴로 추가해서 빌드 시점에 JS 코드를 스타일 코드로 변환하는 방식을 고안했고, 이를 Pigment CSS라는 별도의 스타일 라이브러리로 발표하였습니다. import 문만을 수정하는 것만으로 마이그레이션을 할 수 있을 정도로 API를 비슷하게 만드는 것이 목표이고, codemod 툴을 제공할 예정이라고 합니다. 스타일 코드 추가 과정을 실행 시점에서 빌드 시점으로 옮김으로써 성능에도 이점이 있습니다.
    • 이는 아직 알파 단계이고, MUI v6에서 도입될 예정이라고 합니다.
    • 스퀘어랩에서도 MUI 라이브러리를 주요 스타일 및 컴포넌트 라이브러리로 쓰고 있었고, 기존 방식이 React Server Component를 지원하지 못한다는 소식을 듣고 고민하고 있었는데요. Pigment CSS가 아주 좋은 대안이 될 것 같습니다.
  • React Conf - The next decade of React Native
    • React Native와 React Web은 둘 다 React를 사용하여 코드가 비슷해 보이지만, 실제로 네이티브와 웹 간에 코드를 공유하는 것이 어렵습니다. 코드는 비슷하지만, 동작이 미묘하게 다른 부분이 상당히 많기 때문인데요. 코드 베이스 하나로 모바일 앱과 웹을 다 커버하기 위해서 React Native for Web이라는 방식이 나오기도 했습니다. 하지만, 이는 웹 코드 작성 경험을 React Native 쪽에 맞춰버리는 단점이 있습니다. 우리는 React Web을 작성하듯이 React Native를 작성하고 싶습니다!
    • React Native 팀은 Web의 표준 API들을 React Native 쪽에서 거의 동일하게 동작하도록 구현하여 두 플랫폼에서의 개발 경험의 차이를 줄이고, 더 많은 코드 공유를 가능하게 하는 것이 목표라고 합니다. 특히 기존에는 비즈니스 로직 코드는 두 플랫폼 간에 공유할 수 있었어도, UI를 그리는 코드는 네이티브 플랫폼의 View API와 웹 플랫폼의 DOM 엘리먼트의 API 차이가 크기 때문에 코드를 공유하기가 어려웠는데요. 웹 쪽의 API를 React Native 쪽에 구현하는 방식으로 이 차이를 줄이고, 동일한 방식으로 코드를 작성할 수 있도록 하려는 것 같습니다. 예를 들면, 웹 쪽에서 많이 쓰는 getBoundingClientRect()나, ResizeObserver, IntersectionObserver 같은 API들을 React Native 쪽에 구현할 예정이라고 합니다.
    • React Native가 CSS 스타일시트와 비슷한 개념을 도입하여 스타일 코드를 작성하도록 하고 있지만, CSS의 모든 기능을 반영하고 있는 것은 아닌데요. 예를 들면, flex box의 gap과 같이 길이를 지정하는 속성에서 React Native 스타일시트는 CSS 스타일시트와 달리 단위 없는 숫자만 넣을 수 있었습니다. 이런 것들도 CSS의 동작을 최대한 반영하여, px, vw, % 같은 단위를 쓸 수 있게 하고, calc()와 같이 더 복잡한 기능까지도 사용할 수 있도록 하는 것이 목표라고 합니다.
    • React Native는 JS 코드와 네이티브 코드 간에 통신을 하기 위해 비동기 방식으로 JSON 메시지를 주고받는 bridge를 사용하는데요. bridge의 비동기적인 특성 때문에 JS 코드에서 일어나는 React Native의 렌더부터 네이티브 코드에서 일어나는 UI 컴포넌트의 레이아웃이 동기적으로 진행될 수가 없어서, useLayoutEffect 같은 API가 웹에서와 다르게 동작합니다. React Native의 New Architecture는 이런 구조적인 문제로 구현할 수 없었던 기능들을 지원하기 위해 개발되었습니다. 새로운 아키텍처에서는 비동기 bridge 대신에 JSI(JavaScript Interface)를 도입하여 JS 코드와 네이티브 코드 간에 동기적인 통신을 가능하게 합니다. JSI는 비동기적으로 메시지를 주고받는 대신에 메모리를 공유하는 방식으로 동작한다고 합니다. 또한 새로운 아키텍처에서는 React 18에서 도입된 concurrent features를 지원합니다.
    • 웹쪽의 모든 API를 React Native에서 사용할 수 있도록 polyfill 하는 React Strict DOM이라는 계층 구조에 대해 실험하고 있습니다.
    • 스퀘어랩의 카이트 앱은 코드 베이스 하나로 웹과 앱을 둘 다 만들기 위해 웹뷰 위에 React Web 사이트를 띄우는 하이브리드 앱 방식을 사용하고 있습니다. 이 세션에서 말하는 것처럼 웹의 API를 React Native에 구현하는 작업이 완료되면, 기존의 React Web 코드 베이스를 적은 비용으로 React Native와 호환되게 만들 수 있을 것 같아서 기대가 됩니다. 개인적으로 크로스 플랫폼 기술은 Flutter 쪽에 더 관심이 많았는데, 이번 발표를 듣고, React Native에 대한 관심이 늘었네요.

제가 관심이 가는 내용 위주로 간략하게만 소개해 보았는데요. 이외에도 재미있는 내용들이 많으니 직접 보시는 걸 추천합니다.