Elixir 빌드 결과물인 릴리즈의 런타임 설정은 어떻게 관리해야 할까?
Elixir에서는 두 종류의 설정 파일이 있다. 빌드 타임 설정에 사용하는 config.exs
파일과 런타임 설정에 사용하는 runtime.exs
파일이다. 두 파일 모두 사용할 수밖에 없다. 빌드 타임에 모든 걸 결정할 수 없기 때문이다. DB 접속 정보가 대표적인 예다.
런타임 설정을 어떻게 관리하면 좋을까? runtime.exs
파일을 직접 수정하는 건 좋은 생각이 아니다. runtime.exs
파일은 배포를 위해 릴리즈(release)를 만들면 같이 포함되기 때문이다. 내가 편집한 설정이 릴리즈에 포함된 파일에 덮어 씌여져서 사라지는 걸 방지해야 한다.
환경 변수가 있으면 읽어서 사용
환경 변수가 있으면 읽어서 사용하는 방법을 생각할 수 있다. Heroku 같은 PaaS(platform as a service)를 사용하면 앱마다 환경 변수를 웹에서 손쉽게 관리할 수 있어서 설정하기 편하다.
예를 들어 개발 환경이 아닌 배포 환경에서만 Sentry를 사용한다면 runtime.exs
파일을 통해 설정할 수 있어야 한다.
# runtime.exs
import Config
if sentry_dsn = System.get_env("SENTRY_DSN") do
config :sentry, dsn: sentry_dsn
end
System.get_env/1
함수로 환경 변수를 읽어 있다면 세팅하게 구성한다. release.exs
파일에 elixir 코드를 사용할 수 있어서 N 개의 설정을 읽는 복잡한 작업도 가능하다.
Systemd로 elixir 앱 실행을 관리한다면 서비스 파일로 환경 변수를 세팅한다.
[Service]
...
Environment="ACCOUNT1_INTERVAL_MINUTE=60"
Environment="ACCOUNT1_KEY=[SECRET]"
Environment="ACCOUNT1_SECRET=[SECRET]"
Environment="ACCOUNT1_TOKEN=[SECRET]"
Environment="ACCOUNT1_TOKEN_SECRET=[SECRET]"
...
대부분은 환경 변수만으로 충분하다. 특히 사이드 프로젝트 규모라면. 만약 복잡한 계층 구조를 가진 설정이라서 환경 변수들로 평면적으로 풀 수 없다면 어떻게 하면 될까? 설정 파일을 써야 한다.
외부 설정 파일을 사용
runtime.exs
파일을 직접 수정하는 건 피하고 싶다. 릴리즈를 만들어 배포할 때, runtime.exs
파일이 포함되기 때문이다. 디폴트 설정을 runtime.exs
파일에 하고 사용자가 바꿀 수 있는 설정은 환경 변수나 외부 설정 파일로 빼면 배포할 때마다 설정이 덮어 씌여지는 걸 걱정하지 않아도 된다.
FHS(Filesystem Hierarchy Standard)를 준수한다면 외부 설정 파일 경로는 /etc/opt/my_app/runtime.exs
정도가 좋겠다. /etc/my_app/runtime.exs
정도로 해도 무난하다. 만약 Docker 라면 /config/runtime.exs
경로를 사용해도 된다.
아래와 같은 외부 설정 파일을 만든다.
# /etc/opt/my_app/runtime.exs
import Config
config :my_app, MyApp.Repo,
database: "ecto_simple",
username: "postgres",
password: "postgres",
hostname: "localhost"
디폴트 설정을 모아두는 runtime.exs
파일에서는 외부 설정 파일이 있는지 검사하고 로드한다. 기본 설정을 덮어쓸 수 있게 제일 마지막에 검사하고 적용해야 한다.
import Config
# 설정 마지막에 외부 설정 파일 로드
external_config_path = "/etc/opt/my_app/runtime.exs"
if File.exists?(external_config_path) do
IO.puts("Loading external config from #{external_config_path}")
Code.eval_file(external_config_path)
else
IO.puts("No external config found at #{external_config_path}, using default settings")
end
마치며
release.exs
파일을 직접 수정하는 건 피해야 한다. 릴리즈에 포함돼서 덮어쓰는 걸 주의해야 하기 때문이다. release.exs
파일에서 환경 변수를 로드하거나 외부 설정 파일을 읽도록 지원해야 한다.
사이드 프로젝트는 외부 설정 파일까지는 필요 없고 환경 변수만으로 충분하다. 그래도 또 모른다. 프로젝트가 오래 진행돼서 커진다면 환경 변수를 사용해 복잡한 설정을 1차원으로 풀어내는 게 버거워진다. 그때 외부 설정 파일을 고려하면 된다.
링크
- PaaS(Platform as a Service)란 무엇인가요?- Microsoft Azure - azure.microsoft.com
- Filesystem Hierarchy Standard - en.wikipedia.org
- #TIL systemd로 프로세스를 관리하고 systemd-journald로 로그를 본다 - dev diary, TIL - ohyeclou…
- Elixir 프로젝트를 Heroku에 배포하기 - ohyecloudy’s pnotes - ohyecloudy.com
- #elixir 환경 변수로부터 N개의 설정을 읽기 - ohyecloudy’s pnotes - ohyecloudy.com
- 크래시 리포트, 에러 트래킹이 필요하면 sentry - ohyecloudy’s pnotes - ohyecloudy.com