์ฒซ๊ฑธ์¶
๊ฐ์ฅ ๋จ์ํ 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 ์ ๊ณต):
๋์ API ๋ฌธ์¶
๊ทธ๋ฆฌ๊ณ ์ด์ , http://127.0.0.1:8000/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
์ฒ๋ผ) ๊ฐ๋ฐ ์๋ฒ ์คํ.