from __future__ import annotations from typing import Any class DatabaseService: """MySQL 연결을 캡슐화하는 서비스. 미설정 시 graceful skip.""" def __init__(self, host: str, port: int, db: str, user: str, password: str): self._config = dict(host=host, port=port, db=db, user=user, passwd=password) self._conn = None def connect(self) -> None: if not self._config["user"]: return try: import pymysql self._conn = pymysql.connect(**self._config) except Exception as e: print(f"[DB] 연결 실패 (선택적 기능): {e}") def execute(self, sql: str, params: tuple = ()) -> list[dict[str, Any]]: if self._conn is None: return [] cursor = self._conn.cursor() cursor.execute(sql, params) columns = [d[0] for d in cursor.description or []] return [dict(zip(columns, row)) for row in cursor.fetchall()] def execute_write(self, sql: str, params: tuple = ()) -> int: """INSERT/UPDATE/DELETE 실행 후 lastrowid 반환.""" if self._conn is None: return 0 cursor = self._conn.cursor() cursor.execute(sql, params) self._conn.commit() return cursor.lastrowid def init_schema(self) -> None: if self._conn is None: return cursor = self._conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS td_conversations ( id INT AUTO_INCREMENT PRIMARY KEY, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) """) cursor.execute(""" CREATE TABLE IF NOT EXISTS td_messages ( id INT AUTO_INCREMENT PRIMARY KEY, conversation_id INT NOT NULL, role VARCHAR(20) NOT NULL, content TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (conversation_id) REFERENCES td_conversations(id) ) """) self._conn.commit() def close(self) -> None: if self._conn: self._conn.close() self._conn = None