>  기사  >  백엔드 개발  >  순수 Python 웹 프레임워크 설계

순수 Python 웹 프레임워크 설계

DDD
DDD원래의
2024-09-19 06:21:33642검색

웹 개발은 프로그래밍의 가장 인기 있는 사용 사례 중 하나입니다. Python은 세계에서 가장 인기 있는 프로그래밍 언어 중 하나입니다. 그렇다면 Python으로 웹 앱을 구축할 수 없는 이유는 무엇일까요?

UI를 만드는 것은 간단해야 하지만 팀에 훌륭한 엔지니어가 있더라도 새로운 언어와 도구를 배우는 데 드는 오버헤드는 큰 장벽이었습니다. 종종 UI를 만드는 것이 실제 작업보다 어려울 수 있습니다!

TLDR

내부적으로 Reflex 앱은 React 프런트엔드 앱과 FastAPI 백엔드 앱으로 컴파일됩니다. UI만 Javascript로 컴파일됩니다. 모든 앱 로직과 상태 관리는 Python에 유지되며 서버에서 실행됩니다. Reflex는 WebSocket을 사용하여 프런트엔드에서 백엔드로 이벤트를 보내고, 백엔드에서 프런트엔드로 상태 업데이트를 보냅니다.

기존 Python 솔루션

Python으로 앱을 구축하는 방법은 이미 몇 가지가 있었지만 그 어느 것도 우리 요구 사항에 맞지 않았습니다.

한편에는 프로덕션 수준의 웹 앱을 구축하는 데 적합한 Django 및 Flask와 같은 프레임워크가 있습니다. 하지만 백엔드만 처리합니다. 여전히 JavaScript와 프런트엔드 프레임워크를 사용해야 할 뿐만 아니라 프런트엔드와 백엔드를 연결하기 위해 많은 상용구 코드를 작성해야 합니다.

반면에 Dash 및 Streamlit과 같은 순수 Python 라이브러리는 소규모 프로젝트에 적합할 수 있지만 특정 사용 사례로 제한되며 전체 웹 앱을 구축할 수 있는 기능과 성능이 없습니다. 앱의 기능과 복잡성이 증가함에 따라 프레임워크의 한계에 도달하게 될 수 있으며, 이 시점에서 프레임워크에 맞게 아이디어를 제한하거나 프로젝트를 폐기하고 "실제 웹 프레임워크"를 사용하여 다시 빌드해야 합니다.

저희는 시작하기 쉽고 직관적이면서 모든 앱을 지원할 수 있는 유연하고 강력한 프레임워크를 만들어 이러한 격차를 해소하고 싶습니다.

반사의 목표

  • 순수 Python: 모든 것에 하나의 언어를 사용하세요.
  • 쉬운 시작: 웹 개발 경험 없이도 쉽게 아이디어를 구축할 수 있습니다.
  • 완벽한 유연성: 웹 앱은 기존 웹 프레임워크의 사용자 정의 가능성 및 성능과 일치해야 합니다.
  • 배터리 포함: 프런트엔드부터 백엔드, 배포까지 전체 스택을 처리합니다.

이제 이러한 목표를 달성하기 위해 Reflex를 어떻게 구축했는지 살펴보겠습니다.

반사 아키텍처

풀스택 웹 앱은 프런트엔드와 백엔드로 구성됩니다. 프런트엔드는 사용자 인터페이스이며 사용자의 브라우저에서 실행되는 웹페이지 역할을 합니다. 백엔드는 논리 및 상태 관리(예: 데이터베이스 및 API)를 처리하고 서버에서 실행됩니다.

기존 웹 개발에서는 일반적으로 두 개의 별도 앱이 있으며, 서로 다른 프레임워크나 언어로 작성되는 경우가 많습니다. 예를 들어 Flask 백엔드와 React 프런트엔드를 결합할 수 있습니다. 이 접근 방식을 사용하면 두 개의 별도 앱을 유지 관리해야 하고 결국 프런트엔드와 백엔드를 연결하기 위해 많은 상용구 코드를 작성하게 됩니다.

우리는 단일 코드베이스에서 프런트엔드와 백엔드를 모두 정의하고 모든 작업에 Python을 사용하여 Reflex에서 이 프로세스를 단순화하고자 합니다. 개발자는 낮은 수준의 구현 세부 사항이 아닌 앱의 논리에만 관심을 가져야 합니다.

Designing a Pure Python Web Framework

프런트엔드

우리는 Reflex 앱이 최종 사용자에게 기존 웹 앱처럼 보이고 느껴지면서도 개발자가 쉽게 구축하고 유지 관리할 수 있기를 원합니다. 이를 위해 우리는 성숙하고 대중적인 웹 기술을 기반으로 구축했습니다.

앱을 반사적으로 실행하면 Reflex는 프런트엔드를 단일 페이지 Next.js 앱으로 컴파일하고 브라우저에서 액세스할 수 있는 포트(기본적으로 3000)에 제공합니다.

프런트엔드의 임무는 앱의 상태를 반영하고 사용자가 UI와 상호작용할 때 백엔드로 이벤트를 보내는 것입니다. 프런트엔드에서는 실제 로직이 실행되지 않습니다.

구성요소

Reflex 프런트엔드는 함께 구성하여 복잡한 UI를 만들 수 있는 구성 요소를 사용하여 구축됩니다. HTML과 Python을 혼합한 템플릿 언어를 사용하는 대신 Python 함수를 사용하여 UI를 정의합니다.

내부적으로는 구성 요소가 React 구성 요소로 컴파일됩니다.

많은 핵심 구성 요소는 인기 있는 React 구성 요소 라이브러리인 Radix를 기반으로 합니다. 또한 그래프 작성, 데이터 테이블 등을 위한 다른 많은 구성 요소도 있습니다.

우리가 React를 선택한 이유는 거대한 생태계를 갖춘 인기 라이브러리이기 때문입니다. 우리의 목표는 웹 생태계를 재현하는 것이 아니라 Python 개발자가 접근할 수 있도록 하는 것입니다.

또한 필요한 구성 요소가 없는 경우 사용자가 자신의 구성 요소를 가져올 수도 있습니다. 사용자는 자신의 React 구성 요소를 래핑한 다음 다른 사람이 사용할 수 있도록 게시할 수 있습니다. 시간이 지남에 따라 우리는 사용자가 다른 사람이 만든 구성 요소를 쉽게 찾고 사용할 수 있도록 타사 구성 요소 생태계를 구축할 것입니다.

스타일링

저희는 Reflex 앱이 처음부터 보기 좋게 보이도록 하는 동시에 개발자가 앱의 모양을 완전히 제어할 수 있도록 하고 싶었습니다.

앱 전체에 어두운 모드, 강조 색상 등 높은 수준의 스타일 옵션을 설정하여 앱에 통일된 모양과 느낌을 줄 수 있는 핵심 테마 시스템이 있습니다.

이 외에도 CSS의 모든 기능을 사용하여 Reflex 구성 요소의 스타일을 지정할 수 있습니다. 우리는 Emotion 라이브러리를 활용하여 "CSS-in-Python" 스타일을 허용하므로 모든 CSS 소품을 구성 요소에 키워드 인수로 전달할 수 있습니다. 여기에는 값 목록을 전달하는 반응형 소품이 포함됩니다.

백엔드

Reflex에서는 프런트엔드만 Javascript로 컴파일되어 사용자 브라우저에서 실행되는 반면, 모든 상태와 로직은 Python에 유지되고 서버에서 실행됩니다. 반사 실행 시 프런트엔드가 웹소켓을 통해 연결하는 FastAPI 서버(기본적으로 포트 8000)를 시작합니다.

모든 상태와 로직은 State 클래스 내에 정의됩니다.

상태는 vars이벤트 핸들러로 구성됩니다.

Vars는 시간이 지남에 따라 변경될 수 있는 앱의 모든 값입니다. 이는 State 클래스의 클래스 속성으로 정의되며 JSON으로 직렬화할 수 있는 Python 유형일 수 있습니다.

이벤트 핸들러는 사용자가 UI와 상호작용할 때 호출되는 State 클래스의 메서드입니다. 이는 Reflex에서 변수를 수정할 수 있는 유일한 방법이며, 버튼 클릭이나 텍스트 상자에 입력하는 등의 사용자 작업에 대한 응답으로 호출될 수 있습니다.

이벤트 핸들러는 백엔드에서 실행되므로 그 안에 있는 Python 라이브러리를 사용할 수 있습니다.

Designing a Pure Python Web Framework

이벤트 처리

일반적으로 웹앱을 작성할 때 프런트엔드와 백엔드를 연결하기 위해 상용구 코드를 많이 작성해야 합니다. Reflex를 사용하면 그런 걱정을 할 필요가 없습니다. 우리가 프론트엔드와 백엔드 간의 통신을 대신 처리해 드립니다. 개발자는 이벤트 핸들러 로직을 작성하기만 하면 되며, 변수가 업데이트되면 UI가 자동으로 업데이트됩니다.

이벤트 트리거

사용자는 버튼 클릭, 텍스트 상자에 입력, 요소 위로 마우스를 가져가는 등 다양한 방법으로 UI와 상호 작용할 수 있습니다. Reflex에서는 이를 이벤트 트리거라고 부릅니다.

이벤트 큐

프런트엔드에서는 대기 중인 모든 이벤트의 이벤트 대기열을 유지 관리합니다. 이벤트는 세 가지 주요 데이터로 구성됩니다.

  • 클라이언트 토큰: 각 클라이언트(브라우저 탭)에는 이를 식별하는 고유한 토큰이 있습니다. 이를 통해 백엔드가 업데이트할 상태를 알 수 있습니다.
  • 이벤트 핸들러: 상태에서 실행되는 이벤트 핸들러.
  • arguments: 이벤트 핸들러에 전달할 인수입니다.

이벤트가 발생하면 대기열에 추가됩니다.
한 번에 하나의 이벤트만 처리되도록 하는 처리 플래그가 있습니다. 이렇게 하면 상태가 항상 일관되고 두 개의 이벤트 핸들러가 동시에 상태를 수정하는 경쟁 조건이 발생하지 않습니다. UI를 차단하지 않고 백그라운드에서 이벤트를 실행할 수 있는 백그라운드 이벤트와 같은 예외가 있습니다.

이벤트 처리 준비가 완료되면 WebSocket 연결을 통해 백엔드로 전송됩니다.

상태 관리자

이벤트가 수신되면 백엔드에서 처리됩니다.

Reflex는 클라이언트 토큰과 해당 상태 간의 매핑을 유지하는 상태 관리자를 사용합니다. 기본적으로 상태 관리자는 단지 메모리 내 사전이지만 데이터베이스나 캐시를 사용하도록 확장될 수 있습니다. 프로덕션에서는 Redis를 상태 관리자로 사용합니다.

이벤트 처리

사용자 상태가 확보되면 다음 단계는 인수를 사용하여 이벤트 핸들러를 실행하는 것입니다.

상태 업데이트

이벤트 핸들러가 반환(또는 양보)할 때마다 상태 관리자에 상태를 저장하고 상태 업데이트를 프런트엔드에 보내 UI를 업데이트합니다.

상태가 커짐에 따라 성능을 유지하기 위해 Reflex는 내부적으로 이벤트 핸들러 중에 업데이트된 변수(더티 변수)를 추적합니다.
이벤트 핸들러의 처리가 완료되면 모든 더티 변수를 찾아 상태 업데이트를 생성하여 프런트엔드로 보냅니다.

새 상태를 상태 관리자에 저장한 다음 상태 업데이트를 프런트엔드에 보냅니다.
그러면 프런트엔드가 UI를 업데이트하여 새 상태를 반영합니다.

결론

이 글을 통해 Reflex가 내부적으로 어떻게 작동하는지에 대한 좋은 개요를 얻을 수 있기를 바랍니다. 상태 샤딩 및 컴파일러 최적화와 같은 기능을 통해 Reflex를 확장 가능하고 성능 좋게 만드는 방법을 공유하기 위해 더 많은 게시물이 나올 예정입니다.

위 내용은 순수 Python 웹 프레임워크 설계의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.