환경 변수 지옥에서 벗어나기 (feat. dotenv-vault)

Jiwoo Joy Kim
IHFB  R&D 팀블로그
15 min readFeb 29, 2024
dotenv-vault

안녕하세요, 밀당 프론트엔드팀 김지우입니다.

이번 글에서는 밀당 프론트엔드팀이 환경 변수 관리의 복잡성 증가로 인해 어떤 어려움과 불편함을 겪었고, 이를 어떻게 개선했는지 소개하려고 합니다.

밀당의 개발 환경과 환경변수

기존 밀당 프론트엔드팀의 환경 변수 관리 방식이 실제 개발 생산성에 얼만큼 영향을 미쳤는지 들여다보기 위해서 밀당의 개발 프로세스를 먼저 간략히 설명해보겠습니다.

피쳐 기능 개발이 시작되면 기본적으로 로컬환경에서 작업을 하고, feature, develop, stage 환경을 거쳐 프로덕션에 릴리즈합니다. 아래 나열한 것과 같이 서비스와 개발 환경의 종류가 많아지고 있고, 피쳐 기능 개발 외에 버그 수정 및 빠른 핫픽스 대응을 위해서도 상황에 맞는 신속한 환경 변수 세팅이 필요합니다.

환경 변수 종류와 갯수 (*블로그 작성일 기준)

  • 배포하는 서비스 : CRM, CMS, LMS, B2C, SchoolPT, 기타.. 대략 5개
  • 프론트엔드 내부 환경변수, 서드파티, 백엔드 API 엔드포인트 : 대략 5 ~ 13개
  • 개발환경 : 로컬, feature, develop, stage, production(밀당PT, 스쿨PT).. 대략 5 ~ 6개
  • 베타서비스, PoC(Proof of Concept)나 UT(유저테스트) 등을 위해서 develop, stage 환경으로 세팅해서 확인이 필요한 경우

기존 환경 변수 사용 방법

기존에는 모노레포로 구성되어 있는 프론트엔드 레포지토리에서 실행하고자 하는 서비스 디렉토리마다 작성해둔 .env.example 파일을 복사해 .env파일 안에 변수의 값들을 직접 변경해 넣고 앱을 실행할 수 있었습니다. 빠른 작업을 위해서는 개발자가 각자의 로컬 환경에서 .env파일 안에 모아둔 환경변수들의 주석처리를 바꿔가며 사용하기도 했습니다. 이 방법은 위에서 소개한 밀당의 다양한 서비스, 환경마다 알맞은 환경변수를 모두 직접 확인 적용하기에는 번거롭거나 빠른 이슈 대응에 걸림돌이 될 수 있었습니다. 또, 평소에 개발하는 서비스 앱이 아니라면 최근에 업데이트되거나 누락된 변수가 있는지 알기 어려운 경우도 종종 발생했습니다.

프론트엔드 팀은 이런 기존 환경 변수 관리 방식의 한계를 느꼈고, 더욱이 최근 팀이 커지고 밀당 서비스가 빠르게 고도화됨에 따라 개선에 대한 필요성을 크게 느끼게 되었습니다. 그래서 문제 상황을 정확히 정의하고 개선하면 좋을 부분들을 도출해보았습니다.

문제 상황과 한계점

  1. 프론트엔드에서 백엔드로 API요청하는 서버와 서드파티 엔드포인트가 많아지면서 관리해야하는 환경변수의 종류와 갯수가 늘어나고, 향후에도 더 늘어날 가능성이 있다.
  2. 변수의 종류와 갯수는 늘어났지만 대부분 호스트가 동일하거나 비슷해서 사실상 중복되는 값이 많다.
  3. 개발/배포 환경마다 다른 환경변수를 개발자가 매번 확인하고 변경해야하는 번거로움이 있다.
  4. 환경변수가 업데이트되거나 새롭게 추가되는 경우 바로 알기 어렵다.
  5. 백엔드 개발자가 프론트엔드 개발 환경을 세팅하거나 새로운 팀원이 합류하는 경우 환경변수를 IDE에서 복사해 붙여넣고 Airdrop이나 업무메신저 DM과 같은 비공식적인 채널을 통해 팀원간 공유하게 되는데, 이는 확장성이 떨어지고 보안 리스크가 존재한다.

현황 파악 및 해결 과정

위의 문제 상황들을 해결하기 위해 중복되는 환경변수들은 최대한 통합하고 서비스 및 환경별 변수들을 정리한 뒤, 몇 가지 환경변수 관리 개선 방식과 도입할 라이브러리를 리서치해보기로 했습니다.

  1. 사용중인 환경변수 및 서버 엔드포인트를 모두 취합
  2. 호스트가 동일한 API 엔드포인트는 하나로 통합해서 관리할 수 있을지 프론트엔드팀과 백엔드팀이 교차 확인
  3. 환경변수 관리 방식 및 라이브러리를 리서치하고 도입

그리고 리서치해본 결과 아래 4가지 후보가 추려졌는데요. 이 중 밀당 프론트엔드팀의 상황에 맞는 가장 좋은 방식을 적용하기로 했습니다.

개선 기대 효과

새로운 환경 변수 관리 방식과 라이브러리 도입 기준은 아래의 기대효과를 충족하는지, 기존보다 개선될 수 있는 부분이 얼만큼 명확한지를 중점으로 두었습니다.

환경 변수 관리 방식 및 라이브러리 도입 기준

새로운 환경 변수 관리 방식 비교

.env.example + dotenv-expand

.env.example 파일에 환경변수를 작성하고 git에 올려두는 기존에 사용하던 방식에 호스트가 비슷하거나 중복되는 경우 dotenv-expand 패키지를 도입해 변수를 확장하는 방법입니다.

env-expand는 .env 파일안에서 키값들을 variables로 어느정도 통합하여 재사용할 수 있게 해주고, config에 따라 변수값의 파싱 및 포맷팅 규칙을 부여할 수도 있습니다.

// .env 파일 예시.

TEST_CHANNEL=testchannel07

//TEST_CHANNEL을 value로 재사용
FEATURE_URL=${TEST_CHANNEL}.url:2999
FEATURE_WSS_URL=${TEST_CHANNEL}.url:3004

//FEATURE_URL과 FEATURE_WSS_URL을 value로 재사용
GRAPHQL_URL=https://${FEATURE_URL}/graphql
WEB_SOCKET_URL=wss://${FEATURE_WSS_URL}/graphql

//TEST_CHANNEL을 value로 재사용하는 다른 변수들...

이렇게 중복되는 호스트를 변수로 관리해서 혼동을 어느정도 줄일 수 있습니다. 또한 변수로 만들어둔 값을 한번만 변경하면 되기 때문에 전체 변수들을 주석처리하거나 여러 변수들을 여러 차례 변경하지 않게 되어 사용하기 수월해집니다. 하지만 여전히 업데이트되거나 추가된 환경변수의 실제 값을 팀원 모두가 공유할 수 없는 문제는 남아있습니다.

.env.example + dotenv-expand : 2가지 기준 만족

AWS Secret Manager

환경변수의 실제 값을 한 곳에 모아 관리할 수 있는 방식입니다. AWS 클라우드 상에 키값들을 업로드해두기 때문에 모두가 필요할 때 실제 키값을 확인할 수 있습니다. AWS Secret Manager를 사용하면 부담스럽지 않은 비용으로 첫번째 관리방식의 문제를 보완할 수 있습니다. 그러나 여전히 환경변수를 팀원들이 AWS에 최신상태로 올려둬야하고, 개발시 수동으로 AWS상에 올려둔 환경변수와 비교해 싱크를 맞추는 등의 관리가 필요합니다.

AWS Secret Manager : 3가지 기준 만족

Infisical

AWS Secret Manager와 같이 클라우드에 환경변수를 업로드해두고 사용할 수 있는 서비스입니다. 웹훅 등 연계 기능, Vercel 및 Github CI/CD 연동도 가능하다는 점이 큰 장점으로 다가옵니다. 서비스 구독시 편리한 GUI를 자체 제공해준다는 점도 매력적입니다. 다만 결제 비용 측면에서 부담이 되었습니다. 그럴 경우 오픈소스인 Infisical을 셀프호스트하는 옵션도 있으나 셀프호스팅 및 유지관리를 위한 개발자 리소스가 든다는 단점이 존재합니다.

Infisical : 3가지 기준 만족

dotenv-vault

dotenv-vault

dotenv-vault도 AWS Secret Manager, Infisical과 유사하게 클라우드에 업로드할 수 있습니다. .env.example파일이나 환경별로 구분된 .env.develop , .env.stage 파일 없이 .env파일 하나로 원하는 환경에 맞게 git에 push, pull하여 원하는 환경변수를 사용할 수 있습니다. 이 방식은 새로운 환경변수가 추가되면 push하고, 어떤 환경변수가 업데이트되거나 추가되었는지 비교하지 않고 pull해서 항상 최신화된 환경변수를 팀원 모두가 싱크맞춰 공유할 수 있어 가장 개선하고 싶었던 문제를 해결할 수 있습니다. 결제 비용도 보다 합리적이며, Slack, Vercel 연동과 같은 부가기능도 이용할 수 있습니다. 추가로, 접근 권한이 있는 팀원만 환경변수를 볼 수 있기 때문에 서버 엔드포인트 외에 마스터키번호, 사내계정, 시크릿 등도 안전하게 관리가 가능합니다.

dotenv-vault : 7가지 기준 대부분 만족

아래는 지금까지 설명한 4가지 후보를 비교 정리한 표입니다.

환경 변수 관리 방식 비교

최종적으로 프론트엔드팀에서는 dotenv-vault를 도입하고, 추가적으로는 dotenv-expand를 사용하기로 결정했습니다. 밀당 내부에서 자체적으로 관리하던 방식에서 외부 서비스로 관리하게 되는만큼 도입 전 마지막으로 검토해야할 사항은 크게 두 가지였습니다.

안전하게 보안 유지 관리가 가능한가

public한 서버 엔드포인트가 아닌 밀당 내부에서만 관리되어야하는 환경변수를 안전하게 보안관리할 수 있어야 합니다. dotenv-vault의 보안 방식 문서를 참고하여 신뢰할만 하다고 판단하고 추가적으로 보안 관리에 도움이 될 방법도 확인했습니다. 다음은 dotenv-vault의 보안 방식 소개 문서를 번역, 정리한 내용입니다.

www.dotenv.org/security

서비스 의존성을 덜어내고 장기적으로 사용가능한가

node.js 버전 20부터 env가 built-in으로 내장된다고 하는데 그에 따라 dotenv가 더이상 사용되지 않는 경우, dotenv-vault 서비스가 중단되는 경우도 고려해야 합니다. dotenv 메인테이너는 이 점을 인지하고 있고, 다음과 같은 이유로 dotenv를 사용하는게 좋은 이유를 설명하고 있습니다.

www.dotenv.org/blog
dotenv npm 다운로드 추이
  • 전통적으로 많은 프로젝트에서 환경 변수 관리를 위해 dotenv를 사용해오고 있고,
  • 최근까지도 많은 활성 컨트리뷰터가 존재합니다.
  • 다양한 언어와 프레임워크를 지원하고
  • 추가적으로는 멀티라인 지원, 오버라이드 및 확장 지원 등이 계획되어있다고 하니

node.js 20버전이 안정화되기 전까지는 dotenv와 dotenv-vault 사용을 추천하고, 당분간은 사용에 큰 지장이 없을 거라 판단됩니다.

dotenv-vault로 환경 변수 사용하는 방법

이제 dorenv-vault를 실제로 어떻게 사용할 수 있고 어떤 점이 개선되었는지 설명해보겠습니다.

dependencies로 기존에 사용하던 dotenv에 더해 dotenv-vault와 dotenv-expand를 추가 설치하고, vite를 사용하고 있는 밀당 프론트엔드 코드에서 expand한 환경변수를 사용하기 위해 vite.config 파일 설정을 한 코드입니다.

//vite.config.ts

/** see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import */
import * as dotenv from 'dotenv';
import { expand } from 'dotenv-expand';

expand(dotenv.config()); //추가
...

dotenv-expand에는 파싱 규칙 과 같은 옵션들을 추가 설정해 사용할 수도 있습니다.

환경 변수 초기 세팅 및 사용 방법

최초에 auth key를 발급받아 로그인하는 과정을 거치면 그 다음부터는 git pull과 git push CLI 명령어 한 번으로 쉽게 여러 환경별, 도메인별 환경변수를 사용할 수 있습니다. 공식 문서에도 세팅 방법이 잘 나와있어 쉽게 세팅할 수 있습니다. 밀당 프론트엔드팀은 환경 변수 초기 세팅 가이드를 공유해 기존 팀원들 뿐만 아니라 신규 온보딩 팀원도 쉽게 환경 변수 세팅이 가능하도록 했습니다.

밀당 환경 변수 초기 세팅 가이드

  1. npm install으로 전체 패키지에 dependencies를 설치합니다.
  2. 레포지토리 안의 도메인별 루트 경로에서 dotenv-vault 로그인을 했다면
npx dotenv-vault login

3. pull 명령어로 한 번에 환경변수를 받아올 수 있습니다.

npx dotenv-vault@latest pull ${환경} .env
  • ${환경}은 위에서 배포 환경을 의미합니다. (ex.develop, stage, production, feature )

4. 환경변수를 업데이트할 때는 push합니다.

npx dotenv-vault@latest push ${환경} .env
  • push할 때는 일반적인 코드 git push와 유사하게 약간의 주의가 필요합니다.

그 밖의 좋은 점

  • 버전 히스토리 트래킹: 업데이트 될 때마다 버전이 .env 파일 상단에 기록되어 언제 누가 환경 변수를 업데이트했는지 추적이 편리하고 dotenv 클라우드에 업로드된 최신 버전과 로컬의 버전을 버전 넘버로 확인하기 쉽습니다.
  • 슬랙 채널 알림 연동 : pull, push 후에는 연동해둔 슬랙 채널 #fe-env에서 업데이트 알림을 확인할 수 있어 언제 누가 어떤 환경변수를 사용하고 업데이트했는지 팀원간의 공유가 자연스럽게 이루어집니다.
슬랙 채널 알림 연동
  • VSCode Extension : Dontenv Official + Vault 익스텐션으로 CLI를 쉽게 실행할 수 있습니다. 실제 value값들을 마스킹 처리하거나 자동완성 기능을 사용할 수도 있어 보안과 개발 생산성에 도움이 됩니다.
Dontenv Official + Vault VSCode 익스텐션

궁금한 점

dotenv-vault를 실제 도입한 후에 팀원분들에게 가장 많은 질문을 받았던 건

  • “.env.vault 파일이나 .env.me 파일이 생성되던데, 이 파일들은 뭔가요?”
  • “이 두 파일도 git에 commit이나 push해도 되나요?” 였습니다.

공식 문서 security 파트에는 이렇게 나와있습니다.

dotenv.org/docs/security
  • .env.vault 파일은 dotenv-vault에서 프로젝트를 고유하게 식별하기 위해 사용됩니다. 따라서 꼭 소스컨트롤에 커밋해야합니다. 그리고 그것이 안전합니다. GitHub의 고유한 git URL이라고 생각하면 쉽습니다. 이를 통해 프로젝트를 식별하고 팀원들이 dotenv-vault에서 올바른 .env파일을 가져올 수 있게 합니다.
  • 그러나 .env 나 .env.me 파일은 소스컨트롤에 커밋하면 안됩니다.

마치며

팀원들의 dotenv-vault 사용 후기

dotenv-vault를 도입한 뒤 밀당 프론트엔드팀은 한층 개선된 환경 변수 관리 시스템을 통해 더욱 효율적인 업무를 할 수 있게 되었습니다! 이번 환경 변수 관리 방식을 개선하면서 서비스 기능을 개발하는 것 외에 개발 환경을 개선하는 일도 중요하다는 걸 알게 되었고, 팀원들이 좋은 사용 후기를 남겨주어서 의미있는 작업이 되었습니다. 앞으로도 밀당 프론트엔드팀의 생산성 향상을 위한 계획을 세우고 있습니다.

긴 글 읽어주셔서 감사합니다.

밀당에서 동료를 찾고 있습니다!

IHFB가 최근 급성장하여 에듀테크 유니콘이 되기 위해 새로운 시스템을 개발하고 있습니다. 데이터 파이프라인 구축부터 인프라 개선 등 기존 레거시에 존재하는 다양한 문제를 해결, 개선하고 있습니다. 새로운 도전을 즐기시는 분들과 함께 하면 교육의 혁신을 더욱 빠르고 멋지게 이룰 수 있을 것 같습니다!

밀당과 함께할 동료를 찾습니다.

--

--

Jiwoo Joy Kim
IHFB  R&D 팀블로그
0 Followers

Frontend Web Dev, currently based in Seoul