본문 바로가기
REFLEX 튜토리얼

파인콘 첫 번째 예제, 카운터 앱

by 일코 2023. 1. 17.

카운터 앱 만들어보기

파인콘의 공식문서에서 제공하고 있는 첫 번째 예제, 카운터 앱을 같이 만들어봅시다.
전체 소스코드와 영문 설명은 아래 링크의 문서에서 확인하실 수 있습니다.

https://pynecone.io/docs/getting-started/introduction

 

전체 소스코드를 먼저 보여드리기보다는;;;

같이 틀을 잡아가면서 한 줄씩 완성해봅시다.
파인콘 앱과 인터랙션에 대해 이해하는 좋은 예제이기 때문입니다.

 

1. 파인콘 앱을 추가해줍니다.

앱을 추가하는 것이 복잡한 과정은 아닙니다.
그냥 폴더 하나, 파일 하나 생성하는 것에 지나지 않습니다.

이전 포스팅에서 예제를 테스트하면서 파이참 프로젝트를 생성하셨던 분들이라면
굳이 파이참 프로젝트를 하나 더 생성하지 마시고,
아래와 같은 과정을 통해 프로젝트 내에 앱을 추가하시는 것을 추천드립니다.
(어차피 연습인데요. 파이콘 프로젝트랑 별도 가상환경 몇 개씩 생성하면 몇GB씩 잡아먹습니다ㅠㅠ)

 

1-1. 프로젝트 루트에 새로운 파이콘 앱을 위한 폴더 inc_dec를 생성

이전 포스팅에서 생성한 앱 이름은 pynecone_tutorial이었습니다.
이번엔 프로젝트 루트에 "inc_dec"라는 폴더를 생성해줍시다.

inc_dec라는 폴더를 생성했습니다.

이제 이 폴더가 우리의 두 번째 실습용 앱인 inc_dec를 위한 폴더가 생성되었습니다.

 

1-2. inc_dec 폴더 안에 inc_dec.py 파일 생성

앱 폴더와 동일한 이름(inc_dec.py)의 파이썬 파일을 생성해줍니다.
이 안에 파인콘 카운터 앱의 코드를 한 줄씩 작성할 예정입니다.

1-3. inc_dec 폴더 안에 __init__.py 파일 생성

__init__.py 파일이 없어도 파인콘은 정상적으로 구동되지만,
관례상 네임스페이스 패키지임을 나타내기 위한 절차입니다.
__init__.py 파일은 비어있는 채로 둡니다.

1-4. pcconfig.py 파일 수정

프로젝트 루트에 있는 pcconfig.py 파일을 열고, app_name을 방금 생성한 폴더와 같이 "inc_dec"로 수정해줍니다.
수정된 pcconfig.py 파일은 아래와 같습니다.

import pynecone as pc


config = pc.Config(
    # app_name="pynecone_tutorial",
    app_name="inc_dec",                 # <--
    db_url="sqlite:///pynecone.db",
    env=pc.Env.DEV,
)

새로운 앱을 생성하기 위한 준비를 마쳤습니다.
이제 inc_dec/inc_dec.py 파일을 열고 코드를 작성해봅시다.

 

2. 카운터 앱 작성

(이젠 다들 아실 것 같아서 다소 새삼스럽지만)
기본적인 파인콘 앱의 구조는 아래와 같습니다.

import pynecone as pc


# ①
class State(pc.State):
    pass


# ②
def index():
    return pc.text("Hello World")


# ③
app = pc.App(state=State)
app.add_page(index)
app.compile()

① 각종 상태값을 정의하고 변경하기 위한 State 클래스
② 앱의 본체에 해당하는 함수(index)
③ 앱 인스턴스를 생성하고, 페이지 추가 후 컴파일하는 부분

파인콘 앱의 코드는 일반적으로 위와 같이 세 개의 파트로 구성됩니다.
위의 앱을 터미널에서 pc run 명령어를 통해 실행하면 아래와 같은 화면이 나타납니다.

파인콘으로 헬로월드 찍어보기

django나 다른 웹프레임워크에 비하면 너무너무 간단하게 헬로월드를 찍어보았습니다.

이제 index 함수를 통해 카운터 앱을 만들어봅시다.

우선 눈에 보이는 요소가 세 개 있습니다.
버튼 두 개와 텍스트죠.

index 함수를 아래와 같이 입력해봅시다.

 

2-1. index 함수 작성

본격적으로 index를 작성하기 전에 파인콘 앱의 리턴값에 대해 명심할 점이 있습니다.

index 함수의 리턴값은 기본적으로 한 개의 요소를 받지만,
요소를 리턴하는 함수도 넣을 수 있습니다. (이를 통해 여러 앱의 중첩이 가능합니다.)
예를 들면 위에서 작성한 헬로월드 예제는 아래처럼도 작성 가능합니다.
주의할 점은, 생소하게도 함수에 괄호가 붙어야 한다는 점입니다.
(괄호를 붙이지 않으면 AttributeError 오류가 발생합니다.)

어찌 보면 당연한 사실을 너무 거창하게 설명드린 것 같기도 합니다.
음, hello() 함수가 리턴하는 값이 pc.text 컴포넌트니까요.
저는 그저, django의 함수기반뷰에 익숙해져 있다 보니
저 괄호가 조금 생소해 보이긴 합니다.
def hello():
    return pc.text("Hello, world!")
    

def index():
    return hello()
    
    
app = pc.App(state=State)
app.add_page(index)
app.compile()

앱을 실행해보면(== 브라우저를 열어보면)

다시 Hello world!를 찍어보았습니다.

서론은 여기까지만 하고,
이제 본격적으로 카운터 앱을 작성해봅시다.
딱 아래처럼만 타이핑하고, 터미널에서 pc run을 통해 서버를 실행해준 후
브라우저를 열고 localhost:3000 으로 접속합니다.

add_page에 들어가는 함수 이름이 index일 경우에 해당합니다.
만약 add_page에 넣은 함수 이름이 app이라면
localhost:3000/app 으로 접속해야 우리가 만든 웹앱을 볼 수 있습니다.
import pynecone as pc


class State(pc.State):
    pass


def index():
    return pc.hstack(
        pc.button("감소"), pc.text("0"), pc.button("증가")
    )


app = pc.App(state=State)
app.add_page(index)
app.compile()

이제 파인콘 앱의 구조가 어느 정도 익숙해졌기를 바랍니다.
눈여겨 볼 부분은 index함수 구현부로,
hstack 요소를 통해 가로방향으로 컴포넌트 세 개를 쌓았습니다.
실행결과를 보면 예쁘지 않습니다.

CSS를 적용해서 뭔가 먼저 예쁘게 꾸며보고 싶은 분도 계실 거고, (F-E성향!?)
빨리 인터랙션을 추가하고 싶은 분도 계실 것 같습니다. (B-E성향!?)

저는 인터랙션 먼저 구현을 해보겠습니다.

 

2-1-1. 변수는 가급적 State 클래스 안에서 정의할 것

지금은 가운데 숫자가 텍스트 "0"으로 하드코딩 되어 있는데,
이걸 count라는 변수로 바꿔줘야 인터랙션이 가능해지겠지요?
이 때 count는 State클래스의 변수로 추가해줘야 합니다.

굳이 State클래스에 넣지 않고 메인함수에 넣어도 오류가 나지는 않지만,
State클래스는 특별한 기능을 몇 가지 포함하고 있습니다.
한 가지 예를 들면,
State클래스 안에 정의된 변수가 새로 정의되어 값이 바뀌는 경우
백엔드에서는 FastAPI와 Next.js가 신호(delta라고 부름)를 주고받으면서
실시간으로 화면을 다시 렌더링해줍니다.
뒷단의 프로세스를 우리가 깊숙하게 알 필요는 없지만,
하여튼 이런저런 이유로 파인콘에서 제안하는 방식을 따르는 것이
가장 좋은 성능을 내는 방법인 것 같습니다.

그럼 State클래스와 index 함수를 아래와 같이 수정해봅니다.

import pynecone as pc


class State(pc.State):
    count = 0

    def increment(self):
        self.count += 1

    def decrement(self):
        self.count -= 1


def index():
    return pc.hstack(
        pc.button("감소", on_click=State.decrement),
        pc.text(State.count),
        pc.button("증가", on_click=State.increment),
    )


app = pc.App(state=State)
app.add_page(index)
app.compile()

갑자기 코드가 불어나서 부담스러워 보이지만, State와 index를 번갈아 보면
금방 인터랙션을 이해하실 수 있을 겁니다.
State클래스에서 정의한 클래스변수인 count를 index의 pc.text 안에 넣었습니다.

다른 예제를 따라하면서도 여러 번 체험하시겠지만, 파인콘의 컴포넌트 안에 들어가는 데이터는
문자열(str) 뿐 아니라, int, float, dict, list 등 파이썬의 대부분의 자료형은 다 들어갈 수 있답니다.

2-1-2. 이제 앱이 어떻게 바뀌었는지 확인해볼까요?

서버가 아직 돌고 있다면, 브라우저를 새로고침하지 않아도 자동으로 컴파일을 해줍니다.

 

인터랙션이 제대로 작동하는지 버튼을 클릭해봅시다.

의도한 대로 잘 돌아가네요.
이제 마지막으로 스타일을 추가해봅시다.

 

2-2. 스타일 추가

코드가 다소 길어지지만, 추가된 스타일 부분만 염두에 두고 입력해주시기 바랍니다.

def index():
    return pc.center(
        pc.hstack(
            pc.button("감소", on_click=State.decrement,
                      color_scheme="red", border_radius="1em"),    # <--
            pc.text(State.count, font_size="2em"),                 # <-- 
            pc.button("증가", on_click=State.increment,
                      color_scheme="green", border_radius="1em"),  # <--
        ), padding="50px"                                          # <--
    )

이제 다시 앱을 실행해보면 다소나마 예쁜 모습으로 바뀌어 있습니다.

초록불, 빨간불 신호등 같네요. 여러분 입맛에 맞게 스타일을 추가해보시기 바랍니다.

어떠셨나요?

아직은 너무 간단한 예제라서 뭔가 배우는 느낌이 들지 않는 분도 많을 것 같습니다.
이번 예제는 아주아주 간단한 인터랙션에 대해 다루었다는 의의를 갖고
여기서 마치겠습니다.

다음 포스팅은 파인콘 프로젝트를 생성할 때 만들어지는 폴더와 파일에 대한 간략한 소개를 드리고 
그 이후부터는 파인콘에서 제공하는 60여가지의 컴포넌트에 대한 간략한 소개와 사용법,
그리고 다양한 예제를 포스팅으로 다뤄보도록 하겠습니다.

수고하셨습니다.

다음 포스팅

 

pynecone 프로젝트의 구성파일 및 구조

django를 배우기 시작한지는 7년 정도 된 것 같습니다. 당시에는 데이터분석이나 머신러닝보다는 바로 django 때문에 파이썬을 배우는 사람들이 많았던 분위기였습니다. 저도 다른 언어나 프레임워

martinii.fun


일코가 추천하는 파이썬+한컴오피스 업무자동화 입문강의

 

움짤로 빠르게 배우는 파이썬-아래아한글 자동화 레시피 - 인프런 | 강의

파이썬으로 아래아한글을 다루는 짧은 예제코드들을 소개하고, 중간중간의 결과를 GIF로 보여드립니다. 동영상 강의가 아니지만 오히려 빠르게 배울 수 있고, 따라하기도 쉽습니다., - 강의 소개

www.inflearn.com

이건 제 겁니다. 이번 달 할인중이니까 마음껏 수강신청해주세요!

댓글