FastAPI 살펴보기
🗺️ 전체 학습 로드맵
📚 목차별 상세 내용
📘 1장: FastAPI 시작하기
1.4 FastAPI 설치 및 프로젝트 생성
🎯 첫 번째 FastAPI 앱 만들기
- 터미널 열기
- Windows: PowerShell
-
Mac: Terminal
-
프로젝트 폴더 만들기
- 가상환경 만들기 (프로젝트별 독립 공간)
python -m venv venv
# Windows에서 활성화
venv\Scripts\activate
# Mac/Linux에서 활성화
source venv/bin/activate
- FastAPI 설치하기
- 첫 번째 코드 작성 (main.py)
from fastapi import FastAPI
# FastAPI 앱 만들기
app = FastAPI()
# 첫 번째 API 엔드포인트
@app.get("/")
def read_root():
return {"message": "안녕하세요! FastAPI입니다!"}
- 서버 실행하기
- 브라우저에서 http://localhost:8000 접속
- API 문서는 http://localhost:8000/docs
📗 2장: FastAPI로 기본 API 만들기
2.1 기본 라우팅
🎯 라우팅이란?
- URL 주소에 따라 다른 함수를 실행하는 것
- 예:
/→ 홈페이지,/about→ 소개 페이지
📝 실습 코드
from fastapi import FastAPI
app = FastAPI()
# GET 요청: 데이터 가져오기
@app.get("/")
def home():
return {"message": "홈페이지입니다"}
@app.get("/about")
def about():
return {"message": "소개 페이지입니다"}
# POST 요청: 데이터 보내기
@app.post("/create")
def create():
return {"message": "새로운 데이터를 만들었습니다"}
💡 HTTP 메서드 이해하기 - GET: 데이터 조회 (읽기) - POST: 데이터 생성 (쓰기) - PUT: 데이터 수정 (업데이트) - DELETE: 데이터 삭제 (지우기)
2.2 매개변수 라우팅
🎯 URL에서 값 받기
- URL의 일부를 변수로 사용
- 예:
/users/1→ 1번 사용자 정보
📝 실습 코드
# 숫자 매개변수
@app.get("/users/{user_id}")
def get_user(user_id: int):
return {"user_id": user_id, "name": f"사용자{user_id}"}
# 문자열 매개변수
@app.get("/blog/{category}")
def get_blog_by_category(category: str):
return {"category": category, "posts": f"{category} 관련 글들"}
# 여러 개의 매개변수
@app.get("/blog/{year}/{month}")
def get_blog_archive(year: int, month: int):
return {"year": year, "month": month, "posts": f"{year}년 {month}월 글들"}
💡 타입 힌트의 장점
- user_id: int → 자동으로 숫자로 변환
- 잘못된 타입이 오면 에러 메시지 자동 생성
2.3 요청 본문 처리
🎯 POST 요청으로 데이터 받기
- 사용자가 보낸 데이터를 처리
- Pydantic으로 데이터 모델 정의
📝 실습 코드
from pydantic import BaseModel
# 데이터 모델 정의 (설계도)
class User(BaseModel):
name: str
email: str
age: int = 0 # 기본값 설정 가능
# 회원가입 API
@app.post("/signup")
def signup(user: User):
# user.name, user.email 등으로 접근 가능
return {
"message": f"{user.name}님 환영합니다!",
"user_info": user
}
# 블로그 글 작성 모델
class BlogPost(BaseModel):
title: str
content: str
tags: list[str] = [] # 태그는 선택사항
@app.post("/blog/create")
def create_blog(post: BlogPost):
return {
"message": "글이 작성되었습니다",
"post": post
}
💡 Pydantic의 장점
- 자동으로 데이터 검증
- 타입이 맞지 않으면 친절한 에러 메시지
- 자동으로 JSON ↔ Python 객체 변환
2.4 쿼리 매개변수 처리
🎯 URL 뒤의 ? 파라미터
- 예:
/search?q=python&limit=10 - 선택적인 파라미터 처리
📝 실습 코드
# 기본 쿼리 파라미터
@app.get("/search")
def search(q: str = None):
if q:
return {"query": q, "results": f"{q}에 대한 검색 결과"}
return {"message": "검색어를 입력하세요"}
# 페이지네이션 (페이지 나누기)
@app.get("/posts")
def get_posts(page: int = 1, size: int = 10):
start = (page - 1) * size
end = start + size
return {
"page": page,
"size": size,
"posts": f"{start}번째부터 {end}번째 글"
}
# 여러 개의 쿼리 파라미터
@app.get("/filter")
def filter_items(
category: str = None,
min_price: int = 0,
max_price: int = 1000000
):
return {
"category": category,
"price_range": f"{min_price}원 ~ {max_price}원"
}
2.5 응답 모델 사용하기
🎯 API 응답 형식 정의
- 클라이언트에게 보낼 데이터 형식 지정
- 민감한 정보 숨기기
📝 실습 코드
# 사용자 모델 (전체 정보)
class UserFull(BaseModel):
id: int
name: str
email: str
password: str # 민감한 정보
# 응답용 모델 (공개 정보만)
class UserPublic(BaseModel):
id: int
name: str
email: str
# password는 제외!
# response_model로 응답 형식 지정
@app.post("/users/", response_model=UserPublic)
def create_user(user: UserFull):
# 실제로는 DB에 저장
return user # password가 있어도 응답에서는 제외됨
# 목록 응답
@app.get("/users/", response_model=list[UserPublic])
def get_users():
# 실제로는 DB에서 조회
users = [
{"id": 1, "name": "홍길동", "email": "hong@example.com", "password": "secret"},
{"id": 2, "name": "김철수", "email": "kim@example.com", "password": "hidden"}
]
return users # password는 자동으로 제외
📙 3장: CRUD 애플리케이션 만들기
3.1 CRUD 구현하기
🎯 CRUD란?
- Create: 생성 (새 데이터 만들기)
- Read: 읽기 (데이터 조회하기)
- Update: 수정 (데이터 바꾸기)
- Delete: 삭제 (데이터 지우기)
📝 간단한 메모 앱 만들기
from typing import Dict
# 메모 데이터 모델
class Memo(BaseModel):
title: str
content: str
# 메모 저장소 (임시로 메모리에 저장)
memos: Dict[int, Memo] = {}
memo_counter = 0
# 1. Create - 메모 생성
@app.post("/memos/", response_model=dict)
def create_memo(memo: Memo):
global memo_counter
memo_counter += 1
memos[memo_counter] = memo
return {
"id": memo_counter,
"message": "메모가 생성되었습니다",
"memo": memo
}
# 2. Read - 전체 메모 조회
@app.get("/memos/")
def get_all_memos():
return {
"count": len(memos),
"memos": [
{"id": id, "memo": memo}
for id, memo in memos.items()
]
}
# 3. Read - 특정 메모 조회
@app.get("/memos/{memo_id}")
def get_memo(memo_id: int):
if memo_id not in memos:
raise HTTPException(status_code=404, detail="메모를 찾을 수 없습니다")
return {"id": memo_id, "memo": memos[memo_id]}
# 4. Update - 메모 수정
@app.put("/memos/{memo_id}")
def update_memo(memo_id: int, memo: Memo):
if memo_id not in memos:
raise HTTPException(status_code=404, detail="메모를 찾을 수 없습니다")
memos[memo_id] = memo
return {"message": "메모가 수정되었습니다", "memo": memo}
# 5. Delete - 메모 삭제
@app.delete("/memos/{memo_id}")
def delete_memo(memo_id: int):
if memo_id not in memos:
raise HTTPException(status_code=404, detail="메모를 찾을 수 없습니다")
deleted_memo = memos.pop(memo_id)
return {"message": "메모가 삭제되었습니다", "deleted": deleted_memo}
3.2 API 문서 살펴보기
🎯 자동 생성되는 API 문서
- FastAPI의 킬러 기능!
- 코드만 작성하면 문서는 자동 생성
📝 API 문서 활용하기
- Swagger UI (대화형 문서)
- http://localhost:8000/docs
- API를 직접 테스트 가능
-
Try it out 버튼으로 실행
-
ReDoc (읽기 전용 문서)
- http://localhost:8000/redoc
-
더 깔끔한 문서 형식
-
문서 커스터마이징
app = FastAPI(
title="나의 메모 API",
description="메모를 관리하는 간단한 API입니다",
version="1.0.0",
)
# API 설명 추가
@app.post("/memos/", summary="새 메모 생성", tags=["memos"])
def create_memo(memo: Memo):
"""
새로운 메모를 생성합니다.
- **title**: 메모 제목
- **content**: 메모 내용
"""
# ... 코드 ...
📕 4장: 데이터베이스와 인증
4.1 SQLite와 SQLAlchemy
🎯 데이터베이스란?
- 데이터를 영구적으로 저장하는 창고
- SQLite = 가장 간단한 데이터베이스 (파일 하나)
📝 데이터베이스 설정
# database.py
from sqlalchemy import create_engine, Column, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from datetime import datetime
# 데이터베이스 연결 설정
DATABASE_URL = "sqlite:///./blog.db" # blog.db 파일에 저장
# 엔진 생성
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(bind=engine)
# 모델의 부모 클래스
Base = declarative_base()
# 블로그 글 테이블 정의
class BlogPost(Base):
__tablename__ = "blog_posts" # 테이블 이름
id = Column(Integer, primary_key=True, index=True) # 고유 번호
title = Column(String(100), nullable=False) # 제목 (필수)
content = Column(String(1000), nullable=False) # 내용 (필수)
author = Column(String(50), nullable=False) # 작성자
created_at = Column(DateTime, default=datetime.now) # 작성일
# 테이블 생성
Base.metadata.create_all(bind=engine)
4.2 FastAPI에 DB 적용하기
🎯 데이터베이스 연동
- 의존성 주입으로 DB 연결 관리
- 자동으로 연결 열고 닫기
📝 DB와 연동된 CRUD
from sqlalchemy.orm import Session
# DB 세션 가져오기
def get_db():
db = SessionLocal()
try:
yield db # DB 연결 제공
finally:
db.close() # 자동으로 연결 종료
# Pydantic 모델 (API용)
class BlogPostCreate(BaseModel):
title: str
content: str
author: str
class BlogPostResponse(BaseModel):
id: int
title: str
content: str
author: str
created_at: datetime
class Config:
orm_mode = True # SQLAlchemy 모델과 호환
# 블로그 글 작성
@app.post("/blog/", response_model=BlogPostResponse)
def create_blog_post(post: BlogPostCreate, db: Session = Depends(get_db)):
# DB 모델 생성
db_post = BlogPost(**post.dict())
# DB에 저장
db.add(db_post)
db.commit()
db.refresh(db_post) # 생성된 ID 등 가져오기
return db_post
# 블로그 글 목록
@app.get("/blog/", response_model=list[BlogPostResponse])
def get_blog_posts(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
posts = db.query(BlogPost).offset(skip).limit(limit).all()
return posts
# 특정 블로그 글 조회
@app.get("/blog/{post_id}", response_model=BlogPostResponse)
def get_blog_post(post_id: int, db: Session = Depends(get_db)):
post = db.query(BlogPost).filter(BlogPost.id == post_id).first()
if not post:
raise HTTPException(status_code=404, detail="글을 찾을 수 없습니다")
return post
4.3 JWT 토큰이란?
🎯 JWT (JSON Web Token)
- 사용자 인증을 위한 토큰
- 마치 놀이공원 자유이용권 같은 것
💡 JWT의 구조
- 헤더: 토큰 타입과 암호화 방식
- 페이로드: 사용자 정보 (이름, 권한 등)
- 서명: 위조 방지용 서명
🔐 인증 과정
- 로그인 → JWT 토큰 발급
- API 요청시 토큰 첨부
- 서버가 토큰 검증
- 올바른 토큰이면 요청 처리
4.4 JWT를 이용한 사용자 인증 구현
📝 간단한 로그인 시스템
from datetime import datetime, timedelta
from jose import jwt
from passlib.context import CryptContext
# 비밀번호 암호화 설정
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# JWT 설정
SECRET_KEY = "your-secret-key-change-this" # 실제로는 환경변수로!
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# 사용자 모델
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String, unique=True, index=True)
email = Column(String, unique=True, index=True)
hashed_password = Column(String)
# 회원가입 모델
class UserCreate(BaseModel):
username: str
email: str
password: str
# 로그인 모델
class UserLogin(BaseModel):
username: str
password: str
# 비밀번호 암호화
def get_password_hash(password: str):
return pwd_context.hash(password)
# 비밀번호 검증
def verify_password(plain_password: str, hashed_password: str):
return pwd_context.verify(plain_password, hashed_password)
# JWT 토큰 생성
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
# 회원가입
@app.post("/signup")
def signup(user: UserCreate, db: Session = Depends(get_db)):
# 중복 확인
db_user = db.query(User).filter(User.username == user.username).first()
if db_user:
raise HTTPException(status_code=400, detail="이미 사용중인 아이디입니다")
# 사용자 생성
hashed_password = get_password_hash(user.password)
db_user = User(
username=user.username,
email=user.email,
hashed_password=hashed_password
)
db.add(db_user)
db.commit()
return {"message": "회원가입이 완료되었습니다"}
# 로그인
@app.post("/login")
def login(user: UserLogin, db: Session = Depends(get_db)):
# 사용자 찾기
db_user = db.query(User).filter(User.username == user.username).first()
if not db_user:
raise HTTPException(status_code=400, detail="아이디 또는 비밀번호가 틀렸습니다")
# 비밀번호 확인
if not verify_password(user.password, db_user.hashed_password):
raise HTTPException(status_code=400, detail="아이디 또는 비밀번호가 틀렸습니다")
# 토큰 생성
access_token = create_access_token(data={"sub": db_user.username})
return {"access_token": access_token, "token_type": "bearer"}
📒 5장: 블로그 기능 구현
5.1 요구사항 분석
🎯 우리가 만들 블로그 시스템
- 회원가입/로그인
- 글 작성/수정/삭제 (본인 글만)
- 글 목록/상세 보기
- 웹 페이지 제공
5.2 CORS 설정과 미들웨어 구현
🎯 CORS란?
- Cross-Origin Resource Sharing
- 다른 도메인에서의 API 호출 허용
📝 CORS 설정
from fastapi.middleware.cors import CORSMiddleware
# CORS 미들웨어 추가
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 모든 도메인 허용 (개발용)
allow_credentials=True,
allow_methods=["*"], # 모든 HTTP 메서드 허용
allow_headers=["*"], # 모든 헤더 허용
)
5.3 SPA로 블로그 구현하기
🎯 SPA (Single Page Application)
- 한 페이지에서 모든 기능 동작
- JavaScript로 동적으로 화면 변경
📝 간단한 SPA 예제
<!-- static/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>나의 블로그</title>
<style>
.container { max-width: 800px; margin: 0 auto; padding: 20px; }
.post { border: 1px solid #ddd; padding: 15px; margin: 10px 0; }
.button { padding: 10px 20px; margin: 5px; cursor: pointer; }
</style>
</head>
<body>
<div class="container">
<h1>나의 블로그</h1>
<!-- 로그인 폼 -->
<div id="loginForm">
<h2>로그인</h2>
<input type="text" id="username" placeholder="아이디">
<input type="password" id="password" placeholder="비밀번호">
<button class="button" onclick="login()">로그인</button>
</div>
<!-- 글 목록 -->
<div id="postList"></div>
<!-- 글 작성 폼 -->
<div id="writeForm" style="display:none;">
<h2>새 글 작성</h2>
<input type="text" id="title" placeholder="제목">
<textarea id="content" placeholder="내용"></textarea>
<button class="button" onclick="createPost()">작성</button>
</div>
</div>
<script>
let token = localStorage.getItem('token');
// 로그인
async function login() {
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
const response = await fetch('/login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({username, password})
});
if (response.ok) {
const data = await response.json();
token = data.access_token;
localStorage.setItem('token', token);
document.getElementById('loginForm').style.display = 'none';
document.getElementById('writeForm').style.display = 'block';
loadPosts();
} else {
alert('로그인 실패!');
}
}
// 글 목록 불러오기
async function loadPosts() {
const response = await fetch('/blog/');
const posts = await response.json();
let html = '<h2>글 목록</h2>';
posts.forEach(post => {
html += `
<div class="post">
<h3>${post.title}</h3>
<p>${post.content}</p>
<small>작성자: ${post.author}</small>
</div>
`;
});
document.getElementById('postList').innerHTML = html;
}
// 글 작성
async function createPost() {
const title = document.getElementById('title').value;
const content = document.getElementById('content').value;
const response = await fetch('/blog/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({title, content})
});
if (response.ok) {
alert('글이 작성되었습니다!');
loadPosts();
}
}
// 페이지 로드시 글 목록 표시
loadPosts();
</script>
</body>
</html>
5.4 MPA로 블로그 구현하기
🎯 MPA (Multi Page Application)
- 여러 개의 HTML 페이지
- 서버에서 HTML 생성 (템플릿 엔진)
📝 Jinja2 템플릿 사용
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
# 템플릿 설정
templates = Jinja2Templates(directory="templates")
# 정적 파일 설정
app.mount("/static", StaticFiles(directory="static"), name="static")
# 블로그 목록 페이지
@app.get("/")
def home(request: Request, db: Session = Depends(get_db)):
posts = db.query(BlogPost).all()
return templates.TemplateResponse("index.html", {
"request": request,
"posts": posts
})
템플릿 예제 (templates/index.html)
<!DOCTYPE html>
<html>
<head>
<title>나의 블로그</title>
</head>
<body>
<h1>블로그 글 목록</h1>
{% for post in posts %}
<div class="post">
<h2>{{ post.title }}</h2>
<p>{{ post.content }}</p>
<small>작성자: {{ post.author }}</small>
</div>
{% endfor %}
</body>
</html>
5.5 DB 구성 및 static 파일 서빙
🎯 프로젝트 구조 정리
my-blog/
├── main.py # FastAPI 메인 파일
├── database.py # DB 설정
├── models.py # DB 모델
├── schemas.py # Pydantic 모델
├── auth.py # 인증 관련
├── static/ # CSS, JS, 이미지
│ ├── style.css
│ └── script.js
├── templates/ # HTML 템플릿
│ ├── base.html
│ ├── index.html
│ └── post_detail.html
└── blog.db # SQLite DB 파일
5.6 인증 구현하기
🎯 로그인이 필요한 기능 보호
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
# OAuth2 설정
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
# 현재 사용자 가져오기
async def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
try:
# 토큰 해독
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise HTTPException(status_code=401, detail="인증 실패")
except JWTError:
raise HTTPException(status_code=401, detail="인증 실패")
# 사용자 조회
user = db.query(User).filter(User.username == username).first()
if user is None:
raise HTTPException(status_code=401, detail="사용자를 찾을 수 없습니다")
return user
# 보호된 엔드포인트 (로그인 필요)
@app.post("/blog/")
def create_post(
post: BlogPostCreate,
current_user: User = Depends(get_current_user), # 로그인 확인
db: Session = Depends(get_db)
):
db_post = BlogPost(
**post.dict(),
author=current_user.username # 현재 사용자를 작성자로
)
db.add(db_post)
db.commit()
return {"message": "글이 작성되었습니다"}
# 본인 글만 수정 가능
@app.put("/blog/{post_id}")
def update_post(
post_id: int,
post: BlogPostCreate,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
db_post = db.query(BlogPost).filter(BlogPost.id == post_id).first()
if not db_post:
raise HTTPException(status_code=404, detail="글을 찾을 수 없습니다")
# 작성자 확인
if db_post.author != current_user.username:
raise HTTPException(status_code=403, detail="수정 권한이 없습니다")
# 수정
db_post.title = post.title
db_post.content = post.content
db.commit()
return {"message": "글이 수정되었습니다"}
5.7 스웨거로 테스트하기
🎯 Swagger UI 활용법
- http://localhost:8000/docs 접속
- Authorize 버튼 클릭
- 로그인해서 받은 토큰 입력
- 각 API 테스트
💡 테스트 순서
/signup- 회원가입/login- 로그인 (토큰 받기)- Authorize에 토큰 설정
/blog/POST - 글 작성/blog/GET - 글 목록 확인
📓 6장: FastAPI 실전 활용
6.1 에러 처리와 예외 관리
🎯 친절한 에러 메시지
# 커스텀 예외 만들기
class BlogException(Exception):
def __init__(self, name: str, message: str):
self.name = name
self.message = message
# 예외 처리기
@app.exception_handler(BlogException)
async def blog_exception_handler(request: Request, exc: BlogException):
return JSONResponse(
status_code=400,
content={
"error": exc.name,
"message": exc.message
}
)
# 사용 예시
@app.get("/blog/{post_id}")
def get_post(post_id: int, db: Session = Depends(get_db)):
if post_id < 1:
raise BlogException("INVALID_ID", "올바른 글 번호가 아닙니다")
post = db.query(BlogPost).filter(BlogPost.id == post_id).first()
if not post:
raise BlogException("NOT_FOUND", f"{post_id}번 글을 찾을 수 없습니다")
return post
6.2 파일 업로드 및 처리
🎯 이미지 업로드 기능
from fastapi import File, UploadFile
import shutil
import os
# 업로드 폴더 생성
os.makedirs("uploads", exist_ok=True)
# 파일 업로드 API
@app.post("/upload/")
async def upload_file(file: UploadFile = File(...)):
# 파일 크기 확인 (5MB 제한)
contents = await file.read()
if len(contents) > 5 * 1024 * 1024:
raise HTTPException(status_code=413, detail="파일이 너무 큽니다 (최대 5MB)")
# 파일 확장자 확인
allowed_extensions = ["jpg", "jpeg", "png", "gif"]
file_extension = file.filename.split(".")[-1].lower()
if file_extension not in allowed_extensions:
raise HTTPException(status_code=400, detail="이미지 파일만 업로드 가능합니다")
# 파일 저장
file_path = f"uploads/{file.filename}"
with open(file_path, "wb") as f:
f.write(contents)
return {
"filename": file.filename,
"size": len(contents),
"url": f"/uploads/{file.filename}"
}
# 업로드된 파일 제공
from fastapi.responses import FileResponse
@app.get("/uploads/{filename}")
async def get_uploaded_file(filename: str):
file_path = f"uploads/{filename}"
if not os.path.exists(file_path):
raise HTTPException(status_code=404, detail="파일을 찾을 수 없습니다")
return FileResponse(file_path)
6.3 패키지 관리
🎯 프로젝트 의존성 관리
requirements.txt 만들기
requirements.txt 예시
fastapi
uvicorn[standard]
sqlalchemy
python-jose[cryptography]
passlib[bcrypt]
python-multipart
jinja2
다른 컴퓨터에서 설치
.gitignore 파일
# 가상환경
venv/
env/
# 데이터베이스
*.db
# 캐시
__pycache__/
*.py[cod]
# 환경 설정
.env
# 업로드 파일
uploads/
# IDE
.vscode/
.idea/
🎓 학습 완료 후 만들 수 있는 것들
✅ 완성 프로젝트: 나만의 블로그
- 회원가입/로그인 시스템
- 글 작성/수정/삭제 (CRUD)
- 이미지 업로드
- 인증된 사용자만 글 작성
- 자동 생성되는 API 문서
🚀 다음 단계로 발전시키기
- 댓글 기능 추가하기
- 좋아요 기능 만들기
- 검색 기능 구현하기
- 카테고리 분류 추가하기
- 관리자 페이지 만들기
💡 학습 팁
초보자를 위한 조언
- 에러 메시지를 무서워하지 마세요
- 에러는 뭐가 잘못됐는지 알려주는 친구입니다
-
구글에 에러 메시지를 검색하면 해결책이 나옵니다
-
코드를 복사-붙여넣기만 하지 마세요
- 직접 타이핑하면서 익숙해지세요
-
작은 부분씩 바꿔보면서 실험해보세요
-
문서를 활용하세요
- FastAPI 문서는 매우 친절합니다
-
/docs에서 API를 테스트해보세요 -
작게 시작하세요
- 한 번에 모든 걸 만들려고 하지 마세요
- 작은 기능부터 하나씩 추가하세요
🔗 유용한 링크
🎉 축하합니다!
FastAPI 베이스캠프를 완주하신 것을 축하합니다! 이제 여러분은: - ✅ RESTful API를 만들 수 있습니다 - ✅ 데이터베이스를 다룰 수 있습니다 - ✅ 사용자 인증을 구현할 수 있습니다 - ✅ 파일 업로드를 처리할 수 있습니다
다음 프로젝트는 무엇을 만들어 보시겠어요? 🚀