소개
Python 의 컨텍스트 관리자 (context managers) 는 널리 사용되지만, 그 사용 목적을 이해하는 사람은 많지 않습니다. 파일 읽기 및 쓰기와 같이 흔히 사용되는 이 구문들은 특정 리소스가 특정 프로세스에서만 사용되도록 보장함으로써 애플리케이션이 시스템 메모리를 보존하고 리소스 관리를 개선하도록 돕습니다.
본 랩에서는 with 문을 사용하여 자동 리소스 관리를 수행하는 방법을 배우고, 이어서 두 가지 다른 방법, 즉 함수 기반 접근 방식과 클래스 기반 접근 방식을 사용하여 자신만의 컨텍스트 관리자를 생성해 볼 것입니다.
with 문
이 단계에서는 파일 객체와 같은 컨텍스트 관리자 (context manager) 와 함께 with 문을 사용하는 방법을 배웁니다. 컨텍스트 관리자는 코드 블록 (컨텍스트) 이 시작되고 끝날 때 알림을 받는 객체입니다. with 문은 이 알림 프로세스를 자동으로 처리합니다.
예를 들어, 파일 객체는 컨텍스트 관리자입니다. with 블록이 끝나면 블록 내에서 오류가 발생하더라도 파일 객체가 자동으로 닫힙니다. 이는 데이터 손실과 리소스 누수를 방지합니다.
참고: WebIDE(VS Code 와 유사) 사용에 익숙하지 않다면, 이 랩에서 먼저 학습하십시오.
실제로 어떻게 작동하는지 살펴보겠습니다. 왼쪽에 있는 파일 탐색기에서 main.py 파일을 엽니다. 다음 코드를 복사하여 붙여넣으십시오. 이 코드는 with 문을 사용하여 파일을 생성하고 내용을 작성한 다음, 그 내용을 읽을 것입니다.
## 'with' 문을 시연하기 위해 파일을 생성할 것입니다.
## 먼저, 파일에 일부 내용을 작성해 보겠습니다.
with open('my_file.txt', 'w') as f:
f.write('This is a test file.')
## 이제 컨텍스트 관리자를 사용하여 다시 읽어 보겠습니다.
## 'with' 블록을 벗어나면 파일이 자동으로 닫힙니다.
with open('my_file.txt') as f:
file_contents = f.read()
print(file_contents)
## 오류가 발생하더라도 파일은 여기서 자동으로 닫힙니다.
print("\nFile has been read and closed.")
이제 터미널에서 스크립트를 실행하여 출력을 확인하십시오.
python3 main.py
파일 쓰기 및 읽기가 성공적으로 완료되었음을 확인하는 다음 출력을 보게 될 것입니다. with 문은 쓰기 및 읽기 작업 후에 my_file.txt가 올바르게 닫히도록 보장합니다.
This is a test file.
File has been read and closed.
with 문을 사용하는 것은 파일이나 네트워크 연결과 같은 리소스를 처리하는 권장되는 방법입니다. 코드가 더 깔끔하고 안전해지기 때문입니다.
자신만의 컨텍스트 관리자 작성하기
이 단계에서는 제너레이터 함수와 @contextlib.contextmanager 데코레이터를 사용하여 사용자 정의 컨텍스트 관리자를 만드는 방법을 알아봅니다. 이는 간단한 컨텍스트 관리자를 만드는 간결한 방법입니다.
yield 문 앞의 코드는 with 블록에 진입할 때 실행되며 (설정 로직), yield 문 뒤의 코드는 블록을 나갈 때 실행됩니다 (정리 로직). yield된 값은 with 문에서 as 키워드를 사용하여 변수에 할당될 수 있습니다.
파일 탐색기에서 function_cm.py 파일을 엽니다. 다음 코드를 파일에 복사합니다.
## contextlib 데코레이터를 사용한 함수 기반 컨텍스트 관리자
import contextlib
@contextlib.contextmanager
def context_manager(num):
print('Enter') ## yield 이전 코드는 __enter__에서 실행됨
yield num + 1 ## yield 된 값이 'cm' 변수가 됨
print('Exit') ## yield 이후 코드는 __exit__에서 실행됨
with context_manager(2) as cm: ## cm 은 yield 된 값 (3) 을 받음
print('Right in the middle with cm = {}'.format(cm))
이제 터미널에서 스크립트를 실행합니다.
python3 function_cm.py
다음 출력을 보게 될 것입니다. 실행 순서에 유의하세요. yield 이전 코드가 먼저 실행되고, 그 다음 with 블록 내부 코드가 실행되며, 마지막으로 yield 이후 코드가 실행됩니다.
Enter
Right in the middle with cm = 3
Exit
이 접근 방식은 데이터베이스 연결 설정 및 해제 또는 설정을 일시적으로 변경하는 것과 같이 임시 컨텍스트를 생성하는 데 매우 유용합니다.
클래스 기반 컨텍스트 관리자
이 단계에서는 클래스로 컨텍스트 관리자를 구현하는 방법을 알아봅니다. 이 접근 방식은 더 많은 제어 권한을 제공하며 더 복잡한 시나리오에 적합합니다. 클래스 기반 컨텍스트 관리자를 생성하려면 두 가지 특별한 메서드인 __enter__와 __exit__를 정의해야 합니다.
__enter__:with문에 진입할 때 호출되는 메서드입니다. 설정 로직 (setup logic) 을 수행해야 합니다. 반환 값은as뒤에 변수가 제공된 경우 해당 변수에 할당됩니다.__exit__:with블록을 정상적으로 또는 예외로 인해 종료할 때 호출되는 메서드입니다. 정리 로직 (cleanup logic) 을 수행해야 합니다.
하나를 만들어 보겠습니다. class_cm.py 파일을 열고 다음 코드를 복사하여 붙여넣으세요.
## 클래스 기반 컨텍스트 관리자: __enter__ 및 __exit__ 메서드 구현
class ContextManager:
def __enter__(self, *args, **kwargs): ## 'with' 블록 진입 시 호출됨
print("--enter--")
return self ## 'as' 변수로 사용할 객체를 반환할 수 있음
def __exit__(self, *args): ## 'with' 블록 종료 시 호출됨
print("--exit--")
with ContextManager(): ## __enter__ 호출 후, 완료되면 __exit__ 호출
print("test")
터미널에서 스크립트를 실행합니다.
python3 class_cm.py
출력은 제어 흐름을 보여줍니다. __enter__ 메서드가 먼저 호출되고, 그 다음 with 블록 내부 코드가 실행되며, 마지막으로 정리 작업을 위해 __exit__ 메서드가 호출됩니다.
--enter--
test
--exit--
클래스 기반 접근 방식은 복잡한 설정 및 해제 로직을 단일 재사용 가능한 객체 내에 캡슐화할 수 있으므로 강력합니다.
요약
실습을 완료하신 것을 축하드립니다! Python 에서 컨텍스트 관리자를 사용하여 리소스를 효과적으로 관리하는 방법을 배웠습니다.
안전한 파일 처리를 위한 일반적인 with 문으로 시작했습니다. 그런 다음 두 가지 다른 방법을 사용하여 자신만의 사용자 정의 컨텍스트 관리자를 만드는 방법을 익혔습니다.
- 간단한 설정 및 해제 작업에 유용한
@contextlib.contextmanager데코레이터를 사용한 함수 기반 접근 방식. - 더 복잡한 리소스 관리에 이상적인
__enter__및__exit__메서드를 구현하는 클래스 기반 접근 방식.
이러한 기술은 리소스를 적절하게 처리하는 깔끔하고 안정적이며 효율적인 Python 코드를 작성하는 데 매우 중요합니다.



