GoSuda

Go의 Compile-Time Variable Injection

By wHoIsDReAmer
views ...

배경

이번에 회사 프로젝트 작업을 하면서 .env 없이 컴파일 타임 때 변수를 주입하는 방법이 있나 찾아보았다. 이렇게 하면 .env나 여러 콘피그 파일 없이 단일 파일만 있으면 되기 때문에 굉장히 편리할 거라 생각했다.

일단 처음에 찾아봤던 건 .env를 바탕으로 상수 파일을 생성해주는 go:generate CLI 같은 걸 찾아봤는데, 없었다.

근데 그럴거면 그냥 constants를 수정하면 되지 번거롭게 gen까지 할 필요는 없었고, 러스트에서 include_bytes! 매크로 같이 컴파일 타임 때 값을 주입할 수 있는 방법을 찾았다.

컴파일 타임 변수 주입

사용법은 간단하다.

1package main
2
3import "fmt"
4
5var Foo string
6
7func main() {
8    fmt.Println(Foo)
9}

위와 같은 코드가 있다고 하면, 빌드 시 다음과 같이 주입할 수 있다.

1go build -ldflags="-X 'main.Foo=bar'"

ldflag로 인자를 넘겨주면 빌드 시 컴파일 타임에 Foo 변수에 bar 값이 주입된다. 간단하다.

만약 프로젝트에서 같은 이름의 패키지나 변수가 여러 곳에 있다면 패키지 경로를 명시하면 된다.

1// github.com/myproject/config/config.go
2package config
3
4var Version string
5
6// github.com/myproject/internal/config/config.go  
7package config
8
9var BuildTime string

이런 경우 다음과 같이 구분해서 주입할 수 있다:

1go build -ldflags="-X 'github.com/myproject/config.Version=v1.0.0' -X 'github.com/myproject/internal/config.BuildTime=2025-05-27'"

같은 패키지에 여러 변수가 있는 경우에도 그냥 추가적인 인자를 전달해주면 된다.

1go build -ldflags="-X 'main.Version=v1.0.0' -X 'main.BuildTime=2025-05-27' -X 'main.GitCommit=abc123'"

특징은 다음과 같다:

  • 변수가 public이 아니어도 됨: 소문자로 시작하는 변수도 주입 가능하다
  • string 타입만 지원: 다른 타입은 지원하지 않는다

참조