Golang 1.16에 새로 추가된 기능 — embed로 스태틱 리소스 넣기

Heehong Moon
bgpworks
Published in
3 min readMar 1, 2021

golang의 여러가지 장점 중 하나는 바로 실행 파일 하나(single executable)로 배포 가능하다는 점이다. 윈도우로 치면 별도 설치 없이 exe파일 하나만 전달하면 끝.

하지만, 로컬 웹서버를 띄우는 경우 html, js, css파일과 같은 스태틱 리소스가 딸려 있기 마련인데, 이것들까지 자동으로 실행파일에 넣어주진 않는다. 별도 라이브러리를 이용하면 이런 스태틱 리소스를 실행파일에 포함시킬수도 있긴하다. 보통 이런류의 라이브러리들은 스태틱 파일의 컨텐츠를 go 소스코드로 생성하고, 생성된 파일을 함께 컴파일하여 스태틱 컨텐츠를 참조할수 있게 하는 방식이다.

생성된 asset.go

Golang 1.16 embed

golang 1.16 부터는 별도 외부 라이브러리 없이 임의의 파일/폴더를 바이너리안에 내장할수 있게 되었다. 사용법도 엄청 심플하다.

//go:embed public
var staticPublic embed.FS

이렇게 //go:embed public 주석을 추가하면 public 폴더에 있는 컨텐츠를 staticPublic 이라는 변수를 통해 접근 가능하다.

자세한 사용법은 아래 링크에서 확인 가능하다.

Gin 에서 사용

가장 대중적인 golang의 웹서버인 Gin(https://github.com/gin-gonic/gin)에서 스태틱 리소스를 embed 하려면 아래와 같이 할수 있다.


//go:embed public
var staticPublic embed.FS
type myFS struct {
fs http.FileSystem
}
func (m *myFS) Open(name string) (http.File, error) {
return m.fs.Open("/public" + name)
}
func (m *myFS) Exists(prefix string, path string) bool {
f, err := m.fs.Open("/public" + path)
if err != nil {
return false
}
defer f.Close()
return true
}

....
router := gin.New()
router.Use(static.Serve("/", &myFS{http.FS(staticPublic)}))
router.GET("/", func(c *gin.Context) {
...
})

public 폴더에 포함된 모든 파일을 스태틱 리소스로 서빙한다.

결론

golang 1.16에 들어간 embed 기능은 별도 외부 라이브러리를 쓸필요 없다는 점이 너무 좋다. 기존에는 스태틱 리소스와 생성된 go 소스코드를 git에 중복으로 넣어뒀는데, 앞으로는 깔끔하게 스태틱 리소스만 관리하면 된다 👍

--

--