변수 확장
env 라이브러리는 구성 파일에서 변수 참조를 지원하여 설정 재사용과 동적 값 치환을 구현합니다.
변수 확장 활성화
cfg := env.DefaultConfig()
cfg.ExpandVariables = true // 기본적으로 활성화
loader, _ := env.New(cfg)
loader.LoadFiles(".env")기본 구문
간단한 참조
# 다른 변수 참조
BASE_URL=https://api.example.com
API_URL=${BASE_URL}/v1
# API_URL 확장 결과: https://api.example.com/v1
# 단축 구문
HOST=localhost
URL=$HOST:8080
# URL 확장 결과: localhost:8080기본값 구문
| 구문 | 설명 |
|---|---|
${VAR:-default} | VAR 이 없으면 default 사용 |
${VAR:=default} | VAR 이 없으면 default 사용 (:-과 동일) |
${VAR:?error} | VAR 이 없거나 비어 있으면 오류 반환 |
자기 참조 제한
:-, :=, :?가 참조하는 변수는 대입되는 키와 달라야 합니다. KEY=${KEY:-default} 형태의 자기 참조는 순환 참조로 간주되어 로드 시 ErrExpansionDepth 오류가 발생합니다. 키에 기본값을 설정하려면 리터럴을 직접 대입 (KEY=default) 하거나 다른 변수를 참조하세요 (아래 예시 참고).
구문 상세
${VAR:-default} - 기본값 사용
가장 일반적인 기본값 구문입니다. 변수가 없을 때 기본값을 사용하고, 변수가 존재하면 (비어 있어도) 원래 값을 사용합니다:
# HOST가 정의되어 있으면 해당 값 사용
HOST=localhost
PRIMARY_HOST=${HOST:-127.0.0.1}
# PRIMARY_HOST 확장 결과: localhost
# TIMEOUT이 없으면 기본값 "30s" 사용
TIMEOUT_VALUE=${TIMEOUT:-30s}
# TIMEOUT_VALUE 확장 결과: 30s
# 중첩 기본값
DB_HOST=localhost
DB_URL=${DB_HOST}:${DB_PORT:-5432}
# DB_HOST=localhost이고 DB_PORT가 없으면
# DB_URL 확장 결과: localhost:5432사용 시나리오:
- 선택적 구성 항목의 기본값
- 개발/프로덕션 환경 통합 설정
${VAR:=default} - 기본값 사용
${VAR:-default}와 동일하게 동작하며, 변수가 없을 때 기본값을 사용합니다:
# DEBUG가 없으면 "false" 사용
DEBUG_VALUE=${DEBUG:=false}
# CACHE_TTL이 없으면 기본값 사용
CACHE_TTL_VALUE=${CACHE_TTL:=3600}:-과의 관계
${VAR:=default}는 이 라이브러리에서 ${VAR:-default}와 완전히 동일하게 동작합니다. 변수가 없을 때 기본값을 확장 결과로 사용합니다. :=는 기본값을 변수 저장소에 다시 기록하지 않습니다.
${VAR:?error} - 오류 메시지
변수가 없거나 비어 있으면 오류를 반환합니다:
# DATABASE_URL이 없으면 로딩 실패 및 오류 표시
DB_URL=${DATABASE_URL:?Database URL is required}
# API_TOKEN이 없으면 오류 발생
AUTH_TOKEN=${API_TOKEN:?API_TOKEN must be set}사용 시나리오:
- 필수 구성 항목 검증
- 조기 실패로 런타임 오류 방지
이스케이프
달러 기호 이스케이프
$$를 사용하여 리터럴 $를 나타냅니다:
# 가격 설정
PRICE=$$99.99
# 확장 결과: $99.99
# $가 포함된 문자열
MESSAGE=Price is $$100
# 확장 결과: Price is $100따옴표와 확장
변수 확장은 따옴표 제거 후의 통합 후처리 단계에서 일어나며, 작은따옴표와 큰따옴표 모두 변수 확장에 영향을 주지 않습니다. 예를 들어 SINGLE='${BASE}'(BASE=hello) 는 확장 후 값이 hello가 되며 큰따옴표와 동일하게 동작합니다. 참조된 변수가 정의되어 있지 않은 경우 (예: LITERAL='${NO_EXPANSION}'), 결과는 빈 문자열이 되며 ${NO_EXPANSION} 리터럴이 유지되지 않습니다.
작은따옴표와 큰따옴표의 차이는 리터럴 파싱에만 있습니다. 큰따옴표는 \n, \t 등의 이스케이프 시퀀스를 처리하지만, 작은따옴표는 원문을 그대로 보존합니다 (이스케이프 없음).
참고
따옴표로 "확장 금지"를 지정하지 마세요. ${VAR} 리터럴을 유지하려면 다음 방법을 사용하세요:
# 방법 1: 달러 기호 이스케이프 ($$는 리터럴 $로 확장)
LITERAL='$${NO_EXPANSION}'
# 값: ${NO_EXPANSION}// 방법 2: 전역 변수 확장 비활성화
cfg := env.DefaultConfig()
cfg.ExpandVariables = false중첩 확장
변수를 중첩하여 참조할 수 있습니다:
# 기본 설정 (내장 금지 키 ENV 대신 DEPLOY_ENV 사용)
APP_NAME=myapp
DEPLOY_ENV=production
# 중첩 참조
DB_HOST=db.${DEPLOY_ENV}.example.com
# 확장 결과: db.production.example.com
API_URL=https://${APP_NAME}.${DEPLOY_ENV}.api.example.com
# 확장 결과: https://myapp.production.api.example.com순환 감지
라이브러리는 순환 참조를 자동으로 감지하고 오류를 반환합니다:
# 순환 참조 (오류)
A=${B}
B=${A}
# 로딩 시 ErrExpansionDepth 오류 반환확장 깊이 제한
기본 최대 확장 깊이는 5 이며, 하드 상한선은 20 입니다:
cfg := env.DefaultConfig()
cfg.MaxExpansionDepth = 10 // 커스텀 깊이| 상수 | 값 | 설명 |
|---|---|---|
DefaultMaxExpansionDepth | 5 | 기본값 (공개 API) |
INFO
하드 상한선은 20 (내부 제한) 입니다. 구성의 MaxExpansionDepth는 이 제한을 초과할 수 없습니다.
전체 예시
# .env 파일
# 기본 설정 (내장 금지 키 ENV 사용 회피)
APP_NAME=myapp
DEPLOY_ENV=development
DEBUG=true
# 데이터베이스 설정
DB_HOST=localhost
DB_PORT=5432
DB_NAME=${APP_NAME}
DB_URL=postgres://${DB_HOST}:${DB_PORT}/${DB_NAME}
# API 설정
API_BASE=https://api.${DEPLOY_ENV}.example.com
API_URL=${API_BASE}/v1
# 로그 설정
LOG_LEVEL=info
# 가격 (이스케이프)
PRICE=$$99.99package main
import (
"fmt"
"log"
"github.com/cybergodev/env"
)
func main() {
cfg := env.DefaultConfig()
cfg.ExpandVariables = true
loader, err := env.New(cfg)
if err != nil {
log.Fatal(err)
}
defer loader.Close()
err = loader.LoadFiles(".env")
if err != nil {
log.Fatal(err)
}
fmt.Println("DB_URL:", loader.GetString("DB_URL"))
fmt.Println("API_URL:", loader.GetString("API_URL"))
fmt.Println("PRICE:", loader.GetString("PRICE"))
}관련 문서
- 빠른 시작 - 기본 사용법
- Config API - ExpandVariables 구성
- 상수 및 오류 - 확장 깊이 제한