본문 바로가기
Python

[FastAPI] Getting Started

by llHoYall 2023. 9. 13.

최근 가벼운 서버를 구축할 필요가 생겨 사용하는 김에 정리를 해봅니다.

배우기 쉽고 빠른 성능을 보인다고 하니 가볍게 사용할 수 있고, Python 기반이라 금방 익힐 수 있는 것 같아요.

Install Module

먼저, 필요한 모듈들을 설치해 줍니다.

$ pip install fastapi "uvicorn[standard]"

Implement Server

다음으로, server application을 구현합니다.

# main.py

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

Root("/") 경로로 요청이 오면 "Hello World"를 반환해 줍니다.

Run Server

이제 명령창에 다음 명령을 입력하여 서버를 구동합니다.

$ uvicorn main:app --reload

다음과 같이 서버가 시작되면, 브라우저를 통해 접근해 봅니다.

명령창을 참고하여 "http://127.0.0.1:8000"에 접속해보면 JSON 메세지가 반환되는 것을 확인해 보실 수 있습니다.

Request Parameters

이제 사용자로부터 좀 더 다양한 요청을 받아서 처리해보도록 할게요.

@app.get("/params/{param_id}")
async def params(param_id):
    return {"Param ID": param_id}

먼저, 경로를 입력받아 처리하는 함수를 추가했습니다.

브라우저에서 "http://127.0.0.1:8000/params/3"과 같은 형태로 요청을 보내면 설정한 대로 JSON 메세지가 반환됩니다.

 

이번엔 query를 처리해 보도록 하겠습니다.

@app.get("/queries")
async def queries(x: int = 0, y: str = ""):
    return {"X": x, "Y": y}

x라는 정수와, y라는 문자열을 받아서 처리하는 함수를 추가했습니다.

브라우저에서 "http://127.0.0.1:8000/queries?x=7&y=hello"와 같은 형태로 요청을 보내면 설정한 대로 JSON 메세지가 반환됩니다.

Response with HTML

JSON만 반환하면 너무 밋밋하니 HTML 형태로 반환하도록 해봅시다.

from fastapi.responses import HTMLResponse

@app.get("/hello", response_class=HTMLResponse)
async def hello(name: str=""):
    return f"""
    <html>
        <head>
            <title>FastAPI Example</title>
        </head>
        <body>
            <h1>Hello, {name}!</h1>
        </body>
    </html>
    """

사용자에게 이름을 입력받아 인사를 하는 함수를 추가했습니다.

따로 설명할 게 없을만큼 간단하죠?

브라우저에서 "http://127.0.0.1:8000/hello?name=HoYa"와 같은 형태로 요청을 보내면 결과를 보실 수 있어요.

Using with Jinja2

HTML 코드를 매번 직접 반환하려면 여간 귀찮고 힘든 게 아니죠.

이제 Jinja2를 사용해 봅니다.

먼저 모듈을 설치해 줍니다.

$ pip install jinja2

다음으로, 코드에 적용을 해줍니다.

from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates

templates = Jinja2Templates(directory="templates")

@app.get("/hello", response_class=HTMLResponse)
async def hello(request: Request, name: str=""):
    return templates.TemplateResponse("index.html", {"request": request, "name": name})

코드도 깔끔해지고, 관리도 수월해 졌습니다.

이제, index.html 파일을 작성합니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css">

  <title>FastAPI Example</title>
</head>
<body>
  <main class="container">
    <H1>Hello, {{name}}!</H1>
  </main>
</body>
</html>

밋밋한 건 싫어서 picocss를 사용했고, 나머진 크게 다를 게 없습니다. ^^

테스트를 해보면 역시 잘 동작하는 것을 확인해 보실 수 있습니다.

Post using Form

이제 마지막으로 사용자로부터 입력을 받아봅시다.

@app.get("/hello", response_class=HTMLResponse)
async def hello(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

@app.get("/form", response_class=HTMLResponse)
async def form(request: Request, name: str="", age=0):
    return templates.TemplateResponse("form.html", {"request": request, "name": name, "age": age})

/hello를 받으면 사용자에게 입력받을 form을 출력합니다.

/form은 사용자의 입력을 query로 받아 결과를 출력합니다.

<!-- index.html -->
<body>
  <main class="container">
    <h1>Hello, Let me know who you are!</h1>

    <form class="container" action="/form?name={{name}}&age={{age}}">
      <div class="grid">
        <label for="name">
          Name
          <input type="text" id="name" name="name" placeholder="Name" required>
        </label>

        <label for="age">
          Age
          <input type="number" id="age" name="age" placeholder="Age" required>
        </label>
      </div>

      <button type="submit">Submit</button>
    </form>
  </main>
</body>
<!-- form.html -->
<body>
  <main class="container">
    <h1>Hello, {{name}}!</h1>
    <h2>You are {{age}} years old.</h2>
  </main>
</body>

각각의 페이지는 요렇게 만들었습니다.

브라우저에서 "http://127.0.0.1:8000/hello"에 접속한 후, 정보를 입력하면 정상적으로 출력되는 것이 보일 거에요.

Documentation

FastAPI의 장점 중 하나는 API 문서를 자동으로 생성해 준다는 점입니다.

브라우저에서 "http://127.0.0.1:8000/docs"에 접속하시면 확인하실 수 있습니다.

Wrap Up

알고만 있고 직접 사용해본 것은 이번이 처음이었는 데, 정말 쉽긴 하더라고요.

공식 홈페이지만 참고해서 2시간도 안걸려서 원하는 걸 만들 수 있었어요.

간단히 기본적인 내용을 공유드리려고 포스팅을 했는데, 간결하게 중요한 부분만 설명 드리려고 노력했습니다.

그러다보니 코드도 살짝 생략한 부분들이 있긴 한데, 아마 기본적인 거라 잘 따라하셨을거라 믿습니다. ^^

Jinja2를 사용해 보셨다면 조금 더 편하게 이용하실 수 있을 거에요.

공통 부분을 묶어서 확장하거나, 조건에 따라 내용을 변경하는 등 기본적인 것은 FastAPI와도 다 동작합니다.

도움이 되셨길 바랍니다.

'Python' 카테고리의 다른 글

[Typer] Python으로 CLI App 만들기  (0) 2024.03.30
[Python] PyPI에 패키지 배포하기  (3) 2024.03.16
[PyQt6] Save and Load Settings using QSettings  (0) 2023.04.06
[Python] Create and Draw Graph  (0) 2023.03.01
[Python] Abstract Base Classes  (0) 2023.02.23

댓글