다른 명령
@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, ...) |