11"""
2- 이 모듈은 ClickHouse 데이터베이스에 연결하고 SQL 쿼리를 실행하여 결과를 pandas DataFrame으로 반환하는 기능을 제공합니다 .
2+ ClickHouse 데이터베이스에 연결하고 SQL 쿼리를 실행하여 결과를 pandas DataFrame으로 반환하는 모듈입니다 .
33
44구성 요소:
5- - 환경 변수에서 접속 정보를 불러와 ClickHouse 서버에 연결합니다.
5+ - 환경 변수에서 접속 정보를 불러옵니다.
6+ - ClickHouse에 지연 연결(lazy connection)을 수행합니다.
67- SQL 쿼리를 실행하고 결과를 pandas DataFrame으로 반환합니다.
78- 연결 실패 및 쿼리 오류에 대해 로깅을 통해 디버깅을 지원합니다.
89"""
@@ -29,32 +30,51 @@ class ConnectDB:
2930 """
3031 ClickHouse 데이터베이스에 연결하고 SQL 쿼리를 실행하는 클래스입니다.
3132
32- 환경 변수에서 접속 정보를 로드하여 ClickHouse 서버에 연결하며,
33- SQL 쿼리 실행 결과를 pandas DataFrame으로 반환합니다.
33+ 환경 변수에서 접속 정보를 읽어들이며, 실제 연결은 SQL 실행 시점에 수행됩니다.
34+ 연결된 클라이언트를 통해 SQL 쿼리를 실행하고, 결과를 pandas DataFrame으로 반환합니다.
3435 """
3536
3637 def __init__ (self ):
3738 """
3839 ConnectDB 클래스의 인스턴스를 초기화합니다.
3940
40- 환경 변수에서 ClickHouse 접속 정보를 읽고, 즉시 서버에 연결을 시도합니다 .
41+ 환경 변수에서 ClickHouse 접속 정보를 불러오며, 연결은 즉시 수행하지 않습니다 .
4142 """
4243
4344 self .client : Optional [Client ] = None
44- self .host = os .getenv ("CLICKHOUSE_HOST" )
45- self .dbname = os .getenv ("CLICKHOUSE_DATABASE" )
46- self .user = os .getenv ("CLICKHOUSE_USER" )
47- self .password = os .getenv ("CLICKHOUSE_PASSWORD" )
48- self .port = os .getenv ("CLICKHOUSE_PORT" )
45+ self .is_connected : bool = False
4946
50- self .connect_to_clickhouse ()
47+ self .host = self ._get_env_or_raise ("CLICKHOUSE_HOST" )
48+ self .dbname = self ._get_env_or_raise ("CLICKHOUSE_DATABASE" )
49+ self .user = self ._get_env_or_raise ("CLICKHOUSE_USER" )
50+ self .password = os .getenv ("CLICKHOUSE_PASSWORD" , "" )
51+ self .port = int (self ._get_env_or_raise ("CLICKHOUSE_PORT" ))
52+
53+ def _get_env_or_raise (self , var_name : str ) -> str :
54+ """
55+ 주어진 환경변수를 읽고, 값이 없으면 예외를 발생시킵니다.
56+
57+ Parameters:
58+ var_name (str): 환경 변수 이름
59+
60+ Returns:
61+ str: 환경 변수의 값
62+
63+ Raises:
64+ ValueError: 값이 없을 경우
65+ """
66+
67+ value = os .getenv (var_name )
68+ if not value :
69+ logger .error ("Environment variable '%s' is not set." , var_name )
70+ raise ValueError (f"Environment variable '{ var_name } ' is not set." )
71+ return value
5172
5273 def connect_to_clickhouse (self ) -> None :
5374 """
5475 ClickHouse 서버에 연결을 시도합니다.
5576
56- 연결에 성공하면 client 객체가 설정되며, 실패 시 예외를 발생시킵니다.
57- 연결 상태는 로깅을 통해 출력됩니다.
77+ 연결 성공 시 client가 초기화되며, 실패 시 로그를 남기고 예외를 발생시킵니다.
5878 """
5979
6080 try :
@@ -65,30 +85,31 @@ def connect_to_clickhouse(self) -> None:
6585 password = self .password ,
6686 database = self .dbname ,
6787 )
88+ self .is_connected = True
6889 logger .info ("Successfully connected to ClickHouse." )
6990 except Exception as e :
91+ self .is_connected = False
7092 logger .error ("Failed to connect to ClickHouse: %s" , e )
7193 raise
7294
7395 def run_sql (self , sql : str ) -> pd .DataFrame :
7496 """
75- SQL 쿼리를 실행하고 결과를 pandas DataFrame으로 반환합니다.
76- 내부적으로 ClickHouse 클라이언트가 없으면 자동으로 재연결을 시도합니다.
97+ 주어진 SQL 쿼리를 실행하고 결과를 pandas DataFrame으로 반환합니다.
98+
99+ 연결이 설정되지 않은 경우 자동으로 연결을 시도합니다.
77100
78101 Parameters:
79102 sql (str): 실행할 SQL 쿼리 문자열
80103
81104 Returns:
82- pd.DataFrame: 쿼리 실행 결과를 담은 DataFrame 객체
105+ pd.DataFrame: 쿼리 결과를 포함한 DataFrame
83106
84107 Raises:
85- Exception: SQL 실행 중 오류 발생 시 예외를 발생시킵니다.
108+ Exception: SQL 실행 중 오류가 발생한 경우 예외를 발생시킵니다.
86109 """
87110
88- if not self .client :
89- logger .warning (
90- "ClickHouse client is not initialized. Attempting to reconnect..."
91- )
111+ if not self .is_connected or not self .client :
112+ logger .warning ("ClickHouse client not connected. Attempting to connect..." )
92113 self .connect_to_clickhouse ()
93114
94115 try :
@@ -97,7 +118,6 @@ def run_sql(self, sql: str) -> pd.DataFrame:
97118 column_names = [col [0 ] for col in columns ]
98119 df = pd .DataFrame (rows , columns = column_names )
99120 return df
100-
101121 except Exception as e :
102122 logger .exception ("An error occurred while executing SQL: %s" , e )
103123 raise
0 commit comments