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

Fastapi

[FastAPI] 디자인패턴-팩토리 패턴(Factory Pattern) (11-2)

Suda_777 2025. 1. 27. 17:25

목차

    반응형

    1. 개념

    1.1. 설명

    • 객체 생성 로직을 캡슐화
    • 팩토리(Factory) 역할을 하는 메서드나 클래스를 통해 객체를 생성
    • 객체 생성의 책임을 별도의 팩토리 클래스 또는 메서드에 위임하여, 객체 생성 로직을 단순화하고 클라이언트 코드와의 결합도를 낮추는 것

    1.2. 사용 목적

    • 객체 생성 방식이 변경되더라도 클라이언트 코드에 영향을 최소화
    • 객체 생성 과정의 복잡성을 숨기고 단순화.

    1.3. 언제 사용하는가?

    • 앱 초기화
    • 구성 요소 관리

     


    2. FastAPI 활용 예시

    2.1. 앱 초기화 예시

    다음과 같은 구조로 코드 예시를 정리한다. (여기서 app.py가 핵심이다.)

    project/
    ├── app.py          # 앱 초기화 및 팩토리 메서드 정의
    ├── main.py         # 애플리케이션 실행 진입점
    ├── config.py       # 설정 관리
    ├── routers/        # 라우터 모듈화
    │   ├── user_router.py
    │   └── item_router.py
    └── models/         # 데이터베이스 모델 정의 (예시)
        └── base.py

     

    app.py

    # app.py
    from fastapi import FastAPI
    from config import get_settings
    from routers.user_router import user_router
    from routers.item_router import item_router
    
    def create_app() -> FastAPI:
        """팩토리 패턴을 활용한 FastAPI 앱 초기화"""
        app = FastAPI()
        _register_routers(app) # 라우터 등록
        _register_event_handlers(app) # 이벤트 핸들러 등록
        return app
    
    
    def _register_routers(app: FastAPI):
        """라우터를 FastAPI 앱에 등록"""
        app.include_router(user_router, prefix="/users", tags=["Users"])
        app.include_router(item_router, prefix="/items", tags=["Items"])
    
    
    def _register_event_handlers(app: FastAPI):
        """이벤트 핸들러 등록"""
    
        @app.on_event("startup")
        async def on_startup():
            settings = get_settings()
            print(f"Starting application in {settings.env} environment...")
    
        @app.on_event("shutdown")
        async def on_shutdown():
            print("Shutting down application...")

     

    main.py

    from app import create_app
    
    app = create_app()
    
    if __name__ == "__main__":
        import uvicorn
        uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)

     

    코드 설명

    1. app.py 의 create_app() 함수에서 객체 생성 로직을 캡슐화 한다.

    2. main.py 에서 create_app()를 실행해 객체를 생성해 준다.

     


    2.2. 구성 요소 초기화

    다음 예시는 구성요소들을 초기화 하는 것이다.

     

    코드 구조는 다음과 같다.

    project/
    ├── app.py          # FastAPI 앱과 구성 요소 초기화
    ├── main.py         # 앱 실행 엔트리 포인트
    ├── config.py       # 설정 관리
    ├── components/     # 구성 요소 관리
    │   ├── database.py # 데이터베이스 초기화
    │   └── redis.py    # Redis 클라이언트 초기화
    └── routers/        # 라우터 관리
        └── example_router.py

     

    app.py

    아래 코드에서는 데이터베이스, Redis 를 초기화 하고 있다.

    # app.py
    from fastapi import FastAPI
    from components.database import init_db
    from components.redis import init_redis
    from config import get_settings
    from routers.example_router import example_router
    
    def create_app() -> FastAPI:
        app = FastAPI()
        app.include_router(example_router, prefix="/example", tags=["Example"])
    
        # 구성 요소 초기화
        _init_components(app)
        return app
    
    def _init_components(app: FastAPI):
        """구성 요소 초기화"""
        settings = get_settings()
    
        # 데이터베이스 초기화
        app.state.db = init_db(settings.database_url)
    
        # Redis 초기화
        app.state.redis = init_redis(settings.redis_url)
    
        # 이벤트 핸들러 등록 (시작/종료)
        @app.on_event("startup")
        async def startup():
            print("Application is starting...")
            await app.state.redis.ping()  # Redis 연결 확인
    
        @app.on_event("shutdown")
        async def shutdown():
            print("Application is shutting down...")
            await app.state.redis.close()  # Redis 연결 닫기

     

    config.py: 환경별 설정 관리

    from pydantic import BaseSettings
    
    class Settings(BaseSettings):
        database_url: str = "sqlite:///./test.db"
        redis_url: str = "redis://localhost:6379"
    
        class Config:
            env_file = ".env"
    
    def get_settings() -> Settings:
        """환경 설정 반환"""
        return Settings()

     

    components/database.py: 데이터베이스 초기화

    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker
    
    def init_db(database_url: str):
        """데이터베이스 엔진과 세션 생성"""
        engine = create_engine(database_url, connect_args={"check_same_thread": False})
        SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
        return SessionLocal

     

    components/redis.py: Redis 클라이언트 초기화

    import aioredis
    
    def init_redis(redis_url: str):
        """Redis 클라이언트 초기화"""
        return aioredis.from_url(redis_url)

     

    main.py

    # main.py
    from app import create_app
    
    app = create_app()
    
    if __name__ == "__main__":
        import uvicorn
        uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)

     

    위 코드에서 팩토리가 무엇인지 정리하자면 아래와 같다.

    • get_settings: 환경 설정 객체를 생성해 반환
    • init_db: 데이터베이스 엔진과 세션을 초기화해 객체를 반환
    • init_redis : Redis 세션을 초기화해 객체를 반환
    • create_app : FastAPI() 애플리케이션 객체를 생성해 반환

     

    이처럼 각 구성 요소를 별도의 팩토리 함수로 관리하면 코드의 모듈화가 쉬워지고, 초기화 및 구성이 필요한 모든 요소를 명확하게 관리할 수 있다. 🎯

     

    반응형