Phoenix Local 환경에서 Env 설정 자동화

Table of contents

Problem
Elixir / Phoenix 스택으로 처음 서비스를 구현하고 있다.
민감한 정보를 코드에서 사용해야 할 경우가 생겨서 환경변수를 사용하는 코드가 생겼다.
Production 환경에는 배포 방식에 따라서 서버가 실행되기 전에 환경변수를 미리 설정하는 여러가지 방법들이 있는데,
로컬에서 mix 로 서버를 실행 할 때 환경변수를 깔끔하게 자동으로 적용할 수 있는 방법을 찾기가 어려웠다.
고민끝에 나름대로 마음에 드는 방법을 발견해서 정리 겸 공유를 위해 글을 작성한다.
Requirements
없으면 안되는 환경변수가 없는 경우 서버 실행 시 에러가 발생해야 한다.
환경변수 설정을 위해 기술스택을 벗어난 다른 프로그램을 활용하지 않아야 한다.
- ex) source .env && mix phx.server / env-cmd -f .env && mix phx.server
로컬에서 서버 실행 시 환경변수를 자동으로 설정하기 위해 기존 Application 코드를 수정하지 않아야 한다.
TLDR;
# mix.exs
defmodule MyApp.MixProject do
# ...
defp aliases do
[
# ...
"phx.server.dev": ["load_env .env.dev", "phx.server"]
]
end
end
로컬 개발용 mix alias 를 추가한다. (위 예제 코드의
phx.server.dev
)mix phx.server
가 실행되기 전에 미리 env 파일을 읽어서 환경변수를 설정하는 mix task 를 실행한다.물론
mix load_env .env.dev
가 실행될 수 있도록 Mix Task 를 추가해야 한다.
Prerequisite
먼저 하나 짚고 넘어가야 할 부분이 있다.
모든 환경변수는
runtime.exs
에 존재한다고 가정한다.
. (phoenix root)
└── config/
├── config.exs
├── dev.exs
├── prod.exs
├── runtime.exs
└── test.exs
위 config 파일들 중 runtime.exs
를 제외한 모든 파일은 mix 초기화 시점(mix task 가 실행되기 전)에 평가된다.
mix task 실행 전에 환경변수를 설정해야 한다면 외부 프로그램 사용이 불가피하다.
그렇기 때문에 runtime.exs
를 제외한 다른 config 파일에 환경변수를 읽는 코드가 있으면 해당 글의 방법은 동작하지 않는다.
사실 지금은 runtime.exs
을 통해서 환경변수를 읽는 방법으로 통일된 것으로 알고 있지만 오래된 elixir version 을 사용하는 경우에는 dev.exs
나 prod.exs
파일에서 읽는 경우도 있는 것 같다.
그러면 본격적으로 작업을 시작해보자.
How?
먼저 Mix Task 를 만들자.
env 파일을 직접 읽는 대신 이미 존재하는 Dotenv 패키지를 사용하자.
# lib/mix/tasks/load_env.ex
defmodule Mix.Tasks.LoadEnv do
use Mix.Task
@shortdoc "Loads environment variables from .env file"
@impl Mix.Task
def run(args) do
file = List.first(args) || ".env"
Dotenv.load!(file)
end
end
Task 에서 Dotenv 를 사용하니 의존성에 :dotenv
를 추가해야 한다.
# mix.exs
defmodule Monotick.MixProject do
# ...
defp deps do
[
# ...
{:dotenv, "~> 3.1"}
]
end
end
mix deps.get
을 실행하면 패키지가 추가된다.
그리고 아래와 같이 mix.exs
에 alias 하나를 추가하자.
# mix.exs
defmodule Monotick.MixProject do
# ...
defp aliases do
[
# ...
"phx.server.dev": ["load_env .env.dev", "phx.server"]
]
end
end
이렇게만 하면 끝이다.
마지막으로 env 파일을 추가하기 전에 gitignore 에 env 파일을 무시하는 설정이 있는지 확인하자.
나는 .env.example
를 사용해서 아래와 같이 gitignore 에 설정한 상태로 사용한다.
# Env files
.env*
!.env.example
Test
먼저 필수 환경변수가 없는 경우 에러가 발생하는지 확인해보자. 아래 코드를 runtime.exs
에 추가하자.
# config/runtime.exs
foo = System.fetch_env!("FOO")
fetch_env!
함수는 환경변수에 주어진 Key 값이 없는 경우 에러를 발생시킨다.
터미널에서 mix phx.server.dev
를 실행하면 아래와 같이 에러가 발생하는 것을 확인할 수 있다.** (System.EnvError) could not fetch environment variable "FOO" because it is not set
이제 FOO 환경변수를 env 파일에 추가해서 정상적으로 서버가 올라가는지 확인해보자.
예제는 .env.dev
를 읽도록 했으니 .env.dev
에 아래 환경변수를 추가하자.
# .env.dev
FOO="foo"
mix phx.server.dev
실행 시 서버가 정상적으로 작동하는 것을 확인할 수 있다.
혹시나 다른 좋은 방법이 있다면 댓글로 남겨주시면 감사하겠습니다.
Subscribe to my newsletter
Read articles from 깡부지 directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by