Skip to content

Loader API

Loader 타입의 완전한 메서드 레퍼런스입니다. Loader는 env 라이브러리의 핵심 타입으로, 환경 변수의 로드, 저장 및 접근 기능을 제공합니다.

스레드 안전

Loader의 모든 메서드는 스레드 안전하며, 여러 goroutine에서 동시에 호출할 수 있습니다.

타입 정의

go
type Loader struct {
    // 전용 필드 포함
}

// 컴파일 타임 인터페이스 구현 검사
var _ EnvLoader = (*Loader)(nil)
var _ io.Closer = (*Loader)(nil)

생성

New

go
func New(cfg ...Config) (*Loader, error)

새 로더 인스턴스를 생성합니다.

매개변수:

  • cfg - 선택적 구성 옵션. 제공하지 않거나 제로 값 Config를 전달하면 자동으로 DefaultConfig() 사용

반환값:

  • *Loader - 로더 인스턴스
  • error - 구성 검증 오류

동작:

  • 구성 유효성 검증
  • 내부 컴포넌트 생성(검증기, 감사기, 확장기)
  • cfg.Filenames가 비어 있지 않으면 자동으로 파일 로드
  • cfg.AutoApply가 true이면 자동으로 시스템 환경에 적용
go
// 기본 구성 사용
loader, err := env.New()

// 커스텀 구성 사용
cfg := env.DefaultConfig()
cfg.Filenames = []string{".env"}
cfg.AutoApply = true
loader, err := env.New(cfg)

if err != nil {
    panic(err)
}
defer loader.Close()

파일 로드

LoadFiles

go
func (l *Loader) LoadFiles(filenames ...string) error

하나 이상의 구성 파일을 로드합니다.

매개변수:

  • filenames - 파일 경로 목록, 비어 있으면 기본적으로 .env 로드

반환값:

  • error - 로드 오류

동작:

  • 순서대로 로드하며, 나중에 로드된 것이 먼저 로드된 것을 덮어씀(OverwriteExisting 구성으로 제어)
  • 파일 형식 자동 감지(.env, JSON, YAML)
  • FailOnMissingFile 구성에 따라 파일이 없을 때 동작 결정
  • AutoApply가 true이면 로드 후 자동 적용
go
// 기본 .env 파일 로드
err := loader.LoadFiles()

// 지정된 파일 로드
err := loader.LoadFiles(".env", ".env.local")

// 혼합 형식
err := loader.LoadFiles("config.env", "settings.json", "secrets.yaml")

오류 타입:

  • ErrFileNotFound - 파일이 존재하지 않음(FailOnMissingFile=true일 때)
  • ErrFileTooLarge - 파일이 크기 제한 초과
  • ErrClosed - 로더가 닫힘
  • *ParseError - 파싱 오류
  • *JSONError - JSON 파싱 오류
  • *YAMLError - YAML 파싱 오류
  • *SecurityError - 파일 경로 보안 검증 실패(예: 경로 순회 공격)

형식 감지 규칙:

확장자형식
.envFormatEnv
.jsonFormatJSON
.yaml, .ymlFormatYAML
기타FormatAuto(.env 파서 사용)

값 가져오기

키 이름 해석

모든 Get 메서드는 지능형 키 이름 해석을 지원합니다:

입력 키 이름해석 결과
"DATABASE_HOST""DATABASE_HOST"(정확한 매칭)
"database.host""DATABASE_HOST"(점이 밑줄로 변환)
"app.name""APP_NAME"(대문자 + 밑줄)
"servers.0.host""SERVERS_0_HOST"(배열 인덱스)

해석 순서:

  1. 정확한 매칭 - 직접 키 이름 검색
  2. 대문자 변환 - 단순 키는 대문자 버전 시도
  3. 경로 해석 - 점 표기 경로를 밑줄 형식으로 변환
  4. 인덱스 폴백 - 인덱스 접근 시 쉼표로 구분된 값으로 폴백

GetString

go
func (l *Loader) GetString(key string, defaultValue ...string) string

문자열 값을 가져옵니다. 점 표기 경로 해석을 지원합니다.

매개변수:

  • key - 키 이름(정확한 매칭, 대문자 변환, 점 표기 경로 지원)
  • defaultValue - 선택적 기본값

반환값:

  • string - 값 또는 기본값(찾지 못하고 기본값이 없을 때 빈 문자열 반환)
go
// 기본 사용법
host := loader.GetString("HOST", "localhost")

// 점 표기 경로 접근(JSON/YAML 중첩 구조)
dbHost := loader.GetString("database.host", "localhost")
appName := loader.GetString("app.name")

// 기본값이 없을 때 빈 문자열 반환
value := loader.GetString("NON_EXISTENT")  // ""

GetInt

go
func (l *Loader) GetInt(key string, defaultValue ...int64) int64

정수 값을 가져옵니다. 점 표기 경로 해석을 지원합니다.

매개변수:

  • key - 키 이름(점 표기 경로 지원)
  • defaultValue - 선택적 기본값, 타입은 int64

반환값:

  • int64 - 값 또는 기본값(찾지 못하고 기본값이 없을 때 0 반환)
go
port := loader.GetInt("PORT", 8080)
maxConn := loader.GetInt("database.max_connections", 10)

// 기본값이 없을 때 0 반환
value := loader.GetInt("NON_EXISTENT")  // 0

GetBool

go
func (l *Loader) GetBool(key string, defaultValue ...bool) bool

불리언 값을 가져옵니다. 점 표기 경로 해석을 지원합니다.

매개변수:

  • key - 키 이름(점 표기 경로 지원)
  • defaultValue - 선택적 기본값

반환값:

  • bool - 값 또는 기본값(찾지 못하고 기본값이 없을 때 false 반환)

지원 값:

  • 참 값: true, 1, yes, on, enabled
  • 거짓 값: false, 0, no, off, disabled
go
debug := loader.GetBool("DEBUG", false)
cacheEnabled := loader.GetBool("cache.enabled", true)

// 기본값이 없을 때 false 반환
value := loader.GetBool("NON_EXISTENT")  // false

GetUint64

go
func (l *Loader) GetUint64(key string, defaultValue ...uint64) uint64

부호 없는 정수 값을 가져옵니다. 점 표기 경로 해석을 지원합니다.

매개변수:

  • key - 키 이름(점 표기 경로 지원)
  • defaultValue - 선택적 기본값, 타입은 uint64

반환값:

  • uint64 - 값 또는 기본값(찾지 못하고 기본값이 없을 때 0 반환)
go
port := loader.GetUint64("PORT", 8080)
maxSize := loader.GetUint64("MAX_SIZE", 1024)

// 기본값이 없을 때 0 반환
value := loader.GetUint64("NON_EXISTENT")  // 0

GetFloat64

go
func (l *Loader) GetFloat64(key string, defaultValue ...float64) float64

부동소수점 값을 가져옵니다. 점 표기 경로 해석을 지원합니다.

매개변수:

  • key - 키 이름(점 표기 경로 지원)
  • defaultValue - 선택적 기본값, 타입은 float64

반환값:

  • float64 - 값 또는 기본값(찾지 못하고 기본값이 없을 때 0 반환)
go
rate := loader.GetFloat64("RATE", 0.5)
threshold := loader.GetFloat64("THRESHOLD")

// 기본값이 없을 때 0 반환
value := loader.GetFloat64("NON_EXISTENT")  // 0

GetDuration

go
func (l *Loader) GetDuration(key string, defaultValue ...time.Duration) time.Duration

시간 간격 값을 가져옵니다. 점 표기 경로 해석을 지원합니다.

매개변수:

  • key - 키 이름(점 표기 경로 지원)
  • defaultValue - 선택적 기본값

반환값:

  • time.Duration - 값 또는 기본값(찾지 못하고 기본값이 없을 때 0 반환)

지원 형식: ns, us, ms, s, m, h(예: 30s, 5m, 1h30m)

go
timeout := loader.GetDuration("TIMEOUT", 30*time.Second)
ttl := loader.GetDuration("cache.ttl", 5*time.Minute)

// 기본값이 없을 때 0 반환
value := loader.GetDuration("NON_EXISTENT")  // 0

GetSecure

go
func (l *Loader) GetSecure(key string) *SecureValue

보안 값을 가져옵니다(민감 데이터 보호).

매개변수:

  • key - 키 이름

반환값:

  • *SecureValue - 보안 값의 방어적 복사본, 호출자가 해제 책임; 키가 없거나 로더가 닫혔을 때 nil 반환
go
secret := loader.GetSecure("API_SECRET")
if secret != nil {
    defer secret.Release()

    value := secret.Reveal()   // 평문 값
    masked := secret.Masked()  // [SECURE:32 bytes]
}

경고

사용 후 반드시 Release() 또는 Close()를 호출하여 리소스를 해제해야 합니다.

방어적 복사본

GetSecure는 원래 값의 복사본을 반환하며, 부모 Loader와 독립적입니다. 호출자가 Release() 또는 Close()를 호출하여 해제할 책임이 있습니다.

상세

SecureValue API에서 완전한 문서를 확인하세요.


슬라이스 값 가져오기

Loader는 슬라이스 Get 메서드를 제공하지 않습니다(Go는 제네릭 메서드를 지원하지 않음). 독립적인 제네릭 함수 GetSliceFrom[T]를 사용하여 Loader 인스턴스에서 슬라이스를 가져옵니다:

go
// 독립 제네릭 함수 사용
hosts := env.GetSliceFrom[string](loader, "HOSTS")
ports := env.GetSliceFrom[int64](loader, "PORTS", []int64{80})
portsInt := env.GetSliceFrom[int](loader, "PORTS")  // int도 지원

지원 타입: string, int, int64, uint, uint64, bool, float64, time.Duration

상세

패키지 함수 - GetSliceFrom에서 완전한 문서를 확인하세요.


Lookup

go
func (l *Loader) Lookup(key string) (string, bool)

키 존재 여부를 확인하고 값을 가져옵니다. 점 표기 경로 해석을 지원합니다.

매개변수:

  • key - 키 이름(점 표기 경로 지원)

반환값:

  • string - 값(앞뒤 공백 제거됨)
  • bool - 존재 여부
go
value, exists := loader.Lookup("API_KEY")
if !exists {
    // 키가 존재하지 않음
}

// 점 표기 경로
if value, exists := loader.Lookup("database.host"); exists {
    fmt.Println(value)
}

// 인덱스 접근(쉼표로 구분된 값으로 폴백)
// HOSTS=localhost,example.com
if value, exists := loader.Lookup("hosts.0"); exists {
    fmt.Println(value)  // "localhost"
}

설정 및 삭제

Set

go
func (l *Loader) Set(key, value string) error

환경 변수를 설정합니다.

매개변수:

  • key - 키 이름
  • value - 값

반환값:

  • error - 설정 오류

동작:

  • 키 이름 유효성 검증
  • ValidateValues가 true이면 값의 안전성 검증
  • OverwriteExisting이 false이고 키가 이미 존재하면 건너뜀(nil 반환)
  • AutoApply가 true이면 시스템 환경에도 동시 설정
go
err := loader.Set("CUSTOM_KEY", "value")
if err != nil {
    // 오류 처리
}

오류 타입:

  • *ValidationError - 키 이름 형식이 유효하지 않음(Field="key")
  • *SecurityError - 키가 금지됨(errors.Is(err, env.ErrSecurityViolation)로 매칭 가능)
  • ErrInvalidValue - 값이 유효하지 않음(ValidateValues가 true일 때 값에 널 바이트, 제어 문자 등 안전하지 않은 콘텐츠 포함)
  • ErrClosed - 로더가 닫힘

Delete

go
func (l *Loader) Delete(key string) error

환경 변수를 삭제합니다.

매개변수:

  • key - 키 이름

반환값:

  • error - 삭제 오류

동작:

  • 변수가 시스템 환경에 이미 적용된 경우, 시스템 환경에서도 동시에 삭제
go
err := loader.Delete("TEMP_KEY")
if err != nil {
    panic(err)
}

집합 작업

Keys

go
func (l *Loader) Keys() []string

모든 키 이름을 가져옵니다.

반환값:

  • []string - 키 이름 목록, 로더가 닫혔으면 nil 반환
go
keys := loader.Keys()
for _, key := range keys {
    fmt.Println(key)
}

All

go
func (l *Loader) All() map[string]string

모든 키-값 쌍을 가져옵니다.

반환값:

  • map[string]string - 키-값 매핑, 로더가 닫혔으면 nil 반환
go
all := loader.All()
for key, value := range all {
    fmt.Printf("%s=%s\n", key, value)
}

Len

go
func (l *Loader) Len() int

변수 수를 가져옵니다.

반환값:

  • int - 변수 수, 로더가 닫혔으면 0 반환
go
count := loader.Len()
fmt.Printf("%d개 변수 로드됨\n", count)

시스템에 적용

Apply

go
func (l *Loader) Apply() error

변수를 시스템 환경(os.Environ)에 적용합니다.

반환값:

  • error - 적용 오류

동작:

  • 로드된 모든 변수 순회
  • OverwriteExisting 구성에 따라 이미 존재하는 시스템 환경 변수 덮어쓰기 여부 결정
  • 적용 후 os.Getenv()로 접근 가능

오류 타입:

  • ErrClosed - 로더가 닫힘
  • 래핑된 os 오류 - 환경 변수 설정 실패(키 이름은 마스크되며, 오류 메시지에 민감 키 이름 노출 안 함)
go
err := loader.Apply()
if err != nil {
    panic(err)
}

// 이후 os.Getenv()로도 접근 가능
host := os.Getenv("HOST")

IsApplied

go
func (l *Loader) IsApplied() bool

변수가 시스템 환경에 적용되었는지 확인합니다.

반환값:

  • bool - 적용 여부
go
if loader.IsApplied() {
    // 변수가 os.Environ에 적용됨
}

상태 조회

LoadTime

go
func (l *Loader) LoadTime() time.Time

마지막으로 파일을 로드한 시간을 반환합니다.

반환값:

  • time.Time - 로드 시간, 로드하지 않았으면 제로 값 반환
go
loadTime := loader.LoadTime()
if !loadTime.IsZero() {
    fmt.Printf("마지막 로드 시간: %v\n", loadTime)
}

Config

go
func (l *Loader) Config() Config

로더의 구성을 반환합니다.

반환값:

  • Config - 구성(읽기 전용으로 취급해야 함)

경고

반환된 Config는 읽기 전용으로 취급해야 합니다. KeyPattern, AllowedKeys, ForbiddenKeys, RequiredKeys 등의 필드를 수정하면 로더 동작에 영향을 줄 수 있습니다. 안전한 가변 복사본이 필요하면 필요한 필드를 수동으로 복사하세요.

go
cfg := loader.Config()
fmt.Printf("최대 파일 크기: %d\n", cfg.MaxFileSize)

검증 및 매핑

Validate

go
func (l *Loader) Validate() error

필수 키가 존재하는지 검증합니다.

반환값:

  • error - 검증 오류

동작:

  • ValidationConfig.RequiredKeys에 지정된 모든 키가 존재하는지 검사
go
cfg := env.DefaultConfig()
cfg.RequiredKeys = []string{"DB_HOST", "API_KEY"}

loader, _ := env.New(cfg)
loader.LoadFiles(".env")

if err := loader.Validate(); err != nil {
    // 필수 키 누락
    var missingErr *env.ValidationError
    if errors.As(err, &missingErr) {
        fmt.Printf("누락: %s\n", missingErr.Field)
    }
}

ParseInto

go
func (l *Loader) ParseInto(v any) error

환경 변수를 구조체에 매핑합니다.

매개변수:

  • v - 구조체 포인터

반환값:

  • error - 매핑 오류

지원 태그:

  • env:"KEY" - 환경 변수 이름 지정
  • env:"-" - 이 필드 무시
  • envDefault:"value" - 기본값 지정

슬라이스 필드는 기본적으로 쉼표 ,로 구분됩니다(구분자 앞뒤 공백은 자동 제거되며, 커스텀 구분자 태그는 없습니다).

go
type Config struct {
    Host    string   `env:"HOST" envDefault:"localhost"`
    Port    int64    `env:"PORT" envDefault:"8080"`
    Debug   bool     `env:"DEBUG" envDefault:"false"`
    Hosts   []string `env:"HOSTS"`
    Ignored string   `env:"-"`
}

var cfg Config
err := loader.ParseInto(&cfg)
if err != nil {
    panic(err)
}

리소스 해제

Close

go
func (l *Loader) Close() error

리소스를 해제하고 저장소를 비웁니다.

반환값:

  • error - 닫기 오류

동작:

  • 저장된 모든 민감 데이터를 안전하게 제로화
  • 로더가 ComponentFactory를 소유한 경우 팩토리도 함께 닫음
  • 안전하게 닫히며, 여러 번 호출해도 nil 반환
go
loader, _ := env.New(cfg)
defer loader.Close()

// loader 사용...

닫은 후 동작

닫은 후 모든 작업은 오류 또는 제로 값을 반환합니다:

  • LoadFilesErrClosed
  • GetString → 빈 값 반환
  • SetErrClosed
  • Keys → nil 반환
  • Len → 0 반환

IsClosed

go
func (l *Loader) IsClosed() bool

로더가 닫혔는지 확인합니다.

반환값:

  • bool - 닫혔는지 여부
go
if loader.IsClosed() {
    // 로더가 닫힘
}

완전한 예제

go
package main

import (
    "errors"
    "fmt"
    "log"
    "os"
    "time"

    "github.com/cybergodev/env"
)

func main() {
    // 프로덕션 환경 구성 생성
    cfg := env.ProductionConfig()
    cfg.RequiredKeys = []string{"DB_HOST", "API_KEY"}
    cfg.AuditHandler = env.NewJSONAuditHandler(os.Stdout)

    // 로더 생성
    loader, err := env.New(cfg)
    if err != nil {
        log.Fatal(err)
    }
    defer loader.Close()

    // 파일 로드
    if err := loader.LoadFiles(".env", ".env.production"); err != nil {
        if errors.Is(err, env.ErrFileNotFound) {
            log.Fatal("구성 파일이 존재하지 않음")
        }
        log.Fatal(err)
    }

    // 필수 키 검증
    if err := loader.Validate(); err != nil {
        log.Fatal("필수 구성 누락:", err)
    }

    // 구성 읽기
    host := loader.GetString("DB_HOST")
    port := loader.GetInt("DB_PORT", 5432)
    debug := loader.GetBool("DEBUG", false)
    timeout := loader.GetDuration("TIMEOUT", 30*time.Second)

    fmt.Printf("Server: %s:%d\n", host, port)
    fmt.Printf("Debug: %v, Timeout: %v\n", debug, timeout)

    // 민감 데이터
    secret := loader.GetSecure("API_KEY")
    if secret != nil {
        defer secret.Release()
        fmt.Printf("API Key length: %d\n", secret.Length())
    }

    // 시스템 환경에 적용
    if err := loader.Apply(); err != nil {
        log.Fatal(err)
    }

    // 모든 변수
    fmt.Printf("Loaded %d variables\n", loader.Len())
    fmt.Printf("Load time: %v\n", loader.LoadTime())
}

관련 문서