[FastAPI] FastAPI 입문 part1 - 설치/라우팅

회사에서는 그동안 데이터 파이프라인을 만들고 모델을 만드는데 열중하였다. 그리고 모델 개발이 완료되고, 이를 서비스하기 위해 다양한 방법을 고민하였다. 물론 모델 개발을 기획하기전 서비스를 어떻게 할지 구조와 계획을 세웠으나, 다양한 내부적인 이슈들이 있었다. 실시간성과 빠른 응답이 필요한 time-out 이슈, 장비의 노후화 등 여러가지 문제를 마주하였었고 이를 해결하기 위해서 자체 개발한 API가 필요하다는 것이 결론이었다.

머신러닝 모델을 서비스하고 운영하기 위해 MLOps라는 단어가 등장하였다. 다양한 회사와 플랫폼에서 MLOps를 지원하기 위해 많은 제품을 내놓고 있으나 내가 있는 환경에 딱 들어 맞는 것이 없었다. 그래서 이번 기회에 FastAPI 를 이용해 자체 API 를 만들었다. 실제 배포되어 운영되고 있는 코드는 훨씬 복잡할 수는 있겠지만 기본 뼈대와 구조는 모두 동일할 것이다. 글을 쓰는 나 역시 FastAPI를 처음 사용해본 것이기에 스터디하면서 만들었다. 그간의 삽질과 여정을 한번 정리해보면서, 나와 비슷한 고민을 하는 분들에게 조금이나마 도움이 되길 바란다.

(또한, 이 시리즈를 쓰는데 동기와 용기를 준 글또 커피드백 조원 두 분에게 감사하며 글을 써본다. Shout out to 문현규 & 박다원)

이 글은 FastAPI 의 설치와 그 입문 그리고 기초적인 라우팅까지의 내용을 담았다. 앞으로 FastAPI시리즈로 담을 것이고 시리즈 안의 글의 순서와 목차는 내가 API를 구성하면서 스터디한 순서대로 담으려고 노력할 것이다.

1. FastAPI의 소개 및 설치

Python 세계에 웹 프레임워크는 다양하다. 가장 유명한 장고(Django)와 플라스크(Flask)가 있지만, 이 프레임워크들은 그 유명한 만큼 다양한 기능을 제공한다. 반면에 그 역사와 전통을 자랑하는 것과 비례에 그 속도가 느린 것이 단점이다. FastAPI 는 그 이름에서 느낄 수 있는 것처럼 빠르고 가벼우며, 간단한 API 를 비교적 쉽게 빌드하여 테스트베드로 사용할 수 있다.

먼저 FastAPI를 실습할 수 있게 설치해보자.

1-1. FastAPI 설치

1
$ pip install fastapi
1
2
3
4
5
$ pip install uvicorn 
# or
$ pip install "uvicorn[standard]"
# or
$ pip install gunicorn

이번 실습은 FastAPI 만 설치해도 무난하다. 하지만 웹 어플리케이션을 실제로 배포하고 다양한 request 를 처리하기 위해 나중엔 웹 서버가 필요할 수 있다. 이를 위해 unicorn이나 gunicorn, nginx등이 많이 사용되는데 이에 대해서는 나중에 좀더 자세히 살펴보자. 지금 단계에서는 fastapi, uvicorn 만 치해도 실습하고 배포하는데 큰 문제가 없다.

1-2. HelloWorld

FastAPI 를 설치해보았으니, 간단한 웹 어플리케이션을 빌드하여 hello world 를 찍어보자.

  1. my_first_app라는 폴더를 만들고 그 안에 app.py 라는 파이썬 파일을 만들자.
1
2
3
$ mkdir my_first_app
$ cd my_first_app
$ touch app.py
  1. main.py 안에 다음과 같이 작성하자.
1
2
3
4
5
6
7
8
9
10
11
12
# my_first_app/main.py

from fastapi import FastAPI
from typing import Dict

app = FastAPI() #1

@app.get("/") #2
async def helloworld() -> Dict: #3
return {
"message": "Hello World" #4
}

#1 : app이라는 변수에 FastAPI() 서버의 인스턴스를 생성한다

#2: 데코레이터를 사용하여 이 app에 라우팅을 설정해준다. REST API의 “/”경로로 GET 액션이 들어왔을 때, 실행되는 함수를 밑에 정의한다.

#3: helloworld() 라는 함수를 위 라우트가 왔을 때 실행되는 함수명이고 그 내용은 #4의 dictionary 를 리턴한다.

  1. 간단하게 만든 우리의 첫 어플리케이션을 실행해보자.
1
2
$ cd my_first_app
$ uvicorn main:app --port 8080 --reload

위 실행 명령어를 살펴보면,

uvicorn : ASGI 웹 서버 어플리케이션으로 실행한다.

main : 우리가 실행시키려고 하는 모듈 이름

app : main 모듈 안에 uvicorn 이 바라보는 인스턴스 이름

—port : 포트를 지정한다. 여기서는 8080

—reload : reload 옵션을 주면 우리가 개발하는 프로젝트내에서 코드 변경이 이루어 졌을 때 다시 서버를 구동하여 변경된 코드를 적용한다. 개발하는 단계에서 잘 사용하면 편하다.

이렇게 사용하게 되면 터미널에서는 다음과 같이 결과가 뜬다.

Untitled

웹서버가 잘 떴는지 확인하기 위해 자주 사용하는 크롬이나 사파리와 같은 브라우저에서 우리가 방금 만든 웹서버에 접속해보자.

url : http://localhost:8080/

Untitled

혹은 터미널에서 curl localhost:8080

Untitled

정상적으로 우리의 첫 어플리케이션을 띄우는데 성공했다면, 그 시작이 매우 보람찰 것이다. 내 손으로 띄운 웹통신 서버라니.. 사실 이게 API의 전부이다.

위 간단한 어플리케이션의 동작 원리를 다시 살펴보면,

(1) 우리가 URL 로 접속한다. 정확히는 호스트 주소. 여기서는 localhost:8080

(2) 그리고 접속하고자 하는 경로를 확인한다. 여기서는 “/”

(3) 이 request를 받은 우리의 인스턴스는 라우팅을 통해 “/”에 해당하는 함수를 찾는다.

(4) helloworld()함수를 실행하고 그 함수에서 정의한 결과값을 리턴한다. 여기서는 {”message”: “hello world”}

정상적으로 응답을 했다면, 다음과 같이 200 사인을 준다. 그 결과는 우리의 콘솔에서도 확인할 수 있다.

Untitled

2. 라우팅

앞서 살펴본 라우트 처리 방법은 실제로는 잘 사용하지 못한다. 위와 같은 방식은 라우팅 중에 단일 경로만 처리하게 되기 때문이다. 이는 uvicorn이 하나의 엔트리 포인트만 실행할 수 있기 때문이다. 여러 함수를 사용하여 연속적이고 다중의 라우트 처리는 FastAPI의 APIRouter클래스를 사용하여 이 문제를 해결 할 수 있다.

실습해보자!

  1. my_first_app 안에 routers 라는 폴더를 만들고 test.py 파이썬 파일을 만들자.
1
2
3
$ cd my_first_app
$ mkdir routers
$ touch routers/test.py
  1. new_router.py 에 다음과 같은 코드를 작성하자.
1
2
3
4
5
6
7
8
9
10
11
12
from fastapi import APIRouter
from typing import Dict

router = APIRouter(
prefix="/new"
)

@router.get("/test")
async def helloworld_new( ) -> Dict:
return {
"message": "new router Hello!"
}
  1. main.py 에 다음을 추가하자.
1
2
3
4
# main.py 에 추가
from routers.new_router import router

app.include_router(router)
  • 최종적으로 main.py의 코드는 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from fastapi import FastAPI
from typing import Dict

from routers.new_router import router

app = FastAPI()

app.include_router(router)

@app.get("/")
async def helloworld() -> Dict:
return {
"message": "Hello World"
}
  1. 기능확인

localhost:8080/new/test 라는 주소를 입력하면 우리가 새로 작성한 new router hello 메시지를 볼 수 있다.

Untitled

우리가 추가한 new_router.py 를 살펴보자.

(1) APIRouter 클래스 안에 prefix는 여기서 설정하는 router는 /new 뒤에 오는 경로를 설정하겠다는 의미이다. 이부분을 공란으로 두면, localhost:8080/ 루트에 바로 추가되는 경로가 될 것이다.

(2) /new 아래에 /test라는 경로가 들어오면 아래 함수를 실행하겠다는 뜻이다. 여기서는 “new router Hello”를 리턴한다.

3. 정리

이번 글에서는 FastAPI 를 이용하여 간단하게 첫 어플리케이션을 만들어 보았고, 거기다 더해 다중 라우팅을 처리하기 위한 APIRouter클래스도 살펴보았다. 이번 글에서 미처 설명하지 못한 부분을 한번 개인적으로 찾아보면 좋겠다. 키워드로는 RestAPI, HTTP 메소드중 GET, POST, PUT, DELETE, Router 등의 키워드로 개인적인 공부를 하면 앞으로 업로드하는 FastAPI시리즈를 읽으며 좀더 많은 도움이 될 것이라고 믿는다.

[FastAPI] FastAPI 입문 part1 - 설치/라우팅

https://emjayahn.github.io/2023/04/23/20230423-fast-api-1/

Author

Emjay Ahn

Posted on

2023-04-23

Updated on

2023-05-07

Licensed under

Comments