[파이썬] Psycopg2에서 Best practices 및 common pitfalls

Psycopg2은 Python에서 PostgreSQL 데이터베이스에 대한 접근을 제공하는 인기있는 라이브러리입니다. Psycopg2를 사용하는 동안 일반적인 실수를 피하고 코드를 개선하기 위해 몇 가지 가이드라인을 따를 수 있습니다. 이 글에서는 Psycopg2의 Best practices 및 일반적인 문제에 대해 알아보겠습니다.

Best practices

1. Connection pooling

여러 사용자가 동시에 PostgreSQL 데이터베이스에 접근할 수 있는 경우, connection pooling을 사용하는 것이 좋습니다. Connection pooling은 연결을 재사용하여 연결 오버헤드를 줄일 수 있고, 사용자의 요청에 더 빠르게 응답할 수 있도록 도와줍니다.

import psycopg2.pool

pool = psycopg2.pool.SimpleConnectionPool(
    minconn=1, maxconn=10,
    dbname='mydb', user='myuser', password='mypassword'
)

# Get a connection from the pool
conn = pool.getconn()

# Use the connection for database operations...

# Return the connection to the pool
pool.putconn(conn)

2. Query parameterization

SQL 쿼리를 실행할 때, query parameterization을 통해 SQL 인젝션 공격을 방지할 수 있습니다. Psycopg2는 쿼리 매개 변수를 사용하여 쿼리를 안전하게 구성할 수 있도록 해줍니다.

cursor.execute("SELECT * FROM users WHERE user_id = %s", (user_id,))

위의 예제에서 user_id를 쿼리 문자열 내에 직접 삽입하는 대신 %s와 함께 튜플로 전달하여 쿼리를 매개 변수화했습니다.

3. Error handling

Psycopg2에서 발생하는 예외를 적절히 처리하는 것이 중요합니다. 예외 처리는 데이터베이스 연결이 실패하거나 쿼리 실행 중에 오류가 발생할 때 애플리케이션이 예측 가능한 방식으로 동작하도록 도와줍니다.

try:
    cursor.execute("INSERT INTO users (name, age) VALUES (%s, %s)", (name, age))
    conn.commit()
except psycopg2.Error as e:
    print("Error executing SQL query:", e)
    conn.rollback()

위의 예제에서는 psycopg2.Error 예외를 잡아서 오류 메시지를 출력하고 롤백하는 방식으로 오류를 처리합니다.

Common pitfalls

1. Forgetting to close connections

Psycopg2는 자동으로 연결을 닫지 않습니다. 연결을 사용한 후 반드시 명시적으로 닫아야 합니다. 그렇지 않으면 연결 리소스가 제대로 정리되지 않을 수 있습니다.

cursor.execute("SELECT * FROM users")

# Process the query results...

# Close the connection
conn.close()

2. Mixing synchronous and asynchronous operations

Psycopg2는 동기식(synchronous) 및 비동기식(asynchronous) 작업을 모두 지원합니다. 그러나 동기식 및 비동기식 작업을 섞어서 사용하는 것은 오류를 일으킬 수 있으므로 주의해야 합니다.

conn = psycopg2.connect(host='localhost', dbname='mydb')
conn.autocommit = True

# Synchronous operation
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
results = cursor.fetchall()

# Asynchronous operation
await conn.execute("INSERT INTO users (name, age) VALUES ('John', 30)")

3. Accumulating too much data in memory

대량의 데이터를 처리하는 경우, Psycopg2의 결과를 모두 메모리에 로드하는 것은 성능 이슈를 일으킬 수 있습니다. 이를 피하기 위해 fetchmany() 또는 fetchone() 메서드를 사용하여 필요한 만큼의 데이터만 메모리에 로드할 수 있습니다.

cursor.execute("SELECT * FROM users")
result = cursor.fetchmany(100)

위의 예제에서는 한 번에 100개의 결과만 로드하므로 메모리 사용량을 효율적으로 유지할 수 있습니다.

결론

Psycopg2를 사용할 때, connection pooling, query parameterization 및 error handling과 같은 Best practices를 따르는 것이 중요합니다. 또한, 연결을 닫는 것을 잊지 않고, 동기식 및 비동기식 작업을 올바르게 처리하고, 대량의 데이터를 효율적으로 처리하는 방법을 고려해야 합니다. 이러한 가이드라인을 따르면 Psycopg2를 효과적으로 사용할 수 있습니다.