>  기사  >  위챗 애플릿  >  미니 프로그램의 듀얼 스레드 모델에 대한 심층 분석

미니 프로그램의 듀얼 스레드 모델에 대한 심층 분석

青灯夜游
青灯夜游앞으로
2022-01-30 09:00:314121검색

이 기사는 WeChat 미니 프로그램의 듀얼 스레드 모델을 이해하는 데 도움이 될 것입니다. 미니 프로그램의 듀얼 스레드 모델이 무엇인지 이야기해 보겠습니다. 애플릿이 브라우저의 스레딩 모델을 사용하지 않고 듀얼 스레딩 모델을 사용하는 이유는 무엇입니까? 모든 사람에게 도움이 되기를 바랍니다.

미니 프로그램의 듀얼 스레드 모델에 대한 심층 분석

WeChat 애플릿 개발 경험이 있는 친구들은 모두 "이중 스레드 모델"의 개념을 알아야 합니다. 이 기사에서는 이중 스레드 모델에 대한 몇 가지 대중적인 과학 지식을 간략하게 요약합니다. 실수, 정정해주세요.

저는 "미니 프로그램·클라우드 개발" 팀에서 일했습니다. 일부 외부 교육 및 기술 공유에서 "WeChat Mini 프로그램과 웹 사이트의 주요 기술적 차이점은 무엇입니까?"라는 질문을 자주 받았습니다. 프로그래밍 언어 및 패러다임 측면에서 소규모 프로그램 개발은 웹 프런트엔드 개발과 매우 유사하지만(예를 들어 둘 다 HTML/CSS와 매우 유사한 JavaScript 언어인 WXML/WXSS를 사용합니다.) 직접 사용하지는 않습니다. 네이티브 프론트엔드 기술. [관련 학습 권장 사항: 미니 프로그램 개발 튜토리얼]

WeChat에서 호스팅되는 미니 프로그램은 웹 웹사이트와 비교하여 미니 프로그램이 WeChat 앱 자체에 보안 위험을 초래하지 않도록 보안, 성능 및 기타 요소를 고려해야 합니다. , 네이티브 애플리케이션에 가까운 성능과 사용자 경험을 달성하려고 노력합니다. 이것이 작은 프로그램이 브라우저의 스레드 모델을 직접 사용하지 않고 스스로 듀얼 스레드 모델을 구축해야 하는 두 가지 주요 이유입니다.

그렇다면 작은 프로그램의 듀얼 스레드 모델은 무엇일까요?

새로운 개념이나 기술을 이해하는 가장 좋은 방법은 참조를 제공하는 것입니다. 따라서 작은 프로그램의 스레딩 모델을 이해하려면 먼저 브라우저의 스레딩 모델을 어느 정도 이해해야 합니다.

브라우저는 다중 프로세스입니다

아마 모든 프론트엔드 엔지니어가 업계에 처음 입문했을 때 면접관으로부터 "프론트엔드의 단일 스레드를 어떻게 이해합니까?"라는 질문을 여러 번 받았을 것입니다. 프론트 엔드의 핵심 기술 중 하나인 스레딩은 JS 단일 스레드의 작동을 완전히 이해하고 숙달하는 것이 프론트 엔드 엔지니어에게 가장 기본적인 요구 사항입니다. 그러나 많은 초보자가 쉽게 빠지는 오해가 있습니다. "JavaScript 단일 스레드"를 "브라우저 단일 스레드"로 잘못 이해하는 것입니다.

실제로 브라우저의 내부 아키텍처는 매우 복잡하지만 GUI 렌더링 스레드와 JavaScript 논리 스크립트 스레드를 처리하기 위해 상호 배타적 및 차단 관리 모델을 사용하므로 일부 개발자 사이에 오해가 발생했습니다.

Chrome 브라우저를 예로 들어 보겠습니다. 오른쪽 상단에 있는 설정 버튼을 클릭한 다음 "추가 도구"->"작업 관리자"를 입력하면 다음과 같은 팝업 창이 나타납니다. 브라우저 프로세스, 네트워크 프로세스, GPU 프로세스 등을 포함한 프로세스는 모두 공통 프로세스입니다.

참고

위 그림에는 두 개의 탭 프로세스가 있습니다. Chrome은 각 탭 페이지마다 독립적인 렌더링 프로세스(렌더러 프로세스)를 엽니다. 각 프로세스 간의 리소스(CPU, 메모리 등)와 동작(UI), 로직. 등)은 서로 공유되지 않으므로 한 탭 페이지가 충돌하더라도 다른 탭 페이지에는 영향을 미치지 않습니다.

각 탭 프로세스에서 브라우저는 해당 스레드에 다양한 작업을 넘겨줍니다. 예를 들어 GUI 렌더링 스레드는 HTML을 시각적 UI로 렌더링하는 일을 담당하고 JavaScript 엔진 스레드는 JavaScript 코드 논리를 구문 분석하고 실행하는 일을 담당합니다. 타이밍 트리거링 프로그래머 스레드는 setTimeout/setInterval 타이머 등을 처리합니다.

한 가지 더, 혼동하기 쉬운 부분이 있습니다. 사실 setTimeout/setInterval은 JavaScript 언어의 일부가 아니라 런타임(원래는 브라우저, 이후에는 Node.js)에서 제공하는 기능입니다. 도 지원합니다).

GUI 렌더링 스레드와 JavaScript 엔진 스레드는 상호 배타적입니다. JavaScript는 실행 중에 UI 렌더링을 차단합니다. 스크립트 실행 시간이 너무 길어도 오랫동안 페이지가 응답하지 않아 충돌이 발생합니다. 이러한 스레드 간 상호 배제 및 차단 스레드 관리 방식으로 인해 일부 프런트엔드 개발자는 브라우저가 단일 스레드라고 생각하게 되는 것이 바로 GUI 렌더링 스레드와 JavaScript 엔진입니다.

그럼 JavaScript는 왜 단일 스레드로 설계되었나요?

JavaScript의 창시자는 이 언어를 만드는 데 10일 밖에 걸리지 않았습니다. 처음에 그의 아이디어는 사용자 상호 작용, DOM 작업 등을 처리하기 위해 브라우저에 몇 가지 간단한 스크립트 논리를 제공하는 것이었으므로 디자인은 다음 두 가지 사항을 따라야 합니다.

간단한 구문

  • 간단한 작동 메커니즘.

  • 구문 측면에서 JavaScript는 Java에서 차용했지만 유형 선언, 모듈 시스템(나중에 추가됨) 등과 같은 많은 복잡한 설정을 제거합니다.

    실행 메커니즘 측면에서 JavaScript는 Java와 같은 멀티스레딩 기능을 제공하지 않습니다. 주된 이유는 멀티스레드 DOM 작업으로 인한 UI 충돌을 방지하는 것입니다. 예를 들어 여러 스레드가 동일한 DOM을 동시에 작동하는 경우 최종 UI 효과를 생성하는 데 어떤 스레드가 사용되는지 브라우저는 어떻게 결정해야 합니까? 이는 고전적인 스레드 안전성(스레드 동기화라고도 함) 문제입니다. 다중 스레드 프로그래밍 분야에는 잠금 메커니즘 추가와 같은 많은 솔루션이 있지만 이는 간단하고 사용하기 쉬운 디자인과 달리 더 복잡해집니다. JavaScript의 원래 의도에 어긋납니다.

    이것은 또한 GUI 렌더링 스레드와 JavaScript 엔진 스레드가 상호 배타적인 이유를 설명합니다. JavaScript 코드에는 DOM을 수정할 수 있는 권한이 있습니다.

    JavaScript 코드가 실행되면 GUI 렌더링 스레드가 일시 중지되고 JavaScript 엔진 스레드가 유휴 상태가 될 때까지 기다린 후 실행됩니다. 이는 렌더링 중에 JavaScript에 의한 DOM의 반복적인 수정으로 인한 불필요한 렌더링 부담을 방지하기 위한 것입니다. JavaScript 코드 실행이 완료될 때까지 기다리는 상호 배타적 모드를 사용하면 렌더링이 최종 실행 결과가 되도록 할 수 있습니다. 따라서 브라우저의 유휴 시간은 웹 사이트 성능을 측정하는 중요한 지표 중 하나가 되었습니다. 유휴 시간은 대부분 JavaScript 로직이 집약적이지 않고 이 경우 브라우저가 사용자 상호 작용에 응답할 수 있음을 나타냅니다. 더 빠르고 원활하게 동작합니다.

    React Fiber는 유휴 시간을 사용하여 샤딩 작업을 처리합니다.

    나중에 HTML5에서는 여러 스레드에서 JavaScript 코드를 실행할 수 있는 기능을 제공하는 Web Worker가 도입되었습니다. 그러나 다른 프로그래밍 언어와 달리 Worker 스레드는 메인 스레드와 병렬이 아니라 일종의 마스터-슬레이브입니다. -스레드 모델.

    Worker 내의 JavaScript 코드는 DOM을 작동할 수 없으며 thread-safe로 이해될 수 있습니다. 이것을 기억하세요. 이는 나중에 작은 프로그램의 듀얼 스레드 모델을 위한 중요한 기반이 됩니다.

    그렇다면 WeChat 미니 프로그램은 왜 브라우저의 스레딩 모델을 직접 사용하지 않는 걸까요? 이를 위해서는 제품 및 기술 측면에서 미니 프로그램과 웹사이트의 차이점을 비교해야 합니다.

    미니 프로그램이 브라우저의 스레딩 모델을 사용하지 않는 이유

    처음 미니 프로그램 개발을 접했을 때 웹에 비해 기능이 약하고 Vue에 비해 구문이 지나치게 단순한 것이 " 싫은" 경우가 많았습니다. 그 당시 나는 미니 프로그램이 엄청난 사용자 수에 의존하는 위챗의 기술 독점이라고 느낄 뻔했다.

    그러나 기술과 제품에 대한 지속적인 심층적 이해로 인해 미니 프로그램에 대한 나의 태도도 "혐오"에서 감탄으로 바뀌었습니다. 왜냐하면 미니 프로그램의 제품 포지셔닝을 완전히 이해한 후 Double The Thread 모델을 발견했기 때문입니다. 소규모 프로그램과 같은 제품 시나리오에 최적의 솔루션입니다. 그렇다면 미니프로그램은 어떤 제품일까요?

    미니 프로그램의 호스트는 WeChat이지만 미니 프로그램 버전의 반복은 독립적이며 업그레이드와 업데이트는 호스트에 의존하지 않습니다. 이는 웹 사이트와 동일합니다. 즉, 미니 프로그램은 웹의 장점 중 일부를 상속하지만 웹은 아닙니다. 현재 웹 관련 기술은 매우 포괄적이며 3D 지도, 게임 등과 같은 일부 매우 큰 응용 프로그램을 호스팅할 수 있습니다.

    미니 프로그램의 포지셔닝은 WeChat의 모든 웹 기능을 추구하지 않기 때문에 기능면에서 확실히 웹보다 열등합니다. 기본 기능, 시스템 수준 및 WeChat 생태계 API 등과 같이 WeChat에서 제공하는 일부 기본 기능이 있습니다.

    또한, "미니 프로그램-위챗"의 관계는 "웹사이트-브라우저"의 관계와는 다릅니다. 전자는 CodePen 및 JSFiddler와 같은 온라인 프로그래밍 플랫폼에서 각 프로그램 케이스(이하 케이스)에 더 가깝습니다. 클래스 내 플랫폼 관계라고 함).

    기술적인 관점에서 볼 때, 플랫폼의 핵심 고려 사항 중 하나는 케이스에 대한 충분한 기능을 제공하면서 케이스의 논리가 플랫폼의 보안을 위협하지 않도록 보장하는 것입니다. CodePen의 개인 정보를 얻기 위해 CodePen에 프로그램을 작성할 수 있다면 아마도 CodePen이 다음 날 충돌하여 모든 직원을 해고할 수도 있습니다. 이러한 제품 톤에서 기술 선택이 이루어지면 다음 단계는 건축가와 프로그래머의 작업입니다.

    CodePen을 예로 들어 이러한 프로그래밍 플랫폼을 설계하라는 요청을 받는다면 어떤 기술을 사용하시겠습니까?

    모든 웹 기능을 iframe 내에서 사용할 수 있기 때문에 가장 먼저 iframe을 사용하는 것이 좋을 것 같습니다. 실제로 CodePen은 프로그램 효과를 표시하기 위해 iframe을 사용하지만 실행을 위해 입력 JavaScript 코드를 iframe에 완전히 복사하지는 않습니다. 대신 코드는 iframe에 삽입되기 전에 컴파일 프로세스를 거칩니다. 이것의 출발점은 주로 보안 고려 사항을 기반으로 하며, 컴파일 과정에서 일부 위험한 코드를 제거하고, 둘째, TypeScript와 같은 플랫폼에서 더 많은 언어를 지원할 수도 있습니다. 물론 성능 문제도 있습니다. 성능 문제는 iframe의 일반적인 문제이므로 자세히 설명하지 않겠습니다.

    그러므로 iframe을 사용해야 할 뿐만 아니라 추가적인 JavaScript 컴파일러도 도입해야 합니다. CodePen은 각 경우의 JavaScript 코드가 스레드로부터 안전한지 확인해야 합니다. 가장 기본적인 것은 프로그램이 CodePen 웹 사이트의 DOM을 작동하지 못하도록 하는 것입니다. 이를 달성하는 방법에는 두 가지가 있습니다.

    • One은 Web Worker입니다.

    • 다른 하나는 Shadow DOM을 사용하는 것입니다.

    Web Worker는 스레드로부터 안전합니다. Worker 내의 JavaScript 코드는 Window 및 Document 개체를 얻을 수 없으므로 DOM을 작동할 수 없습니다. 또한 Worker의 스레드 안전 기능으로 인해 Worker 내의 코드는 실행 중에 외부 GUI 렌더링 스레드를 차단하지 않으며 두 스레드가 병렬로 실행될 수 있습니다.

    Shadow DOM은 웹 구성 요소 사양의 일부입니다. ShadowRoot 모드를 closed로 설정하면 ShadowRoot 노드를 얻을 수 없으므로 내부 DOM을 조작할 수 없습니다.

    둘을 비교하면 Shadow DOM은 Web Worker보다 호환성이 떨어지며 아직 대규모 사용에는 거리가 멀기 때문에 Web Worker 솔루션이 더 현실적입니다.

    이것은 간단한 2-스레드 모델을 형성합니다. 작업자 스레드는 계산을 담당하고 postMessage를 통해 결과를 메인 스레드에 전달하며 메인 스레드는 렌더링을 담당합니다.

    그러나 이 모델은 심각한 성능 문제를 가지고 있습니다. Web Worker는 컴퓨팅 소비 외에도 메인 스레드와의 통신 프로세스도 성능에 매우 심각한 영향을 미칩니다.

    그렇다면 성능을 고려하고 좋은 사용자 경험을 보장하면서 Web Worker와 동일한 스레드 안전성을 달성할 수 있는 방법이 있을까요? 이것이 WeChat 애플릿에 듀얼 스레드 모델을 사용하는 주요 목적입니다.

    안전하고 효율적인 듀얼 스레드 모델

    앞서 CodePen과 같은 프로그래밍 플랫폼을 비유로 사용했지만 미니 프로그램과 CodePen의 기술 요구 사항은 정확히 동일하지 않습니다. 주요 차이점은 미니 프로그램이 지원할 필요가 없다는 것입니다. 모든 HTML 태그는 제한된 수의 UI 구성 요소만 제공됩니다. 미니 프로그램의 제품 포지셔닝에 따라 미니 프로그램의 주요 기술 요구 사항을 다음과 같이 요약할 수 있습니다. (모든 새로운 기술이나 아키텍처는 특정 문제를 해결하기 위해 설계되었으므로 미니 프로그램의 주요 기술 요구 사항을 이해해야 합니다.)

    • UI 구성 요소 유형을 제한하여 지정된 몇 가지 구성 요소만 선언하도록 허용하세요

      미니 프로그램은 구성 요소를 선언할 때 기본 HTML 태그를 사용하지 않고 대신 WeChat에서 제공하는 여러 기본 구성 요소만 사용할 수 있습니다. 물론 구성 요소를 사용자 정의할 수도 있지만 이는 조합을 통해서도 달성됩니다. 내장된 기본 구성 요소 중 하나입니다.

    • 논리적 스레드 안전성을 보장하고 UI 구성요소의 직접적인 조작을 허용하지 않습니다.

      미니 프로그램이 UI를 업데이트하는 방식은 Vue/React와 같은 MVVM 프레임워크와 유사합니다. JavaScript 코드는 DOM을 직접 작동할 수 없습니다. 실제로 미니 프로그램에는 DOM 개념이 없지만 상태(setState)를 업데이트하여 UI가 비동기적으로 업데이트됩니다. 이 프로세스에서는 VDOM과 효율적인 diff 알고리즘이 사용됩니다(이 두 가지 사항은 우리가 다룰 내용이 아닙니다. 토론, 수업 후 직접 검색할 수 있습니다) 관련 정보).

    • WeChat에 의존하지 않고 온라인으로 업데이트 가능

      미니 프로그램의 호스트는 WeChat입니다. 순수 Native를 사용하여 구현된 경우 미니 프로그램의 버전 업데이트는 WeChat에 의존하고 함께 출시되어야 합니다. WeChat 코드는 확실히 작동하지 않습니다. 순수 웹 구현이라면 보안과 성능을 보장하기 어려울 것입니다.

      미니 프로그램은 웹처럼 클라우드에서 리소스를 호스팅하고 동시에 독립적으로 업데이트할 수 있어야 하며 충분한 보안과 성능을 보장할 수 있어야 합니다. 그래서 결국 애플릿은 혼합 아키텍처 모델을 채택했습니다. Webview를 사용하여 UI를 렌더링하고 Web Worker와 유사한 독립 스레드를 사용하여 로직을 실행합니다이것이 듀얼 스레드 모델입니다.

    • 사용자 경험을 보장하려면 성능을 최대한 개선해야 합니다

      앞서 언급한 Web Worker 기반의 단순한 듀얼 스레드 모델의 성능이 큰 문제입니다. 프로그램은 Web Worker 하위 스레드를 사용하지 않으며 상대적으로 좋은 성능을 보장할 수 있는 독립적인 "메인 스레드"입니다.

    렌더링 스레드와 로직 스레드

    애플릿의 이중 스레드는 렌더링 스레드와 로직 스레드를 의미하며, 이 두 스레드는 각각 UI 렌더링과 JavaScript 코드 실행을 담당합니다. 아래 그림과 같이:

    렌더링 스레드는 Webview를 사용하여 UI를 렌더링합니다. Webview는 JavaScript를 실행할 수 있는 기능을 갖춘 완전한 브라우저와 유사한 운영 환경입니다. 그러나 애플릿은 논리 스크립트를 Webview에 넣어 실행하는 것이 아니라 논리 계층을 Webview와 병렬 스레드로 분리하여 JavaScript를 제공합니다. 엔진은 코드, iOS의 JavaScriptCore, Android의 JsCore 환경 및 Tencent의 X5 커널에서 제공하는 nwjs IDE 도구를 실행합니다.

    논리 스레드는 JavaScript만 실행할 수 있는 샌드박스 환경입니다. DOM 작업과 관련된 API를 제공하지 않으므로 UI를 직접 조작할 수 없으며 setData를 통해 데이터를 업데이트하여 UI를 비동기적으로 업데이트할 수 있습니다.

    이벤트 기반 통신 방식

    위 그림의 렌더링 스레드와 로직 스레드 간의 통신 방식에 주목하세요. Vue/React와는 다르게 애플릿의 렌더링 계층과 로직 계층 간의 통신입니다. 데이터나 이벤트는 사용자 간에 직접 전송되지만 중개자로서 Native에 의해 전달됩니다.

    전체 프로세스는 일반적인 이벤트 중심 모델입니다.

      렌더링 레이어(뷰 레이어라고도 함)는 사용자와의 상호 작용을 통해 특정 이벤트를 트리거합니다.
    • 그런 다음 이벤트가 전달됩니다.
    • 논리 계층은 일련의 논리적 처리, 데이터 요청, 인터페이스 호출 및 기타 동작을 통해 처리된 데이터를 렌더링 계층으로 전달합니다.
    • 마지막 렌더링 계층은 데이터를 시각적 개체로 렌더링합니다. UI.
    • 이 데이터 기반 UI 모델은 이제 프런트엔드 프로그래밍 분야에서 더욱 존경받는 프로그래밍 패러다임입니다. 5년 이상의 개발 경험을 가진 프런트엔드 개발자라면 분명히 그렇게 되리라 믿습니다. 이 모델을 처음 접했을 때 약간의 불편함이 있었습니다. 이전에는 JavaScript를 사용하여 DOM을 작동하는 것이 거의 "업계 규칙"이었기 때문입니다. 심지어 DOM을 시작하기 위한 책, 블로그, 교과서도 많이 있습니다. DOM 작업으로 시작하는 프런트 엔드는 실제로 약간 오래된 것 같습니다.

    한편으로는 로직과 렌더링을 분리하는 이 스레드 분할 모드는 논리적 스레드 샌드박스에서 실행되는 JavaScript 코드가 스레드로부터 안전한지 확인할 수 있는 반면, 렌더링 스레드의 계산량이 매우 적기 때문에, 사용자 상호 작용 동작이 안전하도록 보장하여 사용자 경험을 향상시킵니다.

    일반적으로 브라우저의 스레드 모델과 비교하여 미니 프로그램의 듀얼 스레드 모델은 성능과 보안 측면에서 Web Worker와 동일한 스레드 안전성을 달성하면서 Web Worker의 우려되는 성능을 해결하거나 피합니다. 여러 각도에서 개선이 이루어졌습니다.

    이중 스레드 모드는 브라우저의 기존 프로세스 및 스레드 관리 모델

    에 의해 제한되는 작은 프로그램의 특정 시나리오 내에서 향상된 아키텍처 솔루션이라고 요약할 수 있습니다. 요약

    내 생각에 프로그래머의 핵심 역량과 경쟁력은 특정 언어나 프레임워크의 API를 완전히 이해하는 것이 아니라, 이러한 언어와 프레임워크의 기본 원리에 대한 지식입니다. 소규모 프로그램 개발자의 경우 직장에서 기술적인 문제에 직면했을 때의 해결책은 종종 기본 원칙을 기반으로 합니다(더 간단하게 말하면 취업 면접을 찾을 때 아무도 소규모 프로그램의 구문에 대해 묻지 않습니다).

    미니 프로그램의 듀얼 스레드 모델의 배경, 디자인, 커뮤니케이션을 이해함으로써 모두가 미니 프로그램의 기본 아키텍처에 대해 더 깊이 이해할 수 있기를 바랍니다. 후속 작업에서도 유사한 시나리오가 필요합니다. 물론, 작은 프로그램의 듀얼 스레드 모델을 이해하는 것이 유일한 목표는 아닙니다. 이 지식은 주로 성능 측면에서 일상적인 개발 작업에 어느 정도 영감을 줄 수 있습니다.

      보장하면서 간단한 구조를 사용하십시오.
    • JavaScript 로직의 복잡성을 줄이세요.
    • setData 호출 빈도와 전달되는 데이터 양을 줄여보세요.
    • 더 많은 프로그래밍 관련 지식을 보려면
    프로그래밍 비디오

    를 방문하세요! !

위 내용은 미니 프로그램의 듀얼 스레드 모델에 대한 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 cnblogs.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제