파이썬에서는 변수, 함수, 라이브러리, 모듈 등 다양한 이름(name)을 다룹니다. 그런데 사용하려는 변수의 이름이 이미 다른 변수나 함수, 메서드의 이름으로 존재할 가능성이 있습니다. 이런 이름 충돌을 피하려면 파이썬 프로그램이 수많은 이름을 어떻게 관리하는지 이해해야 하는데, 바로 이것이 네임스페이스(namespace)의 개념입니다.
네임스페이스의 세 가지 종류
- 지역 네임스페이스(Local Namespace): 함수 내부에서 선언된 변수와 함수의 이름들이 포함됩니다. 함수가 호출될 때 생성되며, 함수의 실행이 끝나면 함께 소멸합니다.
- 전역 네임스페이스(Global Namespace): 모듈 수준에서 정의된 함수와 변수들의 이름을 담고 있습니다. 프로그램(모듈)이 실행되는 동안 유지되며, 해당 모듈 안의 지역 네임스페이스에 속한 이름들을 포괄하는 상위 개념입니다.
- 내장 네임스페이스(Built-in Namespace): 가장 상위에 위치한 네임스페이스로, 파이썬 인터프리터가 기본적으로 제공하는 이름들(print, len, range 등)이 여기에 포함됩니다. 내장 네임스페이스는 전역 네임스페이스를 포함하고, 전역 네임스페이스는 다시 지역 네임스페이스를 포함하는 계층 구조를 이룹니다.
파이썬의 스코프(Scope)
네임스페이스에는 생성부터 소멸까지의 수명(lifetime)이 있으며, 이를 스코프(scope, 범위)라고 부릅니다. 스코프는 변수나 객체가 코드상에서 어느 위치에 선언되었는지에 따라 결정됩니다. 파이썬은 특정 이름을 찾을 때 LEGB 규칙에 따라 지역(Local) → 둘러싸인 영역(Enclosing) → 전역(Global) → 내장(Built-in) 순서로 검색합니다. 따라서 상위 범위에 선언된 이름은 하위 범위에서 접근할 수 있지만, 그 반대는 불가능합니다.
예제
아래 예제는 dir() 함수를 사용해 각 범위에서 접근 가능한 이름들을 출력합니다.
prog_var = 'Hello'
def outer_func():
outer_var = 'x'
def inner_func():
inner_var = 'y'
print(dir(), '- 내부 함수의 지역 변수')
inner_func()
print(dir(), '- 외부 함수의 지역 변수')
outer_func()
print(dir(), '- 전역 변수')
위 코드를 실행하면 다음과 같은 결과가 출력됩니다.
출력 결과
['inner_var'] - 내부 함수의 지역 변수
['inner_func', 'outer_var'] - 외부 함수의 지역 변수
['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'outer_func', 'prog_var'] - 전역 변수
실행 결과를 살펴보면 각 범위마다 접근 가능한 이름이 다르다는 것을 알 수 있습니다. 내부 함수에서는 자신의 지역 변수인 inner_var만 보이고, 외부 함수에서는 inner_func와 outer_var가 추가로 확인됩니다. 전역 범위에서는 모듈에 정의된 outer_func와 prog_var뿐 아니라 인터프리터가 제공하는 __name__, __file__ 같은 던더(dunder) 이름들까지 모두 조회됩니다. 이처럼 dir() 함수를 활용하면 현재 범위의 네임스페이스에 어떤 이름들이 존재하는지 손쉽게 확인할 수 있습니다.