setState를 호출할 때 어떤 일이 일어난다고 생각하시나요?{ clicked: true }로 컴포넌트를 다시 렌더링하고, 반환된 <h1>Thanks</h1> 엘리먼트와 일치하도록 DOM을 업데이트합니다.this.setState()를 호출하고 있지, React DOM의 무언가를 호출하는 게 아닙니다. 그리고 저희의 React.Component 기본 클래스는 React 자체 내부에 정의되어 있습니다.React.Component 내부의 setState()는 어떻게 DOM을 업데이트할 수 있을까요?React.Component 클래스가 DOM 업데이트 로직을 포함하고 있다고 생각할 수 있습니다.this.setState()가 다른 환경에서는 어떻게 작동할까요? 예를 들어, React Native 앱의 컴포넌트들도 React.Component를 확장합니다. 위에서 한 것처럼 this.setState()를 호출하지만, React Native는 DOM 대신 Android와 iOS 네이티브 뷰와 함께 작동합니다.this.setState()를 호출할 수 있게 해줍니다. 하지만 둘 다 DOM과는 작동하지 않습니다.React.Component는 상태 업데이트 처리를 플랫폼별 코드에 위임합니다. 이것이 어떻게 일어나는지 이해하기 전에, 패키지가 어떻게 분리되어 있는지, 그리고 왜 그런지 더 깊이 파고들어 봅시다.react 패키지 내부에 있다는 일반적인 오해가 있습니다. 이것은 사실이 아닙니다.react-dom, react-dom/server, react-native, react-test-renderer, react-art는 렌더러의 몇 가지 예입니다 (그리고 저희는 자신만의 렌더러를 만들 수 있습니다).react 패키지가 어떤 플랫폼을 대상으로 하든 유용한 이유입니다. React.Component, React.createElement, React.Children 유틸리티 및 (결국) Hooks와 같은 모든 내보내기는 대상 플랫폼과 무관합니다. React DOM, React DOM Server 또는 React Native를 실행하든, 저희의 컴포넌트는 동일한 방식으로 이들을 가져오고 사용합니다.ReactDOM.render()와 같은 플랫폼별 API를 노출하여 React 계층을 DOM 노드에 마운트할 수 있게 해줍니다. 각 렌더러는 이와 같은 API를 제공합니다. 이상적으로, 대부분의 컴포넌트는 렌더러에서 아무것도 가져올 필요가 없어야 합니다. 이는 이들을 더 이식 가능하게 유지합니다.react-dom과 같이 한 번에 하나의 렌더러만 필요합니다.)react 패키지가 저희에게 React 기능을 사용하게만 해주지만, 이들이 어떻게 구현되는지는 알지 못한다는 것입니다. 렌더러 패키지 (react-dom, react-native 등)는 React 기능과 플랫폼별 로직의 구현을 제공합니다. 그 코드의 일부는 공유됩니다 ("reconciler")이지만 이는 개별 렌더러의 구현 세부 사항입니다.react와 react-dom 패키지 모두를 업데이트해야 하는 이유를 알고 있습니다. 예를 들어, React 16.3이 Context API를 추가했을 때, React.createContext()는 React 패키지에 노출되었습니다.React.createContext()는 실제로 context 기능을 구현하지 않습니다. 구현은 React DOM과 React DOM Server 사이에서 다를 필요가 있습니다. 따라서 createContext()는 몇 가지 평범한 객체를 반환합니다:<MyContext.Provider> 또는 <MyContext.Consumer>를 사용할 때, 이들을 처리하는 방법을 결정하는 것은 렌더러입니다. React DOM은 한 가지 방식으로 context 값을 추적할 수 있지만, React DOM Server는 다르게 할 수 있습니다.react를 16.3+로 업데이트했지만 react-dom을 업데이트하지 않았다면, 특수한 Provider와 Consumer 타입을 아직 인식하지 못하는 렌더러를 사용하게 됩니다. 이것이 이전 react-dom이 이 타입들이 유효하지 않다고 말하며 실패하는 이유입니다.react 패키지가 흥미로운 것을 포함하지 않으며, 구현이 react-dom, react-native 등과 같은 렌더러에 있다는 것을 알고 있습니다. 하지만 이것이 저희의 질문에 답하지는 않습니다. React.Component 내부의 setState()는 어떻게 올바른 렌더러와 "대화"할까요?updater라고 불립니다. 이것은 저희가 설정할 무언가가 아닙니다 — 오히려 React DOM, React DOM Server 또는 React Native가 저희 클래스의 인스턴스를 생성한 직후에 설정하는 것입니다:this.setState()가 React 패키지에 정의되어 있음에도 불구하고 DOM을 업데이트할 수 있는 비법입니다. 이것은 this.updater를 읽으며, 이는 React DOM에 의해 설정되었고, React DOM이 업데이트를 예약하고 처리하도록 합니다.useState는 어떻게 "무엇을 해야 할지 알까"? 보통 사람들의 생각은 기본 React.Component 클래스의 this.setState()보다 더 "마법 같다"는 것입니다.setState() 구현은 처음부터 환상이었습니다. 이것은 현재 렌더러에 호출을 전달하는 것 외에는 아무것도 하지 않습니다. 그리고 useState Hook은 정확히 동일한 일을 합니다.updater 필드 대신, Hooks는 "dispatcher" 객체를 사용합니다. React.useState(), React.useEffect() 또는 다른 내장 Hook을 호출할 때, 이 호출들은 현재 dispatcher로 전달됩니다.react-dom과 같은 렌더러가 저희가 Hooks를 호출하는 동일한 react 패키지에 접근해야 하는 이유입니다. 그렇지 않으면, 저희의 컴포넌트가 dispatcher를 "보지" 못할 것입니다! 이는 동일한 컴포넌트 트리에 React의 여러 복사본이 있을 때 작동하지 않을 수 있습니다. 하지만 이는 항상 모호한 버그로 이어졌으므로 Hooks는 저희가 비용을 치르기 전에 패키지 중복을 해결하도록 강제합니다.__currentDispatcher 이름에 대해 거짓말을 했지만 React 저장소에서 실제 이름을 찾을 수 있습니다.) 예를 들어, React DevTools는 JavaScript 스택 추적을 캡처하여 Hooks 트리를 내부 검사하기 위해 특수 목적의 dispatcher를 사용합니다. Don’t repeat this at home.updater 필드와 __currentDispatcher 객체 모두 의존성 주입이라고 불리는 일반적인 프로그래밍 원칙의 형태입니다. 두 경우 모두, 렌더러는 setState와 같은 기능의 구현을 일반 React 패키지에 "주입"하여 저희의 컴포넌트를 더 선언적으로 유지합니다.this.setState() 또는 useState()가 어떻게 무엇을 해야 할지 아는지 궁금해하셨다면, 이것이 도움이 되기를 바랍니다.아직 댓글이 없습니다.
첫 번째 댓글을 작성해보세요!