본문 바로가기
Python

[Python] @contextmanager 데코레이터 에 대해서

by 윤팍 2025. 4. 1.

❓ @contextmanager란?

Python의 @contextmanager 데코레이터는 컨텍스트 매니저(Context Manager) 를 손쉽게 만들 수 있도록 도와주는 도구이다. 컨텍스트 매니저는 주로 리소스(파일, 네트워크 연결, 락 등)를 열고 닫는 등의 정리(cleanup) 작업을 자동으로 처리해줘서, 코드의 안정성과 가독성을 높여줍니다.

with 문과 함께 사용되어, 리소스를 열고 사용한 뒤 자동으로 정리(종료)해주는 구조를 만들어줍니다.

 

🤔 왜 사용하나요?

프로그래밍을 하다 보면 자원을 열고 나서 반드시 닫아줘야 하는 경우가 많죠.

예를 들면:

  • 파일을 열면 반드시 닫아야 하고,
  • 데이터베이스 연결도 끊어줘야 하며,
  • 락(lock)을 잡았다면 해제를 해줘야 해요.

이걸 매번 try-finally로 쓰면 코드가 지저분해지기 쉬운데, @contextmanager를 사용하면 이 과정을 간단하고 우아하게 처리할 수 있습니다.

 

📌 특징

  • 단 하나의 함수로 리소스 열기/사용/정리까지 모두 정의 가능
  • with 문을 통해 진입/종료 시점을 명확하게 컨트롤
  • 코드의 가독성, 안정성, 재사용성 향상

 

⚙️ 동작 방식

컨텍스트 매니저 함수는 내부에 yield를 사용해 두 부분으로 나눕니다.

  1. yield 앞쪽 코드: 리소스를 초기화하거나 열어주는 부분
  2. yield 뒤쪽 코드: with 블록이 끝났을 때 정리(clean-up) 작업을 수행
@contextmanager
def my_manager():
    # 진입 시 동작
    print("🔓 리소스를 엽니다")
    yield
    # 종료 시 동작
    print("🔒 리소스를 닫습니다")

 

🌟 장점

✅ 예외가 발생해도 정리 코드는 반드시 실행됨
✅ 코드가 간결하고 깔끔해짐
✅ 반복되는 try-finally 블록을 없애줘서 생산성 증가
✅ 다양한 리소스에 대해 재사용 가능한 구조를 만들 수 있음

 

🛠 언제 사용하면 좋을까?

📁 파일 처리 파일 열고 닫을 때 (open)
💾 DB 연결 커넥션 열고 닫을 때
🔐 락 처리 락(lock) 획득 및 해제
🔌 소켓 연결 네트워크 자원 관리
🧪 테스트 코드 테스트 setup/teardown 처리

 

💾  실제 사용 예시

데이터베이스 트랙잭션

class DatabaseTransaction:
    def __init__(self, session_factory):
        self.session_factory = session_factory

    @contextmanager
    def transaction(self):
        session = self.session_factory()
        try:
            yield session
            session.commit()
        except Exception as e:
            session.rollback()
            raise
        finally:
            session.close()

# 사용 예시
db = DatabaseTransaction(SessionFactory)

def update_user(user_id, new_data):
    with db.transaction() as session:
        user = session.query(User).get(user_id)
        user.update(new_data)
        # 자동으로 commit 또는 rollback

 

렇게 @contextmanager를 사용하면 코드의 안성과 가독성을 크게 향상시킬 수 있습니다! 🚀