환경과 전역 환경

환경과 전역 환경 (Environments and the Global Environment)

루아에서 전역 변수(global variable)는 문자열 키로 전역 테이블(global table)에 저장돼요. 전역 테이블 자체는 _G라는 전역 변수에 저장돼요. 즉 _G는 전역 테이블을 가리키는 참조예요.

어떤 코드 블록이 실행될 때마다 그 블록은 자신의 "환경(environment)"을 가져요. 환경은 코드 블록이 전역 변수에 접근하는 방식을 결정하는데, 구체적으로는 함수나 청크(chunk)가 전역 변수를 _ENV라는 업밸류(upvalue)를 통해 참조해요. 각 코드 블록은 _ENV라는 업밸류를 하나 갖는데, _ENV는 전역 테이블을 가리키는 테이블이에요. 코드 블록 안에서 전역 변수 이름 name_ENV.name과 동일하게 취급돼요.

즉 전역 변수에 대한 접근은 다음과 같이 번역돼요.

name        →  _ENV.name
name = v    →  _ENV.name = v

다시 말해, 전역 변수는 사실 "환경 테이블의 필드"예요. 모든 전역 변수(심지어 _G 자신조차도)는 이 규칙의 적용을 받아요. _ENV라는 이름 자체는 Special 키워드가 아니며, 단지 블록의 첫 번째 업밸류의 관례적인 이름일 뿐이에요.

전역 환경은 어떤 코드 블록이든 바꿀 수 있어요. 예를 들어 함수 정의 안에서 _ENV = {} 와 같은 선언은 이후의 그 함수/블록 전역 접근이 전부 빈 새 테이블을 대상으로 하게 만들어요. _ENV에 다른 테이블을 할당하면, 그 블록의 전역 의미를 그 테이블로 리다이렉트해요.

모든 청크(chunk)는 컴파일할 때 자신만의 _ENV 업밸류를 만들어요. 즉 각 청크는 자신만의 환경을 갖고, 환경은 청크가 실행될 때 정해져요. 루아의 표준 라이브러리는 전역 테이블의 필드로 로드되며, 이 전역 테이블은 청크들이 공유하는 기본 환경을 구성해요.

_G로 접근하는 전역 테이블은 실제로는 _ENV._G 형태로 참조되는데, 기본 환경에서는 _G가 전역 테이블 자신을 가리켜요. _G를 다른 테이블로 재할당할 수도 있지만, 보통 그렇게 하지 않아요.

출처: 환경과 전역 환경 (Environments and the Global Environment)

본문

전역 변수

전역 변수는 전역 테이블(global table)의 필드일 뿐이라서, 초기값은 nil이에요. 전역 변수를 읽으면 그 필드의 현재 값을 가져오고, 쓰면 필드에 값을 저장해요. 존재하지 않는 전역 변수를 읽으면 nil을 반환해요. _G를 통해 전역 테이블 자체를 사전처럼 열거할 수도 있어요.

환경 설정

_ENV는 업밸류이므로, 일반 함수(Function) 블록 안에서는 지역 변수처럼 취급돼요. _ENV를 함수 내에서 재할당하면 그 함수의 전역 의미만 바뀌고, 외부로 전파되지 않아요. 청크의 최상위 레벨에서 실행되는 코드도 자신만의 _ENV를 갖고, 독립 실행(standalone) 인터프리터는 청크를 실행할 때 기본 전역 테이블을 환경으로 사용해요. load 계열 함수로 읽은 청크는 호출자 환경을 상속받을 수 있어요 (환경 인자를 전달할 때).

더 알아보기