본문 바로가기
Language & Tool/Python

🐍컨텍스트 관리자와 자동 자원 관리, with 키워드

by 박수무당벌레 2025. 8. 4.

관련글 : 

try 구문 https://waydd.tistory.com/59

 

 

1. 핵심 개념

 

자원의 획득과 해제를 자동으로 처리 하기 위해 사용하는 컨텍스트 관리자(context manager) 구문

자원 관리의 안전성과 편의성 향상 목적의 문법

※ 컨텍스트 관리자란? __enter__와 __exit__ 메서드를 가진 객체

  • 동작 원리는 컨텍스트 관리자 역할을 하는 인스턴스 (ex. 파일) 에 있음
    → with 구문 안에서의 코드 실행 환경(context)을 열고(__enter__),
        코드 실행이 끝나면 그 문맥을 닫는(__exit__) 역할
    즉, 컨텍스트 관리자는 자원 사용 범위와 시점 이라는 문맥을 관리 + with 문법 속에서 위 과정을 자동화하도록 메서드 규약을 지킨 객체
  • 파일 (open), 데이터베이스 연결 (sqlite3.connect), 네트워크 소켓 (socket.socket), 쓰레드 락 (threading.Lock) 등 사용 후 반드시 닫아야 하는 자원을 다룰 때, 자동으로 정리 과정을 수행
    혹은 __enter__와 __exit__ 을 구현한 사용자 정의 클래스의 사용도 가능
    명시적으로 close()나 release()를 호출하지 않아도 블록 종료 시 자동으로 정리 작업이 실행됨
    → 안전 + 간결한 코드 작성
# 기존 방식 (try-finally)
file = open('data.txt', 'r')
try:
    content = file.read()
finally:
    file.close()

# with 사용 예시
with open('data.txt', 'r') as file:
    content = file.read()
# 여기서 자동으로 file.close() 호출
※ 동작 원리
①  문맥 관리자 객체 의 __enter__() 메서드를 호출하여 초기화 작업을 수행
②  as 뒤에 지정한 변수에 __enter__() 의 반환값을 할당
③  블록 내부의 코드를 실행
④  with 블록이 빠져나올 때, 예외 발생 여부와 상관없이 __exit__() 메서드를 호출하여 자원 해제

 

 

- 사용 목적 정리

  • 자원 관리 자동화 : 블록을 빠져나올 때 자동으로 자원을 해제
  • 코드 간결화 : try-finally 구조를 직접 작성하지 않아도 됨
  • 자원 누수 방지 : 예외가 발생해도 자동으로 자원이 해제
    → 기존 방식 사용시, 작업 후 close()를 직접 호출 깜박하면,  파일이 제대로 닫히지 않아 자원 낭비는 물론 오류 발생
  • 가독성 향상 : 자원 사용 범위가 명확하게 블록 단위로 구분됨

 

 

2. 사용 예시

 

- 파일 입출력

with open('data.txt', 'r') as f:
    content = f.read()
print(content)
# 블록을 벗어나면 f.close() 자동 호출

 

- 데이터베이스 연결

import sqlite3

with sqlite3.connect('example.db') as conn:
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE IF NOT EXISTS test(id INTEGER)")
    conn.commit()
# conn.close() 자동 실행

 

- 쓰레드 락

import threading

lock = threading.Lock()

with lock:
    # 임계 구역(critical section)
    print("Lock이 걸린 상태에서 실행")
# 자동으로 lock.release()

 

- 사용자 정의 컨텍스트 관리자

class MyContext:
    def __enter__(self):
        print("자원 준비")
        return "데이터"
    def __exit__(self, exc_type, exc_value, traceback):
        print("자원 해제")

with MyContext() as value:
    print("사용 중:", value)