✍️ 필사 모드: Python 완전 가이드 — FastAPI·AsyncIO·Pydantic·uv·Polars·AI 엔지니어링 (Season 2 Ep 5, 2025)
한국어들어가며 — 2025년의 Python은 2015년의 Python이 아니다
Python을 10년 전 배우고 지금 돌아온 사람이 가장 놀랄 변화들:
- uv (2024): pip·poetry·pyenv·pip-tools를 모두 대체하는 Rust 작성 통합 도구. 10~100배 빠름
- Pydantic v2 (2023): 검증 엔진을 Rust로 재작성. 5~50배 빠름
- FastAPI: 타입 힌트 기반 API 프레임워크의 사실상 표준
- Polars (2024~): Pandas 대체. Rust 기반, 10~100배 빠름, 메모리 효율
- Python 3.13 (2024/10): Free-threading(No-GIL) 실험, JIT 컴파일러, 개선된 인터랙티브 쉘
- LangChain·LangGraph·Pydantic AI (2024~): AI 에이전트 스택
- Ruff + mypy / pyright: Lint·Format·타입체크 모두 빠른 도구로 교체
Python은 "AI 엔지니어링의 공용어"로 확고히 자리잡았고, 도구 체인 전체가 Rust로 재작성되며 속도 문제도 해결되고 있다.
1부 — Python 3.13: 언어의 미래
1.1 Free-threading (No-GIL) — PEP 703
30년 된 GIL(Global Interpreter Lock)을 제거하는 Experimental Build 등장 (2024/10):
python3.13t # free-threaded build
- GIL: 한 번에 1개 스레드만 Python 바이트코드 실행
- No-GIL: 진정한 멀티코어 병렬성
한계: 현재 실험적, 단일 스레드 성능 10% 하락, C 확장 호환성 이슈. 20262027년 안정화 예상.
1.2 JIT Compiler — PEP 744
Copy-and-Patch JIT 추가 (실험):
python --enable-experimental-jit
초기 벤치마크는 미미(~5%)지만 장기적으로 PyPy 수준의 성능 가능성.
1.3 개선된 REPL
3.13의 표준 REPL이 드디어 사용 가능:
- 멀티라인 편집
- 구문 하이라이팅
- 페이스트 모드
- 블록 히스토리
PyPy·ipython에 의존했던 것들이 기본으로.
1.4 Type System 개선 (3.12~3.13)
# PEP 695: Generic Syntax
def first[T](items: list[T]) -> T:
return items[0]
class Stack[T]:
def __init__(self) -> None:
self.items: list[T] = []
# PEP 696: Type Parameter Defaults
def process[T = str](x: T) -> T: ...
# PEP 742: TypeIs
from typing import TypeIs
def is_str(x: object) -> TypeIs[str]:
return isinstance(x, str)
2부 — uv: 패키지 매니저 혁명
2.1 왜 uv가 게임 체인저인가
Astral이 만든 Rust 기반 통합 도구 (Ruff 제작사). 대체 대상:
- pip → 설치
- pip-tools → 해시 pinned requirements
- pyenv → 파이썬 버전 관리
- virtualenv/venv → 가상환경
- poetry → 프로젝트 관리
- pipx → CLI 도구 설치
속도: pip install이 10초 걸리는 프로젝트가 uv로는 0.1초.
2.2 기본 사용법
# 설치
curl -LsSf https://astral.sh/uv/install.sh | sh
# 프로젝트 초기화
uv init my-app
cd my-app
# 의존성 추가 (pyproject.toml 자동 업데이트)
uv add fastapi uvicorn
uv add --dev pytest ruff mypy
# 실행
uv run python main.py
uv run pytest
# Python 버전 관리
uv python install 3.13
uv python pin 3.13
# Lock 파일 (uv.lock)
uv lock
uv sync
2.3 uv script (단일 파일 Python)
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "httpx",
# "rich",
# ]
# ///
import httpx
from rich import print
print(httpx.get("https://api.github.com").json())
uv run script.py
# 의존성 자동 다운로드 후 실행
2025년 새 프로젝트는 uv로 시작하는 것이 표준.
3부 — Pydantic v2: 타입 기반 검증
3.1 v2의 혁명
- Rust로 재작성된
pydantic-core - 5~50배 빠름
Annotated기반 강력한 제약- Serialization API 분리
3.2 기본 사용
from pydantic import BaseModel, EmailStr, Field
from typing import Annotated
from datetime import datetime
class User(BaseModel):
id: int
email: EmailStr
name: Annotated[str, Field(min_length=1, max_length=100)]
age: Annotated[int, Field(ge=0, le=150)]
created_at: datetime
# 검증 + 변환
user = User.model_validate({
"id": 1,
"email": "alice@example.com",
"name": "Alice",
"age": 30,
"created_at": "2025-01-01T00:00:00Z"
})
# 직렬화
json_str = user.model_dump_json()
dict_data = user.model_dump()
3.3 고급 기능
from pydantic import field_validator, model_validator
class Post(BaseModel):
title: str
content: str
tags: list[str] = []
@field_validator('title')
@classmethod
def title_not_empty(cls, v: str) -> str:
if not v.strip():
raise ValueError('title cannot be empty')
return v.strip()
@model_validator(mode='after')
def check_tags_limit(self) -> 'Post':
if len(self.tags) > 10:
raise ValueError('too many tags')
return self
3.4 Pydantic Settings
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
database_url: str
api_key: str
debug: bool = False
class Config:
env_file = ".env"
settings = Settings()
환경변수·config 관리의 표준.
4부 — FastAPI: 타입 안전 API 표준
4.1 기본 예제
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
app = FastAPI()
class UserCreate(BaseModel):
email: str
password: str
class UserResponse(BaseModel):
id: int
email: str
@app.post("/users", response_model=UserResponse)
async def create_user(user: UserCreate) -> UserResponse:
# user는 이미 검증됨
# 응답은 UserResponse로 자동 직렬화
return UserResponse(id=1, email=user.email)
- Pydantic 모델이 요청·응답 스키마
- OpenAPI 자동 생성 (
/docs) - Dependency Injection 내장
4.2 Dependency Injection
async def get_db() -> AsyncGenerator[AsyncSession, None]:
async with async_session() as session:
yield session
async def get_current_user(token: str = Header(...)) -> User:
# 토큰 검증 로직
return user
@app.get("/me")
async def me(user: User = Depends(get_current_user)) -> UserResponse:
return user
4.3 2025년 FastAPI 스택
| 목적 | 라이브러리 |
|---|---|
| Web | FastAPI |
| ORM | SQLAlchemy 2.0 (async), SQLModel |
| DB 드라이버 | asyncpg (Postgres), motor (Mongo) |
| Migration | Alembic |
| 큐 | Dramatiq, Celery 5.x, Taskiq |
| 캐시 | Redis + aioredis |
| 테스트 | pytest + httpx |
| 관측성 | OpenTelemetry + Prometheus |
5부 — AsyncIO 실전
5.1 기본 구조
import asyncio
async def fetch(url: str) -> str:
# 시뮬레이션
await asyncio.sleep(1)
return f"data from {url}"
async def main() -> None:
# 순차
r1 = await fetch("a")
r2 = await fetch("b")
# 동시 (2배 빠름)
r1, r2 = await asyncio.gather(fetch("a"), fetch("b"))
asyncio.run(main())
5.2 TaskGroup (Python 3.11+)
async def main():
async with asyncio.TaskGroup() as tg:
t1 = tg.create_task(fetch("a"))
t2 = tg.create_task(fetch("b"))
t3 = tg.create_task(fetch("c"))
# 컨텍스트 나오면 모든 task 완료
# 하나라도 예외면 나머지 취소 + ExceptionGroup
print(t1.result(), t2.result(), t3.result())
TaskGroup이 asyncio.gather보다 낫다: 구조적 동시성, 자동 취소, 명확한 에러.
5.3 asyncio.timeout (Python 3.11+)
async def fetch_with_timeout():
async with asyncio.timeout(5.0):
return await slow_operation()
5.4 AsyncIO 함정 5가지
- 블로킹 코드 혼합:
requests.get대신httpx.AsyncClient asyncio.run중첩: 이벤트 루프 충돌.nest_asyncio는 아티 패턴- task 참조 유지 실패:
asyncio.create_task결과를 어딘가 저장해야 GC 안됨 - CPU 바운드 작업:
run_in_executor로 별도 스레드/프로세스 async def안에서time.sleep:asyncio.sleep써야
6부 — Polars: Pandas의 2025년 대체재
6.1 왜 Polars인가
| 항목 | Pandas | Polars |
|---|---|---|
| 엔진 | NumPy (C) | Rust + Arrow |
| 속도 | 기준 | 5~100배 빠름 |
| 메모리 | 많이 씀 | Pandas의 ~50% |
| 병렬성 | 거의 없음 | 자동 다중 스레드 |
| Lazy 실행 | ❌ | ✅ (옵티마이저) |
| 대규모 데이터 | 어려움 | 스트리밍 가능 |
6.2 기본 사용
import polars as pl
df = pl.read_csv("data.csv")
result = (
df
.filter(pl.col("age") > 30)
.group_by("country")
.agg([
pl.col("salary").mean().alias("avg_salary"),
pl.col("id").count().alias("count"),
])
.sort("avg_salary", descending=True)
)
6.3 Lazy Evaluation
lazy_df = pl.scan_csv("huge.csv") # 실제 읽지 않음
result = (
lazy_df
.filter(pl.col("year") == 2024)
.group_by("category")
.agg(pl.col("amount").sum())
.collect() # 이제 실행 (옵티마이저가 계획 수립)
)
쿼리 옵티마이저가 SQL DBMS처럼 실행 계획을 최적화.
6.4 2025년 전환 가이드
- 새 프로젝트: Polars 기본값
- 기존 Pandas 프로젝트: 점진 전환 (
df.to_pandas()브릿지) - 시각화는 여전히 Pandas가 편할 수 있음 (matplotlib/seaborn)
- ML 라이브러리 호환은 아직 Pandas 우세 (개선 중)
7부 — AI 엔지니어링 스택 2025
7.1 LangChain의 현재
LangChain은 2023년 폭발, 2024년 성장통, 2025년 LangGraph 중심으로 재편.
- LangChain Core: 기본 추상화 (Runnable)
- LangGraph: 상태 기반 에이전트 그래프 (2025년 표준)
- LangSmith: 관측성·평가
7.2 LangGraph 예제
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
class State(TypedDict):
messages: Annotated[list, operator.add]
def agent(state: State):
response = llm.invoke(state["messages"])
return {"messages": [response]}
def should_continue(state: State) -> str:
last = state["messages"][-1]
if last.tool_calls:
return "tools"
return END
workflow = StateGraph(State)
workflow.add_node("agent", agent)
workflow.add_node("tools", tool_node)
workflow.set_entry_point("agent")
workflow.add_conditional_edges("agent", should_continue)
workflow.add_edge("tools", "agent")
app = workflow.compile()
Directed Graph + 상태 머신 모델. 복잡한 에이전트 흐름에 이상적.
7.3 Pydantic AI (2024~)
Pydantic 팀이 만든 타입 안전 에이전트 프레임워크. 경량·직관적.
from pydantic_ai import Agent
from pydantic import BaseModel
class WeatherResponse(BaseModel):
city: str
temp_c: float
condition: str
agent = Agent(
'openai:gpt-4o',
result_type=WeatherResponse,
system_prompt='You are a weather assistant.',
)
result = await agent.run('Weather in Seoul?')
print(result.data) # WeatherResponse 타입
7.4 2025년 AI 스택 추천
| 상황 | 추천 |
|---|---|
| 복잡한 멀티스텝 에이전트 | LangGraph |
| 간단한 타입 안전 에이전트 | Pydantic AI |
| RAG 특화 | LlamaIndex |
| 프로덕션 최소 의존성 | OpenAI SDK 직접 |
| TS 팀과 협업 | Vercel AI SDK (TS) 매치 |
8부 — Modern Python 개발 환경
8.1 도구 체인 (2025 표준)
# pyproject.toml
[project]
name = "my-app"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"fastapi>=0.115",
"pydantic>=2.9",
"uvicorn>=0.30",
]
[dependency-groups]
dev = [
"pytest>=8",
"ruff>=0.7",
"mypy>=1.13",
]
[tool.ruff]
line-length = 100
[tool.ruff.lint]
select = ["E", "F", "I", "N", "UP", "B", "S", "C4", "PL"]
[tool.mypy]
strict = true
8.2 Ruff — 10~100배 빠른 린터/포매터
- Flake8, Black, isort, pyupgrade, pylint 대체
- Rust 작성
- 800+ 규칙 내장
8.3 타입 체커 선택
| 도구 | 특징 |
|---|---|
| mypy | 가장 오래됨, 느림, 보수적 |
| pyright | MS 제작, 빠름, 엄격 |
| pyre | Meta 제작, 서버 모드 |
| ty | Astral 제작 (2025), Rust 기반 (개발 중) |
2025년 추천: 신규는 pyright, 기존은 mypy 유지. ty 출시 기다리는 중.
8.4 테스트
# pytest + httpx for FastAPI
import pytest
from httpx import AsyncClient, ASGITransport
from myapp.main import app
@pytest.mark.asyncio
async def test_create_user():
async with AsyncClient(
transport=ASGITransport(app=app), base_url="http://test"
) as ac:
r = await ac.post("/users", json={"email": "a@b.com", "password": "pw"})
assert r.status_code == 200
9부 — Python이 빛나는 분야 vs 빛나지 않는 분야
9.1 빛남
- AI/ML: PyTorch, JAX, scikit-learn, Hugging Face
- 데이터 엔지니어링: Airflow, dbt, Dagster
- API 서버: FastAPI의 생산성
- 과학 컴퓨팅: NumPy, SciPy
- 스크립팅/자동화: 글루 언어
- 교육: 학습 곡선 낮음
9.2 빛나지 않음
- CPU 바운드 고성능: Rust/Go/C++
- 모바일 앱: Swift/Kotlin
- 임베디드: C/Rust
- 게임 엔진: C++
- 브라우저: JS/TS (Pyodide는 특수 용도)
2025년 현실: Python은 "AI·데이터·API"의 표준이지만, "모든 것을 위한" 언어는 아니다.
10부 — Python 마스터 로드맵 6개월
Month 1: 3.13 기본기
- 타입 힌트 완전 이해 (PEP 695, Union, Literal, Protocol)
- uv로 프로젝트 관리
- Ruff + mypy/pyright 설정
Month 2: Pydantic + FastAPI
- Pydantic v2 심화 (Annotated, Validators)
- FastAPI 실전 API 만들기
- Dependency Injection 패턴
Month 3: AsyncIO
- TaskGroup, asyncio.timeout
- httpx·asyncpg 비동기 DB
- 동시성 제한 (Semaphore)
Month 4: 데이터 처리
- Polars 마스터
- SQL + SQLAlchemy 2.0 async
- DuckDB + Parquet
Month 5: AI 엔지니어링
- OpenAI/Anthropic SDK
- LangGraph 또는 Pydantic AI
- Vector DB (Qdrant, Pinecone, pgvector)
- RAG 파이프라인 구축
Month 6: 운영
- Docker + Kubernetes 배포
- 관측성 (OpenTelemetry, Prometheus)
- CI/CD (GitHub Actions)
- 프로파일링 (py-spy, scalene)
11부 — Python 체크리스트 12
- uv의 4가지 대체 도구(pip/poetry/pyenv/pip-tools)를 안다
- Pydantic v1 vs v2 주요 변화를 안다
- FastAPI Dependency Injection 사용법을 안다
- TaskGroup vs asyncio.gather 차이를 안다
- Polars Lazy Evaluation의 장점을 안다
- 타입 힌트 Protocol, TypeIs 사용법을 안다
- SQLAlchemy 2.0 async 스타일을 안다
- GIL과 Free-threading의 의미를 안다
- LangGraph와 LangChain의 관계를 안다
- Ruff가 대체하는 도구들을 안다
- Pydantic Settings로 설정 관리를 할 수 있다
- pytest + httpx로 async API 테스트를 쓸 수 있다
12부 — Python 안티패턴 10
pip install+requirements.txt만 사용: 재현성 취약.uv+uv.lock- 타입 힌트 없이 Python 코드 작성: mypy/pyright로 잡힐 버그 방치
from X import *: 네임스페이스 오염print()로 디버깅:logging또는richexcept Exception: pass: 조용히 실패. 구체 예외 + 로깅- 뮤터블 기본 인자:
def f(x=[]):→ 공유됨.x=None후x or [] - Pandas에서
iterrows: 느림. 벡터 연산 또는 Polars - Sync 라이브러리를 async 함수에서: 이벤트 루프 블록
os.path대신pathlib를 안 씀: pathlib 훨씬 깔끔- 도커 이미지에
pip install -r requirements.txt: layer caching 망침.uv sync --frozen
마치며 — Python은 AI 시대에 다시 태어났다
Python의 원래 강점은 "생산성과 학습 곡선"이었다. 단점은 "속도와 동시성"이었다.
2024~2025년:
- 속도: uv·Pydantic·Polars·Ruff가 Rust 엔진으로 해결
- 동시성: Free-threading 실험, AsyncIO 성숙
- 타입: 3.12~3.13의 PEP들로 강력해짐
- 생태계: AI 엔지니어링의 표준 언어
"Python이 느리다"는 2020년까지의 이야기였다. 2025년 Python은 **"AI 시대의 공용어이자, Rust 도구들로 빨라진 언어"**다.
시니어 엔지니어가 Python을 안 다룰 수 없는 이유는 명확하다. AI·데이터·API·스크립팅에서 Python은 여전히, 그리고 앞으로도 지배적이다.
다음 글 예고 — "LLM 완전 가이드: Transformer·Attention·RLHF·RAG·Agent·Evaluation"
Season 2 Ep 6은 2025년 엔지니어의 교양, LLM의 내부 구조. 다음 글은:
- Transformer가 실제로 어떻게 동작하는가
- Attention 메커니즘 수식까지
- Pre-training → SFT → RLHF → DPO 흐름
- RAG의 3세대 진화 (Naive → Advanced → Agentic)
- Agent 설계 (ReAct, Plan-and-Execute, Multi-Agent)
- LLM 평가의 진짜 어려움 (LM-as-a-Judge의 한계)
블랙박스를 뜯어보는 시간, 다음 글에서 이어진다.
현재 단락 (1/346)
Python을 10년 전 배우고 지금 돌아온 사람이 가장 놀랄 변화들: