1. Fast API
FastAPI는 Python 기반의 웹 프레임워크로, 주로 API를 빠르게 개발하기 위해 설계되었습니다. FastAPI는 자동으로 생성되는 OpenAPI 문서(Swagger UI)를 통해 API의 사용성과 테스트를 쉽게 할 수 있으며, 데이터 유효성 검사와 타입 힌트를 활용한 코드 자동완성 및 오류 방지를 지원합니다. 특히, 비동기 처리를 활용하여 속도가 중요한 대규모 애플리케이션 개발에 적합하며, RESTful API와 GraphQL 같은 현대적 웹 API 개발에 유용합니다.
타입 힌팅(Type Hints)
타입 힌팅(Type Hints)은 프로그래밍 언어에서 변수, 함수 매개변수, 함수 반환값 등에 대한 데이터 타입 정보를 코드에 명시적으로 제공하는 기술입니다. Python 3.5 이상에서 도입된 기능으로, 코드의 가독성을 높이고 프로그램의 안정성을 강화하는 데 도움이 됩니다.
2. 설치
FastAPI를 사용하려면 먼저 FastAPI 패키지를 설치해야 합니다.
pip install fastapi
FastAPI 애플리케이션을 실행하기 위해 uvicorn이라는 ASGI 서버가 필요합니다. Uvicorn은 Python으로 작성된 가볍고 빠른 웹 서버로, 비동기 웹 애플리케이션과 API를 실행하는 데 사용됩니다. 특히 FastAPI와 잘 어울리며, WebSocket과 HTTP/2 같은 최신 웹 기술을 지원합니다. 개발할 때는 자동 리로드 기능으로 편리하게 작업할 수 있고, 운영 환경에서는 다중 프로세스로 높은 성능을 제공합니다.
pip install "uvicorn[standard]"
uvicorn[standard]
1. 이 패키지는 uvicorn에 기본적으로 포함된 기능 외에도 추가적인 표준 미들웨어를 포함합니다.
2. 표준 미들웨어는 보안, 로깅 및 기타 서버 관련 기능을 추가하는 데 도움이 됩니다.
3. 예를 들어, Gzip 압축, CORS(Cross-Origin Resource Sharing) 지원 등이 기본적으로 포함되어 있습니다.
uvicorn
1. 기본적으로 필요한 최소한의 기능만을 제공하는 패키지입니다.
2. uvicorn[standard]에 비해 미들웨어가 적고, 기본적인 서버 기능만을 제공합니다.
ASGI 서버
ASGI 서버는 Python에서 비동기 웹 애플리케이션을 실행할 수 있게 해주는 서버입니다. 기존의 WSGI 서버는 동작이 느리고 실시간 기능(WebSocket, HTTP/2 등)을 지원하지 않았지만, ASGI 서버는 비동기로 동작해 더 빠르고 실시간 데이터 처리도 가능합니다. FastAPI 같은 최신 웹 프레임워크가 ASGI 서버와 잘 어울리며, 대표적인 서버로 Uvicorn과 Daphne가 있습니다. 이를 통해 많은 요청을 동시에 처리하고, 실시간 기능이 필요한 앱을 쉽게 만들 수 있습니다.
3. 기본 예제
myapp/
├── main.py
├── static/
│ └── script.js
├── templates/
│ └── index.html
main.py
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
app = FastAPI()
# 정적 파일 (JS, CSS 등) 제공
app.mount("/static", StaticFiles(directory="static"), name="static")
# HTML 템플릿 디렉토리
templates = Jinja2Templates(directory="templates")
# HTML 페이지 제공
@app.get("/", response_class=HTMLResponse)
async def get_page(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
# 백엔드 API – JSON 데이터 제공
@app.get("/api/data")
async def get_data():
return {"message": "FastAPI에서 보내는 데이터입니다"}
script.js
document.addEventListener("DOMContentLoaded", () => {
fetch("/api/data")
.then((response) => response.json())
.then((data) => {
document.getElementById("result").textContent = data.message;
})
.catch((error) => {
document.getElementById("result").textContent = "데이터 불러오기 실패";
console.error(error);
});
});
index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>FastAPI Frontend</title>
<script defer src="/static/script.js"></script>
</head>
<body>
<h1>프론트엔드 페이지</h1>
<p id="result">데이터를 불러오는 중...</p>
</body>
</html>
4. 실행
작성한 FastAPI 애플리케이션을 실행합니다. 다음 명령을 사용하여 uvicorn을 통해 실행할 수 있습니다.
uvicorn main:app --reload
FastAPI는 자동으로 생성된 Swagger UI를 통해 API 문서를 제공합니다. 기본적으로 http://127.0.0.1:8000/docs 또는 http://127.0.0.1:8000/redoc에서 확인할 수 있습니다. Swagger UI를 통해 API의 엔드포인트, 매개변수, 응답 형식 등을 살펴볼 수 있습니다.
5. REST와 RESTful API
REST: "Representational State Transfer"의 약자로, 웹 상에서 자원을 표현하고 상태를 전송하기 위한 아키텍처적인 스타일입니다. REST는 네트워크 아키텍처의 한 형식으로, 리소스(자원)를 정의하고 이를 고유하게 식별하는 데 중점을 두며, HTTP 프로토콜을 기반으로 하고 있습니다. REST는 간결하고 확장 가능한 디자인을 지향하여 웹 서비스를 위한 표준 아키텍처로 널리 사용되고 있습니다.
RESTful API(REST API): REST 아키텍처를 따르는 웹 서비스의 인터페이스를 말합니다. 이 API는 클라이언트와 서버 간의 통신을 위한 규칙을 제공하며, 자원의 생성, 조회, 수정, 삭제(CRUD)와 같은 기본적인 데이터 조작을 위한 메서드를 제공합니다. RESTful API는 HTTP를 기반으로 하기 때문에 웹에서 쉽게 사용할 수 있습니다. 클라이언트와 서버 간의 통신은 자원의 표현을 통해 이루어지며 표현은 일반적으로 JSON 또는 XML 형식으로 이루어집니다.
예를 들어, 다음은 간단한 RESTful API의 예시입니다:
자원(리소스): /users
HTTP 메서드: GET (모든 사용자 조회), POST (새로운 사용자 생성), PUT 또는 PATCH (사용자 정보 업데이트), DELETE (사용자 삭제)
from fastapi import FastAPI
users = {
0: {"userid": "apple", "name": "김사과"},
1: {"userid": "banana", "name": "반하나"},
2: {"userid": "orange", "name": "오렌지"}
}
app = FastAPI()
# http://127.0.0.1:8000/users/0
# uvicorn main:app --reload
@app.get("/users/{id}")
def find_user(id: int):
user = users[id]
return user
# http://127.0.0.1:8000/users/0/userid
# http://127.0.0.1:8000/docs
@app.get("/users/{id}/{key}")
def find_user_by_key(id: int, key: str):
user = users[id][key]
return user
6. JSON
JSON은 "JavaScript Object Notation"의 약어로, 데이터를 표현하고 교환하기 위한 경량의 데이터 형식입니다. 주로 서버와 클라이언트 간에 데이터를 주고 받을 때 사용되며, 텍스트 형태로 이루어져 있습니다. JSON은 간결하면서도 읽기 쉽고 파싱하기 쉬운 구조를 가지고 있어 많은 프로그래밍 언어에서 지원하고 있습니다.
{
"키1": "값1",
"키2": "값2",
"키3": {
"키4": "값4",
"키5": "값5"
},
"배열키": [
"배열값1",
"배열값2",
"배열값3"
]
}
7. HTTP Method
FastAPI에서는 각 메서드에 대응하는 데코레이터를 제공하여 해당 엔드포인트에 대한 핸들러 함수를 등록할 수 있습니다. 이러한 데코레이터를 사용하여 각각의 HTTP 메서드에 대한 동작을 정의할 수 있습니다.
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Annotated
users = {
0: {"userid": "apple", "name": "김사과"},
1: {"userid": "banana", "name": "반하나"},
2: {"userid": "orange", "name": "오렌지"}
}
app = FastAPI()
# 사용자 조회
@app.get("/users/{id}")
def find_user(id: int):
user = users.get(id)
if user is None:
return {"error": "해당 id 없음"}
return user
# 사용자 필드 조회
@app.get("/users/{id}/{key}")
def find_user_by_key(id: int, key: str):
user = users.get(id)
if user is None or key not in user:
return {"error": "잘못된 id 또는 key"}
return user[key]
# 이름으로 사용자 조회
@app.get("/id-by-name")
def find_user_by_name(name: str):
for idx, user in users.items():
if user["name"] == name:
return user
return {"error": "데이터를 찾지 못함"}
# 사용자 생성
class User(BaseModel):
userid: str
name: str
@app.post("/users/{id}")
def create_user(id: int, user: User):
if id in users:
return {"error": "이미 존재하는 키"}
users[id] = user.model_dump()
return {"success": "ok"}
# 사용자 수정
class UserForUpdate(BaseModel):
userid: str | None = None
name: str | None = None
@app.put("/users/{id}")
def update_user(id: int, user: UserForUpdate):
if id not in users:
return {"error": "id가 존재하지 않음"}
if user.userid is not None:
users[id]["userid"] = user.userid
if user.name is not None:
users[id]["name"] = user.name
return {"success": "ok"}
# 사용자 삭제
@app.delete("/users/{id}")
def delete_item(id: int):
if id not in users:
return {"error": "존재하지 않는 사용자"}
users.pop(id)
return {"success": "ok"}