본문 바로가기
파이썬으로 웹 App 작성하기

Anvil 로 웹 앱 만들어서 배포하기 (기능편) - <1> 서버랑 파일 주고 받기(Uplink 및 서드파티 사용법)

by Slate_Knowledge 2023. 5. 5.
728x90

이전 포스팅:

2023.03.20 - [파이썬으로 웹 App 작성하기] - Anvil 로 웹 앱 만들어서 배포하기 (1) - Getting Started

 

Anvil 로 웹 앱 만들어서 배포하기 (1) - Getting Started

보통 웹 앱을 만드는 건 프론트엔드, 백엔드의 개발을 요구하는데 이때 각 파트에서 필요한 개발 능력 및 언어상황이 다른 경우가 많아서 1인 개발의 난이도를 높이게 된다. Anvil(링크)은 이러한

doodlrudco.tistory.com

상기 이전글에서 소개한 바 있는 Anvil은 파이썬만을 이용해서 프론트부터 백엔드, DB 등 웹 개발에 필요한 모든걸 수행할 수 있도록 만들어주는 프로젝트이다. 

친절한 UI와 더 친절한 Document 및 Tutorial이 있어서 어지간한 기능을 구현하는건 어렵지 않지만, 아무래도 아직 그렇게 유명하지 않다보니 블로그 글도 많이 없고 알맞은 설명에 접근하는게 어려운 경우들이 있어 본 포스팅 시리즈를 시작한다. 

기능편은 말 그대로 필자가 개발하면서(포스팅 시리즈 중 코인 트레이더 어플 같은) 필요했던 기능 모듈이 어디 있는지, 참고할만한 튜토리얼은 무엇인지 메모장스럽게 기술하는 시리즈이므로 모든 필요한 기능을 포함하지는 않을것이다. 댓글로 요청이 들어오면 우선적으로 그 부분을 기술 할 수 있다.

파일 업로드 기능

서비스 어플리케이션을 만드는데에 있어서 사용자가 원하는 데이터에 작업(딥러닝 추론이든, 영상처리든)을 해서 결과를 넘겨주려면 사용자가 파일을 업로드하고 서버가 다운로드 할 수 있도록 하는 형상이 필수적일 것이다. 따라서, 본 포스팅에서는 Anvil의 Uplink 기능을 이용해서 로컬 서버와 연동한 서비스 시나리오를 기반으로 

  1. 사용자가 이미지 파일을 업로드하면
  2. 로컬서버는 이를 받아서 1)파일을 저장하고, 2) 주어진 이미지에 빨간 원을 그려서 반환하고,
  3. 사용자 UI에 해당 결과값을 출력하는

예제를 다루도록 하겠다.

기본 UI 세팅

제일 먼저, blank project를 생성한 다음 그 위에 아래와 같이 file uploader 객체와 결과값을 받을 image 객체를 만들어준다.

파일 업로더 객체와 이미지 캔버스 객체로 이루어진 간단한 UI 구성

업로드 이벤트 핸들링

파일 업로드 이벤트는, 파일의 내용이 바뀌는 change 이벤트에 해당하는데 파일 업로더 객체를 클릭하면 우측에 보이는(스크롤 맨 아래) property에 각 이벤트별 핸들링 함수를 연결시킬 수 있다.

이벤트 핸들러 함수 할당하기

여기서 우하단의 파란색 화살표 버튼을 클릭하거나(split view) 아니면 좌상단의 Code 버튼을 누르면 아래와 같이 핸들러 코드를 수정할 수 있는 서식으로 넘어간다.

이벤트 핸들러 함수

상기 코드 블럭은 이전 예제(링크)에서도 사용했던 것과 유사하게 서버 모듈의 callable 함수를 호출하고, 이때의 리턴값을 이미지 객체의 source로 삼는 간단한 기능을 수행하게 짜여진 핸들러이다. 

그런데, 이때 업로드 된 이미지를 OpenCV로 처리하고 싶다면 어떻게 해야할까? 이전처럼 서버 모듈을 이용할 수도 있겠다 싶겠지만,import cv2 를 첫 줄에 삽입하고 관련 함수를 호출하는 순간

서드파티를 사용하려면 돈을 내시오

위와 같이 과금권장 안내문이 등장한다. Anvil의 발전을 위해 과금러들이 많이 늘어나면 좋긴 하겠지만 필자는 당장은 과금 생각이 없으므로 다른 방법이 필요하다. 이때 등장하는 기능이 Anvil Uplink이다. 

Uplink 를 통한 로컬 서버 연동

Anvil은 매우 좋은 개발 툴이고, 심지어는 이걸 오픈소스로 공개하고 있지만 우리가 anvil.works 페이지에서 웹 UI를 통해 개발한 서버는 제한적인 연산자원과 기능만을 무료로 제공한다. 무료로 이정도를 지원한다는거 자체가 대단하고, 모든 기능은 깃허브 소스를 다운받아서 동일하게 작동시킬 수 있다고는 하지만 다운로드 받아서 개발을 하게 되면 개인적으로 필자가 Anvil의 최대 장점이라고 생각하는 웹 UI 개발 및 배포 환경이 사라진다. 

다운 받자니 UI가 사라지고, 그렇다고 웹에서 모든걸 돌리자니 유료 회원이 아니라면 연산량 및 기능이 제한되는 곤란한 상황을 타개할 수 있는게 바로 Uplink 기능이다. Anvil에서는 이 Uplink 기능을 통해서 웹 UI와 로컬 파이썬 프로세스를 자연스럽게 묶어주고 무료 회원들에게도 실질적으로 무한한 가능성을 열어준다! 그 사용도 아래와 같이 매우 쉽다.

[참조] Anvil Uplink 튜토리얼(링크)

먼저, 웹 UI 의 좌측 사이드바 맨 아래의 + 표시를 눌러보면 

uplink feature 추가하기

위와 같이 Uplink feature 추가를 누를 수 있는데, 그러면 다음과 같이 Uplink client와 server 각각에 해당하는 key를 발급받을 수 있다.

설치법을 포함하는 uplink 추가 페이지

본 포스팅에서는 server module을 대체할 계획이므로 server uplink 키만 발급받은 다음 발급받은 키를 바탕으로 위 그림 하단부의 설치를 수행한다. 기존에 내가 cv2 패키지를 가지고 있던 환경에 anvil-uplink를 설치해주고 아래와 같이 코드를 작성해줬다.

import anvil
from anvil import server

import cv2
import numpy as np

@server.callable
def circle_drawer(file):
    file = file.get_bytes()
    img = cv2.imdecode(np.frombuffer(file, np.uint8), -1)
    
    cv2.circle(img, (img.shape[1]//2, img.shape[0]//2), img.shape[1]//4, (0, 0, 255), -1)
    _, img_encoded = cv2.imencode('.jpg', img)
    # return img as a file object
    return anvil.BlobMedia("image/jpeg", img_encoded.tobytes())

if __name__ == "__main__":
    uplink_key = open("credentials.txt", "r").read()
    key = uplink_key.split(':')[1]
    # uplink_key --> you can get this from the Anvil directly
    
    anvil.server.connect(key)
    anvil.server.wait_forever()

위 코드를 보면,

  1. file_change 핸들러에서 넘어온 파일 객체에 대해서 byte 정보(파일 바이너리)를 가져온 다음, 
  2. Numpy 및 OpenCV로 이 바이너리 파일을 디코딩하여 이미지 객체로 만들고
  3. opencv로 이미지에 대문짝만한 붉은 원을 그려넣고
  4. 다시 blobmedia 형식으로 클라이언트 프로세스에 넘겨주는

과정을 차례로 수행한다. 이때 anvil.BlobMedia로 넘겨주는 이유는, 미디어나 파일 객체로 넘겨줘야 아까 생성한 image display객체에 제대로 source 할당이 되기 때문이다. 이런 부분은 찾아도 잘 안나와서 디버깅을 좀 해봐야한다.

2번에서 디코딩한 파일을 저장하려면 cv2의 imwrite를 사용해도 되고, 아니면

with open(file.name, 'wb') as f:
	f.write(file.get_bytes())

와 같이 바이너리를 바로 저장할 수 있다.

이렇게 하면 무료 계정에서도 opencv 등 서드파티를 제한없이 사용할 수 있다! 이 말인즉슨 딥러닝이든 뭐든 가능해졌다는 말이기도 하다. 본인이 강력한 연산기를 가졌으면 이 장점이 더더욱 두드러진다고 할 수 있다. 연구실에 지피유는 빵빵한데 급하게 데모는 만들어야하고 웹 배포는 몰라서 곤란했던 대학원생이 좋아할 소식이다.

결과물

위의 파이썬 코드를 먼저 로컬 서버에서 실행시켜주면 아래와 같이 클라이언트를 대기한다. 사실 이걸 나중에 틀어도 무방하다. Anvil에서 대기하는 로직을 다 핸들해주는듯.

서버 업링크 대기중

그 다음 클라이언트 UI를 Run 해주자

실행 예시

위와 같이 아무 사진을(필자의 깃허브 아바타 사진이다) 업로드 하면 중앙에 붉은 원을 떡하니 박아서 리턴해준다.

왔다갔다 하는 시간이 좀 걸리긴 하는데, 이정도면 적당히 쓰는데에는 전혀 문제가 없을 것 같다.

본 포스팅은 이정도에서 마치지만, 포스팅에서 다룬 기능들을 잘 활용하면 이후 훨씬 복잡한 작업들까지도 수월하게 웹으로 배포 가능할 것으로 보인다.

728x90
반응형

댓글