메뉴 여닫기
개인 메뉴 토글
로그인하지 않음
만약 지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.

@with async connection(db name func()) → 런타임에 동적으로 DB 선택

데브카페

@with_async_connection(db_name_func())

  • 데코레이터에서 런타임에 DB 이름을 동적으로 선택하는 건 불가능합니다.
  • 이유는 Python의 데코레이터는 함수 정의 시점에 실행되기 때문입니다
    — 즉, @가 붙는 순간에 이미 db_name_func()는 실행되고, 나중에 바꿀 수 없습니다.

해결 방법 1

  • 동적 DB 이름을 인자로 넘기기
async def run_query_dynamic(db_name):
    await run_dynamic_query(db_name, "SELECT * FROM users")

이때 데코레이터 대신 일반 함수로 구성:

async def run_dynamic_query(db_name, sql):
    pool = await init_connection_pool(db_name)
    async with pool.acquire() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute(sql)
            return await cursor.fetchall()

해결 방법 2

  • 함수를 감싸는 헬퍼 데코레이터
  • 좀 더 데코레이터처럼 쓰고 싶다면 아래처럼 만들 수 있습니다:
async def run_query_dynamic(db_name, func, *args, **kwargs):
    pool = await init_connection_pool(db_name)
    async with pool.acquire() as conn:
        async with conn.cursor() as cursor:
            return await func(cursor, *args, **kwargs)
  • 사용 예시:
async def get_user_by_id(cursor, user_id):
    await cursor.execute("SELECT * FROM users WHERE id = :1", [user_id])
    return await cursor.fetchone()

# 호출 시 동적으로 DB 선택
user = await run_query_dynamic("MyDB2", get_user_by_id, user_id=42)

ĉ=== 해결 방법 3 ===

  • 데코레이터 내부에서 동적으로 DB 결정 (함수 인자 기반)
- 이 방식은 데코레이터가 함수의 첫 번째 인자 또는 키워드 인자에서 DB 이름을 가져오는 방식입니다:
def dynamic_db_decorator():
    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            db_name = kwargs.get("db_name") or args[0]  # 첫 인자 또는 키워드에서
            pool = await init_connection_pool(db_name)
            async with pool.acquire() as conn:
                async with conn.cursor() as cursor:
                    return await func(cursor, *args[1:], **kwargs)
        return wrapper
    return decorator
  • 사용:
@dynamic_db_decorator()
async def get_all_users(cursor, db_name=None):
    await cursor.execute("SELECT * FROM users")
    return await cursor.fetchall()

await get_all_users("MyDB1")

추천 방식

코드가 단순해야 함 run_query_dynamic() 방식
데코레이터 스타일을 유지하고 싶음 dynamic_db_decorator()
복잡한 쿼리 로직 분리 원함 run_query_dynamic(func, ...)

Comments