SQLAlchemy ORM을 활용한 Python 데이터베이스 연동

SQLAlchemy ORM 소개

SQLAlchemy는 Python에서 널리 사용되는 ORM(Object-Relational Mapping) 프레임워크로, 데이터베이스 작업을 효율적이고 유연하게 처리할 수 있습니다.

설치 방법

pip install sqlalchemy

데이터베이스별 드라이버 추가 설치:

# PostgreSQL
pip install psycopg2

# MySQL
pip install pymysql

# SQLite (별도 설치 불필요)

핵심 구성 요소

  • Engine: 데이터베이스 연결 관리
  • Session: 트랜잭션 및 영속성 제어
  • Model: 데이터베이스 테이블 매핑 클래스
  • Query: 데이터 조회 객체

데이터베이스 연결 설정

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# SQLite 연결 예제
db_engine = create_engine('sqlite:///app_data.db', echo=False)

# PostgreSQL 연결 예제
# db_engine = create_engine('postgresql://user:pass@localhost:5432/appdb')

# 세션 팩토리 생성
DatabaseSession = sessionmaker(autocommit=False, autoflush=False, bind=db_engine)

# 세션 인스턴스화
db_session = DatabaseSession()

데이터 모델 정의

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship, declarative_base

ModelBase = declarative_base()

class Customer(ModelBase):
    __tablename__ = 'customers'
    
    customer_id = Column(Integer, primary_key=True, index=True)
    full_name = Column(String(50), nullable=False)
    contact_email = Column(String(100), unique=True)
    
    orders = relationship("Order", back_populates="customer")

class Order(ModelBase):
    __tablename__ = 'orders'
    
    order_id = Column(Integer, primary_key=True)
    product_name = Column(String(100))
    quantity = Column(Integer)
    customer_ref = Column(Integer, ForeignKey('customers.customer_id'))
    
    customer = relationship("Customer", back_populates="orders")
    categories = relationship("Category", secondary="order_categories")

class Category(ModelBase):
    __tablename__ = 'categories'
    
    category_id = Column(Integer, primary_key=True)
    category_name = Column(String(30), unique=True)
    
    orders = relationship("Order", secondary="order_categories")

# 다대다 관계 연결 테이블
class OrderCategory(ModelBase):
    __tablename__ = 'order_categories'
    
    order_ref = Column(Integer, ForeignKey('orders.order_id'), primary_key=True)
    category_ref = Column(Integer, ForeignKey('categories.category_id'), primary_key=True)

테이블 생성

ModelBase.metadata.create_all(bind=db_engine)

CRUD 작업

데이터 생성

new_customer = Customer(full_name="김철수", contact_email="chulsoo@domain.com")
db_session.add(new_customer)
db_session.commit()

데이터 조회

customer = db_session.query(Customer).filter_by(full_name="김철수").first()

데이터 수정

customer.contact_email = "new_email@domain.com"
db_session.commit()

데이터 삭제

db_session.delete(customer)
db_session.commit()

고급 쿼리

from sqlalchemy import func, or_

# 조건 필터링
results = db_session.query(Customer).filter(
    or_(Customer.full_name.startswith("김"), 
        Customer.contact_email.contains("domain"))
).all()

# 집계 연산
order_count = db_session.query(
    Customer.full_name, 
    func.count(Order.order_id)
).join(Order).group_by(Customer.full_name).all()

관계형 데이터 작업

customer = Customer(full_name="이영희", contact_email="younghee@company.com")
new_order = Order(product_name="노트북", quantity=1, customer=customer)
db_session.add(new_order)
db_session.commit()

# 관계 접근
for order in customer.orders:
    print(f"{customer.full_name}의 주문: {order.product_name}")

트랜잭션 관리

try:
    new_data = Customer(full_name="트랜잭션 테스트", contact_email="tx_test@mail.com")
    db_session.add(new_data)
    db_session.commit()
except Exception:
    db_session.rollback()

권장 사항

  • 요청 단위 세션 관리
  • 예외 발생 시 롤백 처리
  • N+1 문제 해결을 위한 적절한 로딩 전략
  • 커넥션 풀 설정 최적화
from contextlib import contextmanager

@contextmanager
def db_session_scope():
    session = DatabaseSession()
    try:
        yield session
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()

# 사용 예시
with db_session_scope() as session:
    session.add(Customer(full_name="홍길동", contact_email="gildong@hong.com"))

태그: sqlalchemy Python ORM 데이터베이스 연동 SQL 데이터 모델링

5월 30일 01:52에 게시됨