Go 1.16 embed 패키지로 정적 파일 바이너리에 포함하기
문제 상황
사내 CLI 도구를 Go로 만들어 배포하는데, SQL 마이그레이션 파일과 설정 템플릿을 함께 배포해야 했다. 기존에는 바이너리와 별도로 assets/ 디렉토리를 같이 압축해서 전달했는데, 경로 문제로 이슈가 자주 발생했다.
embed 패키지
Go 1.16부터 표준 라이브러리에 embed 패키지가 추가되었다. //go:embed 디렉티브를 사용하면 컴파일 타임에 파일을 바이너리에 포함할 수 있다.
package main
import (
"embed"
"fmt"
"io/fs"
)
//go:embed migrations/*.sql
var migrationsFS embed.FS
//go:embed templates
var templatesFS embed.FS
func main() {
// 파일 읽기
data, err := migrationsFS.ReadFile("migrations/001_init.sql")
if err != nil {
panic(err)
}
fmt.Println(string(data))
// 디렉토리 순회
fs.WalkDir(templatesFS, ".", func(path string, d fs.DirEntry, err error) error {
if !d.IsDir() {
fmt.Println(path)
}
return nil
})
}
적용 결과
- 단일 바이너리로 배포 가능
- 경로 관련 이슈 해결
- CI/CD 파이프라인 단순화 (파일 복사 스크립트 제거)
주의사항
숨김 파일(.로 시작)은 명시적으로 지정해야 포함된다. 와일드카드만으로는 포함되지 않는다.
//go:embed templates/.env.example
//go:embed templates/*
var templatesFS embed.FS
바이너리 크기가 커질 수 있으니 포함할 파일은 최소화하는 게 좋다. 대용량 파일은 여전히 외부에서 관리하는 편이 낫다.