Skip to content

첫걸음

κ°€μž₯ λ‹¨μˆœν•œ FastAPI νŒŒμΌμ€ λ‹€μŒκ³Ό 같이 보일 κ²λ‹ˆλ‹€:

from fastapi import FastAPI

app = FastAPI()


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

μœ„λ₯Ό main.py에 λ³΅μ‚¬ν•©λ‹ˆλ‹€.

라이브 μ„œλ²„λ₯Ό μ‹€ν–‰ν•©λ‹ˆλ‹€:

$ uvicorn main:app --reload

<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<span style="color: green;">INFO</span>:     Started reloader process [28720]
<span style="color: green;">INFO</span>:     Started server process [28722]
<span style="color: green;">INFO</span>:     Waiting for application startup.
<span style="color: green;">INFO</span>:     Application startup complete.

μ°Έκ³ 

uvicorn main:app λͺ…령은 λ‹€μŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€:

  • main: 파일 main.py (파이썬 "λͺ¨λ“ˆ").
  • app: main.py λ‚΄λΆ€μ˜ app = FastAPI() μ€„μ—μ„œ μƒμ„±ν•œ 였브젝트.
  • --reload: μ½”λ“œ λ³€κ²½ ν›„ μ„œλ²„ μž¬μ‹œμž‘. κ°œλ°œμ—λ§Œ μ‚¬μš©.

좜λ ₯에 μ•„λž˜μ™€ 같은 쀄이 μžˆμŠ΅λ‹ˆλ‹€:

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

ν•΄λ‹Ή 쀄은 λ‘œμ»¬μ—μ„œ 앱이 μ„œλΉ„μŠ€λ˜λŠ” URL을 λ³΄μ—¬μ€λ‹ˆλ‹€.

ν™•μΈν•˜κΈ°

λΈŒλΌμš°μ €λ‘œ http://127.0.0.1:8000λ₯Ό μ—¬μ‹­μ‹œμ˜€.

μ•„λž˜μ™€ 같은 JSON 응닡을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€:

{"message": "Hello World"}

λŒ€ν™”ν˜• API λ¬Έμ„œ

이제 http://127.0.0.1:8000/docs둜 κ°€λ΄…λ‹ˆλ‹€.

μžλ™ λŒ€ν™”ν˜• API λ¬Έμ„œλ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€ (Swagger UI 제곡):

Swagger UI

λŒ€μ•ˆ API λ¬Έμ„œ

그리고 이제, http://127.0.0.1:8000/redoc둜 κ°€λ΄…λ‹ˆλ‹€.

λŒ€μ•ˆ μžλ™ λ¬Έμ„œλ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€ (ReDoc 제곡):

ReDoc

OpenAPI

FastAPIλŠ” APIλ₯Ό μ •μ˜ν•˜κΈ° μœ„ν•œ OpenAPI ν‘œμ€€μ„ μ‚¬μš©ν•˜μ—¬ μ—¬λŸ¬λΆ„μ˜ λͺ¨λ“  APIλ₯Ό μ΄μš©ν•΄ "μŠ€ν‚€λ§ˆ"λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

"μŠ€ν‚€λ§ˆ"

"μŠ€ν‚€λ§ˆ"λŠ” λ¬΄μ–Έκ°€μ˜ μ •μ˜ λ˜λŠ” μ„€λͺ…μž…λ‹ˆλ‹€. 이λ₯Ό κ΅¬ν˜„ν•˜λŠ” μ½”λ“œκ°€ μ•„λ‹ˆλΌ 좔상적인 μ„€λͺ…일 λΏμž…λ‹ˆλ‹€.

API "μŠ€ν‚€λ§ˆ"

이 경우, OpenAPIλŠ” API의 μŠ€ν‚€λ§ˆλ₯Ό μ–΄λ–»κ²Œ μ •μ˜ν•˜λŠ”μ§€ μ§€μ‹œν•˜λŠ” κ·œκ²©μž…λ‹ˆλ‹€.

이 μŠ€ν‚€λ§ˆ μ •μ˜λŠ” API 경둜, κ°€λŠ₯ν•œ λ§€κ°œλ³€μˆ˜ 등을 ν¬ν•¨ν•©λ‹ˆλ‹€.

데이터 "μŠ€ν‚€λ§ˆ"

"μŠ€ν‚€λ§ˆ"λΌλŠ” μš©μ–΄λŠ” JSON처럼 μ–΄λ–€ λ°μ΄ν„°μ˜ ν˜•νƒœλ₯Ό λ‚˜νƒ€λ‚Ό μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

μ΄λŸ¬ν•œ 경우 JSON 속성, 가지고 μžˆλŠ” 데이터 νƒ€μž… 등을 λœ»ν•©λ‹ˆλ‹€.

OpenAPI와 JSON μŠ€ν‚€λ§ˆ

OpenAPIλŠ” API에 λŒ€ν•œ API μŠ€ν‚€λ§ˆλ₯Ό μ •μ˜ν•©λ‹ˆλ‹€. λ˜ν•œ 이 μŠ€ν‚€λ§ˆμ—λŠ” JSON 데이터 μŠ€ν‚€λ§ˆμ˜ ν‘œμ€€μΈ JSON μŠ€ν‚€λ§ˆλ₯Ό μ‚¬μš©ν•˜μ—¬ APIμ—μ„œ 보내고 받은 λ°μ΄ν„°μ˜ μ •μ˜(λ˜λŠ” "μŠ€ν‚€λ§ˆ")λ₯Ό ν¬ν•¨ν•©λ‹ˆλ‹€.

openapi.json 확인

κ°€κ³΅λ˜μ§€ μ•Šμ€ OpenAPI μŠ€ν‚€λ§ˆκ°€ μ–΄λ–»κ²Œ μƒκ²ΌλŠ”μ§€ κΆκΈˆν•˜λ‹€λ©΄, FastAPIλŠ” μžλ™μœΌλ‘œ API의 μ„€λͺ…κ³Ό ν•¨κ»˜ JSON (μŠ€ν‚€λ§ˆ)λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

μ—¬κΈ°μ—μ„œ 직접 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€: http://127.0.0.1:8000/openapi.json.

λ‹€μŒκ³Ό 같이 μ‹œμž‘ν•˜λŠ” JSON을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€:

{
    "openapi": "3.0.2",
    "info": {
        "title": "FastAPI",
        "version": "0.1.0"
    },
    "paths": {
        "/items/": {
            "get": {
                "responses": {
                    "200": {
                        "description": "Successful Response",
                        "content": {
                            "application/json": {



...

OpenAPI의 μš©λ„

OpenAPI μŠ€ν‚€λ§ˆλŠ” ν¬ν•¨λœ 두 개의 λŒ€ν™”ν˜• λ¬Έμ„œ μ‹œμŠ€ν…œμ„ μ œκ³΅ν•©λ‹ˆλ‹€.

그리고 OpenAPI의 λͺ¨λ“  것을 기반으둜 ν•˜λŠ” μˆ˜μ‹­ 가지 λŒ€μ•ˆμ΄ μžˆμŠ΅λ‹ˆλ‹€. FastAPI둜 λΉŒλ“œν•œ μ‘μš©ν”„λ‘œκ·Έλž¨μ— μ΄λŸ¬ν•œ λŒ€μ•ˆμ„ μ‰½κ²Œ μΆ”κ°€ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

API와 ν†΅μ‹ ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μœ„ν•΄ μ½”λ“œλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•˜λŠ” 데도 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 예둜 ν”„λ‘ νŠΈμ—”λ“œ, λͺ¨λ°”일, IoT μ‘μš©ν”„λ‘œκ·Έλž¨μ΄ μžˆμŠ΅λ‹ˆλ‹€.

단계별 μš”μ•½

1 단계: FastAPI μž„ν¬νŠΈ

from fastapi import FastAPI

app = FastAPI()


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

FastAPIλŠ” API에 λŒ€ν•œ λͺ¨λ“  κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” 파이썬 ν΄λž˜μŠ€μž…λ‹ˆλ‹€.

기술 세뢀사항

FastAPIλŠ” Starletteλ₯Ό 직접 μƒμ†ν•˜λŠ” ν΄λž˜μŠ€μž…λ‹ˆλ‹€.

FastAPI둜 Starlette의 λͺ¨λ“  κΈ°λŠ₯을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

2 단계: FastAPI "μΈμŠ€ν„΄μŠ€" 생성

from fastapi import FastAPI

app = FastAPI()


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

μ—¬κΈ° μžˆλŠ” app λ³€μˆ˜λŠ” FastAPI 클래슀의 "μΈμŠ€ν„΄μŠ€"κ°€ λ©λ‹ˆλ‹€.

이것은 λͺ¨λ“  APIλ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ μƒν˜Έμž‘μš©μ˜ μ£Όμš” 지점이 될 κ²ƒμž…λ‹ˆλ‹€.

이 app은 λ‹€μŒ λͺ…λ Ήμ—μ„œ uvicorn이 μ°Έμ‘°ν•˜κ³  것과 λ™μΌν•©λ‹ˆλ‹€:

$ uvicorn main:app --reload

<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

μ•„λž˜μ²˜λŸΌ 앱을 λ§Œλ“ λ‹€λ©΄:

from fastapi import FastAPI

my_awesome_api = FastAPI()


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

이λ₯Ό main.py νŒŒμΌμ— λ„£κ³ , uvicorn을 μ•„λž˜μ²˜λŸΌ ν˜ΈμΆœν•΄μ•Ό ν•©λ‹ˆλ‹€:

$ uvicorn main:my_awesome_api --reload

<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

3 단계: 경둜 λ™μž‘ 생성

경둜

μ—¬κΈ°μ„œ "경둜"λŠ” 첫 번째 /μ—μ„œ μ‹œμž‘ν•˜λŠ” URL의 λ§ˆμ§€λ§‰ 뢀뢄을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€.

κ·ΈλŸ¬λ―€λ‘œ μ•„λž˜μ™€ 같은 URLμ—μ„œ:

https://example.com/items/foo

...κ²½λ‘œλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

/items/foo

정보

"경둜"λŠ” 일반적으둜 "μ•€λ“œν¬μΈνŠΈ" λ˜λŠ” "라우트"라고도 λΆˆλ¦½λ‹ˆλ‹€.

APIλ₯Ό λΉŒλ“œν•˜λŠ” λ™μ•ˆ "경둜"λŠ” "관심사"와 "λ¦¬μ†ŒμŠ€"λ₯Ό λΆ„λ¦¬ν•˜λŠ” μ£Όμš” λ°©λ²•μž…λ‹ˆλ‹€.

λ™μž‘

μ—¬κΈ°μ„œ "λ™μž‘(Operation)"은 HTTP "λ©”μ†Œλ“œ" 쀑 ν•˜λ‚˜λ₯Ό λ‚˜νƒ€λƒ…λ‹ˆλ‹€.

λ‹€μŒ 쀑 ν•˜λ‚˜μ΄λ©°:

  • POST
  • GET
  • PUT
  • DELETE

...이ꡭ적인 것듀도 μžˆμŠ΅λ‹ˆλ‹€:

  • OPTIONS
  • HEAD
  • PATCH
  • TRACE

HTTP ν”„λ‘œν† μ½œμ—μ„œλŠ” μ΄λŸ¬ν•œ "λ©”μ†Œλ“œ"λ₯Ό ν•˜λ‚˜(λ˜λŠ” 이상) μ‚¬μš©ν•˜μ—¬ 각 κ²½λ‘œμ™€ 톡신할 수 μžˆμŠ΅λ‹ˆλ‹€.


APIλ₯Ό λΉŒλ“œν•˜λŠ” λ™μ•ˆ 일반적으둜 νŠΉμ • 행동을 μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄ νŠΉμ • HTTP λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

일반적으둜 λ‹€μŒμ„ μ‚¬μš©ν•©λ‹ˆλ‹€:

  • POST: 데이터λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•΄.
  • GET: 데이터λ₯Ό 읽기 μœ„ν•΄.
  • PUT: 데이터λ₯Ό μ—…λ°μ΄νŠΈν•˜κΈ° μœ„ν•΄.
  • DELETE: 데이터λ₯Ό μ‚­μ œν•˜κΈ° μœ„ν•΄.

κ·Έλž˜μ„œ OpenAPIμ—μ„œλŠ” 각 HTTP λ©”μ†Œλ“œλ“€μ„ "λ™μž‘"이라 λΆ€λ¦…λ‹ˆλ‹€.

μ΄μ œλΆ€ν„° μš°λ¦¬λŠ” λ©”μ†Œλ“œλ₯Ό "λ™μž‘"이라고도 λΆ€λ₯Όκ²λ‹ˆλ‹€.

경둜 λ™μž‘ λ°μ½”λ ˆμ΄ν„° μ •μ˜

from fastapi import FastAPI

app = FastAPI()


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

@app.get("/")은 FastAPIμ—κ²Œ λ°”λ‘œ μ•„λž˜μ— μžˆλŠ” ν•¨μˆ˜κ°€ λ‹€μŒμœΌλ‘œ μ΄λ™ν•˜λŠ” μš”μ²­μ„ μ²˜λ¦¬ν•œλ‹€λŠ” 것을 μ•Œλ €μ€λ‹ˆλ‹€.

  • 경둜 /
  • get λ™μž‘ μ‚¬μš©

@decorator 정보

이 @something 문법은 νŒŒμ΄μ¬μ—μ„œ "λ°μ½”λ ˆμ΄ν„°"라 λΆ€λ¦…λ‹ˆλ‹€.

ν•¨μˆ˜ 맨 μœ„μ— λ†“μŠ΅λ‹ˆλ‹€. 마치 예쁜 μž₯μ‹μš©(Decorative) λͺ¨μžμ²˜λŸΌ(개인적으둜 이 μš©μ–΄κ°€ μ—¬κΈ°μ„œ μœ λž˜ν•œκ±° κ°™μŠ΅λ‹ˆλ‹€).

"λ°μ½”λ ˆμ΄ν„°" μ•„λž˜ μžˆλŠ” ν•¨μˆ˜λ₯Ό λ°›κ³  κ·Έκ±Έ μ΄μš©ν•΄ 무언가 ν•©λ‹ˆλ‹€.

우리의 경우, 이 λ°μ½”λ ˆμ΄ν„°λŠ” FastAPIμ—κ²Œ μ•„λž˜ ν•¨μˆ˜κ°€ 경둜 /에 ν•΄λ‹Ήν•˜λŠ” get λ™μž‘ν•˜λΌκ³  μ•Œλ €μ€λ‹ˆλ‹€.

이것이 "경둜 λ™μž‘ λ°μ½”λ ˆμ΄ν„°"μž…λ‹ˆλ‹€.

λ‹€λ₯Έ λ™μž‘λ„ μ“Έ 수 μžˆμŠ΅λ‹ˆλ‹€:

  • @app.post()
  • @app.put()
  • @app.delete()

μ΅μˆ™ν•˜μ§€ μ•Šμ€ 것듀도 μžˆμŠ΅λ‹ˆλ‹€:

  • @app.options()
  • @app.head()
  • @app.patch()
  • @app.trace()

팁

각 λ™μž‘(HTTP λ©”μ†Œλ“œ)을 μ›ν•˜λŠ” λŒ€λ‘œ μ‚¬μš©ν•΄λ„ λ©λ‹ˆλ‹€.

FastAPIλŠ” νŠΉμ • 의미λ₯Ό κ°•μ œν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

μ—¬κΈ°μ„œ μ •λ³΄λŠ” μ§€μΉ¨μ„œμΌλΏ μš”κ΅¬μ‚¬ν•­μ΄ μ•„λ‹™λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄ GraphQL을 μ‚¬μš©ν• λ•Œ 일반적으둜 POST λ™μž‘λ§Œ μ‚¬μš©ν•˜μ—¬ λͺ¨λ“  행동을 μˆ˜ν–‰ν•©λ‹ˆλ‹€.

4 단계: 경둜 λ™μž‘ ν•¨μˆ˜ μ •μ˜

λ‹€μŒμ€ 우리의 "경둜 λ™μž‘ ν•¨μˆ˜"μž…λ‹ˆλ‹€:

  • 경둜: λŠ” /μž…λ‹ˆλ‹€.
  • λ™μž‘: 은 getμž…λ‹ˆλ‹€.
  • ν•¨μˆ˜: λŠ” "λ°μ½”λ ˆμ΄ν„°" μ•„λž˜μ— μžˆλŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€ (@app.get("/") μ•„λž˜).
from fastapi import FastAPI

app = FastAPI()


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

이것은 파이썬 ν•¨μˆ˜μž…λ‹ˆλ‹€.

GET λ™μž‘μ„ μ‚¬μš©ν•˜μ—¬ URL "/"에 λŒ€ν•œ μš”μ²­μ„ 받을 λ•Œλ§ˆλ‹€ FastAPI에 μ˜ν•΄ ν˜ΈμΆœλ©λ‹ˆλ‹€.

μœ„μ˜ 경우 async ν•¨μˆ˜μž…λ‹ˆλ‹€.


async def λŒ€μ‹  일반 ν•¨μˆ˜λ‘œ μ •μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

from fastapi import FastAPI

app = FastAPI()


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

Note

차이점을 λͺ¨λ₯΄κ² λ‹€λ©΄ Async: "In a hurry?"을 ν™•μΈν•˜μ‹­μ‹œμ˜€.

5 단계: μ½˜ν…μΈ  λ°˜ν™˜

from fastapi import FastAPI

app = FastAPI()


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

dict, list, 단일값을 가진 str, int 등을 λ°˜ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Pydantic λͺ¨λΈμ„ λ°˜ν™˜ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€(λ‚˜μ€‘μ— 더 μžμ„Ένžˆ μ‚΄νŽ΄λ΄…λ‹ˆλ‹€).

JSON으둜 μžλ™ λ³€ν™˜λ˜λŠ” 객체듀과 λͺ¨λΈλ“€μ΄ 많이 μžˆμŠ΅λ‹ˆλ‹€(ORM 등을 ν¬ν•¨ν•˜μ—¬). κ°€μž₯ λ§ˆμŒμ— λ“œλŠ” 것을 μ‚¬μš©ν•˜μ‹­μ‹œμ˜€, 이미 μ§€μ›λ˜κ³  μžˆμ„ κ²λ‹ˆλ‹€.

μš”μ•½

  • FastAPI μž„ν¬νŠΈ.
  • app μΈμŠ€ν„΄μŠ€ 생성.
  • (@app.get("/")처럼) 경둜 λ™μž‘ λ°μ½”λ ˆμ΄ν„° μž‘μ„±.
  • (μœ„μ— μžˆλŠ” def root(): ...처럼) 경둜 λ™μž‘ ν•¨μˆ˜ μž‘μ„±.
  • (uvicorn main:app --reload처럼) 개발 μ„œλ²„ μ‹€ν–‰.