이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
안녕하세요
K-IN 입니다.
서론
"이것만 알면 나도 개발 전문가" 시리즈입니다.
"Gin 을 이용한 CRUD RESTful API 개발 Part-2" 를 진행하겠습니다.
Part-2 에서는 dotenv 파일을 로드하여 환경변수 정보를 불러오는 과정을 학습해보겠습니다.
2023.03.01 - [Go] - 고 (Golang) | 이것만 알면 나도 개발 전문가 | Gin 을 이용한 CRUD RESTful API 개발 Part-1
Part-1 코드 내려 받기
코드는 이전 시간에 작성한 코드에 이어서 진행하도록 하겠습니다. 아래의 링크에 접근하여 clone 후 코드를 내려 받아 주세요.
아래 웹사이트에 방문하셔서 Clone 버튼을 눌러주세요
https://bitbucket.org/kinstory/gin-tutorial/src/part1/
Viper 를 이용한 환경 변수 로드
배포 시에 테스트, 개발 등의 다양한 stage 환경 별로 환경변수를 관리해야 합니다.
이는 웹 어플리케이션의 가장 기본입니다.
이전 시간에 config 폴더에서 환경 변수를 로드하여 관리한다고 안내 드렸습니다.
config 폴더에서 default.go 파일을 생성해주세요.
$ touch config/default.go
프로젝트 폴더 구조에 default.go 파일이 추가되었습니다.
dotenv 파일을 효율적으로 로드하기 viper 패키지를 사용하도록 하겠습니다.
아래의 명령어로 viper 를 설치해주세요.
go get github.com/spf13/viper
Listen 할 TCP 포트 환경 변수 설정
viper 는 환경 변수(configuration)을 불러오는 역할을 합니다.
그리고 환경 변수 파일은 JSON, TOML, YAML, HCL, envfile, Java properties 포맷들을 모두 지원합니다.
우선, Gin 웹 어플리케이션이 Listen 할 포트를 app.env 에 정의해보도록 하겠습니다.
프로젝트 루트 폴더에 app.env 파일을 생성해주세요.
$ touch app.env
파일의 생성 위치는 아래의 그림을 참고해주세요.
app.env 파일에 PORT 라는 변수를 생성하고 8000 을 입력합니다.
Gin 웹 어플리케이션이 8000번 TCP 포트로 Listen 할 것을 의미합니다.
또한, 향후에 CI/CD 를 구성하면서 배포할 Stage 별로 PORT 정보를 교체하여 웹 어플리케이션을 제어할 수 있습니다.
PORT=8000
다음 차례는 default.go 파일입니다. viper 의 자세한 사용법은 그리 중요하지 않습니다.
어차피 우리는 환경 변수를 로드하는데 쓰이기 때문에 기본 코드 Snippet 만 알고 있다면 편리하게 응용할 수 있습니다.
- Config 타입을 정의하고 app.env 파일 설정과 맵핑되는 Port 필드를 설정합니다. struct 타입은 field 의 모음(collection)을 의미합니다.
- Port 변수는 PORT 환경변수와 맵핑되도록 설정이 필요합니다. 이럴때 사용하는 것이 Go 언어에서 제공하는 Tag 입니다. Tag 는 backtick 문자로 둘러쌓인 문자열입니다. 우리는 viper 에게 PORT 환경변수를 Port 에 맵핑하라고 지시해야 하므로 `mapstructure:"PORT"` Tag 를 설정하여 viper 에게 정보를 전달합니다. viper 는 내부적으로 https://github.com/mitchellh/mapstructure 를 통해 mapstructure Tag 를 지원합니다.
- LoadConfig 함수를 정의하여 환경 변수의 경로(path string)를 입력 받고 정의한 Config 타입과 error 정보를 리턴하도록 합니다.
- viper.AddConfigPath 함수는 Viper 가 config 파일을 검색할 경로를 추가하는 역할을 합니다. 여러 번 호출이 가능하기 때문에 환경 변수 파일이 분리된 경우에도 사용할 수 있습니다.
- viper.SetConfigType 함수는 환경 변수 파일의 유형을 설정하는 역할을 합니다. 앞서 json, toml, yml 등의 다양한 포맷에 대해 Viper 가 지원한다고 말씀드렸습니다. "env" 타입을 입력해줍니다.
- viper.SetConfigName 함수는 "app.env" 파일의 이름 영역을 의미합니다. 확장자 정보를 빼고 "app" 이름을 입력해주세요.
- viper.AutomaticEnv 함수는 Viper 로 하여금 환경 변수들과 Config 타입의 필드를 자동으로 맵핑하도록 설정합니다.
- viper.ReadInConfig 함수는 실제로 환경 설정 파일을 탐색하고 로드하는 역할을 합니다.
- 불러온 환경 설정 파일의 정보를 struct 타입에 맵핑합니다. config Named Return 변수가 사용된 점과 Unmarshal 함수에 전달될 때 변수의 주소(&) 연산자를 이용하는 부분에 주의를 기울여주세요. 함수의 실행의 결과는 config 변수에 저장됩니다. (만약 config 변수가 어디에 있는지 모르시는 분은 해당 링크를 참고해주세요. https://go.dev/tour/basics/7 )
package config
import "github.com/spf13/viper"
type Config struct { // (1)
Port string `mapstructure:"PORT"` // (2)
}
func LoadConfig(path string) (config Config, err error) { // (3)
viper.AddConfigPath(path) // (4)
viper.SetConfigType("env") // (5)
viper.SetConfigName("app") // (6)
viper.AutomaticEnv() // (7)
err = viper.ReadInConfig() // (8)
if err != nil {
return
}
err = viper.Unmarshal(&config) // (9)
return // (10)
}
config 타입은 아래와 같이 viper.go 소스에서 지원하는 유형과 이를 가리키는 키워드를 손쉽게 확인할 수 있습니다.
// FileName: github.com/spf13/viper@v1.15.0/viper.go
// (생략)
SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
// (생략)
환경 변수 정보를 이용한 웹 어플리케이션 포트 정보 변경
자 이제 main.go 파일을 조금 수정해봅시다.
- LoadConfig 함수를 실행합니다. 여기서 주의할 점은 "." 입니다. 이는 현재 폴더라는 의미이고 터미널에서 go 명령어를 실행하는 현재 디렉터리 위치에 영향을 받습니다. 보통 프로그램 실행 시에는 폴더의 경로가 PROJECT_ROOT 입니다. 따라서, 보통 "." 으로 지정합니다. 절대 경로도 가능하므로 상황에 따라 유연하게 변경해주세요.
- Go 언어에서 흔하게 사용하는 error 처리 로직입니다. log.Fatal 함수는 에러 로그를 출력하고 프로그램을 종료합니다.
- 웹 어플리케이션이 Listen 할 TCP 포트를 환경 변수 파일에 의존하도록 설정하는게 목표이므로 Run 함수에 config.Port 정보를 전달합니다.
// FileName: cmd/main.go
package main
import (
"log"
"net/http"
"github.com/gin-gonic/gin"
"k-in.com/gin-tutorial/config"
)
func main() {
config, err := config.LoadConfig(".") // (1)
if err != nil { // (2)
log.Fatal("Could not load config", err)
}
server := gin.Default()
server.GET("/health", func(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{"message": "ok"})
})
log.Fatal(server.Run(":" + config.Port)) // (3)
}
환경 변수 정보를 바꾸어가면서 실행해보기
환경 변수 정보를 변경해가면서 프로그램을 실행하여 로직이 우리 의도대로 흘러가는지 테스트해볼까요?
$ cat app.env
PORT=8000%
$ go run cmd/main.go
프로그램을 실행하면 8000 포트로 Listen 하는 것을 확인할 수 있습니다.
이번엔 8001 포트로 변경해서 적용해볼까요?
마찬가지로 8001 포트로 Listen 하고 있음을 확인하였습니다.
$ cat app.env
PORT=8001%
$ go run cmd/main.go
맺음말
오늘은 "Gin 을 이용한 CRUD RESTful API 개발" 시리즈의 Part-2 를 진행하였습니다.
Part-1 의 소스코드를 수정해 Viper 를 이용해서 환경 변수를 불러오고
웹 어플리케이션의 Listen 포트를 수정하는 과정을 진행하였습니다.
오늘 진행한 튜토리얼의 소스는 아래의 경로에서 다운받아서 살펴볼 수 있습니다.
아래 웹 사이트에 방문하셔서 Clone 버튼을 꾹 눌러주세요.
https://bitbucket.org/kinstory/gin-tutorial/src/part2/
이상으로 K-IN 이었습니다.
즐거운 하루되세요