Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 하늘도시맛집
- 하루기록
- 클라우드엔지니어
- 카카오엔터프라이즈
- 카카오클라우드
- 개발자교육
- 포트폴리오
- olist
- 파이썬문법
- 하늘도시속눈썹
- 데이터분석
- AIaaS마스터클래스2기
- 부트캠프
- AIaaS
- Kaggle
- 태블로
- 데이터분석포트폴리오
- 클라우드개발자
- tableau
- 이커머스데이터분석
- 한국생산성본부
- 인턴생활
- 오늘의로하
- 영종도카페
- 스나이퍼팩토리
- 꾸석지돌판한우
- wecookieyou
- sql
- 판교생활
- 판교타코익스프레스
Archives
- Today
- Total
Alroha
[스나이퍼팩토리] 카카오클라우드 - 클라우드 개발자 교육 6주차(3) 본문
REST & FastAPI
(REST 아키텍처, FastAPI·Uvicorn·APIRouter 관계, 경로 매개변수, API 문서(Swagger/Redoc), 응답 유형 & 헤더, 디자인 패턴)
📅 REST와 FastAPI 기초
🧩 REST 개념 요약
| 아키텍처 스타일 | 웹 서비스 설계 원칙의 모음 | “메뉴판(API 문서)에서 음식(리소스) 고르고 주문(요청) → 음식(응답) 받기” |
| 자원(Resource) | 명사형으로 표현, URI로 식별 | /products/123, /users/42/orders/7 |
| 표현(Representation) | 같은 자원을 JSON, XML, HTML 등 여러 표현으로 주고받음 | 웹: HTML, 앱: JSON |
| 상태 전이(State Transfer) | 링크를 따라 리소스 간 이동하며 애플리케이션 상태 변화 | 목록 → 상세 → 장바구니 → 결제 |
| 무상태성(Stateless) | 요청은 독립적, 서버는 클라이언트 상태 저장 X | 매 요청에 토큰 포함 |
| 통합 인터페이스 | 일관된 조작 방식(보통 HTTP) | 모든 가전의 전원 버튼처럼 일관성 |
RESTful vs Non-RESTful 예시
# RESTful
GET /users/123
POST /users
PATCH /users/123
DELETE /users/123
# Non-RESTful (행위 동사 노출, 파라미터 위주)
GET /getUser?id=123
🧭 FastAPI · Uvicorn · APIRouter
- FastAPI: 앱 프레임워크(라우팅, 요청/응답, 검증, 의존성 주입, 문서화)
- Uvicorn: ASGI 서버(실제 HTTP 서버, 비동기 고성능)
- APIRouter: 라우트를 기능별 모듈로 분리/조합
[Client] ⇄ HTTP ⇄ [Uvicorn] ⇄ ASGI ⇄ [FastAPI(App)] ⇄ [APIRouter…]
실습
# app/main.py
from fastapi import FastAPI, APIRouter
from pydantic import BaseModel
app = FastAPI(title="Todo API")
router = APIRouter(prefix="/todo", tags=["todo"])
class Todo(BaseModel):
id: int
text: str
done: bool = False
DB = {1: Todo(id=1, text="REST 복습")}
@router.get("", response_model=list[Todo])
def list_todos():
return list(DB.values())
@router.get("/{todo_id}", response_model=Todo)
def get_todo(todo_id: int):
return DB[todo_id]
app.include_router(router)
실행
uvicorn app.main:app --reload
# 문서: http://127.0.0.1:8000/docs (Swagger) / http://127.0.0.1:8000/redoc (Redoc)
🧵 경로 매개변수(동적 라우팅)
- URL 템플릿과 정규식 기반 매칭 → OpenAPI 스펙으로 타입·범위 검증, 지정된 Python 타입으로 자동 캐스팅
- 예: @router.get("/users/{user_id}") → user_id: int로 자동 변환 및 유효성 검사
🧪 curl 호출 구성 이해
curl -X 'GET' 'http://127.0.0.1:8000/todo' -H 'accept: application/json'
# -X: 메서드 지정, URL: 엔드포인트, -H: 헤더(원하는 응답 타입)
🧰 프레임워크 비교 (장단점 & 사용 사례)
항목 FastAPI Flask Django
| FastAPI | Flask | Django | |
| 특징 | 현대적 API-first, 타입 힌트 기반 검증/문서 자동화 | 마이크로 프레임워크, 유연 | 배터리 포함 풀스택(ORM/관리자/인증) |
| 성능 | 매우 높음(ASGI, 비동기) | 중간(WSGI, 확장에 따라) | 중간(WSGI; ASGI 지원은 점진적) |
| 개발속도 | 빠름(Pydantic 검증, 자동 스웨거) | 빠름(간단한 시작) | 복잡하지만 큰 서비스에 구조적 |
| 생태계 | 중간↑(폭발적 성장) | 매우 넓음(플러그인 다수) | 매우 넓음(ORM, Admin, Auth 강력) |
| 적합도 | REST/GraphQL API, 마이크로서비스 | 소규모 API/PoC/확장 자유 | 대규모 서비스, 관리 백오피스, 전통적 웹 |
| 문서화 | /docs, /redoc 자동 제공 | 확장 필요(Flasgger 등) | DRF 사용 시 스키마/문서화 지원 |
| 학습곡선 | 낮음~중간 | 낮음 | 중간~높음(DRF 포함 시) |
=> 사용 사례
- FastAPI: 고성능 API, 실시간/비동기 I/O, 데이터 검증 많은 서비스, MSA 게이트웨이
- Flask: 아주 가벼운 API, 프로토타이핑, 커스텀 구성이 중요한 경우
- Django(+DRF): 인증/권한/ORM/관리자 콘솔이 필요한 일반 웹 서비스 전반, 대규모 팀
📅 응답 & 헤더
📦 기본 응답 유형
| JSON | 표준 API 응답 | 기본 반환(dict) 또는 JSONResponse |
| HTML | 템플릿 렌더링 | HTMLResponse, Jinja2 연동 |
| 텍스트 | 단순 메시지 | PlainTextResponse |
| 파일 | 다운로드/정적 | FileResponse, StreamingResponse |
커스텀 응답
- 상태 코드/헤더/바디를 명시적으로 제어
- 예: 비즈니스 규칙에 맞는 에러 포맷, 캐시 전략
from fastapi import FastAPI, Response, status
from fastapi.responses import JSONResponse, HTMLResponse, FileResponse, PlainTextResponse
app = FastAPI()
@app.get("/health")
def health():
return {"status": "ok"}
@app.get("/hello", response_class=PlainTextResponse)
def hello():
return "Hello"
@app.get("/page", response_class=HTMLResponse)
def page():
return "<h1>Hi</h1>"
@app.get("/download")
def download():
return FileResponse("report.pdf", filename="report.pdf")
@app.get("/custom")
def custom():
return JSONResponse(
status_code=status.HTTP_202_ACCEPTED,
content={"message": "accepted"},
headers={"Cache-Control": "no-store"}
)
📨 주요 HTTP 헤더 🔑
- Content-Type: application/json, text/html; charset=utf-8
- Authorization: Bearer <token>
- Cache-Control: no-store, max-age=60
- Custom Headers: X-Request-Id, X-Rate-Limit-Remaining 등
🏗️ FastAPI 심화 — 구조 & 패턴
권장 디렉터리 예
app/
├─ core/ # 설정, 의존성, 보안
├─ routers/ # APIRouter 모듈(users.py, posts.py, auth.py)
├─ schemas/ # Pydantic 모델
├─ services/ # 비즈니스 로직
├─ repositories/# 데이터 접근(Repository 패턴)
├─ models/ # ORM 모델(SQLAlchemy 등)
└─ main.py
디자인 패턴 요약
패턴 목적 FastAPI에서의 이점/예
| 계층형 아키텍처 | 책임 분리 | Router ↔ Service ↔ Repository로 결합도↓ |
| 모듈화(단일 책임) | 기능별 분리 | users, posts, auth 라우터·서비스·스키마 분리 |
| Repository | DB 접근 캡슐화 | DB 교체 용이, 테스트에서 in-memory 대체 쉬움 |
| 싱글턴 | 인스턴스 1개 보장 | 설정/클라이언트(예: Redis, Kafka) 공유 |
| 팩토리 | 생성 로직 캡슐화 | 클라이언트/서비스 구성 시 파라미터별 객체 선택 |
| 옵저버(이벤트) | 상태 변화 통지 | 사용자 가입 시 이메일 전송/로그 기록 비동기 처리 |
Repository 스케치
# app/repositories/todo.py
class TodoRepo:
def __init__(self, db):
self.db = db
def list(self): ...
def get(self, id: int): ...
def create(self, dto): ...
서비스는 Repo에 의존하고, 라우터는 서비스에 의존해 테스트가 수월함.
💡 궁금한 것
❗️“Uvicorn이 FastAPI 인스턴스를 가리킨다” ?
- FastAPI()로 앱 인스턴스를 생성하고, Uvicorn이 module_name:app_object 형태로 해당 객체를 엔트리포인트로 실행한다는 뜻.
예: uvicorn app.main:app --reload → app/main.py의 app 객체.
🧠 Summary
- REST: 자원(명사) 중심 + 표현 교환 + 무상태 + 일관 인터페이스
- URI: 계층 구조 유지(/users/{id}/orders/{id}), 동사 대신 메서드 사용
- 경로 매개변수: 타입·유효성 자동 검증, 문서화 자동 생성(OpenAPI)
- 문서화: Swagger /docs(상호작용), Redoc /redoc(정독용)
- 응답: JSON/HTML/텍스트/파일 + 커스텀(상태·헤더 제어)
- 헤더: Content-Type, Authorization, Cache-Control 필수 숙지
- 구조/패턴: Router 분할 + Service/Repository로 책임 분리 → 테스트/확장성 ↑
- 비교: 실시간/비동기는 FastAPI, 단촐한 실험은 Flask, 풀스택·관리도구는 Django
본 후기는 [카카오엔터프라이즈x스나이퍼팩토리] 카카오클라우드로 배우는 AIaaS 마스터 클래스 2기(B-log) 리뷰로 작성 되었습니다.
'IT > Kakao cloud 부트캠프' 카테고리의 다른 글
| [스나이퍼팩토리] 카카오클라우드 - 클라우드 개발자 교육 7주차(입출력, 텍스트 처리) (0) | 2025.09.18 |
|---|---|
| [스나이퍼팩토리] 카카오클라우드 - 클라우드 개발자 교육 7주차(리눅스 기본) (0) | 2025.09.18 |
| [스나이퍼팩토리] 카카오클라우드 - 클라우드 개발자 교육 6주차(4) (0) | 2025.09.12 |
| [스나이퍼팩토리] 카카오클라우드 - 클라우드 개발자 교육 6주차(2) (2) | 2025.09.09 |
| [스나이퍼팩토리] 카카오클라우드 - 클라우드 개발자 교육 6주차(1) (1) | 2025.09.08 |