지금 주인장은 Nest.js 공부 중 ···
Sign In
아카이브

매번 .env 를 팀원들에게 알려줘야할까?

현우
Category
Empty
사이드 프로젝트를 진행하다보면 신규 팀원이 들어오는 경우에는 환경변수 파일에 대한 내용을 공유한다. 그런데 사실 이미 개발을 진행하다보면, 프로젝트가 점점 커지면서 어떤 환경변수가 구성되어있는지 잘 모르는 경우도 있고, 만약 누군가 새로운 환경변수를 추가한 경우에는 다른 사람에게 알림을 주지 않는 이상 잘 모르고 넘어간다.
그런데 여기서 문제는.. 나중에 빌드 상황에서 누락된 환경변수로 인해 빌드 에러가 발생하거나, 환경변수 히스토리가 누락된 경우에는 어떤 환경 변수가 있었는지에 대한 추적이 불가능하다. 여기서 매번 .env 파일을 공유하다 문득 궁금한 점이 생겼다. "환경 변수를 이렇게 매번 파일로 공유하고, 매번 메신저로 공유해줘야하나?"

클라우드 환경에서 환경변수 가져오기

보통 .env 의 경우에는 파일 내에 정적 정보로 저장된다. 그래서 .env 는 외부로 유출되면 절대적으로 안되며, 정말 중요한 정보들이 들어가는 경우가 많다. 또 실수로 환경변수가 공개된 저장소에 올라가게되면, 잠깐의 찰나라도 공격당하는 경우가 있을 수 있다. (여기서 공격 당하는 경우라고 하면, 중요한 내부 키가 탈취당해 과금이 나오는 경우 ^,^ ..)
그래서 이러한 환경변수들을 클라우드 환경에서 업데이트될 때마다 내려받고, 더이상 개발자는 환경변수가 어떤 것들이 비어져있고, 담당자는 누구인지를 체킹하지 않아도 되는 번거로움을 없앨 수 있다.

dotenv-vault로 환경 변수 컨트롤하기

npx dotenv-vault push # 최신 .env 업로드 npx dotenv-vault pull # 팀원이 최신 .env 받기
가장 단순하면서 환경변수 파일을 가장 쉽게 관리할 수 있는 오픈소스 솔루션이다. 기존의 .env 워크 플로우를 유지하면서 암호화된 .env.vault파일만을 git 에 올리는 방식이다. 변경사항은 팀원이 pull 을 하면 항상 반영되며 도입 시에 가장 진입 장벽이 낮다.
가장 빠르게 적용 가능하면서, 팀원들이 혼동하지 않도록 하는 방식이 제일 효율적이었다. doppler와 같은 다른 솔루션의 경우에는 권한에 따른 환경변수 부여도 가능하지만, 내가 진행하는 사이드 프로젝트에서는 개발자 모두가 동등한 권한을 가지고 개발을 진행하는 것이기에 dotenv-valut 로 불편한 점들을 먼저 해결하고, 추가적으로 필요할 때 고려해보고자 했다.
비교를 하고자했던 세 가지 솔루션 모두 결국에는 해결하고자 하는 문제점이 최종 끝에서는 동일하기 때문이다.
해당 프로젝트는 무료였는데, 유료로 변경되었다..

dotenv-vault 동작 원리

.env (비밀값 원본) → git에 절대 올리면 안 됨 .env.vault (암호화된 파일) → git에 올려도 안전 .env.me (인증 파일) → 인증 여부 확인 파일
dotenv-vault 를 통해 로그인을 하게 되면 .env.me 를 통해 인증 여부 파일을 하나 받게 되는데, 저 파일을 기반으로 .env.vault 를 복호화하는데 인증을 수행하고 내부적으로는 DOTENV_KEY 를 통해 복호화를 진행하게 된다.
복호화 자체는 서버에서 진행을 해준다. 로컬에서는 DOTENV_KEY 없이도 .env 를 받게되는데, 이 DOTENV_KEY 는 서버에 직접근을 하지 못해 복호화를 하지 못하는 상황(CI/CD와 같은) 에서 사용을 하게 된다.

dotenv-vault 사용 방법

만약 아레와 같이 환경변수 파일이 있다고 가정을 해보자.
// .env // CRA는 REACT_APP_ 접두사 필수 REACT_APP_API_URL=https://api.example.com REACT_APP_API_KEY=your_key_here // Vite는 VITE_ 접두사 필수 VITE_API_URL=https://api.example.com
아래와 같이 순차적으로 명령어를 실행하게 되면, 초기 사용자는 push 명령어와 함께 .env.vault 파일을 받게 되고 새로운 사용자는 로그인 후, pull 명령어와 함꼐 .env.vault 파일을 받게 된다.
# 설치 (초기에 환경변수 프로젝트를 구성할 때) npm install dotenv --save npx dotenv-vault new # 로그인 (이미 누군가 구성을 해놓았다면 로그인 진행) npx dotenv-vault login # .env 파일 push (신규 업로드 또는 환경변수 업데이트 시) npx dotenv-vault push # 다른 팀원이 pull (다운로드) npx dotenv-vault pull # 만약 `.env.vault` 파일이 없다면 아래 명령어를 실행해보자 npx dotenv-vault build
로컬환경에서는 로그인한 사용자의 .env.me 를 통해 .env.vault 파일을 기반으로 내부적으로 복호화 key 값을 통해 .env 파일을 서버에서 내려준다.

만약 빌드 환경에도 자동으로 적용하고 싶다면?

현재 서비스에서는 .env 를 소스코드에 포함시키고 있지 않아, vercel 에서 배포될 경우에는 환경변수를 명시적으로 입력하여 서비스를 프로덕션 환경으로 배포하고 있다. 그런데 만약 .env.vault 를 읽어 자동으로 환경변수를 매핑하고 싶다면 어떻게 해야할까?
# 현재 환경변수의 복호화 키를 조회할 수 있다. npx dotenv-vault keys # 환경 별로 키가 달라, 환경 별로도 확인 가능하다. npx dotenv-vault keys development npx dotenv-vault keys production /** * 환경 별로 키가 출력이 된다. * dotenv://:key_development_xxx…?environment=development * dotenv://:key_production_xxx…?environment=production */
DOTENV_KEY = dotenv://:key_xxx…?environment=production
💬
.env 은 암호화되어 해당 파일에 작성을 해주는 것이 아니라, 배포 플랫폼의 환경변수 설정 삽입하기
Vercel
Settings → Environment Variables
DOTENV_KEY = dotenv://:key_xxx…?environment=production
Netfilfy
Site Settings → Environment Variables
DOTENV_KEY = dotenv://:key_xxx…?environment=production
Git Actions
# .github/workflows/deploy.yml env: DOTENV_KEY: ${{ secrets.DOTENV_KEY }}

빌드 시에, 환경변수를 읽는 흐름은 이렇게 진행된다.

매번 vercel 에 환경변수를 명시적으로 주입하는 방법보다,
이렇게 하나의 복호화 키로 모든 플로우를
dotenv-vault 로 묶을 수도 있다.
배포 플랫폼 환경 변수에 DOTENV_KEY 등록 ↓ 빌드 시 .env.vault (Git에 커밋된 파일) 복호화 ↓ 환경 변수 주입 완료
프로젝트를 만들고, 최종적으로 환경변수가 업로드되면 UI 환경으로도 쉽게 파악이 가능하다.
물론 npx dotenv-vault pull 을 하게 되면 .env 를 로컬 환경에서도 확인할 수 있다.
정말 편리하고 좋은 서비스이지만, 반면 걱정해야하는 부분도 있다.
환경변수 파일을 클라우드 환경으로 믿고 업로드를 하는 행위가, 과연 보안상 안전하다는 것이냐에 대한 물음이다.
사이드 프로젝트이면서, 사용하고 있는 환경변수들의 플랫폼이 플랜제를 마음대로 바꿀 수 있는 종량제의 플랜이 아니기 때문에 비교적 민감한 데이터들이 아니어서 dotenv-vault 를 사용해도 된다고 판단을 했었다.
하지만 dotenv-vault 서버가 해킹당하거나, 서비스가 종료하게 되면 의존성으로 인한 문제 · dotenv-vault 계정이 털리게 되면 .env 내용에 접근이 가능한 부분 등이 보안상의 문제점이라 생각이 들었는데.. 마침 이에 따른 대안이 나와있길래 추가로 찾아보았

보안 문제로 등장한 dotenvx

클라우드 서버에 의존하고, 또 이로 인해 .env 파일이 유출될 가능성이 있기 때문에 (유료화 문제도 ^^,,) dotenv-vault 가 클라우드 환경으로 구성되었었다면 dotenvx 는 클라우드 없이 Git 환경으로만 구성이 되었다.
dotenvx 는 아래 세가지 문제들을 중점적으로 해결하게 된다.
플랫폼 불일치 문제 : 어떤 언어 · 프레임워크에도 종속받지 않고 동일하게 동작할 수 있다.
멀티 환경 관리 : .env.production , .env.staging 등의 명시적 파일 분리
파일 유출 : 암호화로 Git 에 올려도 안전하게 관리
또 AI 코딩 도구들의 발전으로 인해, .env 파일을 읽어서 LLM에 시크릿이 노출될 수 있는 위험이 생겼고, 암호화된 .env 파일은 에이전트가 읽어도 내용을 해석할 수 없어 프롬프트나 모델 컨택스트로 시크릿이 유출되는 것을 막을 수 있다.

dotenvx의 암호화 흐름

dotenvx의 암호화 및 복호화 흐름은 아래와 같다.
.env (평문 작성) → dotenvx encrypt → .env (암호화됨) + .env.keys (비밀키) → .env는 Git 커밋 ✅, .env.keys는 커밋 ❌ → 배포 플랫폼에 DOTENV_PRIVATE_KEY 등록 → 빌드/런타임에 자동 복호화

설치 방법

먼저 .env 를 정의한다.
# .env (개발용) VITE_API_URL=https://dev-api.example.com # .env.production (프로덕션용) VITE_API_URL=https://api.example.com
그리고 .env 를 암호화하게 위해 dotenvx 를 설치한다.
# 설치 npm install @dotenvx/dotenvx # 개발용 .env 암호화 npx dotenvx encrypt # 복호화는 아래 커맨드로 npx dotenvx decrypt # 프로덕션용 암호화 npx dotenvx encrypt -f .env.production
암호화 후에는 아래와 같이 .env 파일 내부 내용이 변환된다.
#/-------------------[DOTENV_PUBLIC_KEY]--------------------/ DOTENV_PUBLIC_KEY="037cfbfc90234..." # .env VITE_API_URL="encrypted:BAZb6wDPFaFeFzq8..."
그리고 새로운 파일로 .env.key 파일이 생기게 된다. .env.key 파일에는 정말 중요한 비밀 복호화 키가 생성되기 떄문에 해당 키 파일은 외부로 절대 유출되어서는 안된다. ( .gitignore 파일을 통해 Git 에 올라가지 않도록 하자)
.env 가 암호화되었다면, 암호화된 환경변수 그대로 프로젝트를 실행하게 되면 오류가 발생한다.
프론트엔드 프로젝트에서 실행 전 .env 를 복호화해주면서 실행해주는 스크립트를 추가해줘야한다.
{ "scripts": { "dev": "dotenvx run -- vite", "build": "dotenvx run -- vite build" } }
그러면 내부적으로 .env.keys 파일을 통해 복호화된 환경변수를 가지고 프로젝트를 실행한다.

만약 빌드 환경에도 자동으로 적용하고 싶다면?

dotenvx 도 마찬가지로 똑같이 .env.keys 의 비밀 복호화 키를 배포 플랫폼의 환경변수에 아래와 같이 넣어주면 된다.
Vercel 환경변수 설정: DOTENV_PRIVATE_KEY = "bd7c50b352..."
그리고 빌드 스크립트에서는 아래와 같이 명시를 해준다.
# package.json scripts에 직접 명시 "build": "dotenvx run -- vite build"
현업에서는 Zookeeper 을 통해 환경변수를 동적으로 제어하고 있는데, 사이드 프로젝트에서는 매번 .env 문서를 어떻게 공유해야할까 걱정이 들었다. 역시 개발자들은 문제가 있으면 어떻게 해결할 수 있을까에 대한 해답을 다양한 방법으로 많이 만들어내는 것 같다.
당장은 dotenv 를 적용하여 해결하였고, 조만간 dotenvx 를 적용해 .env 파일을 저장소에 암호화된 상태로 올려 배포할 생각이다. 더 좋은 솔루션이나, 문제 상황이 맞는 솔루션이 나오게 되면 그걸 한번 적용해봐야겠다.
Subscribe to '悠悠自適'
Subscribe to my site to be the first to receive notifications and emails about the latest updates, including new posts.
Join Slashpage and subscribe to '悠悠自適'!
Subscribe
👍