Skip to main content

환경변수

warning

This explanation is only for bash shells in the systems like Linux, BSD, Mac, and Cygwin.

의미
운영체제프로그램에서 사용되는 데이터를 저장하고 있는 변수로써, 이름과 값을 가진다. 환경변수는 case-sensitive 하며, 특정 환경의 성격을 정의한다.

fork()라는 시스템 콜을 통해 생성된 child process는 부모의 환경변수 복사본(메모리 레이아웃)을 상속받게 된다(실제 물리 메모리 주소는 다르다). 그렇게 생성된 child process에서 execve()를 실행해, path 경로에 해당하는 새로운 프로그램의 데이터를 메모리로부터 로드해 메모리 공간(Stack, Heap, Data Segments)을 대체(overwritten)한다. 하지만 환경변수는 프로그램으로 복사되기 때문에, 이전 부모 프로세스로부터 상속받은 환경변수 값을 가진다.

환경변수에 접근하려는 경우,
extern으로 선언된 외부 변수 environ으로부터 environment라고 하는 포인터 배열을 가리킬 수 있다(마지막 pointer는 NULL이다).

또는, POSIX.1이 아닌 경우(POSIX.1에서는 세 번째 인자가 정의 돼 있지 않다.), int main(int argc, char *argv[], char *envp[]) 함수에서 char *envp[](세 번째 인자로 넘어옴)로 환경변수에 접근할 수 있다.

이러한 특성으로 인해 환경변수는 아주 다양하게 활용된다. (참고로 환경변수는 '변수' 이다.)

$ brew doctor -v

이렇게 활용할 수 있는 이유는 현재 shell에서 PATH 라는 환경변수로부터 경로를 참조하기 때문이다.

참고로 현재 로그인 된 shell의 profile에 설정된 환경변수는 다음과 같이 확인할 수 있다.

$ printenv

활용

환경변수는 현재 로그인된 shell로부터 사용하기도 하지만, 런타임 또는 프로그램에서 일회성으로(.bashrc, .zshrc, .bash_profile, .zprofile 등에 저장하지 않고) 사용하기도 한다.

# export로 환경변수를 지정하면 shell의 환경변수를 overwrite 하게 된다.
$ export NODE_ENV=development node index.js

환경변수는 어디에 저장되나?

warning

이 예시는 Node.js에서 일반적으로 일회성으로 사용하는 경우(.env 파일 등)를 가정한다. (a.k.a. 런타임 환경변수)

메모리 상에는 Stack Segment의 상단에 위치한다. 이는 실제 Heap, Data, Code 메모리와는 별도로 관리되고, 운영체제에 의해 설정된다.

Node.js에서 process.envNode.js 환경에서만 사용할 수 있는 전역으로 설정된 객체로, Node.js 런타임에 주입된다. 또한, 이는 일회성을 띠는 객체이고 프로세스 종속적이라, 프로세스가 종료되면 Node.js 자체의 메모리가 할당 해제되면서 마찬가지로 사라지게 된다.

즉, process.env라는 객체는 프로세스에 할당된 메모리 공간에 함께 저장되는 것은 너무나 당연하고, environ 포인터를 통해 읽어들인 환경변수(포인터 배열)를 Node.js 프로세스에 주입했다고 할 수 있다.

만약 누군가가 환경변수가 어디에 저장되는지 묻는다면 다음과 같이 대답하면 된다.

프로세스에 종속적인 process.env 라는 전역 객체에 저장된다. 그리고 이 객체는 프로그램이 실행 시에 Node.js에서 제공하는(built-in) core module인 process에 있는 property 이다. 그리고 이 process.env의 생명주기는 프로세스에 종속적이다.

Related Links