PyQt개발강좌, 데이터베이스 연동, 데이터베이스 트랜잭션 관리

안녕하세요! 오늘은 PyQt를 이용한 데이터베이스 연동 및 트랜잭션 관리에 대해 알아보겠습니다. PyQt는 파이썬에서 GUI 애플리케이션을 쉽게 개발할 수 있게 해주는 강력한 라이브러리입니다. 이번 강좌에서는 SQLite 데이터베이스를 사용하여 PyQt 애플리케이션에서 데이터를 저장, 조회, 수정 및 삭제하는 방법을 설명합니다. 또한, 데이터베이스에서의 트랜잭션 관리에 대해서도 다루겠습니다. 트랜잭션 관리는 데이터베이스의 일관성과 무결성을 유지하는 데 매우 중요하므로 꼭 필요한 주제입니다.

1. 기본 개념 이해하기

첫 번째로, 데이터베이스와 트랜잭션의 기본 개념부터 살펴보겠습니다.

1.1. 데이터베이스

데이터베이스란 데이터의 집합을 체계적으로 저장하고 관리할 수 있는 시스템입니다. 다양한 종류의 데이터베이스가 있지만, 이번 강의에서는 경량인 SQLite를 사용할 것입니다.

1.2. 트랜잭션

트랜잭션은 데이터베이스의 상태를 변경하는 작업의 단위를 말합니다. 트랜잭션은 반드시 다음 네 가지 특성을 충족해야 합니다. 이를 통틀어 ACID이라고 부릅니다:

  • Atomicity(원자성): 트랜잭션 내의 작업이 모두 성공적으로 완료되거나, 아무 것도 적용되지 않아야 함.
  • Consistency(일관성): 트랜잭션 수행 전후의 데이터가 일관성 있어야 함.
  • Isolation(격리성): 여러 트랜잭션이 동시에 실시되더라도 서로의 결과에 영향을 주지 않아야 함.
  • Durability(지속성): 트랜잭션이 완료된 결과는 시스템 오류가 발생하더라도 취소되지 않아야 함.

2. PyQt 환경설정

이제 PyQt와 SQLite를 설치해야 합니다. 아래의 명령어를 사용하여 설치해 주세요.

pip install PyQt5 PyQt5-sip
pip install pysqlite3

설치가 완료되면, PyQt 애플리케이션을 만들기 위한 기본 템플릿을 설정합니다.

2.1. PyQt 기본 템플릿

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel, QMessageBox

class App(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(100, 100, 300, 200)
        self.setWindowTitle('PyQt Database Example')
        layout = QVBoxLayout()

        self.label = QLabel('데이터베이스 연동 예제', self)
        layout.addWidget(self.label)

        self.btn = QPushButton('데이터베이스 연결', self)
        self.btn.clicked.connect(self.connect_to_db)
        layout.addWidget(self.btn)

        self.setLayout(layout)

    def connect_to_db(self):
        QMessageBox.information(self, '알림', '데이터베이스에 연결되었습니다!')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    ex.show()
    sys.exit(app.exec_())

3. SQLite 데이터베이스 연동

이제 SQLite 데이터베이스에 연결하는 방법을 알아보겠습니다. 여기에서 데이터베이스를 생성하고, 테이블을 만들고, 데이터를 삽입하고 조회하는 기능을 구현할 것입니다.

3.1. 데이터베이스 연결하기

import sqlite3

class Database:
    def __init__(self, db_name):
        self.connection = sqlite3.connect(db_name)
        self.cursor = self.connection.cursor()
        self.create_table()

    def create_table(self):
        self.cursor.execute('''
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL,
                age INTEGER NOT NULL
            )
        ''')
        self.connection.commit()

    def insert_user(self, name, age):
        self.cursor.execute('INSERT INTO users (name, age) VALUES (?, ?)', (name, age))
        self.connection.commit()

    def fetch_all_users(self):
        self.cursor.execute('SELECT * FROM users')
        return self.cursor.fetchall()
    
    def close(self):
        self.connection.close()

3.2. 데이터를 삽입하고 조회하기

위에서 만든 Database 클래스를 활용하여 사용자 정보를 삽입하고 조회하는 방법을 구현합니다.

class App(QWidget):
    def __init__(self):
        super().__init__()
        self.db = Database('example.db')  # 데이터베이스 연결
        self.initUI()
    
    def initUI(self):
        # ... (initUI 코드는 이전과 동일)
        self.insertBtn = QPushButton('사용자 추가', self)
        self.insertBtn.clicked.connect(self.add_user)
        layout.addWidget(self.insertBtn)

    def add_user(self):
        name = "홍길동"  # 예시 이름
        age = 25  # 예시 나이
        self.db.insert_user(name, age)
        QMessageBox.information(self, '알림', f'{name}이(가) 추가되었습니다!')

    def show_users(self):
        users = self.db.fetch_all_users()
        user_text = "\n".join([f'{user[1]}, {user[2]}세' for user in users])
        QMessageBox.information(self, '사용자 목록', user_text)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    ex.show()
    sys.exit(app.exec_())

4. 데이터베이스 트랜잭션 관리

트랜잭션 관리는 데이터베이스 작업의 원자성을 보장하기 위한 필수 과정입니다. 데이터베이스에서 일어나는 여러 작업을 하나의 단위로 묶어서, 모든 작업이 성공적으로 수행되거나 모두 실패하도록 만들 수 있습니다.

4.1. 트랜잭션 시작하기

트랜잭션은 BEGIN TRANSACTION 명령어로 시작합니다.

def insert_users(self, users):
    try:
        self.cursor.execute('BEGIN TRANSACTION')
        for user in users:
            self.insert_user(user['name'], user['age'])
        self.cursor.execute('COMMIT')
    except Exception as e:
        self.connection.rollback()  # 에러 발생 시 롤백
        print(f'Error occurred: {e}')  # 오류 로그

위 코드에서 insert_users 함수는 여러 사용자를 트랜잭션으로 삽입하는 함수입니다. 사용자가 추가되는 동안 에러가 발생하면, 이전 작업은 모두 취소됩니다.

4.2. 트랜잭션 관리 예제

def add_multiple_users(self):
    users = [{'name': '이순신', 'age': 30},
             {'name': '강감찬', 'age': 40},
             {'name': '유관순', 'age': 22}]
    self.insert_users(users)
    QMessageBox.information(self, '알림', '사용자 여러 명이 추가되었습니다!')

5. 결론

이번 포스트에서는 PyQt를 활용하여 SQLite 데이터베이스와 연동하는 방법과, 트랜잭션을 관리하는 방법에 대해 알아보았습니다. 데이터베이스 연동은 애플리케이션에서 매우 중요한 기능이며, 트랜잭션 관리를 통해 데이터의 무결성을 유지할 수 있습니다. 이러한 기법들을 잘 활용하면 안정적이고 신뢰성 있는 애플리케이션을 작성할 수 있습니다.

마지막으로, 이 강좌가 여러분에게 도움이 되었기를 바라며, 궁금한 점이나 의견이 있으시면 댓글로 남겨주세요. 다음 강좌에서 만나요!