환경 변수는 프로세스가 컴퓨터에서 동작하는 방식에 영향을 미치는, 동적인 값의 모임이다. - wikipedia
위키피디아에 따른 환경 변수의 사전적 의미는 위와 같다. OS의 환경 변수는 시스템의 실행 파일이 놓여 있는 디렉터리의 지정 등 OS 상세적으로 응용소프트웨어가 참조하기 위한 설정이 기록된다. 응용소프트웨어는 시스템콜(system call)이나 OS의 표준 API 등을 통하여 간단히 값을 얻을 수 있도록 되어 있다. 쉽게 이야기해서 OS 각자 깊숙이 있는 응용프로그램을 쉽게 꺼내 쓰기 위해서 미리 변수로 등록해 놓는 것을 말한다.
환경 변수란 무엇인가? 똑똑하면서도 어리버리한 컴퓨터를 위해서 미리 경로나 값 등을 지정해 둔 것을 환경 변수(env)라고 할 수 있다. 우리가 python main.py 와 같은 명령어를 CLI로 입력하면 main.py라는 파일이 python을 통해 실행이 될 것이라고 생각하고 있겠지만, OS는 환경 변수가 설정되어있지 않으면 이런 간단한 CLI 조차 이해할 수 없다! 좀 더 깊은 이해를 위해 다양한 예시들을 살펴보자.
개발을 하게 되면, 환경 변수가 쓰이는 부분은 다양하지만 이번 포스팅에서는 OS 레벨의 환경 변수와 Application 레벨의 환경 변수에 대해서 다룰 것이다.
OS 레벨의 환경 변수 설정
Window OS
윈도우 운영체제에서는 어떻게 환경 변수를 컨트롤하는지 알아보자.
윈도우의 경우 [ 제어판 > 시스템 및 보안 > 시스템 > 고급 시스템 설정 ]으로 들어가면 위와 같은 창이 뜨게 된다. 여기서 환경 변수(N)를 클릭하게 되면 환경 변수를 설정할 수 있는 창으로 들어갈 수 있다. 언제 이 환경 변수를 설정해줘야 할까?
윈도우에서 Java를 통한 개발을 하려고 하는 사람이라면 필연적으로 환경 변수를 설정하게 될 것이다. Java 프로그래밍 언어를 컴파일하기 위해서는 JDK(Java Developer Kit)가 필요하다. 하지만 윈도우에서 JDK를 설치하고 바로 Java로 만들어진 코드를 컴파일하여 실행하려고 하면 필연적으로 에러가 발생하게 된다.
다음과 같이 JDK가 설치된 경로를 환경 변수로 지정해 줌으로써 OS에게 "Java에 관해서 컴파일 할 땐 이 경로에 있는 jdk를 써"라고 명시해 주는 꼴이 된다. 이러한 설정 덕분에 OS는 정상적으로 Java 코드를 컴파일할 때 다음과 같은 JDK의 경로를 참조하여 컴파일할 수 있게 된다.
Mac OS
그렇다면 Mac에서는 어떤 방식으로 환경 변수를 컨트롤할까? 다양한 방법이 있지만 다음과 같은 몇 개의 케이스를 알아보자. 먼저 Mac에서는 Terminal에서 printenv 명령어를 통해 현재 OS가 읽어들이고 있는 환경 변수를 확인할 수 있다.
환경 변수를 설정하는 첫 번째는 다음과 같은 명령어를 터미널에 입력하는 것이다.
export ENVIRONMENT_VARIABLE=value
이렇게 설정하면 ENVIRONMENT_VARIABLE의 값을 value라고 설정할 수 있다. 이렇게 터미널의 CLI를 통해서 환경 변수를 명시해 줄 수도 있고, 직접 설정 파일을 열어 파일 내부에 export로 Path를 명시해 줄 수도 있다.
다음은 vi ~/.zshrc 명령어를 통해서. zshrc 파일을 확인한 것이다. 네 번째 라인을 보면 export ZSH="$HOME/.oh-my-zsh"라고 환경 변수가 명시되어 있는데, 다음과 같이 파일에 직접 export를 통해 환경 변수를 명시해 줄 수 있다.
여기까지 알아본 것은 OS 레벨에서 환경 변수를 설정해 주는 것이었다. 대표적인 윈도우와 맥에서 환경 변수를 어떻게 설정하는지에 대해서 다루어보았다. 어떤 운영체제를 쓰던, 일반적이지 않지만 가끔씩 환경 변수 설정의 부재로 인한 에러가 발생하는 경우가 있다. 일반적으로는 응용소프트웨어를 설치함에 따라 직접 환경 변수를 설정해 주기 때문에, 환경 변수 설정의 부재로 인한 에러는 거의 발생하지 않는다.
Application 레벨의 환경 변수 설정
애플리케이션의 레벨에서도 env를 다루게 된다. 어떤 프로젝트를 하게 되던 환경 변수 설정은 필수적일텐데, 예시를 보며 어플리케이션 레벨에서의 환경 변수를 어떻게 설정하는 지에 다뤄 보자. 어플리케이션 레벨에서도 운영체제 레벨에서의 환경 변수의 정의와 마찬가지이다. 컴퓨터가 이해할 수 있도록 값을 정의해 두고, 가져다 쓰게 만드는 것이다. OS 레벨에서의 환경 변수 설정은 왜 필요한지 직관적으로 알 수 있겠지만, Application 레벨에서 환경 변수를 따로 설정해 두는 것이 어떤 이점이 있는지는 직관적으로 알기 어렵다.
Application이라 함은 Java 서버 및 node 서버 등 우리가 구현한 코드로 실행되는 서버라고 생각하자. 다음과 같은 이점이 있어 환경 변수를 사용하게 된다.
- 보안 : 민감한 데이터(Secret Key, Access Token) 등을 안전하게 관리할 수 있다.
- 다중 환경 : Local, Prod 등 다양한 환경에 맞게 환경 변수만 다르게 관리하면서 애플리케이션을 구동할 수 있다.
- 호환성 : 클라우드 서비스 및 컨테이너 환경에서 env를 관리할 때, 더욱 용이하게 관리할 수 있게 된다.
이 외에도 많은 이점이 있다. 따라서 개발하다 보면 "이 변수는 하드코딩하지 말고, 환경 변수로 빼는 건 어떨까요?"와 같은 리뷰를 받을 수 있는데, 이러한 이점을 얻기 위해서 환경 변수로의 전환을 고려하게 된다.
Javascript에서 환경 변수 구현
자바스크립트(이하 노드라고 표현)에서는 주로 .env 파일을 통해서 환경 변수를 관리하게 된다. 환경 변수에 필요한 값을 미리 .env 파일에 정의해 두고, 노드에서 .env의 값을 주입해 주는 패키지를 통해서 사용하게 된다. 다음과 같은 예시 상황을 생각해 보자.
redis 서버와 연결시키는 node 서버를 만들어야 해, 하지만 내 컴퓨터에서는 개발할 때에는 내 컴퓨터에 있는 redis 서버에 연결하고, 배포하여 운영할 때에는 다른 redis 서버에 연결하고 싶어.
이러한 경우에 .env를 다음과 같이 사용할 수 있다.
REDIS_HOST=localhost
REDIS_PORT=6379
그 후 redis에 연결하는 코드는 다음과 같이 작성한다.
import * as dotenv from "dotenv";
dotenv.config();
const redis: Redis = new Redis({
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
})
이와 같이 설정하게 되면 node의 패키지인 dotenv가 .env에 쓰여 있는 환경 변수를 process.env.REDIS_HOST과 같은 키워드로 가져다 쓸 수 있게 해 준다. ( dotenv.config(); 를 먼저 선언해두어야 함 )
환경 변수 설정을 도와주는 패키지 덕분에 redis에 연결하기 위한 host 및 port는 .env에 쓰여있는 설정을 따르게 된다. 잠깐! 이렇게 .env 파일을 이용해 환경 변수를 선언한 파일을 github에 올리기 전에 주의할 점이 하나 있다. 환경 변수에 민감한 데이터를 담고 있을 수 있기 때문에 .gitignore 파일에 .env 파일을 등록함으로써 민감한 정보가 github에 올라가지 않도록 주의해야 한다. ( 이래야 보안상의 이점을 얻을 수 있다. )
.gitignore란? 사용자가 원하지 않는 파일들을 git의 버전 관리에서 제외하는 역할을 한다. 즉 .gitignore에 명시된 파일들은 github에 올라가지 않는다.
Python
파이썬의 경우도 비슷하게 작동하게 된다.
REDIS_HOST=localhost
REDIS_PORT=6379
.env 파일이 자바스크립트와 똑같이 다음과 같다면 파이썬에서 환경 변수를 주입받는 부분은 다음과 같다.
import dotenv
import os
dotenv_file = dotenv.find_dotenv()
dotenv.load_dotenv(dotenv_file)
print(os.environ["REDIS_HOST"]) # localhost 출력
print(os.environ["REDIS_PORT"]) # 6379 출력
파이썬의 dotenv 패키지를 이용해서 자바스크립트와 비슷하게 환경 변수를 주입할 수 있다.
Java
자바의 경우에는 Spring을 사용한다고 가정하면 application.yml 파일을 사용하게 된다. spring이라는 자바로 이루어진 프레임워크는 애플리케이션을 실행하면서 자동적으로 application.yml 파일을 읽어 환경 변수를 주입하기 때문이다.
server:
port: 8080
spring:
datasource:
url: jdbc:postgresql://localhost:5432/marsboy
username: marsboy
password: marsboy
driver-class-name: org.postgresql.Driver
hikari:
initialization-fail-timeout: 3600
jpa:
hibernate:
ddl-auto: validate
database-platform: org.hibernate.dialect.PostgreSQLDialect
data:
redis:
host: localhost
port: 6379
다음은 application.yml 파일의 예시이다. DB는 postgres를 사용하고, 그와 관련된 설정이 나와있고 redis는 마찬가지로 다음과 같이 쓰게 된다. spring.data.redis.host 와 같은 키워드를 통해 환경 변수를 가져다 쓸 수 있다.
References
'CS > OS' 카테고리의 다른 글
패키지 매니저(Package Manager) 그리고 ubuntu 기본 세팅 (3) | 2023.09.29 |
---|