Skip to main content

FastAPI 기초

·4 mins· loading · loading ·
CS FastAPI
Soeun Uhm
Author
Soeun Uhm
problem-solving engineer, talented in grit.
Table of Contents

FastAPI 란?
#

  • Django, FastAPI, Flask 등 웹서비스의 백엔드 프레임워크는 다양하다.
  • 그 중에서 왜 FastAPI 에 대해 공부해봤나 ?
    • ASGI(비동기 처리 (async) 가능 = 병렬 처리 가능)
    • pydantic을 이용한 validation -> API 사용자, 개발자 간 소통을 정확하게
    • OpenAPI 문서 자동 생성 -> LocalHost/docs 로 이동하면 FastAPI 에서 만들어놓은 Swagger UI 문서로 테스트 가능
    • 뛰어난 문서->따라하기 쉽고 상세한 문서가 있다
  • 내 목적인 ML Model Deploy를 하기 위해 가장 배우기 쉽고, 따라할 수 있는 문서가 많아서 선택해서 배워보기로 했다.

FastAPI 이용해서 API 설계하기
#

  • HTTP Method 에는 POST, GET, PUT, DELETE 가 있다. 이것은 데이터를 처리하는 가장 기본 규칙인 CRUD (Create, Read, Update, Delete) 에 맞게 설계된 규칙이다.

img

GET
#

우선 아래와 같이 내 FastAPI 를 만들었다.

from fastapi import FastAPI, Body
app = FastAPI(
    title = "API Practice"
    version = "1.0"
    )

1. 단순하게 정보를 읽어오는 GET 을 구현하기

@app.get('/')
async def first_api():
    return ("FastAPI 를 배워봅시다!")


@app.get('/api-endpoint')
async def first_api_endpoint():
    return ("내 api-endpoint !")

@app.get(’/api-endpoint’) 에서 / 뒤에 있는 것은 내 api-endpoint 이다. 이제 uvicorn 서버를 실행시켜서 결과물을 확인해보자.

uvicorn 서버를 실행하려면, 실행하려는 파일이 있는 디렉토리에서 uvicorn books1:app --reload를 실행하면 된다.

여기서 books1 은 내 FastAPI 가 있는 .py 파일 이름이고, app 은 위에 명시한 것 처럼 내 FastAPI 이름이다. –reload는 내가 파이썬 파일을 수정하면 바로바로 반영할 수 있게 하는 파라미터이다.

URL : 127.0.0.1:8000/ 에 접속하면, 아래와 같이 뜰 것이다.

img

그리고 URL : 127.0.0.1:8000/api-endpoint 에 접속하면, 아래와 같이 뜬다.

img

2. Dynamic Parameter 사용하기

내 api endpoint 에 직접 변수를 입력하는 dynamic parameter 를 입력할 수 있다. 아래는 BOOKS 라는 책들의 정보 모음을 저장해두고, book_title 이 내가 가지고 있는 BOOKS 모음에 있으면 그 책에 대한 정보를 리턴하고, 아니면 new_book : book_title 을 리턴하도록 함수를 설계했다.

BOOKS = [
    {'title': 'Mockingbird', 'author': 'Harper Lee', 'category': 'fiction'},
    {'title': 'MobyDick', 'author': 'Herman Melville', 'category': 'fiction'},
    {'title': '1984', 'author': 'George Owell', 'category': 'history'},
    {'title': 'Great Gatsby', 'author': 'Fitzgerald', 'category': 'fiction'},
    {'title': 'Frankenstien', 'author': 'Shelly', 'category': 'zombie'},
    {'title': 'HarryPotter', 'author': 'J.K.Rolling', 'category': 'fiction'}
]
@app.get('/books/{book_title}')
async def read_book(book_title: str):
    for book in BOOKS:
        if book.get('title').casefold() == book_title.casefold():
            return book
        else:
            return {'new_book': book_title}

이렇게 실제 있는 책 정보를 입력하면 그 정보가 뜨고,

img

없는 책 정보를 입력하면 new_book 을 리턴한다.

img

3. Query Parameters

  • {name=value} pair 를 가진 파라미터이다.
  • URL 에서 ?뒤에 붙여진다.

내가 만약 특정 카테고리에 해당하는 책을 BOOKS 에서 찾고 싶다고 해보자. 아래 코드는 내가 검색한 카테고리가 BOOKS 내의 카테고리와 일치하면 그 책을 리턴하는 함수이다.

@app.get("/books/")
async def read_category_by_query(category:str):
    books_to_return = []
    for book in BOOKS:
        if book.get('category').casefold() == category.casefold():
            books_to_return.append(book)
    return books_to_return

img

POST
#

  • POST 는 새로운 정보를 생성하는 HTTP Method이다.
  • POST 는 Request Body 가 있다. <-> GET 은 Request Body 를 가질 수 없다

이제 FastAPI 의 큰 장점인 Swagger UI 를 사용해서 내 API 를 테스트 해보자. Swagger UI 접속은 http://127.0.0.1:8000/docs 로 이동하면 접속할 수 있다.

POST Method 를 설계해보자. 나는 새로운 책을 만드는 함수를 만들었다.

@app.post("/books/create_book")
async def create_book(new_book = Body()):
    BOOKS.append(new_book)
    return BOOKS

img
새로운 책을 추가하면, Status code 200 ok 와 함께 BOOKS 아래 새롭게 추가된 것을 볼 수 있다.
img

PUT
#

  • PUT 은 정보를 업데이트 하는데 사용한다.

아래 Body() 는 사용자가 Request Body 에 입력하는 정보이다. 사용자가 입력한 정보를 updated_book 으로 받고, 이 updated_book 의 title 과 BOOKS 내의 title 이 일치하는 것이 있으면 이 updated_book 의 정보로 업데이트 해주는 함수이다.

조심해야 하는 것이 있는데, Request Body 에서 입력할 때 무조건 쌍따옴표("") 를 사용해야 한다 ! 작은따옴표(’’)를 입력하면 422 semantic error 가 뜬다.

@app.put("/books/update_book")
async def update_book(updated_book = Body()):
    for i in range(len(BOOKS)):
        if BOOKS[i].get('title').casefold() == updated_book.get('title').casefold():
            BOOKS[i] = updated_book
    return BOOKS

DELETE
#

  • DELETE 는 있는 정보를 삭제하는 데 사용한다.

아래 함수는 book_title 을 endpoint 로 입력받고, 입력한 book_tile 과 BOOKS 의 title 이 일치하는 것이 있으면 BOOKS 에서 삭제(pop) 하는 함수이다.

@app.delete("/books/delete_book/{book_title}")
async def delete_book(book_title:str):
    for i in range(len(BOOKS)):
        if BOOKS[i].get('title').casefold() == book_title.casefold():
            BOOKS.pop(i)
            break
    return BOOKS

Reference
#

  • Udemy, FastAPI - The complete course 2023

사용한 자료와 코드
#

  • 사용한 자료와 코드는 모두 제 GitHub 에서 볼 수 있습니다.
  • GitHub books1.py 파일 참고