NiceGUI를 만나보세요 곧 여러분의 최애 파이썬 UI 라이브러리가 될 이유

NiceGUI를 만나보세요 곧 여러분의 최애 파이썬 UI 라이브러리가 될 이유
TILPosted On Jul 9, 202414 min read

사용자 정의 웹 앱을 쉽고 빠르게 만드세요

이미지

만나보세요, NiceGUI! 이 간단한 Python 기반 UI 프레임워크는 웹 브라우저나 데스크톱 앱에서 원활하게 작동합니다. 작은 웹 앱, 대시보드, 또는 로봇 프로젝트를 만들고 있는 중이던 중이든, NiceGUI는 쉬운 인터페이스와 다양한 기능으로 여러분을 도와줄 거예요.

이 글의 목표는 이 라이브러리의 장단점을 나열하고 어떻게 NiceGUI 앱을 만들고 배포할 수 있는지 보여줌으로써 여러분이 한 번 시도해보길 설득하는 것입니다. (이 게시물은 후원받은 것이 아니에요, 그냥 이 라이브러리를 좋아해서 쓴거에요 🙃)

Streamlit 대 NiceGUI: 왜 바꾸어야 할까요?

Streamlit은 대화형 앱을 만드는 데 좋지만, 이벤트 및 상태 처리가 어려울 수 있습니다. 특히 큰 프로젝트의 경우 더 그렇습니다. NiceGUI는 다릅니다. NiceGUI를 사용하면 추가적인 단계나 고난한 해결책 없이 상태와 상호작용을 직접 제어할 수 있습니다.

간단한 상태 관리

NiceGUI는 상태를 쉽게 관리할 수 있습니다. Streamlit과 달리 예상치 못한 상태 재설정이 발생하지 않습니다. NiceGUI는 시작 상태든 사용자가 만든 변경 사항이든 모든 것을 안정적으로 유지합니다. 사용자 상호작용을 처리하기 위해 콜백을 사용할 수 있으며 전체 페이지 새로고침으로 인한 괴롭힘 없이 상태 데이터를 유지할 수 있습니다.

많은 기능들

NiceGUI에는 여러 가지 멋진 기능들이 많이 있어요:

  • 상호 작용을 위한 버튼, 스위치, 슬라이더, 입력 등 다양한 요소들이 있어요.
  • 화면에 요소들을 쉽게 배치할 수 있는 방법이 있어요.
  • 차트, 테이블, 심지어 3D 씬까지 시각화에 사용할 수 있어요.
  • Matplotlib 또는 Plotly와 같은 데이터 시각화 라이브러리와 통합이 되어 있어요.
  • 색상과 스타일을 쉽게 사용자 정의할 수 있어요.
  • 코딩과 테스트에 도움이 되는 도구들이 있어요.
  • 주 개발자들은 항상 질문에 대답할 준비가 되어 있고, GitHub 공간에 피드백을 매우 긍정적으로 반영해요.
  • 인기 있는 프레임워크 위에 구축되어 있어요: FastAPI, Vue3, Tailwind, Quasar.
  • 전체 사이트가 NiceGUI 라이브러리로 제작되었어요: https://nicegui.io/documentation

제한사항

NiceGUI은 정말 멋지지만, 작은 커뮤니티 규모 때문에 다소 제약이 있을 수 있습니다. Streamlit과 같이 인기 있는 프레임워크보다 학습 곡선이 조금 더 길 수도 있습니다. 라이브러리의 기능을 최대한 활용하려면 CSS와 Tailwind CSS에 익숙해지는 것이 좋습니다. 또한, FastAPI, Vue, 그리고 Quasar에 대한 지식은 더 큰 유연성을 제공하고 구현할 수 있는 기능을 확장할 수 있습니다.

실습

이제 NiceGUI의 몇 가지 기능을 탐험하고 데모 앱을 만들고 배포해 봅시다.

기본 앱

먼저 NiceGUI를 설치해주세요:

pip install nicegui[highcharts]

주요 문서의 예제에서 시작해보겠습니다:

# https://nicegui.io/documentation/section_data_elements
from nicegui import ui
from random import random

chart = ui.highchart({
    'title': False,
    'chart': {'type': 'bar'},
    'xAxis': {'categories': ['A', 'B']},
    'series': [
        {'name': 'Alpha', 'data': [0.1, 0.2]},
        {'name': 'Beta', 'data': [0.3, 0.4]},
    ],
}).classes('w-full h-64')

def update():
    chart.options['series'][0]['data'][0] = random()
    chart.update()

ui.button('Update', on_click=update)

ui.run()

여기서 UI 모듈은 UI 요소를 만들 수 있도록합니다. 이 예시에서 먼저 Highchart 요소를 생성하는데, 이에 w-full과 h-64의 tailwind 클래스를 할당합니다. w-full은 반응형으로 화면 전체를 가로로 사용하고 h-64는 높이를 지정합니다.

image

버튼을 클릭하면 콜백 함수가 트리거됩니다. 이 콜백은 차트에 사용되는 데이터를 업데이트하고 그것을 순조롭게 다시 렌더링합니다.

또한, 새로운 막대를 추가하기 위해 콜백을 변경할 수도 있습니다:

def update():
    chart.options["xAxis"]["categories"].append(random.choice(string.ascii_uppercase))
    for series in chart.options['series']:
        series["data"].append(random.random())
    chart.update()

image

또한 페이지를 새로 고침해도 데이터가 손실되지 않는다는 것을 알아두세요! 이것은 다른 Python UI 라이브러리로는 할 수 없는 일입니다. 이렇게 작동하는 이유는 데이터가 모든 사용자 사이에서 공유되기 때문이지만, 앱 저장소의 사용자 객체나 앱 저장소 브라우저같은 방법으로 데이터를 사용자별로 유지하는 방법이 많이 있습니다. @ui.page 데코레이터로 감싸기 위해 app.storage.user 객체나 app.storage.browser를 사용할 수 있습니다.

하지만 주기적 타이머를 사용하여 UI를 업데이트하고 싶다면 어떻게 할까요? 쉽습니다! 버튼 요소를 ui.timer로 변경해주기만 하면 됩니다.

ui.timer(5, callback=lambda: (update(), ui.notify("데이터가 업데이트되었습니다")))

gif

자, 이제 사용자가 범주를 선택한 다음 무작위로 Chuck Norris Fact를 생성할 수 있는 데모 앱을 만들어 봅시다.

먼저, 여기에 메인 코드가 있습니다:

import requests  # HTTP 요청을 만들기 위해 requests 라이브러리를 가져옵니다
from nicegui import ui  # NiceGUI 라이브러리에서 UI 구성 요소를 가져옵니다
from nicegui_app.header import add_head_html  # HTML 헤드 내용을 추가하는 함수를 가져옵니다

# Chuck Norris 사실 카테고리 목록
CATEGORIES = [
    "동물",
    "직업",
    "연예인",
    "개발",
    "패션",
    "음식",
    "돈",
    "영화",
    "음악",
    "과학",
    "스포츠",
    "여행",
]

# Chuck Norris 사실을 처리하는 클래스
class Fact:
    def __init__(self):
        self.fact = None  # fact 속성을 None으로 초기화

    # 주어진 카테고리를 기반으로 사실을 업데이트하는 메서드
    def update_fact(self, category):
        url = f"https://api.chucknorris.io/jokes/random?category={category}"  # Chuck Norris API URL

        for i in range(10):  # 유효한 사실을 가져오려고 최대 10번 시도
            result = requests.get(url)  # Chuck Norris API로 GET 요청을 보냄

            if result.status_code == 200:  # 요청이 성공하면
                result_json = result.json()  # JSON 응답을 파싱
                if self.fact != result_json["value"]:  # 가져온 사실이 현재 사실과 다르면
                    self.fact = result_json["value"]  # 사실을 업데이트하고
                    break  # 루프를 종료

# Chuck Norris 사실 UI를 생성하는 함수
def chuck():
    add_head_html()  # NiceGUI 앱에 HTML 헤드 내용 추가

    default_value = CATEGORIES[0]  # Chuck Norris 사실의 기본 카테고리

    fact = Fact()  # Fact 클래스의 인스턴스 생성
    fact.update_fact(default_value)  # 기본 카테고리로 사실을 업데이트

    # 12개 열을 가진 그리드 레이아웃 생성
    with ui.grid(columns=12).classes("w-full"):
        # 카테고리 선택을 위한 열
        with ui.column().classes("col-span-4 sm:col-span-2 space-x-0"):
            ui.label("사실 카테고리 선택:")  # 카테고리 선택을 위한 레이블 표시
            # 카테고리 선택을 위한 라디오 버튼 그룹
            category = ui.radio(
                CATEGORIES,
                value=default_value,
                on_change=lambda _: fact.update_fact(category.value),  # 카테고리가 변경되면 사실 업데이트
            ).classes("w-full")
            # 선택한 카테고리에 대한 사실을 다시 생성하는 버튼
            ui.button(
                "⟳ 다시 생성", on_click=lambda _: fact.update_fact(category.value)
            )

        # Chuck Norris 사실을 표시하는 열
        with ui.column().classes(
            "flex col-span-8 sm:col-span-10 w-full justify-center mx-auto max-w-screen-md"
        ):
            # Chuck Norris 사실을 표시하기 위한 레이블, Fact 인스턴스의 fact 속성에 바인딩
            ui.label().bind_text_from(fact, "fact").classes(
                "text-lg sm:text-3xl text-gray-800 bg-gray-100 rounded-lg shadow-lg p-6"
            )

class Fact:
    def __init__(self):
        self.fact = None  # fact 속성을 None으로 초기화합니다.

    # 주어진 카테고리에 따라 팩트를 업데이트하는 메소드
    def update_fact(self, category):
        url = f"https://api.chucknorris.io/jokes/random?category={category}"  # 척 노리스 API의 URL입니다.

        for i in range(10):  # 유효한 팩트를 가져오기 위해 최대 10번 시도합니다.
            result = requests.get(url)  # 척 노리스 API에 GET 요청을 보냅니다.

            if result.status_code == 200:  # 요청이 성공한 경우
                result_json = result.json()  # JSON 응답을 파싱합니다.
                if self.fact != result_json["value"]:  # 가져온 팩트가 현재 팩트와 다른 경우
                    self.fact = result_json["value"]  # 팩트 속성을 업데이트합니다.
                    break  # 루프를 종료합니다

이 클래스는 "fact" 속성에 팩트를 저장하고 Chuck Norris 팩트 API를 호출하는 update_fact 메소드를 가지고 있습니다. https://api.chucknorris.io

다음으로, "chuck" 함수에서 페이지를 정의합니다. NiceGUI는 여러 모듈과 Python 파일을 거쳐 앱을 정의할 수 있는 모듈식 접근 방식을 채택합니다.

우리는 데이터 클래스의 인스턴스인 fact = Fact()을 정의합니다. 이는 각 사용자별로 구체적인 인스턴스입니다. 그리고 다음으로 update_fact 메소드를 사용하여 팩트를 초기화합니다.

이제 UI 요소를 정의하기 시작합니다.

두 개의 열을 갖는 그리드를 정의합니다:

  • 카테고리 옵션 및 생성 버튼이있는 첫 번째 열입니다. 이 열은 다음과 같은 tailwind 클래스를 갖습니다: col-span-4 sm:col-span-2. 이것은 매우 작은 화면의 경우 화면의 4/12을 사용하고, 그렇지 않으면 화면의 2/12을 사용합니다. 이렇게 함으로써 디자인을 모바일 전화에서도 작동하게 할 수 있습니다.
  • 사실을 표시할 두 번째 열입니다.

첫 번째 열을 위해:

  • 라디오 메뉴 ui.radio.
  • 무작위 사실을 생성하는 버튼이 있습니다.

두 요소 모두 클릭되거나 변경될 때 fact.update_fact를 호출하는 콜백을 사용합니다.

두 번째 열에 대해서:

  • fact.fact 값을 바인딩하는 ui.label이 있습니다. 이 변수가 변경될 때마다 디스플레이가 자동으로 업데이트됩니다.

아래에 있는 테일윈드 클래스를 가진 레이블입니다: text-lg sm:text-3xl 이렇게 하면 텍스트가 작은 화면에서 더 작아집니다.

다음 앱을 얻게 되요:

앱 이미지

멋지죠?

배포

앱을 배포하는 것은 쉬워요! 예를 들어 CloudRun을 사용하면 매우 간단해요. Dockerfile을 생성한 다음 다음 gcloud 명령어를 실행하기만 하면 돼요:

PROJECT_ID=$(gcloud config get-value project)
REPO="demo"
LOCATION="europe-west1"
IMAGE="nicegui_app"
SERVICE_NAME="nicegui-app"
VERSION="0.0.1"
GAR_TAG=$LOCATION-docker.pkg.dev/$PROJECT_ID/$REPO/$IMAGE:$VERSION

# 저장소 생성
gcloud artifacts repositories create $REPO --repository-format=docker \
    --location=$LOCATION --description="Docker repository" \
    --project=$PROJECT_ID  || true # 이미 존재하는 경우를 위해 실패해도 괜찮아요

# 이미지 빌드
gcloud builds submit --tag $GAR_TAG

# Cloud Run 배포
gcloud run deploy $SERVICE_NAME --image=$GAR_TAG --max-instances=1 --min-instances=0 --port=8080 \
 --allow-unauthenticated --region=europe-west1 --memory=0.5Gi --cpu=1 -q --no-cpu-throttling --session-affinity

이렇게 하면 클라우드 빌드를 사용하여 도커 이미지를 빌드한 다음 CloudRun에 배포할 수 있어요.

여기서 유일한 키큰 옵션은 다음과 같습니다: "— no-cpu-throttling — session-affinity". 이를 통해 동일한 사용자가 가능한 경우 동일한 컨테이너로 라우팅되고 요청 사이에 CPU가 활성 상태로 유지됩니다.

마지막으로

NiceGUI는 파이썬을 사용해 빠르고 쉽게 사용자 인터페이스를 만들고 싶을 때 좋은 선택입니다. 여기에서는 내부 상태를 완전히 제어하고 테스트하고 쉽게 배포할 수 있는 강력한 파이썬 앱을 구축할 수 있습니다. 이를 통해 데이터 과학 프로젝트에서도 도구로 제한받지 않고 창의성을 발휘할 수 있을 것입니다.

여기에 표시된 내용은 NiceGUI로 할 수 있는 작은 부분에 불과합니다. 아래 링크를 따라가면 더 많은 것을 배울 수 있습니다.

자원: