skills/fastapi/SKILL.md
FastAPI 백엔드 패턴 가이드를 실행합니다.
npx skillsauth add excatt/superclaude-plusplus fastapiInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
FastAPI 백엔드 패턴 가이드를 실행합니다.
app/
├── main.py
├── config.py
├── dependencies.py
├── api/
│ ├── __init__.py
│ ├── deps.py
│ └── v1/
│ ├── __init__.py
│ ├── router.py
│ └── endpoints/
│ ├── users.py
│ └── auth.py
├── core/
│ ├── config.py
│ ├── security.py
│ └── exceptions.py
├── models/
│ ├── __init__.py
│ └── user.py
├── schemas/
│ ├── __init__.py
│ └── user.py
├── services/
│ └── user_service.py
├── repositories/
│ └── user_repository.py
└── db/
├── session.py
└── base.py
# schemas/user.py
from pydantic import BaseModel, EmailStr, ConfigDict
from datetime import datetime
class UserBase(BaseModel):
email: EmailStr
name: str
class UserCreate(UserBase):
password: str
class UserUpdate(BaseModel):
email: EmailStr | None = None
name: str | None = None
class UserResponse(UserBase):
id: int
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class UserListResponse(BaseModel):
data: list[UserResponse]
total: int
# models/user.py
from sqlalchemy import String, DateTime
from sqlalchemy.orm import Mapped, mapped_column
from datetime import datetime
from app.db.base import Base
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
email: Mapped[str] = mapped_column(String(255), unique=True, index=True)
name: Mapped[str] = mapped_column(String(255))
hashed_password: Mapped[str] = mapped_column(String(255))
created_at: Mapped[datetime] = mapped_column(
DateTime, default=datetime.utcnow
)
# repositories/user_repository.py
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.user import User
class UserRepository:
def __init__(self, session: AsyncSession):
self.session = session
async def get_by_id(self, user_id: int) -> User | None:
result = await self.session.execute(
select(User).where(User.id == user_id)
)
return result.scalar_one_or_none()
async def get_by_email(self, email: str) -> User | None:
result = await self.session.execute(
select(User).where(User.email == email)
)
return result.scalar_one_or_none()
async def get_all(
self, skip: int = 0, limit: int = 10, search: str | None = None
) -> tuple[list[User], int]:
query = select(User)
count_query = select(func.count()).select_from(User)
if search:
query = query.where(User.name.ilike(f"%{search}%"))
count_query = count_query.where(User.name.ilike(f"%{search}%"))
result = await self.session.execute(
query.offset(skip).limit(limit)
)
count_result = await self.session.execute(count_query)
return list(result.scalars().all()), count_result.scalar()
async def create(self, user: User) -> User:
self.session.add(user)
await self.session.commit()
await self.session.refresh(user)
return user
async def update(self, user: User) -> User:
await self.session.commit()
await self.session.refresh(user)
return user
async def delete(self, user: User) -> None:
await self.session.delete(user)
await self.session.commit()
# services/user_service.py
from fastapi import HTTPException, status
from app.repositories.user_repository import UserRepository
from app.schemas.user import UserCreate, UserUpdate
from app.models.user import User
from app.core.security import get_password_hash
class UserService:
def __init__(self, repository: UserRepository):
self.repository = repository
async def get_user(self, user_id: int) -> User:
user = await self.repository.get_by_id(user_id)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
return user
async def get_users(
self, skip: int = 0, limit: int = 10, search: str | None = None
) -> tuple[list[User], int]:
return await self.repository.get_all(skip, limit, search)
async def create_user(self, data: UserCreate) -> User:
existing = await self.repository.get_by_email(data.email)
if existing:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Email already registered"
)
user = User(
email=data.email,
name=data.name,
hashed_password=get_password_hash(data.password)
)
return await self.repository.create(user)
async def update_user(self, user_id: int, data: UserUpdate) -> User:
user = await self.get_user(user_id)
update_data = data.model_dump(exclude_unset=True)
for field, value in update_data.items():
setattr(user, field, value)
return await self.repository.update(user)
async def delete_user(self, user_id: int) -> None:
user = await self.get_user(user_id)
await self.repository.delete(user)
# api/v1/endpoints/users.py
from fastapi import APIRouter, Depends, Query, status
from app.schemas.user import (
UserCreate, UserUpdate, UserResponse, UserListResponse
)
from app.services.user_service import UserService
from app.api.deps import get_user_service, get_current_user
router = APIRouter(prefix="/users", tags=["users"])
@router.post("", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
async def create_user(
data: UserCreate,
service: UserService = Depends(get_user_service)
):
user = await service.create_user(data)
return user
@router.get("", response_model=UserListResponse)
async def get_users(
skip: int = Query(0, ge=0),
limit: int = Query(10, ge=1, le=100),
search: str | None = None,
service: UserService = Depends(get_user_service)
):
users, total = await service.get_users(skip, limit, search)
return UserListResponse(data=users, total=total)
@router.get("/me", response_model=UserResponse)
async def get_current_user_info(
current_user = Depends(get_current_user)
):
return current_user
@router.get("/{user_id}", response_model=UserResponse)
async def get_user(
user_id: int,
service: UserService = Depends(get_user_service)
):
return await service.get_user(user_id)
@router.put("/{user_id}", response_model=UserResponse)
async def update_user(
user_id: int,
data: UserUpdate,
service: UserService = Depends(get_user_service)
):
return await service.update_user(user_id, data)
@router.delete("/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_user(
user_id: int,
service: UserService = Depends(get_user_service)
):
await service.delete_user(user_id)
# core/security.py
from datetime import datetime, timedelta
from jose import jwt, JWTError
from passlib.context import CryptContext
from app.core.config import settings
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def create_access_token(subject: str | int) -> str:
expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode = {"exp": expire, "sub": str(subject)}
return jwt.encode(to_encode, settings.SECRET_KEY, algorithm="HS256")
def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password: str) -> str:
return pwd_context.hash(password)
# api/deps.py
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import jwt, JWTError
from app.core.config import settings
from app.services.user_service import UserService
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
async def get_current_user(
token: str = Depends(oauth2_scheme),
service: UserService = Depends(get_user_service)
):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
user_id: str = payload.get("sub")
if user_id is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user = await service.get_user(int(user_id))
return user
# db/session.py
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
from app.core.config import settings
engine = create_async_engine(settings.DATABASE_URL, echo=True)
async_session = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async def get_db():
async with async_session() as session:
try:
yield session
finally:
await session.close()
# core/exceptions.py
from fastapi import Request, status
from fastapi.responses import JSONResponse
class AppException(Exception):
def __init__(self, status_code: int, detail: str):
self.status_code = status_code
self.detail = detail
async def app_exception_handler(request: Request, exc: AppException):
return JSONResponse(
status_code=exc.status_code,
content={"detail": exc.detail}
)
# main.py에서 등록
app.add_exception_handler(AppException, app_exception_handler)
# main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
from app.api.v1.router import api_router
from app.db.session import engine
from app.db.base import Base
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield
# Shutdown
await engine.dispose()
app = FastAPI(
title="My API",
version="1.0.0",
lifespan=lifespan
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(api_router, prefix="/api/v1")
@app.get("/health")
async def health_check():
return {"status": "healthy"}
## FastAPI Implementation
### Endpoints
| Method | Path | Description |
|--------|------|-------------|
| POST | /users | Create user |
| GET | /users | List users |
### Schemas
```python
# Pydantic 모델
# 비즈니스 로직
---
요청에 맞는 FastAPI 구현을 설계하세요.
testing
사용자 계획을 기존 도메인 모델에 대해 stress-test하는 인터뷰 세션. 용어를 날카롭게 다듬고, 결정이 굳어질 때마다 CONTEXT.md(도메인 어휘 사전)와 ADR을 인라인으로 갱신한다. 새 기능 요구사항 탐색은 `/brainstorm`을, 기존 도메인 모델·용어와의 정합성 점검은 이 스킬을 사용한다.
development
# Excel (XLSX) Spreadsheet Skill Claude Code supports comprehensive spreadsheet operations through the **xlsx** skill, enabling creation, editing, and analysis of Excel files (.xlsx, .xlsm, .csv, .tsv). ## Trigger - When user needs Excel spreadsheet creation or editing - Financial modeling or data analysis required - Spreadsheet formulas and calculations needed - Data import from CSV/TSV files ## Core Capabilities **Primary functions include:** - Creating new spreadsheets with formulas and f
tools
Generate structured implementation workflows from PRDs and feature requirements
development
실시간 통신 설계 가이드를 실행합니다.