FastAPI
# FastAPI란 무엇인가?
FastAPI는 파이썬으로 웹 서버(API)를 만들기 위한 현대적이고 매우 빠른 프레임워크입니다.
- 왜 쓰는가?: 코드가 직관적이고, 실행 속도가 매우 빠르며, 비동기(Async) 처리가 쉬워서 현대적인 웹 서비스 구축에 적합합니다.
- 핵심 개념: @app.get이나 @app.post처럼 데코레이터(@)를 사용해 "이 주소(URL)로 접속하면 이 함수를 실행해라"라고 지정하는 방식입니다.
* Flask vs FastAPI
| 구분 | Flask | FastAPI |
| 속도 | 상대적으로 느림 (동기 방식) | 매우 빠름 (Node.js/Go와 비견됨) |
| 비동기 처리 | 지원이 제한적임 | 완벽하게 지원 (Async/Await) |
| 데이터 검증 | 직접 구현하거나 외부 라이브러리 필요 | Pydantic을 통한 자동 검증 |
| 문서화 | 직접 만들어야 함 | Swagger API 문서 자동 생성 |
| 학습 난이도 | 아주 쉬움 | 중간 정도 (비동기 개념 필요) |
# Uvicorn
Python으로 작성된 초고속 비동기 ASGI(Asynchronous Server Gateway Interface) 웹 서버
💡 Uvicorn의 핵심 역할
- 웹 서버와 애플리케이션 연결: 외부(사용자)로부터 들어오는 HTTP 요청을 받아 애플리케이션에 전달하고, 애플리케이션의 응답을 다시 사용자에게 돌려주는 역할을 합니다.
- 비동기(Async/Await) 지원: 파이썬의 asyncio를 기반으로 설계되어 빠르고 효율적인 비동기 처리가 가능합니다.
- 초고속 성능: uvloop 및 httptools와 같은 라이브러리를 사용하여 Node.js나 Go와 견줄 만큼 빠른 속도를 자랑합니다.
- 웹소켓(WebSocket) 기본 지원: HTTP 요청뿐만 아니라 실시간 양방향 통신인 WebSocket을 기본적으로 지원합니다.
## FastAPI랑 Uvicorn 관계
- FastAPI (웹 프레임워크): 누가 어떤 주소로 들어왔을 때, 어떤 함수를 실행할지 결정하는 '두뇌'입니다. 하지만 이 두뇌는 스스로 외부와 통신하는 능력이 없습니다.
- Uvicorn (서버/통신사): 외부 브라우저(크롬 등)로부터 오는 복잡한 신호를 받아서, FastAPI라는 두뇌가 이해할 수 있는 형식으로 전달해 주는 '심장'이자 '통신사'입니다.
# EX) PYTHON01
1. 라이브러리 임포트 및 앱 생성
from fastapi import FastAPI
from pydantic import BaseModel, Field
from fastapi.responses import HTMLResponse, PlainTextResponse, JSONResponse
import uvicorn
app = FastAPI()
- FastAPI: 웹 서버 기능을 제공하는 핵심 클래스입니다.
- BaseModel: 데이터의 구조를 정의하고 검증하기 위한 Pydantic의 도구입니다.
- responses: JSON 외에 HTML이나 일반 텍스트 등 다양한 형식의 응답을 반환할 때 사용합니다.
2. Pydantic 모델 정의 (데이터 틀 만들기)
class UserItem(BaseModel):
name: str
age: int # 나이는 반드시 정수여야 함
class Item(BaseModel):
name: str = Field(examples=["맥북 프로"]) # 예시 값 지정
price: float
- BaseModel: 이 클래스를 상속받으면, 들어오는 데이터가 name은 문자열(str), age는 정수(int)인지 자동으로 확인합니다. 틀린 타입이 들어오면 서버가 알아서 에러 메시지를 보내줍니다.
- Field(examples=[...]): API 문서(Swagger)를 볼 때 사용자에게 "이런 값을 넣으세요"라고 예시를 보여주는 친절한 기능입니다.
3. API 엔드포인트 분석
[상품 생성 API]
@app.post("/items", response_model=Item)
def create_item(item: Item):
"""
## 상품을 생성합니다
이 API는 ...
"""
return item
- response_model=Item: 이 API가 돌려주는 데이터도 Item 모델을 따르도록 강제합니다.
- Docstring ("""..."""): 함수 안에 쓴 주석은 나중에 자동으로 API 문서(Swagger)의 상세 설명으로 변환됩니다.
[기본 응답 및 사용자 생성]
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.post("/users")
def create_user(user: UserItem):
return {"message": f"{user.name}님 환영합니다."}
- create_user: UserItem 모델을 사용하여 클라이언트가 보낸 데이터가 올바른지 검증하고, 정상일 경우 user.name을 이용해 환영 메시지를 반환합니다.
4. 다양한 응답 형식 반환
FastAPI는 기본적으로 JSON을 반환하지만, 특정 형식으로 강제할 수 있습니다.
# 1. 텍스트 반환
@app.get("/text", response_class=PlainTextResponse)
def get_text():
return "Hello World"
# 2. HTML 반환
@app.get("/html", response_class=HTMLResponse)
def get_html():
return "<h1>안녕하세요</h1>"
- response_class: 서버가 응답을 보낼 때 브라우저에게 "이건 JSON이야", "이건 HTML이야"라고 알려주는 역할을 합니다.
5. 서버 실행
if __name__ == "__main__":
uvicorn.run("S001:app", host="127.0.0.1", port=8000, reload=True)
# 콘솔과 동일: uvicorn main:app --host 127.0.0.1 --port 8000 --reload
- uvicorn.run: FastAPI 애플리케이션(app)을 실행하는 서버 엔진입니다.
- reload=True: 코드를 수정하고 저장하면 서버를 껐다 켜지 않아도 자동으로 반영해주는 개발용 핵심 옵션입니다.
# EX) PYTHON02
1. 필수 라이브러리 및 설정
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
app = FastAPI()
# 템플릿(HTML)이 있는 폴더 지정
templates = Jinja2Templates(directory="0610/templates")
# 정적 파일(CSS, JS, 이미지)이 있는 폴더 마운트
app.mount("/static", StaticFiles(directory="0610/static"), name="static")
- Jinja2Templates: HTML 파일 안에 파이썬 변수를 쏙 집어넣어 동적인 웹 페이지를 만드는 도구입니다. (예: {{ title }})
- app.mount("/static", ...): 브라우저가 CSS나 JS 파일을 요청할 때, 서버 내부의 0610/static 폴더에서 파일을 찾아 건네주겠다는 약속입니다.
2. 메인 페이지 라우팅
@app.get("/")
async def read_root(request: Request):
context = {"title": "FastAPI 템플릿 예제", "message": "Hello World"}
return templates.TemplateResponse(
request=request,
name="index.html",
context=context
)
- request: Request: FastAPI가 현재 접속한 사용자의 정보(IP, 헤더 등)를 담아 자동으로 전달해주는 객체입니다. 템플릿을 렌더링할 때 반드시 필요합니다. (HTML 페이지를 보여줄 때만 필요)
- async (비동기): 이 함수가 실행되는 동안 서버가 멈추지 않고 다른 요청도 동시에 처리할 수 있게 합니다. 데이터베이스 조회나 파일 읽기처럼 시간이 걸리는 작업을 할 때 매우 중요합니다.
- request=request: 이 템플릿을 요청한 사용자가 누구인지, 어떤 환경(브라우저 언어, 쿠키 등)인지 파악해서 보내기
- name = "index.html": 어떤 HTML 파일을 가져올 지 보내기
- context: HTML 파일로 보낼 파이썬 데이터입니다. index.html 안에서 {{ title }}이라고 쓰면 "FastAPI 템플릿 예제"라는 글자가 나타나게 됩니다.
Q. 왜 async를 붙이나요?
FastAPI는 비동기 프레임워크입니다.
- 보통 웹 서버는 한 번에 한 명의 요청만 처리하면 느려지는데, async를 사용하면 "데이터를 DB에서 가져오는 동안(기다리는 시간)" 다른 사용자의 접속을 먼저 처리할 수 있습니다.
- 따라서, 성능을 극대화하려면 DB 작업이 포함된 함수에는 async를 붙이는 것이 권장됩니다.
# EX) PYTHON03
1. 주요 라이브러리 및 변수
from fastapi import FastAPI
import asyncio
import uvicorn
from fastapi.responses import PlainTextResponse
app = FastAPI()
total = ''
- asyncio: 파이썬에서 비동기 프로그래밍을 할 때 사용하는 표준 라이브러리입니다.
- total: 여러 비동기 함수들이 결과를 합치는 공용 변수입니다.
2. 비동기 함수 (Async Tasks)
async def async_func():
await asyncio.sleep(2) # 2초 동안 '대기' (다른 일 할 수 있음)
global total
total += "Async World1 "
async def async_func2():
await asyncio.sleep(1) # 1초 동안 '대기'
global total
total += "Async World2 "
- async def: 이 함수는 비동기 함수(코루틴)임을 선언합니다.
- await asyncio.sleep(n): 가장 중요한 부분입니다. 여기서 "n초간 쉬어라"라고 명령하는데, 이때 "나는 쉬는 동안 CPU는 다른 일을 해!"라고 컴퓨터에게 제어권을 넘겨줍니다.
- 덕분에 async_func가 2초를 쉬는 동안 CPU는 1초 쉬는 async_func2를 먼저 처리할 수 있게 됩니다.
3. 메인 API 엔드포인트 (read_root)
@app.get("/", response_class=PlainTextResponse)
async def read_root():
global total
total = ""
# 작업을 생성하고 동시에 실행 시작
task1 = asyncio.create_task(async_func())
task2 = asyncio.create_task(async_func2())
# 모든 작업이 끝날 때까지 기다림
await task1
await task2
return total
- asyncio.create_task(...): 이 명령은 함수를 바로 실행하지 않고, "이 작업을 백그라운드에서 실행해 놔!"라고 예약하는 것과 같습니다.
- 동시 처리의 마법: task1을 만들자마자 바로 task2도 만들어버립니다. 즉, task1이 2초를 쉬는 동안 task2가 1초를 쉬고 먼저 완료되는 구조가 됩니다.
- await task1, await task2: 예약해 둔 작업들이 끝날 때까지 기다렸다가 다음 단계로 넘어갑니다.
# EX) PYTHON04
1. 외부 데이터 호출의 핵심 httpx
import httpx
# ...
async with httpx.AsyncClient() as client:
response = await client.get(url)
weather_data = response.json()
- httpx: 파이썬에서 다른 서버(여기서는 Open-Meteo)로 데이터를 요청할 때 사용하는 라이브러리입니다. requests와 비슷하지만, 비동기(Async)를 지원하기 때문에 FastAPI와 궁합이 매우 좋습니다.
- AsyncClient(): 비동기 방식으로 데이터를 받아옵니다. await를 사용하여 데이터가 올 때까지 서버가 멈추지 않게 합니다.
2. 데이터 가공 (데이터 정제)
times = weather_data["hourly"]["time"]
temperatures = weather_data["hourly"]["temperature_2m"]
hourly_forecast = list(zip(times, temperatures))
- zip(times, temperatures): 이것은 아주 효율적인 기법입니다. 시간 리스트와 기온 리스트가 따로 놀고 있을 때, 이 둘을 순서대로 하나씩 짝을 지어 (시간, 온도) 형태의 튜플 리스트로 만들어 줍니다.
- HTML에서 반복문을 돌릴 때 아주 편리한 구조가 됩니다.
3. 화면 전달 및 제한
context = {
"title": "서울 시간별 기온 예보",
"forecast": hourly_forecast[:24]
}
- hourly_forecast[:24]: 데이터가 너무 많으면 사용자가 읽기 힘듭니다. 파이썬의 슬라이싱([:24]) 기능을 사용해 딱 필요한 24시간치만 잘라서 깔끔하게 보여줍니다.
——————————————————————————
본 후기는 [한글과컴퓨터x한국생산성본부x스나이퍼팩토리] 한컴 AI 아카데미 (B-log) 리뷰로 작성 되었습니다.
'학습일지' 카테고리의 다른 글
| [스나이퍼팩토리] 한컴AI아카데미(26.06.17) Pandas (0) | 2026.06.17 |
|---|---|
| [스나이퍼팩토리] 한컴AI아카데미(26.06.11) JWT 기반 인증 (0) | 2026.06.11 |
| [스나이퍼팩토리] 한컴AI아카데미(26.06.09) 네이버메일보내기자동화(Selenium) (0) | 2026.06.10 |
| [스나이퍼팩토리] 한컴AI아카데미(26.06.08) Selenium (0) | 2026.06.09 |
| [스나이퍼팩토리] 한컴AI아카데미(26.06.05) 웹 스크랩핑(BeautifulSoup) (0) | 2026.06.05 |