Golang
[Golang]config 파일 관리는 viper 괜찮아요
stayhungri
2022. 6. 16. 23:11
Go에서 config 파일을 별도로 두고 관리하고 싶을 때 많이 쓰는 것중 하나가 viper 입니다.
바이퍼에 대해 간략하게 알아보면요.
- 다양한 형식(JSON, TOML, YAML, HCL, envfile 그리고 Java properties)의 config 파일들을 지원하고
- config 파일이 바뀌면 실시간으로 읽어서 반영합니다.
- 환경설정 변수도 지원하고요
- 원격 config 시스템 (etcd or Consul) 도 지원하고요
- 커맨드 라인으로도 config 를 설정할 수 있습니다.
- 그 외로 buffer 에 있는 config 도 읽을 수 있고, 특정 값을 직접 셋팅할 수도 있습니다.
그럼 이제 어떻게 사용하는지 알아볼게요. 먼저 아래와 같은 명령어로 패키지를 설치합니다.
go get github.com/spf13/viper
Database 설정 정보를 YAML 형식으로 관리한다고 가정해볼게요.
database:
host:
- 127.0.0.1
- 192.168.0.1
port: 3306
name: test
user: root
pass: 1234
s3:
accessKey: aakey
secretKey: sskey
route:
region: great-region
bucket: test.bucket.route
isActive: true
viper 로 읽어서 사용해보겠습니다.
func readAndPrint() {
viper.SetConfigName("config") // config 파일 이름 부분
viper.SetConfigType("yaml") // config 파일 확장자 부분
viper.AddConfigPath("./viper") // config 파일 위치
err := viper.ReadInConfig() // config 파일 읽기
if err != nil {
log.Fatalf("Fatal error config file: %s\n", err)
}
type config struct {
Database struct {
Host []string
Port int
User string
Pass string
Name string
}
S3 struct {
AccessKey string
SecretKey string
Route struct {
Region string
Bucket string
}
IsActive bool
}
}
var C config
err = viper.Unmarshal(&C) // config 구조체로 언마샬링
if err != nil {
log.Fatalf("unable to decode into struct, %v", err)
}
log.Printf("Config: %+v", spew.Sdump(C))
}
위 코드를 설명 드리면 구조체로 설정 파일 구조를 잡고, 설정 파일을 읽은 후 언마샬링을 통해 구조체에 값을 할당한 예제입니다.
계층 구조를 가진 구조체를 지원하고, 문자열, 정수, 배열, 불린(boolean) 등 Go에서 사용하는 모든 변수 타입을 지원합니다.
위 코드를 실행하면 아래와 같은 결과가 나옵니다.
$ go run vier.go
2022/06/16 23:10:48 Config: (main.config) {
Database: (struct { Host []string; Port int; User string; Pass string; Name string }) {
Host: ([]string) (len=2 cap=2) {
(string) (len=9) "127.0.0.1",
(string) (len=11) "192.168.0.1"
},
Port: (int) 3306,
User: (string) (len=4) "root",
Pass: (string) (len=4) "1234",
Name: (string) (len=4) "test"
},
S3: (struct { AccessKey string; SecretKey string; Route struct { Region string; Bucket string }; IsActive bool }) {
AccessKey: (string) (len=5) "aakey",
SecretKey: (string) (len=5) "sskey",
Route: (struct { Region string; Bucket string }) {
Region: (string) (len=12) "great-region",
Bucket: (string) (len=17) "test.bucket.route"
},
IsActive: (bool) true
}
}