<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko">
	<id>https://devcafe.co.kr/w/index.php?action=history&amp;feed=atom&amp;title=Oracle_%EC%A0%91%EC%86%8D%EC%9C%A0%EC%A7%80_%EC%BB%A4%EB%84%A5%EC%85%98%ED%92%80</id>
	<title>Oracle 접속유지 커넥션풀 - 편집 역사</title>
	<link rel="self" type="application/atom+xml" href="https://devcafe.co.kr/w/index.php?action=history&amp;feed=atom&amp;title=Oracle_%EC%A0%91%EC%86%8D%EC%9C%A0%EC%A7%80_%EC%BB%A4%EB%84%A5%EC%85%98%ED%92%80"/>
	<link rel="alternate" type="text/html" href="https://devcafe.co.kr/w/index.php?title=Oracle_%EC%A0%91%EC%86%8D%EC%9C%A0%EC%A7%80_%EC%BB%A4%EB%84%A5%EC%85%98%ED%92%80&amp;action=history"/>
	<updated>2026-05-17T11:11:42Z</updated>
	<subtitle>이 문서의 편집 역사</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://devcafe.co.kr/w/index.php?title=Oracle_%EC%A0%91%EC%86%8D%EC%9C%A0%EC%A7%80_%EC%BB%A4%EB%84%A5%EC%85%98%ED%92%80&amp;diff=2349&amp;oldid=prev</id>
		<title>Devcafe: 새 문서: == Oracle DB 접속 유지 및 종료 처리 방법 == 1. 접속 유지 방법 (Connection Pool 사용)  from sqlalchemy import create_engine, event from sqlalchemy.orm import sessionmaker from sqlalchemy.pool import QueuePool import cx_Oracle  # Oracle 접속 정보 username = &quot;your_user&quot; password = &quot;your_password&quot; dsn = &quot;hostname:1521/service_name&quot;  # Connection Pool 설정으로 Engine 생성 engine = create_engine(     f&#039;oracle+cx_oracle://{username}:{password}@{dsn}&#039;,     p...</title>
		<link rel="alternate" type="text/html" href="https://devcafe.co.kr/w/index.php?title=Oracle_%EC%A0%91%EC%86%8D%EC%9C%A0%EC%A7%80_%EC%BB%A4%EB%84%A5%EC%85%98%ED%92%80&amp;diff=2349&amp;oldid=prev"/>
		<updated>2026-01-22T23:47:57Z</updated>

		<summary type="html">&lt;p&gt;새 문서: == Oracle DB 접속 유지 및 종료 처리 방법 == 1. 접속 유지 방법 (Connection Pool 사용)  from sqlalchemy import create_engine, event from sqlalchemy.orm import sessionmaker from sqlalchemy.pool import QueuePool import cx_Oracle  # Oracle 접속 정보 username = &amp;quot;your_user&amp;quot; password = &amp;quot;your_password&amp;quot; dsn = &amp;quot;hostname:1521/service_name&amp;quot;  # Connection Pool 설정으로 Engine 생성 engine = create_engine(     f&amp;#039;oracle+cx_oracle://{username}:{password}@{dsn}&amp;#039;,     p...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;새 문서&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Oracle DB 접속 유지 및 종료 처리 방법 ==&lt;br /&gt;
1. 접속 유지 방법 (Connection Pool 사용)&lt;br /&gt;
&lt;br /&gt;
from sqlalchemy import create_engine, event&lt;br /&gt;
from sqlalchemy.orm import sessionmaker&lt;br /&gt;
from sqlalchemy.pool import QueuePool&lt;br /&gt;
import cx_Oracle&lt;br /&gt;
&lt;br /&gt;
# Oracle 접속 정보&lt;br /&gt;
username = &amp;quot;your_user&amp;quot;&lt;br /&gt;
password = &amp;quot;your_password&amp;quot;&lt;br /&gt;
dsn = &amp;quot;hostname:1521/service_name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Connection Pool 설정으로 Engine 생성&lt;br /&gt;
engine = create_engine(&lt;br /&gt;
    f&amp;#039;oracle+cx_oracle://{username}:{password}@{dsn}&amp;#039;,&lt;br /&gt;
    poolclass=QueuePool,&lt;br /&gt;
    pool_size=5,              # 유지할 커넥션 수&lt;br /&gt;
    max_overflow=10,          # 추가로 생성 가능한 커넥션 수&lt;br /&gt;
    pool_recycle=3600,        # 1시간마다 커넥션 재생성 (초단위)&lt;br /&gt;
    pool_pre_ping=True,       # 커넥션 사용 전 유효성 체크&lt;br /&gt;
    echo=False&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
# Session 생성&lt;br /&gt;
Session = sessionmaker(bind=engine)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
2. Keep-Alive 이벤트 리스너 추가&lt;br /&gt;
&lt;br /&gt;
# 커넥션 체크아웃 시 유효성 검증&lt;br /&gt;
@event.listens_for(engine, &amp;quot;connect&amp;quot;)&lt;br /&gt;
def receive_connect(dbapi_conn, connection_record):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;커넥션 생성 시 실행&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    print(&amp;quot;Database connected&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
@event.listens_for(engine, &amp;quot;checkout&amp;quot;)&lt;br /&gt;
def receive_checkout(dbapi_conn, connection_record, connection_proxy):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;커넥션 풀에서 꺼낼 때 ping 테스트&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    cursor = dbapi_conn.cursor()&lt;br /&gt;
    try:&lt;br /&gt;
        cursor.execute(&amp;quot;SELECT 1 FROM DUAL&amp;quot;)&lt;br /&gt;
        cursor.close()&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        # 커넥션이 끊어진 경우 재생성&lt;br /&gt;
        raise exc.DisconnectionError()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
3. Context Manager로 안전한 세션 관리&lt;br /&gt;
&lt;br /&gt;
from contextlib import contextmanager&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def get_db_session():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;안전한 세션 관리&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    session = Session()&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
        session.commit()&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        print(f&amp;quot;Error: {e}&amp;quot;)&lt;br /&gt;
        raise&lt;br /&gt;
    finally:&lt;br /&gt;
        session.close()&lt;br /&gt;
&lt;br /&gt;
# 사용 예시&lt;br /&gt;
def query_example():&lt;br /&gt;
    with get_db_session() as session:&lt;br /&gt;
        result = session.execute(&amp;quot;SELECT * FROM your_table&amp;quot;)&lt;br /&gt;
        for row in result:&lt;br /&gt;
            print(row)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
4. 프로그램 종료 시 접속 종료&lt;br /&gt;
&lt;br /&gt;
import atexit&lt;br /&gt;
import signal&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def cleanup_connections():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;모든 커넥션 정리&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    print(&amp;quot;Closing all database connections...&amp;quot;)&lt;br /&gt;
    engine.dispose()  # 모든 커넥션 풀 정리&lt;br /&gt;
    print(&amp;quot;Database connections closed&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# 정상 종료 시&lt;br /&gt;
atexit.register(cleanup_connections)&lt;br /&gt;
&lt;br /&gt;
# 강제 종료 시그널 처리&lt;br /&gt;
def signal_handler(signum, frame):&lt;br /&gt;
    print(f&amp;quot;\nReceived signal {signum}&amp;quot;)&lt;br /&gt;
    cleanup_connections()&lt;br /&gt;
    sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
signal.signal(signal.SIGINT, signal_handler)   # Ctrl+C&lt;br /&gt;
signal.signal(signal.SIGTERM, signal_handler)  # kill 명령&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5. 완전한 예제&lt;br /&gt;
&lt;br /&gt;
from sqlalchemy import create_engine, event, exc&lt;br /&gt;
from sqlalchemy.orm import sessionmaker&lt;br /&gt;
from sqlalchemy.pool import QueuePool&lt;br /&gt;
from contextlib import contextmanager&lt;br /&gt;
import atexit&lt;br /&gt;
import signal&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
class OracleDBManager:&lt;br /&gt;
    def __init__(self, username, password, dsn):&lt;br /&gt;
        self.engine = create_engine(&lt;br /&gt;
            f&amp;#039;oracle+cx_oracle://{username}:{password}@{dsn}&amp;#039;,&lt;br /&gt;
            poolclass=QueuePool,&lt;br /&gt;
            pool_size=5,&lt;br /&gt;
            max_overflow=10,&lt;br /&gt;
            pool_recycle=3600,&lt;br /&gt;
            pool_pre_ping=True,&lt;br /&gt;
            echo=False&lt;br /&gt;
        )&lt;br /&gt;
        &lt;br /&gt;
        # 이벤트 리스너 등록&lt;br /&gt;
        event.listen(self.engine, &amp;quot;connect&amp;quot;, self._on_connect)&lt;br /&gt;
        event.listen(self.engine, &amp;quot;checkout&amp;quot;, self._on_checkout)&lt;br /&gt;
        &lt;br /&gt;
        self.Session = sessionmaker(bind=self.engine)&lt;br /&gt;
        &lt;br /&gt;
        # 종료 핸들러 등록&lt;br /&gt;
        atexit.register(self.cleanup)&lt;br /&gt;
        signal.signal(signal.SIGINT, self._signal_handler)&lt;br /&gt;
        signal.signal(signal.SIGTERM, self._signal_handler)&lt;br /&gt;
    &lt;br /&gt;
    def _on_connect(self, dbapi_conn, connection_record):&lt;br /&gt;
        print(&amp;quot;New database connection established&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
    def _on_checkout(self, dbapi_conn, connection_record, connection_proxy):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;커넥션 사용 전 유효성 체크&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        cursor = dbapi_conn.cursor()&lt;br /&gt;
        try:&lt;br /&gt;
            cursor.execute(&amp;quot;SELECT 1 FROM DUAL&amp;quot;)&lt;br /&gt;
            cursor.close()&lt;br /&gt;
        except Exception:&lt;br /&gt;
            raise exc.DisconnectionError()&lt;br /&gt;
    &lt;br /&gt;
    @contextmanager&lt;br /&gt;
    def get_session(self):&lt;br /&gt;
        session = self.Session()&lt;br /&gt;
        try:&lt;br /&gt;
            yield session&lt;br /&gt;
            session.commit()&lt;br /&gt;
        except Exception as e:&lt;br /&gt;
            session.rollback()&lt;br /&gt;
            raise&lt;br /&gt;
        finally:&lt;br /&gt;
            session.close()&lt;br /&gt;
    &lt;br /&gt;
    def cleanup(self):&lt;br /&gt;
        print(&amp;quot;\nCleaning up database connections...&amp;quot;)&lt;br /&gt;
        self.engine.dispose()&lt;br /&gt;
        print(&amp;quot;All connections closed&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
    def _signal_handler(self, signum, frame):&lt;br /&gt;
        print(f&amp;quot;\nReceived termination signal {signum}&amp;quot;)&lt;br /&gt;
        self.cleanup()&lt;br /&gt;
        sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
# 사용 예시&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    db = OracleDBManager(&amp;quot;scott&amp;quot;, &amp;quot;tiger&amp;quot;, &amp;quot;localhost:1521/ORCL&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
    # 쿼리 실행&lt;br /&gt;
    with db.get_session() as session:&lt;br /&gt;
        result = session.execute(&amp;quot;SELECT sysdate FROM dual&amp;quot;)&lt;br /&gt;
        print(f&amp;quot;Current time: {result.fetchone()[0]}&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
    # 프로그램이 종료되면 자동으로 cleanup() 호출됨&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
6. 추가 옵션 - 주기적 Keep-Alive&lt;br /&gt;
&lt;br /&gt;
import threading&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
class KeepAliveThread(threading.Thread):&lt;br /&gt;
    def __init__(self, db_manager, interval=300):&lt;br /&gt;
        super().__init__(daemon=True)&lt;br /&gt;
        self.db_manager = db_manager&lt;br /&gt;
        self.interval = interval  # 5분마다&lt;br /&gt;
        self.running = True&lt;br /&gt;
    &lt;br /&gt;
    def run(self):&lt;br /&gt;
        while self.running:&lt;br /&gt;
            try:&lt;br /&gt;
                with self.db_manager.get_session() as session:&lt;br /&gt;
                    session.execute(&amp;quot;SELECT 1 FROM DUAL&amp;quot;)&lt;br /&gt;
                print(&amp;quot;Keep-alive ping successful&amp;quot;)&lt;br /&gt;
            except Exception as e:&lt;br /&gt;
                print(f&amp;quot;Keep-alive error: {e}&amp;quot;)&lt;br /&gt;
            time.sleep(self.interval)&lt;br /&gt;
    &lt;br /&gt;
    def stop(self):&lt;br /&gt;
        self.running = False&lt;br /&gt;
&lt;br /&gt;
# 사용&lt;br /&gt;
db = OracleDBManager(&amp;quot;scott&amp;quot;, &amp;quot;tiger&amp;quot;, &amp;quot;localhost:1521/ORCL&amp;quot;)&lt;br /&gt;
keep_alive = KeepAliveThread(db, interval=300)&lt;br /&gt;
keep_alive.start()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
주요 포인트:&lt;br /&gt;
	∙	pool_pre_ping=True: 커넥션 사용 전 자동 검증&lt;br /&gt;
	∙	pool_recycle=3600: 1시간마다 커넥션 재생성으로 stale connection 방지&lt;br /&gt;
	∙	atexit.register(): 정상 종료 시 자동 cleanup&lt;br /&gt;
	∙	signal 핸들러: Ctrl+C나 kill 명령어로 강제 종료 시에도 안전하게 종료&lt;br /&gt;
	∙	Context manager: 예외 발생 시에도 세션 정리 보장&lt;br /&gt;
이 방식으로 안정적인 DB 접속 관리가 가능합니다.​​​​​​​​​​​​​​​​&lt;/div&gt;</summary>
		<author><name>Devcafe</name></author>
	</entry>
</feed>