Share
Sign In
Lighthouse Dev
SQLAlchemy 알아보기
D
donggyun_woo
👍🏻
1
시작 하면서
최근 KRM ver2.0 프로젝트를 시작하면서 웹서버를 구현하기 위해 SQLAlchemy를 사용하면서 모델링을 했습니다. 작업을 하면서 SQLAlchemy에 대해 공부한 내용을 공유해 보겠습니다.
SQLAlchemy?
SQLAlchemy는 파이썬을 위한 SQL 툴킷 및 Object-Relational Mapping(ORM) 라이브러리로, 데이터베이스와의 상호작용을 보다 쉽고 직관적으로 할 수 있게 도와줍니다.
SQLAlchemy는 데이터베이스 연결 관리, 트랜잭션 관리, 스키마 정의 및 관리 등 다양한 기능을 제공합니다.
SQLAlchemy 구조
크게 Core와 ORM으로 나뉘어져 있습니다.
Core (SQL Expression Language):
SQLAlchemy의 Core는 SQL 표현 언어를 사용하여 데이터베이스 쿼리를 생성하고 실행하는 데 중점을 둡니다.
SQLAlchemy Core는 SQL을 직접 작성하고 데이터베이스와 상호작용할 수 있는 저수준 인터페이스를 제공합니다.
Engine
데이터베이스와의 연결을 관리하는 핵심 구성 요소입니다.
Engine 객체는 데이터베이스와의 상호작용을 위한 연결 풀(Connection Pool) 및 데이터베이스 드라이버를 포함하여 SQLAlchemy의 다른 부분과의 통신을 조정
Engine의 주요 기능
데이터베이스 연결 설정:
Engine은 데이터베이스 URL을 통해 데이터베이스 연결 정보를 설정합니다.
연결 풀 관리:
Engine은 연결 풀을 관리하여 데이터베이스 연결의 효율성을 높이고 성능을 최적화합니다.
연결 풀은 데이터베이스 연결을 재사용하여 연결 생성 및 소멸에 따른 오버헤드를 줄입니다.
트랜잭션 관리:
Engine은 트랜잭션을 관리할 수 있는 기능을 제공합니다. 트랜잭션은 데이터베이스 작업을 원자적으로 처리하는 단위입니다.
트랜잭션은 begin 메서드를 사용하여 시작하고, commit 또는 rollback 메서드를 통해 종료할 수 있습니다.
SQL 실행:
Engine은 SQL 문을 실행하고 결과를 반환하는 메서드를 제공합니다.
connect 메서드를 사용하여 데이터베이스 연결을 수동으로 관리할 수 있습니다.
통합된 데이터베이스 드라이버 지원:
Engine은 다양한 데이터베이스 드라이버와 통합되어, 여러 종류의 데이터베이스(MySQL, PostgreSQL, SQLite 등)를 지원합니다.
데이터베이스 URL을 통해 사용하려는 데이터베이스 드라이버를 지정할 수 있습니다.
연결 풀(Connection Pool)
데이터베이스 연결의 효율적인 관리와 성능 최적화를 위한 메커니즘
연결을 미리 생성하고 재사용함으로써, 연결 생성과 소멸에 따른 오버헤드를 줄이고 애플리케이션의 성능을 향상
pool_size: 연결 풀의 최대 연결 수(기본값은 5).
max_overflow: 풀의 연결 수가 초과되었을 때 추가로 생성할 수 있는 연결 수(기본값은 10).
pool_timeout: 풀에서 연결을 가져오기 위해 대기하는 최대 시간(기본값은 30초).
pool_recycle: 지정된 시간이 지나면 연결을 재활용하여 새로 고침(기본값은 -1, 사용 안 함).
Connection Pool 종류
1.
QueuePool:
기본 연결 풀로, 고정된 크기의 연결 풀을 사용하며 초과 요청에 대해 큐잉을 지원합니다.
2.
SingletonThreadPool:
SQLite와 같은 단일 스레드 데이터베이스에 적합하며, 각 스레드가 고유의 연결을 가지도록 합니다.
3.
NullPool:
연결 풀을 사용하지 않으며, 각 연결 요청 시 새 연결을 생성합니다. 연결 풀링이 필요하지 않은 경우에 사용합니다.
Dialect
Dialect는 데이터베이스와의 구체적인 통신을 담당하는 구성 요소입니다. 각 데이터베이스 시스템(MySQL, PostgreSQL, SQLite 등)은 고유한 SQL 문법과 기능을 가지고 있으며,
Dialect는 이러한 특성을 추상화하여 SQLAlchemy가 다양한 데이터베이스를 지원할 수 있도록 함.
# Engine ## **create_engine** 함수는 주어진 데이터베이스 URL을 기반으로 **Engine** 객체를 생성합니다. engine = create_engine( # Dialect 'postgresql+psycopg2://user:password@localhost/mydatabase', # Connection Pool pool_size=10, max_overflow=20, pool_timeout=30, pool_recycle=3600 )
ORM (Object-Relational Mapping):
SQLAlchemy ORM은 데이터베이스 테이블을 파이썬 클래스에 매핑하여 객체 지향 프로그래밍의 편리함을 제공하는 고수준 인터페이스입니다.
ORM을 사용하면 데이터베이스 레코드를 파이썬 객체로 표현할 수 있어 더 직관적이고 생산성 높은 코드 작성이 가능합니다.
ORM을 활용한 DB 구현하기
코드를 보면서 관련된 내용들을 설명 드리겠습니다.
SQLAlchemy 2.0 기준으로 구현
1.
데이터 베이스 연결
from sqlalchemy import create_engine from sqlalchemy.orm import Session engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/") # create session and add objects with Session(engine) as session: session.add(some_object) session.add(some_other_object) session.commit() # OR from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/") # a sessionmaker(), also in the same scope as the engine Session = sessionmaker(engine) # we can now construct a Session() without needing to pass the # engine each time with Session() as session: session.add(some_object) session.add(some_other_object) session.commit()
세션: 세션(Session)은 데이터베이스와의 모든 상호작용을 캡슐화하며, 데이터베이스 작업을 관리하는 중요한 역할.
트랜잭션 관리:
세션은 데이터베이스 트랜잭션을 관리합니다. 데이터베이스 작업은 세션을 통해 시작되고, commit() 또는 rollback()을 호출하여 트랜잭션을 명시적으로 완료하거나 취소할 수 있습니다.
객체 상태 관리:
세션은 데이터베이스에서 조회된 객체들의 상태를 추적합니다. 객체가 세션에 추가되면 세션은 그 객체의 변경 사항을 추적하고, 필요할 때 데이터베이스에 반영합니다.
연결 관리:
세션은 엔진(Engine)과 연결(Connection)을 관리하며, 데이터베이스 연결 풀(Connection Pool)을 통해 연결을 효율적으로 재사용합니다. 세션이 종료되면 연결이 풀로 반환됩니다.
쿼리 실행:
세션은 데이터베이스에 대해 쿼리를 실행하고 결과를 반환합니다. 이는 세션을 통해 SQL 쿼리 또는 ORM 쿼리를 실행함으로써 이루어집니다.
Session() VS sessionmaker()
구성 편의성:
Session() 직접 사용: 세션을 생성할 때마다 엔진을 명시적으로 바인딩해야 합니다.
sessionmaker 사용: 세션 팩토리에서 한 번만 구성을 설정하면, 팩토리를 통해 생성된 모든 세션은 동일한 구성을 따릅니다.
일관성:
Session() 직접 사용: 세션 생성 시 구성 설정을 반복해야 하므로 일관성이 떨어질 있습니다.
sessionmaker 사용: 모든 세션이 일관된 구성을 가지므로 코드가 더 일관성 있고 관리하기 쉽습니다.
유연성:
Session() 직접 사용: 특정 상황에서 더 세밀한 제어가 필요할 때 유용할 수 있습니다.
sessionmaker 사용: 여러 세션을 쉽게 생성하고 관리할 수 있어, 대부분의 경우 더 유연하고 효율적입니다.
2.
Table 매핑
from datetime import datetime from typing import Optional from sqlalchemy import ForeignKey from sqlalchemy import func from sqlalchemy import Integer from sqlalchemy import String from sqlalchemy.orm import DeclarativeBase from sqlalchemy.orm import Mapped from sqlalchemy.orm import mapped_column from sqlalchemy.orm import relationship class Base(DeclarativeBase): pass class User(Base): __tablename__ = "user" id = mapped_column(Integer, primary_key=True) name: Mapped[str] fullname: Mapped[Optional[str]] nickname: Mapped[Optional[str]] = mapped_column(String(64)) create_date: Mapped[datetime] = mapped_column(insert_default=func.now()) addresses: Mapped[List["Address"]] = relationship(back_populates="user") class Address(Base): __tablename__ = "address" id = mapped_column(Integer, primary_key=True) user_id = mapped_column(ForeignKey("user.id")) email_address: Mapped[str] user: Mapped["User"] = relationship(back_populates="addresses")
DeclarativeBase
데이터베이스 테이블과 파이썬 클래스를 매핑하기 위해 사용되는 기본 클래스입니다.
DeclarativeBase를 통해 테이블 정의와 클래스 정의를 동시에 할 수 있어 코드의 가독성과 유지보수성을 높입니다.
# 사용하지 않고 매핑하는 경우 user_table = Table( "user", Base.metadata, Column("id", Integer, primary_key=True), Column("name", String(50)), Column("fullname", String()), Column("nickname", String(30)), )
nullable, Optional
class SomeClass(Base): # ... # will be String() NULL, but type checker will not expect # the attribute to be None data: Mapped[str] = mapped_column(nullable=True)
파이썬 코드: None이 아닌 값을 사용하지만,
데이터베이스 스키마: 널 값을 허용해야 할 때 mapped_column.nullable=True로 설정합니다
relationship()
위의 코드를 보면 back_populates 를 사용해서 명시적으로 user, addresses 를 정의 했습니다. 이외에도 backref 도 같이 알아 보겠습니다.
class User(Base): __tablename__ = "user" id = mapped_column(Integer, primary_key=True) name: Mapped[str] fullname: Mapped[Optional[str]] nickname: Mapped[Optional[str]] = mapped_column(String(64)) create_date: Mapped[datetime] = mapped_column(insert_default=func.now()) addresses: Mapped[List["Address"]] = relationship(backref="user") class Address(Base): __tablename__ = "address" id = mapped_column(Integer, primary_key=True) user_id = mapped_column(ForeignKey("user.id")) email_address: Mapped[str] # user 를 명시하지 않고 User테이블에서만 정의가 가능한 장점이 있음.
특성
backref
back_populates
설정 방식
한쪽에서만 정의
양쪽에서 명시적으로 정의
코드 간결성
더 간결함
더 명시적
자동 생성
자동으로 반대편 관계를 생성
자동 생성 없음
명시적 참조
없음
관계 설정이 명시적
복잡한 관계 처리
덜 유연함
더 유연하고 복잡한 관계 설정 가능
유지보수성
작은 프로젝트에 적합
큰 프로젝트나 복잡한 관계에 적합
💬
관계가 나온김에 자주 에러가 발생하거나 실수하는 Lazy Loading에대해서 알아보겠습니다.
레이지 로딩(Lazy Loading)은 SQLAlchemy와 같은 ORM(Object Relational Mapper)에서 사용되는 기법으로, 데이터베이스로부터 데이터를 실제로 필요할 때 가져오는 방식.
객체의 특정 속성에 접근할 때까지 데이터를 지연 로드(접근 할 때, 쿼리 실행)하는 방법
성능 최적화와 메모리 사용을 줄이기 위해 유용한 기법.
#위의 테이블을 봤을때. with Session() as session: addr = session.query(Address).first() addr.user # 세션이 열려있을때는 접근이 가능하지만 반복된다면 # N+1문제가 발생할 수도 있다. addr.user # lazy loading 에러 발생
Lazy Loading의 단점
1.
N+1 문제: 부모 객체를 반복적으로 로드할 때마다 자식 객체에 대한 개별 쿼리가 실행되어 성능 저하를 초래할 수 있습니다. 이를 피하기 위해 joined 또는 **subquery**와 같은 다른 로딩 전략을 사용할 수 있습니다.
2.
복잡성 증가: 데이터를 필요할 때 로드하므로, 코드의 흐름을 이해하는 데 다소 복잡성이 추가될 수 있습니다.
해결 방법
joinedload: 관련 데이터를 JOIN을 통해 한 번에 로드하여 N+1 문제를 해결하는 데 일반적으로 사용되는 로딩 전략입니다.
with Session() as session: addr = session.query(Address).options(joinedload(Address.user)).first() addr.user addr.user
마무리
SQLAlchemy에 대해서 사용방법(주로 쿼리 위주)만 알고 있었는데, KRM 프로젝트와 세션을 준비하면서 SQLAlchemy에대해 좀 더 알 수 있게 된것 같습니다.
SQLAlchemy로 할 수 있는 성능 최적화, 쿼리문 등에 대해 추가적으로 공부할 예정입니다.
참조
Kp
Subscribe to 'kpmg-lighthouse'
Welcome to 'kpmg-lighthouse'!
By subscribing to my site, you'll be the first to receive notifications and emails about the latest updates, including new posts.
Join SlashPage and subscribe to 'kpmg-lighthouse'!
Subscribe
👍🏻
1
Lighthouse
모바엑스텀(MobaXterm)과 소나큐브(SonarQube): 효율적인 개발 환경 구축을 위한 완벽한 조합
안녕하세요, 여러분! 오늘은 개발자와 IT 전문가에게 필수적인 두 가지 도구인 모바엑스텀(MobaXterm)과 소나큐브(SonarQube)에 대해 깊이 있게 다뤄보려 합니다. 이 두 도구는 각각의 강력한 기능을 통해 개발 및 코드 품질 관리에 큰 도움을 줍니다. 이제 각 도구의 사용법과 장점을 자세히 살펴보겠습니다. 모바엑스텀(MobaXterm) 모바엑스텀은 원격 컴퓨팅을 위한 올인원 솔루션으로, SSH, RDP, VNC 등 다양한 프로토콜을 지원합니다. 또한, X 서버와 탭 기반 터미널을 제공하여 여러 세션을 효율적으로 관리할 수 있습니다. 모바엑스텀의 주요 기능 다양한 프로토콜 지원: SSH, RDP, VNC, FTP, SFTP 등 다양한 프로토콜을 지원하여 원격 서버와의 연결이 매우 용이합니다. 탭 기반 터미널: 여러 터미널 세션을 하나의 창에서 관리할 수 있어 작업 효율이 높아집니다. X 서버 내장: 리눅스 GUI 애플리케이션을 윈도우 환경에서 실행할 수 있습니다. 플러그인 지원: 다양한 플러그인을 통해 기능을 확장할 수 있습니다. 파일 전송: 드래그 앤 드롭으로 파일을 쉽게 전송할 수 있습니다. 모바엑스텀 사용법 설치: MobaXterm 공식 웹사이트에서 최신 버전을 다운로드하고 설치합니다. 세션 생성: 프로그램을 실행하고 'Session' 버튼을 클릭합니다. 원하는 프로토콜(예: SSH)을 선택하고 연결할 서버 정보를 입력합니다. 탭 관리: 새로운 세션을 생성하면 탭이 추가됩니다. 여러 세션을 동시에 열어 작업할 수 있습니다. 파일 전송: 터미널 창에서 원격 서버와 로컬 시스템 간의 파일을 드래그 앤 드롭으로 쉽게 전송할 수 있습니다. 플러그인 설치: 필요에 따라 다양한 플러그인을 설치하여 기능을 확장할 수 있습니��. 소나큐브(SonarQube) 소나큐브는 코드 품질 관리 도구로, 코드의 버그, 취약점, 코드 스멜 등을 자동으로 분석하여 보고합니다. 이를 통해 코드의 품질을 향상시키고 유지보수를 용이하게 합니다. 소나큐브의 주요 기능 다양한 언어 지원: 자바, C#, 파이썬 등 다양한 프로그래밍 언어를 지원합니다. 자동 분석: 코드의 버그, 취약점, 코드 스멜 등을 자동으로 분석합니다. 품질 게이트: 코드 품질 기준을 설정하고, 이를 기준으로 빌드 통과 여부를 결정할 수 있습니다. 통합: Jenkins, Azure DevOps 등 다양한 CI/CD 도구와 통합할 수 있습니다. 대시보드: 코드 품질 상태를 시각적으로 확인할 수 있는 대시보드를 제공합니다.
Lighthouse
LAM 로깅 및 모니터링 시스템
Lighthouse에서 개발되는 모든 Product 모니터링 시스템을 갖춥니다. 모니터링이 필요한 부분은 잘 아시다 시피 시스템 영역 그리고 사용자 영역으로 구분될 수 있지요. 시스템 영역에서는 서버 상태, 데이터베이스 성능, 네트워크 트래픽, API 응답 시간 등을 실시간으로 모니터링하여 장애 발생 시 신속하게 대응할 수 있도록 합니다. 이를 통해 가용성, 신뢰성, 성능 등을 지속적으로 최적화하며, 문제 발생 시 그 원인을 빠르게 파악하고 해결할 수 있는 환경을 조성합니다. 또한 로그 분석 및 자동 알림 기능을 통해 예측 가능한 문제를 미리 식별하고 사전에 대응할 수 있도록 합니다. 사용자 영역에서는 사용자 행동 분석, 사용 패턴 추적, 인터페이스 반응 시간 등을 모니터링하여 사용자 경험(UX)을 극대화하는 데 중점을 둡니다. 이를 통해 사용자의 요구를 정확히 이해하고, 서비스 개선을 위한 데이터를 축적할 수 있습니다. 사용자의 피드백을 실시간으로 수집하고 분석하여, 즉각적인 조치와 더불어 장기적인 발전 계획에 반영합니다. 이와 같은 모니터링 시스템은 제품의 전체적인 품질 향상은 물론, 비즈니스 목표 달성에도 크게 기여할 것입니다. Kibana의 강력한 시각화 도구를 활용해, 이러한 데이터를 직관적이고 이해하기 쉬운 형태로 제공함으로써, 제품 개발 및 개선에 필요한 핵심 인사이트를 얻을 수 있습니다. 또한, 사용자 피드백을 자동으로 수집하고 분석하여, 제품에 대한 사용자의 반응을 실시간으로 파악하고 즉각적으로 대응할 수 있는 체계를 갖춥니다.
김원준
Python의 Decorator
0. 들어가며 이번 시간에는, 파이썬의 데코레이터에 대해서 발표해보도록 하겠다. 1. Decorator 란? 파이썬을 사용하다보면, 함수 혹은 메서드 위에 “@” 골뱅이가 붙은 특이한 이름을 본 적이 있을 것이다. 이러한 특이한 문법을 decorator라고 하는데, 영어 사전에서 decorator는 “장식자”이라는 뜻을 가지고 있다. 파이썬의 decorator 역시 동일한 의미로 사용된다. 어떤 함수가 있을 때, 해당 함수를 직접 수정하지 않고, 함수에 기능을 추가 /변경 / 확장 하고자 할 때 decorator를 사용한다. decorator는 함수를 인자로 받고, 또 다른 함수를 반환하는 고차함수 이다. 고차함수 ? 함수를 인자로 받아서, 함수를 반환하는 함수 파이썬에서 함수는 일급 객체로 취급되기 때문에 가능하다. 일급객체 ? → 아래에서 살펴보자. 그렇다면, 도대체 어떤 기능 이길래 추가 /변경 / 확장 모두 가능한 것일까? 지금부터 알아보자. 1.1. 데코레이터 기본 예시
😀👍🏻
2