1- import mysql .connector
2- from mysql .connector import pooling , Error
31import pandas as pd
42import json
53import os
4+ from dotenv import load_dotenv
5+ from sqlalchemy import create_engine , exc , text
6+
7+ # .env 파일에서 환경 변수 로드
8+ load_dotenv ()
69
710class DatabaseService :
811 """DB 커넥션 풀을 이용한 쿼리 서비스 클래스 (환경 변수 설정 및 타임아웃 적용)"""
912 def __init__ (self ):
1013 """환경 변수에서 설정을 읽어와 커넥션 풀을 초기화합니다."""
11- self .pool = None
14+ self .engine = None
1215 try :
13- db_config = {
14- 'host' : os .getenv ('DB_HOST' , '15.164.50.188' ),
15- 'port' : int ( os .getenv ('DB_PORT' , 3307 )),
16- 'user' : os .getenv ('DB_USER' , 'root' ),
17- 'password' : os .getenv ('DB_PASSWORD' , 'pwd1234' ),
18- 'database' : os . getenv ( 'DB_DATABASE' , 'daywalk' )
19- }
20- pool_size = int ( os . getenv ( 'DB_POOL_SIZE' , 5 ) )
16+ db_host = os . getenv ( 'DB_HOST' )
17+ db_port = os .getenv ('DB_PORT' )
18+ db_user = os .getenv ('DB_USER' )
19+ db_password = os .getenv ('DB_PASSWORD' )
20+ db_database = os .getenv ('DB_DATABASE' )
21+
22+ if not all ([ db_host , db_port , db_user , db_password , db_database ]):
23+ raise ValueError ( "DB 연결을 위한 모든 환경 변수가 설정되지 않았습니다." )
2124
22- self .pool = mysql .connector .pooling .MySQLConnectionPool (
23- pool_name = "daywalk_pool" ,
24- pool_size = pool_size ,
25- pool_reset_session = True ,
26- ** db_config
25+ # MySQL Connector/Python 용 SQLAlchemy URI
26+ db_uri = f"mysql+mysqlconnector://{ db_user } :{ db_password } @{ db_host } :{ db_port } /{ db_database } "
27+
28+ self .engine = create_engine (
29+ db_uri ,
30+ pool_size = 5 ,
31+ pool_recycle = 3600 , # 1시간마다 연결 재설정
32+ connect_args = {'connect_timeout' : 10 }
2733 )
28- print ("MySQL 커넥션 풀 생성 성공" )
29- except Error as e :
34+ print ("SQLAlchemy 커넥션 풀 생성 성공" )
35+ except ( exc . SQLAlchemyError , ValueError ) as e :
3036 print (f"커넥션 풀 생성 오류: { e } " )
3137
32- def _get_connection (self , timeout = 3 ):
33- """풀에서 커넥션을 가져옵니다. 타임아웃을 적용하여 무한 대기를 방지합니다."""
34- if not self .pool :
35- print ("커넥션 풀을 사용할 수 없습니다." )
36- return None
37- try :
38- # 타임아웃(초)을 설정하여 커넥션을 기다립니다.
39- return self .pool .get_connection (timeout = timeout )
40- except pooling .PoolError as e :
41- print (f"풀에서 커넥션을 가져오는 데 실패했습니다 (타임아웃 또는 풀 문제): { e } " )
42- return None
43- except Error as e :
44- print (f"커넥션 가져오는 중 알 수 없는 오류 발생: { e } " )
45- return None
38+ def close_connection (self ):
39+ if self .engine :
40+ self .engine .dispose ()
41+ print ("커넥션 풀 종료" )
4642
4743 def execute_query (self , query , params = None ):
4844 """쿼리 실행 후 데이터프레임 반환"""
49- connection = self ._get_connection ()
50- if not connection :
45+ if not self .engine :
46+ print ( "DB 엔진을 사용할 수 없습니다." )
5147 return None
5248
5349 try :
54- df = pd .read_sql (query , connection , params = params )
55- return df
56- except Error as e :
50+ with self .engine .connect () as connection :
51+ df = pd .read_sql (text (query ), connection , params = params )
52+ return df
53+ except exc .SQLAlchemyError as e :
5754 print (f"쿼리 실행 오류: { e } " )
5855 return None
59- finally :
60- if connection and connection .is_connected ():
61- connection .close ()
62- print ("사용한 커넥션을 풀에 반환했습니다." )
56+
57+ def user_table_query (self ):
58+ query = """
59+ SELECT * FROM user LIMIT 10;
60+ """
61+ return self .execute_query (query )
6362
6463 def get_user_info_by_user_id (self , user_id ):
6564 """user_id로 사용자 정보 조회"""
66- query = """
65+ query = f """
6766 SELECT
6867 HEX(u.id) AS user_id,
6968 u.name AS user_name,
@@ -81,23 +80,16 @@ def get_user_info_by_user_id(self, user_id):
8180 ) AS jt ON TRUE
8281 LEFT JOIN tag t ON t.id = UNHEX(REPLACE(jt.tag_id, '-', ''))
8382 WHERE
84- u.id = UNHEX(%s )
83+ u.id = UNHEX(:user_id_hex )
8584 GROUP BY
8685 u.id, c.id;
8786 """
88- user_id_hex = user_id [2 :] if user_id .startswith ('0x' ) else user_id
89- return self .execute_query (query , params = (user_id_hex ,))
90-
91- if __name__ == '__main__' :
92- # 아래 코드는 웹 프레임워크(예: FastAPI)의 시작 지점에서 한 번만 실행되어야 합니다.
93- # export DB_HOST=... 와 같은 방식으로 환경 변수 설정 후 실행할 수 있습니다.
94- db_service = DatabaseService ()
95-
96- if db_service .pool :
97- # 특정 사용자 데이터 조회 예시
98- test_user_id = '0x0034B410791D47A38ABFE03E0898A61A'
99- user_data_df = db_service .get_user_info_by_user_id (test_user_id )
100-
101- if user_data_df is not None :
102- print (f"{ test_user_id } 사용자의 전체 데이터를 성공적으로 가져왔습니다." )
103- print (user_data_df .to_string ())
87+ user_id_hex = user_id .replace ('-' , '' )
88+ df = self .execute_query (query , params = {'user_id_hex' : user_id_hex })
89+ if df is not None :
90+ df = df .rename (columns = {
91+ 'user_id' : 'userid' ,
92+ 'user_name' : 'name' ,
93+ 'tag_names' : 'like_list'
94+ })
95+ return df
0 commit comments