2019-09-24 TIL

2019-09-24

오랜만에 번역.

스크린 사이즈의 복잡한 컴포넌트들을 리스트로 나열하고 스와이프할 수 있는 UI를 최근 작업했는데, 사용자의 터치를 통해 렌더링을 컨트롤 하는것이 마음대로 되지 않았다. 리액트의 이벤트 핸들링에 대해 이해하면 레벨업이 되지 않을까? 하던 중 아래 글을 발견해 차근차근 읽어보고자 한다.

https://levelup.gitconnected.com/how-exactly-does-react-handles-events-71e8b5e359f2

The React and React Native Event System Explained: A Harmonious Coexistence (1 / 2)

리액트의 이벤트 핸들링 시스템을 설명하는 많은 포스트들이 있지만 어떻게 동작하는지 설명하는건 많지 않다. 최근 나는 리액트 네이티브로 작업을 하고있고, 이벤트 핸들링을 하기 위한 고군분투는 어떻게 돌아가는지 정확하게 이해하는 것이 얼마나 중요한지 상기시키는 리마인더가 되었다. 그래서 나는 리액트에서 이벤트 핸들링에 대한 가능한 한 많은 정보를 모으기로 결심했고 이 글은 리액트 소스 코드를 살펴보며 찾아낸 것들에 대한 일종의 보고서다.

Event handling in React: An overview

개념상으로 리액트의 이벤트 핸들링은 전혀 혁신적이지 않다. 이것의 단 하나의 목표는 다양한 이벤트들(클릭, 터치 등..)을 인터셉트 하고 관련된 콜백들(여러분이 작성한 그것!)을 트리거하는 것이다. 이게 리액트의 이벤트 핸들링 시스템을 뛰어나게 만드는 구현이다.

An overview of React’s event handling flow

주석: 터치 > 네이티브 > 리액트 브릿지 > RN EventEmitter > 리액트의 이벤트 시스템 (콜백 실행 등)

리액트가 강조하는 것들 중 하나는 조화로움이다 : 리액트 웹의 크로스 브라우징, 리액트 네이티브의 크로스 플랫폼. 그러나 이벤트 시스템은 사실상 이 컨셉을 한발짝 더 발전시킨다. 리액트 웹과 RN 모두 거의 동일한 이벤트 프로세싱 시스템을 갖게 했다. 그렇다. DOM과 네이티브 이벤트는 정확히 같은 코드를 사용해 다뤄진다. (약간의 전처리는 들어간다.) 어떻게 이런 마법을 부리는가? 그게 이 글의 주제다.

Welcome to the magical world of Fiber

앱이 업데이트될 때(버튼을 클릭할 때 라든지) 무슨 일이 벌어질까? 새로운 정보가 전파(propagate)되고, 앱은 이걸 갖고 다시 렌더된다. 리액트(웹과 앱)의 배후에 있는 핵심 아이디어는 이 과정을 두가지 페이즈로 분리하는 것이다 : “reconciliation” 과 “rendering”이다. reconciliation은 리액트가 차이점을 계산하고 업데이트가 필요한게 무엇인지 결정하는 과정이고, rendering은 실제로 변화를 적용하는 과정이다.

“reconciliation” 페이즈는 렌더링이 어떻게, 어디서 행해지는지는 신경쓰지 않고 오직 무엇이 렌더돼야 하는지만 다룬다. 그 결과로, 같은 프로세스가 리액트 웹과 네이티브에 모두 사용될 수 있게 되었다. 남은 태스크는 단지 적절한 렌더링 엔진에 꽂아넣는 것 뿐이다.

이벤트 프로세싱은 “reconciliation” 페이즈의 일부다. 따라서 브라우저 이벤트와 DOM 컴포넌트, 네이티브 이벤트와 컴포넌트가 서로 다르지 않은 동일한 추상화 세계에서 일어난다. 이 세계는 어떻게 생겼을까? 그려내기 다소 복잡한데, 그건 우리가 보이고 만질 수 있는 오브젝트들에 너무 익숙하기 때문이다. 하지만 이 평행 우주에서, 각각의 모든 컴포넌트들은 Fiber가 된다. 다시 말하지만, 리액트 reconciliation 알고리즘은 컴포넌트들이 어떻게 렌더될지 신경쓰지 않고, 두 렌더 iteration 사이에 무엇이 달라지는지만 신경쓴다. 이전 상태의 컴포넌트가 새 상태로 가기 위해 행해져야 하는 작업만이 중요하다. (변화가 일어나지 않았다면 이 작업은 아무것도 하지 않는 작업이 될 수도 있다.) 그리고 이것이 Fiber다 : 물리적 존재가 아니고 일의 단위 즉 거대한 reconciliation 프로세스의 작은 단계다.

Fiber에 대한 이 소개를 통해 머리속에 궁금증이 강타한 사람들은 Fiber와 React Fiber에 대해 더 알아보길 추천한다! 이 재밌는 프리젠테이션 (by Lin Clark)이 좋은 시작점이 될 것이다. 모두들 걱정하지 말아라 : Fiber를 이해하는 것이 이 글의 나머지 부분을 따라잡는 데 필수는 아니다. (Fiber로 전환한 것은 다소 최근에 일어난 일이고, 이벤트 관리 시스템은 어떤 메이져한 변화를 겪지 않았다.) 기억해야 할 것은 : 리액트는 “추상화된 세계”에서 동작하는데 컴포넌트의 물리적 표현과는 별개로 업데이트가 일어나는 곳이다: 컴포넌트가 렌더되는 다수의 “현실 세계”(브라우저, 스마트폰 ..)는 이 유니크하고 디바이스 독립적인 우주의 투영일 뿐이다. 이벤트 핸들링도 다르지 않으며 이 “추상화된 세계” 안에서 일어난다. 이벤트가 최초에 DOM에서 왔는지 네이티브에서 왔는지는 중요하지 않다.

주석: 원글 표현이 너무 무슨 마블코믹스같음.. projection까지 나오니까 물리학느낌

이벤트 핸들링의 경우에, “listening, normalizing & re-emitting” 페이즈는 실제 이벤트들과 컴포넌트들을 추상화된 카운터파트로 변환하는 목적으로 존재한다. 이 페이즈는 컴포넌트로 부터 온 네이티브 이벤트를 잡아내서 리액트가 topLevelType이라 칭하는 녀석으로 바꾼다. (이놈은 Fiber와 관련되어있다.) 결과적으로, 네이티브 이벤트와 컴포넌트 자신들은 효과적으로 아래에 깔린 이벤트 프로세싱 이벤트와 분리되며, 어떠한 핸들러도 “실제” 환경에 설치되지 않는다: 모든 것은 가상 DOM 안에서 일어난다.

.. 다음에 계속


Minchang Kim
Minchang Kim
웹/앱 개발자 김민창입니다! 좋은 하루 되세요!