Vercel로 Flask 배포하기

SeonDal·2023년 12월 8일
2

🚑 에러치유소

목록 보기
12/12

flask로 네이버 블로그 포스팅을 크롤링해서 타이틀만 모아서 목차를 만들어주는 웹사이트를 만들었다.
이 웹사이트를 배포하려한다.
Replit 에서 플라스크 배포가 가능하지만 안타깝게도 유료다.
보통 무료 배포로 가장 유명한건 Vercel 인데 배포 과정에서 너무 많은 오류를 겪었다.
그 과정을 남겨보려한다.


0. 배포하기

프로젝트의 깃허브 레포를 import 해서 vercel로 배포하는 기본 방식은 같다.

Framework Preset은 Flask라는 템플릿이 없으므로 Other을 선택한다



1. 폴더 구조 맞추기 (404 에러)

가장 먼저 마주하게 되는 에러는 404: NOT_FOUND 에러로 실행할 파일의 경로를 찾지 못해 생기는 이슈다.

보통 플라스크 프로젝트를 로컬에서 잘 구동했다면 루트에 다음과 같은 폴더구조를 가질 것이다

  • app.py (또는 init.py)
  • templates (이 안에 html 파일들)
  • 그 외 이것저것

이렇게 하면 flask run 을 터미널에 입력했을 때 (또는 Run을 눌렀을 때) 로컬 서버가 잘 구동되지만 vercel은 인식하지 못한다.

vercel에서 flask 프로젝트를 배포하려면 아래와 같은 폴더구조를 가져야한다

  • api > index.py
  • templates
  • 그 외 이것저것

즉 app.py 에 해당하는 파일은 사진처럼 index.py로 이름을 바꿔서 루트 디렉토리에 있는 api 폴더에 넣어줘야한다



2. 사용된 라이브러리 알려주기 (unable to import module)

프로젝트가 라이브러리를 사용하는 경우 pip install을 이용하여 라이브러리를 설치한다.

예를 들어 본 글의 예시인 블로그 목차 생성기의 경우 beautifulsoup4 를 사용하고 있기 때문에

pip install beautifulsoup4 

를 터미널에 입력해야 로컬에서 구동 가능 했다.

만약 라이브러리가 포함된 플라스크 프로젝트를 vercel에서 그대로 배포하면

[ERROR] Runtime.ImportModuleError: Unable to import module 'vc__handler__python': No module named 'requests'
Traceback (most recent call last):

이런 로그가 뜨며 모듈을 import 할 수 없다고 뜬다.

리액트 프로젝트에서는 node_modules와 package.json으로 프로젝트가 사용하는 라이브러리가 잘 정리되기 때문에 배포해보면 라이브러리가 자동으로 적용되는 것과 달리 플라스크는 그런게 없다.

따라서 해당 프로젝트에서 사용하는 라이브러리와 프레임워크들을 명시적으로 Vercel에게 알려줘야한다.

Flask==3.0.0
requests==2.26.0
beautifulsoup4==4.10.0

루트 디렉토리에 requirements.txt 파일을 만들어서 필요한 라이브러리와 버전을 작성하자



3. Serverless Function has Crashed (500 에러)

다 잘되었다고 생각했는데 이젠 500: INTERNAL_SERVER_ERROR 가 뜬다.

vercel "this serverless function has crashed." 를 검색해봐도 뾰족한 해결책이 없었다.

찍힌 로그를 확인했더니 503 * Serving Flask app 이라고만 뜬다.


사실 이 부분은 아주 간단하게 해결할 수 있었던 문제였다 (삽질ㅠㅠ)

원래 사용하고 있던 api/index.py (로컬에서는 app.py) 파일의 코드다.

이 코드를 예제와 비교해보자

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return 'Hello, World!'

@app.route('/about')
def about():
    return 'About'

일반적으로 flask 의 app.py 와 마찬가지로 app = Flask(name) 같은 줄이나 @app.route("경로") 로 해당 경로에 보여질 내용을 보여주는 부분은 동일하다.

def 함수()의 return 으로 보여질 내용을 내 프로젝트에선 return render_template() 을 이용해 html 형식으로 보여줬다는 부분만 다를 뿐.
처음에는 이게 문제인건가 싶었다

잘 보니 app.run("0.0.0.0")이 없더라.

생각해보면 프로덕션에 배포하려는 코드에 로컬 서버를 구동시키는 app.run이 포함되어있으면 당연히 에러가 날 수 밖에 없었다.
이걸 왜 이제 알았을까

app.run 한 줄 지웠더니 갑자기 500 에러는 사라지고 멀쩡하게 배포되었다.



본 글이 도움이 되었다면 공감 한번씩 부탁드립니다 ❤️

Ref

profile
김선달 개발블로그

2개의 댓글

comment-user-thumbnail
2024년 2월 9일

index.py를 api에 넣으니 templates폴더 안에 있는 html 파일을 못 찾아요..............

1개의 답글