인공지능 개발자 수다(유튜브 바로가기) 자세히보기

Fastapi

[FastAPI] 공통 코드(Common Code) 작성 방법 (12)

Suda_777 2025. 2. 2. 22:35
반응형

 

 

1. 공통 코드(Common Code)란?

공통 코드반복되는 로직을 모듈화하여 여러 곳에서 재사용할 수 있도록 구성하는 것

 

 장점

  • 코드 중복 감소 → 동일한 로직을 여러 곳에서 사용 가능
  • 가독성 향상 → 핵심 로직만 남아 코드가 깔끔해짐
  • 유지보수 용이 → 하나의 파일에서 수정하면 모든 곳에 적용됨
  • 테스트 용이 → 공통 모듈을 독립적으로 테스트 가능

 


2. 공통 코드 작성 방법

공통 코드 디렉토리 구조

  • 보통 utils/ 디렉터리에 작성하며, 프로젝트 전반에서 사용
my_fastapi_project/
│── main.py
│── routers/
│── services/
│── repositories/
│── models/
│── schemas/
│── database.py
│── utils/  # ✅ 공통 코드 디렉터리
│   ├── hash.py       # 비밀번호 해싱 관련 공통 함수
│   ├── exceptions.py  # 커스텀 예외 처리
│   ├── dependencies.py  # 공통 의존성 관리
│   ├── logging.py    # 로깅 설정
│   ├── time_utils.py # 날짜, 시간 관련 함수

 

 

utils/hash.py

  • 비밀번호 해싱 (예시)
from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def hash_password(password: str) -> str:
    """비밀번호를 해싱하는 함수"""
    return pwd_context.hash(password)

def verify_password(plain_password: str, hashed_password: str) -> bool:
    """입력된 비밀번호가 저장된 해시와 일치하는지 확인"""
    return pwd_context.verify(plain_password, hashed_password)

 

📌  서비스에서 적용 예시

from utils.hash import hash_password

def register_user(db: Session, user: UserCreate):
    user.password = hash_password(user.password)  # 비밀번호 해싱
    return create_user(db, user)

 

 

utils/exceptions.py

  • 공통 예외 처리 (Custom Exception) (예시)
from fastapi import HTTPException

class UserAlreadyExistsException(HTTPException):
    def __init__(self):
        super().__init__(status_code=400, detail="이미 존재하는 사용자입니다.")

class UserNotFoundException(HTTPException):
    def __init__(self):
        super().__init__(status_code=404, detail="사용자를 찾을 수 없습니다.")

 

📌  서비스에서 적용 예시

from utils.exceptions import UserAlreadyExistsException, UserNotFoundException

def register_user(db: Session, user: UserCreate):
    existing_user = get_user_by_email(db, user.email)
    if existing_user:
        raise UserAlreadyExistsException()  # 공통 예외 사용

    return create_user(db, user)

def retrieve_user(db: Session, user_id: int):
    user = get_user_by_id(db, user_id)
    if not user:
        raise UserNotFoundException()  # 공통 예외 사용
    return user

 

 

utils/dependencies.py

  • 공통 의존성 관리
from fastapi import Depends
from database import get_db
from sqlalchemy.orm import Session

def get_db_session(db: Session = Depends(get_db)):
    """SQLAlchemy 세션을 가져오는 공통 의존성"""
    return db

 

📌  라우터에서 적용 예시

  • 데이터베이스 세션은 라우터에서 직접 받는 것이 좋음
from fastapi import Depends
from utils.dependencies import get_db_session
from sqlalchemy.orm import Session

@router.get("/")
async def get_users(db: Session = Depends(get_db_session)):
    return list_users(db)

 

 

utils/logging.py

공통 로깅 설정

import logging

def get_logger(name: str):
    """FastAPI에서 사용할 로거 생성"""
    logger = logging.getLogger(name)
    logger.setLevel(logging.INFO)
    handler = logging.StreamHandler()
    formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    return logger

 

📌 적용 예시

from utils.logging import get_logger

logger = get_logger(__name__)

def register_user(db: Session, user: UserCreate):
    logger.info(f"새로운 사용자 등록: {user.email}")  # 공통 로깅 사용
    return create_user(db, user)

 

 

utils/time_utils.py

  • 날짜 & 시간 유틸리티
from datetime import datetime, timedelta

def get_current_time() -> str:
    """현재 시간을 ISO 포맷으로 반환"""
    return datetime.utcnow().isoformat()

def add_days_to_now(days: int) -> str:
    """현재 시간에 특정 일수를 추가하여 반환"""
    return (datetime.utcnow() + timedelta(days=days)).isoformat()

 

📌 적용 예시

from utils.time_utils import get_current_time

print(get_current_time())  # ✅ 공통 함수 사용
반응형