상세 컨텐츠

본문 제목

[Golang]config 파일 관리는 viper 괜찮아요

Golang

by 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
 }
}

 

참고

관련글 더보기