contextvars — 컨텍스트 변수
contextvars — 컨텍스트 변수
contextvars 모듈은 컨텍스트 변수(Context Variables)를 관리하기 위한 API를 제공해요. 컨텍스트 변수는 전역 상태와 달리, 같은 스레드 안에서 실행되는 여러 비동기 작업이나 동시성 코드가 서로 간섭하지 않도록 독립적인 상태를 가지려고 할 때 유용합니다.
출처: Python 표준 라이브러리
본문
대표적인 사용 예가 비동기(동시성) 코드에서 각 태스크가 자기만의 컨텍스트 변수 값 집합을 갖는 것이에요. 웹 요청을 처리하는 서버에서 요청마다 고유한 ID나 인증 정보를 컨텍스트 변수에 넣어 두고, 같은 스레드에서 여러 요청을 처리해도 서로 값이 섞이지 않도록 하는 식입니다.
컨텍스트 변수 만들기
contextvars.ContextVar(name, *, default=_NO_DEFAULT) — 새 컨텍스트 변수를 만들어요. name은 주로 디버깅 목적으로 쓰이는 이름이고, default는 현재 컨텍스트에 값이 설정돼 있지 않을 때 반환할 기본값이에요.
var = contextvars.ContextVar('my_var', default='기본값')
값 설정과 조회
ContextVar.get(default=_NO_DEFAULT) — 현재 컨텍스트에서 이 변수의 값을 반환해요. 값이 없고 default가 주어지면 그 값을, 변수 생성 시 기본값이 있었으면 그 값을 반환하고, 둘 다 없으면 LookupError를 일으킵니다.
ContextVar.set(value) — 현재 컨텍스트에 이 변수의 값을 설정하고, 나중에 reset()으로 되돌리기 위한 토큰을 반환해요.
ContextVar.reset(token) — 이 변수의 값을 token이 만들어진 시점의 상태로 되돌려요. set()이 반환한 토큰만 사용해야 하며, 같은 변수의 토큰을 다른 변수에 쓰면 ValueError가 발생합니다.
값의 스코프를 제한하려면 전형적으로 Token을 with 문이나 try/finally와 함께 사용해요.
import contextvars
var = contextvars.ContextVar('var')
token = var.set('new value')
try:
# ... 이 블록 안에서는 var.get() == 'new value'
pass
finally:
var.reset(token) # 이전 값으로 되돌림
현재 컨텍스트 가져오기
contextvars.copy_context() — 현재 컨텍스트의 복사본을 만들어 반환해요. 반환된 Context 객체를 다른 곳(예: 새 태스크)에서 사용해 독립된 컨텍스트를 구성할 수 있습니다.
class contextvars.Context — 컨텍스트 변수와 그 값들의 매핑을 나타내는 객체예요. Context.run(callable, *args, **kwargs)로 그 컨텍스트 안에서 callable을 실행할 수 있고, copy()로 복사하며, keys()로 변수 목록을 얻거나 items()로 (변수, 값) 쌍을 순회할 수 있어요.
컨텍스트는 asyncio 태스크마다 자동으로 전파되므로, 비동기 코드 안에서도 컨텍스트 변수가 태스크 경계를 넘어 일관되게 유지됩니다.
주의할 점
컨텍스트 변수는 스레드 로컬 저장소처럼 동작하지만 스레드 수준이 아니라 실행 컨텍스트 수준으로 분리된다는 점이 핵심이에요. 따라서 동일한 스레드 안의 여러 비동기 태스크가 서로 다른 값을 가질 수 있고, 스레드 간에는 기본적으로 각자의 컨텍스트를 가집니다.
더 알아보기
- 원문: python: contextvars — Context Variables
- asyncio — 비동기 I/O — 태스크별 컨텍스트 전파 동작