학습일지

[스나이퍼팩토리] 한컴AI아카데미(26.06.10) Fast API

cd-record 2026. 6. 10. 19:29

 

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시간치만 잘라서 깔끔하게 보여줍니다.

001.ipynb
0.02MB

 

 

 

 



——————————————————————————

본 후기는 [한글과컴퓨터x한국생산성본부x스나이퍼팩토리] 한컴 AI 아카데미 (B-log) 리뷰로 작성 되었습니다.