최신글

스터디 챕터 7 정리 - 프러덕션을 위해, Streamlit을 FastAPI로 마이그레이션

반응형

이 글은 스터디에서 공부한 내용을 정리했습니다.

- 주제: 챕터 7은 챕터 6에서 만든 Streamlit으로 만든 웹앱을 프로덕션으로 사용하기 위해 FastAPI로 마이그레이션 하는 내용

 

왜 Streamlit을 프로덕션에 사용하지 않는가?

저는 Streamlit 사용 경험이 많지 않아서, 이번 스터디를 준비하면서 조사한 내용을 정리했습니다. 여기서 제가 말하는 프로덕션은 “내 노트북에서 데모로 실행하는 것”이 아니라, 돈을 받고 사용자에게 서비스하는 상황을 기준으로 합니다.

 

Streamlit는 여러 한계 때문에 프로덕션에 사용하지 않습니다.

1. 전체 스크립트 재실행 구조
Streamlit은 사용자가 버튼을 누르거나 입력값을 바꾸면 스크립트를 다시 실행하는 방식으로 동작합니다. 작은 데모에서는 이 구조가 편합니다. 그런데 LLM 호출, 데이터베이스 저장, 외부 API 호출이 섞이면 “내가 원하지 않은 코드가 다시 실행되는 상황”이 발생하면서 원치 않는 현상이 발생할 수 있습니다.

2. 긴 작업을 다루는 방식
AI 서비스에서는 임베딩 생성, LLM 추론, 로그 저장처럼 시간이 오래 걸리는 작업이 자주 나옵니다. 짧으면 몇 초지만, 길면 몇십 초 이상 걸릴 수도 있습니다. FastAPI는 ASGI(Asynchronous Server Gateway Interface)를 기반으로 동작해서 이런 웹 API 서버 구조를 만들기 좋습니다.

3. API 생성
Streamlit은 API를 만드는 기능을 제공하지 않지만, FastAPI는 처음부터 HTTP API를 만들기 위한 프레임워크입니다.

4. 운영구조로 확장
프로덕션으로 가면 인증, rate limit, timeout, retry, logging, tracing, autoscaling 같은 주제가 따라옵니다. Streamlit에서는 목적 자체가 빠르게 기능을 보여주는 것이기 때문에, 운영을 위한 기능은 없습니다. 또한 오토스케일링이 발생했을때 여전히 비지니스 로직이 잘 동작하는지 검증된 자료를 찾을 수 없었습니다.

 

책에서 선택한 프로덕션 방법은?

책에서는 프러덕션으로 배포하기 위해 Streamlit을 FastAPI로 변경했습니다. FastAPI는 파이썬으로 API와 html을 만들 수 있는 장점이 있지만, 제 생각은 비동기 지원이 AI관련 프로덕션 API에 좋은 것 같습니다.

 

FastAPI는 eventloop가 구현되어 있어서 비동기에 친화적입니다. API가 실행하는 로직에서 임베딩, 추론 등이 있을때 최소 몇초에서 몇십분 latency가 길어집니다. 이런 로직에 비동기가 지원되지 않으면 다른 요청이 block되어서 대기해야합니다.

 

다른 웹 프레임워크인 Django는 비동기를 부분지원하고 있습니다. 또한, 인터페이스가 ASGI가 아니여서 튜닝이 필요합니다. 아래 블로그에서 AI서비스를 하면서 Django에서 FastAPI로 왜 옮겼는지에 대한 설명이 있으니 참고바랍니다.

 

비동기 이외에 FastAPI는 Pydantic를 적극 사용하고 있어 데이터 관리가 쉽고, FastAPI CLI, swagger 지원, 검색자료가 많음 등의 장점이 있습니다.

 

FastAPI 아키텍처 간단히 살펴보기

FastAPI의 아키텍처 핵심은 ASGI입니다. FastAPI는 ASGI 프레임워크인 starlette를 쉽게 사용할 수 있도록 감싼 것입니다. 그리고 ASGI server 역할을 하는 uvicorn이 FastAPI를 구동합니다.

 

ASGI가 등장하기 전에는 파이썬 진영에서 WSGI를 사용했습니다. 하지만 WSGI는 비동기를 처리하는 데 한계가 있었고, ASGI server 중 하나인 uvicorn은 uvloop를 사용해 비동기 처리를 해결했습니다.

 

결국 프로덕션에서 FastAPI 성능을 최적화하려면, 애플리케이션 코드(async 처리 패턴 등)와 uvicorn/gunicorn 설정을 튜닝해야 합니다. guicorn은 uvicorn 워커 프로세스를 관리하는 프로세스 매니저입니다.

 

더 자세한 FastAPI 아키텍처는 아래 블로그를 참고하면 좋습니다.
- https://m.blog.naver.com/pjt3591oo/222772705407

 

[fastapi] uvicorn, fastapi 비동기 메커니즘 이해

안녕하세요 멍개입니다. 최근에 MLOps를 공부하면서 새로운 스택을 다뤄보고 싶어서 fastapi를 다뤄보게...

blog.naver.com

 

실습

실습 예제는 저의 github에 공개되어 있습니다.

- github 주소: https://github.com/choisungwook/portfolio/tree/master/computer_science/ai/study_coobok/chapter7 

 

파이썬 패키지 관리: uv

프로젝트와 Python 패키지 관리를 위해 uv를 사용했습니다. 책에는 없는 내용이지만 프로젝트와 패키지를 관리하는 도구는 프로덕션에 필수여서 추가했습니다.

 

환경변수 생성

.env파일을 만들고 OPENAI_API_KEY를 넣습니다.

cp .env.example .env

 

도커 컨테이너 생성

docker compose 명령어로 컨테이너를 실행합니다. 컨테이너 실행 과정에 docker build가 같이 실행됩니다.

docker compose up -d

 

예제 1번

예제 1번은 2개 기능을 구현했습니다.
- “/ask” API생성
- 사용자 요청과 사용자에게 줄 응답을 Pydantic로 관리

 

저는 vscode에서 http extension을 사용하여 테스트를 진행했습니다. http extension은 http파일을 postman처럼 API를 요청하고 응답을 보여줍니다.

 

swagger로도 테스트 가능합니다. question에 질문할 내용을 적고 Execute버튼을 누르면 API응답을 받을 수 있습니다.
- 접속주소: http://localhost:8001/
- 질문내용: Configure OSPF area 0

 

예제 2번

두번째 예제는 예제 1번에서 디바이스 타입을 받도록 API가 수정되었습니다.
- Pydantic에서 input model에서 device_type 추가
- 시스템프롬프트 관리 변수 추가
- 질문가능한 device 목록을 보여주는 API 추가

 

“/devices” API를 호출하면 질문가능한 device목록이 나옵니다.

 

cisco로 device_type을 지정하여 “/ask”API를 호출하면, cisco에 맞는 응답을 줍니다.

 

예제 3번

예제 3번은 사용자의 요청을 DB에 저장하고 조회하는 기능이 추가되었습니다.

 

이 책은 간단한 예제여서 DB라이브러리에 대해 설명은 하지 않습니다. sqlalchemy라이브러리로 DB세션을 간단히 관리하고 Pydantic으로 ORM로 DML을 제어합니다.

 

Pydantic은 API 요청/응답처럼 스키마 관리를 class로 관리(ORM)할 수 있습니다.

 

이 예제에서는 SessionLocal로 DB세션을 생성해서 API에서 필요할 때 사용합니다.

 

예제 3번에서 “/ask” API요청을 실행할 때 마다 sqlite에 요청과 AI가 생성한 응답이 저장됩니다. 그리고 “/hisotry”API를 호출하면 지금까지 요청과 생성한 응답을 보여줍니다.

 

예제 4번

예제 4번은 Jinja 템플릿을 사용하여 html페이지와 FastAPI의 API를 연동합니다.

 

기존 예제는 html이 파이썬 코드에 하드코딩되어 있어서, html은 파일로 추출했습니다.

 

FastAPI는 HTMLResponse class를 사용하여 HTML포맷으로 사용자에게 html응답을 줄 수 있습니다. html의 API요청은 결국 javascript로 http요청을 하기 때문에, 기존 API를 따로 수정하지 않아도 됩니다. 다만, 이 예제에서는 구분을 쉽게하기 위해 “/web-ask”라는 API를 생성했습니다.

 

참고자료

반응형