티스토리 뷰
개요
서버에는 다양한 설정이 필요하며, 이러한 설정을 별도로 관리하고 서버 실행 시 런타임에 주입하는 것이 유지 보수성과 확장성 측면에서 유리하다. 여기서는 파일로 관리하지만 Vault, AWS Secret Manager, AWS Parameter Store 등을 이용하면 보안에 있어 더욱 좋을 것이다.
(참고) 앞선 글의 코드를 누적하고 싶었지만, 오류와 개선 사항이 있어 전면적으로 수정했다. 양해를 구한다.
링크
- GitHub 브랜치: https://github.com/nicewook/gocore/tree/2_config-and-db
- 블로그 링크
설정
프로젝트 구조
설정과 관련한 프로젝트의 주요 디렉토리와 파일 구조는 다음과 같다(일부 생략)
├── cmd
│ └── gocore
│ └── main.go
├── config
│ └── config.dev.yaml
└── internal
├── config
│ └── config.go
├── domain
│ ├── errors.go
│ └── user.go
├── handler
│ └── userHandler.go
├── repository
│ └── postgres
│ └── userRepository.go
└── usecase
└── userUsecase.go
- config/config.dev.yaml 파일은 설정을 담고 있다.
- internal/config/config.go 는 설정정보를 가져오는 코드이다.
- cmd/gocore/main.go 에서 설정정보를 가져올 것이다.
config/config.dev.yaml
설정을 가져오는 건 viper 라이브러리를 사용하는데 YAML 타입을 다룰 수 있다.
여기서는 config.dev.yaml 파일 하나이지만 qa, stg, prod에 대해 각각의 파일을 만들어둘 수 있겠다. 보안이 필요한 정보를 담고있다면 이처럼 파일에 담아 Git 저장소에 올리는 것은 위험하기에 실제 운영 환경에서는 중요한 정보를 코드 저장소에 포함하지 말고, Vault, AWS Secret Manager 등을 활용하는 것이 안전하다.
- app: env는 dev, qa, stg, prod 환경중 어떠한 환경인지를 담고있다. 코드 내에서 환경에 따라 분기하여 동작할 필요가 있을때에 유용하다. port는 서버의 포트이며, debug는 디버깅 모드인지를 설정해준다.
- db: PostgreSQL 연결정보를 담고 있다.
app:
env: "dev"
port: 8080
debug: false
db:
host: "localhost"
port: 5432
user: "dev_user"
password: "dev_password"
dbname: "dev_db"
sslmode: "disable"
internal/config/config.go
위 YAML 파일을 읽어서 매칭이 되는 다음 구조체에 담는다.
type Config struct {
App AppConfig `yaml:"app"`
DB DBConfig `yaml:"db"`
}
type AppConfig struct {
Env string `yaml:"env"`
Port int `yaml:"port"`
Debug bool `yaml:"debug"`
}
type DBConfig struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
User string `yaml:"user"`
Password string `yaml:"password"`
DBName string `yaml:"dbname"`
SSLMode string `yaml:"sslmode"` // sslmode는 disable, require, verify-ca, verify-full 를 설정 가능
}
LoadConfig 함수는 환경 정보를 가져와 Config 인스턴스 포인터를 리턴해준다.
- 하나 이상의 위치에서 특정한 이름과 타입의 설정파일을 읽은 다음, 이를 Config 구조체에 담아준다.
func LoadConfig(env string) (*Config, error) {
viper.SetConfigName(fmt.Sprintf("config.%s", env))
viper.AddConfigPath("./config") // 실행 파일 기준 경로
viper.AddConfigPath("../../config") // 테스트 환경에서 상대 경로로 접근 시 대비
viper.SetConfigType("yaml")
if err := viper.ReadInConfig(); err != nil {
return nil, fmt.Errorf("failed to read config: %w", err)
}
var config Config
if err := viper.Unmarshal(&config); err != nil {
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
}
return &config, nil
}
cmd/gocore/main.go
flag 라이브러리를 이용하여 env 값을 받아오도록 한 다음, 앞서 생성해둔 config.LoadConfig 함수를 이용해 설정을 가져온다. cfg 를 출력하도록 하여 잘 읽어오는지를 간단히 확인해보았다.
func main() {
env := flag.String("env", "dev", "Environment (dev, qa, stg, prod)")
flag.Parse()
validEnvs := map[string]bool{"dev": true, "qa": true, "stg": true, "prod": true}
if !validEnvs[*env] {
log.Fatalf("Invalid environment: %s. Valid environments are: dev, qa, stg, prod", *env)
}
cfg, err := config.LoadConfig(*env)
if err != nil {
log.Fatalf("Config load error: %v", err)
}
fmt.Printf("config: %+v\\n", cfg)
// 하략
}
마무리
이번 글에서는 설정 파일을 효율적으로 관리하는 방법에 대해 살펴보았다.
다음 글에서는 이러한 설정을 기반으로 데이터베이스 연결과 실제 데이터베이스를 활용한 리포지토리 구현에 대해 다룰 예정이다.
'golang' 카테고리의 다른 글
Go 백엔드 3: 데이터베이스 연결 (0) | 2025.02.09 |
---|---|
Go 백엔드 1: 클린 아키텍처 기본 (0) | 2025.02.06 |
Go, XORM, Soft delete, Unscoped (0) | 2024.02.14 |
Golang: http.Client의 Timeout (0) | 2023.12.20 |
Go: 함수가 리턴해도 함수 속 고루틴은 종료되지 않는다 (0) | 2023.10.10 |
![잡학툰 뱃지](https://tistory1.daumcdn.net/tistory/2908812/skin/images/badge.png)
- Total
- Today
- Yesterday
- solid
- 티스토리챌린지
- 독서
- go
- golang
- 인텔리제이
- 2024년
- Bug
- strange
- Gin
- clean agile
- 노션
- notion
- 클린 아키텍처
- 잡학툰
- 독서후기
- intellij
- API
- 오블완
- 영화
- OpenAI
- 2023
- 클린 애자일
- bun
- folklore
- ChatGPT
- agile
- 엉클 밥
- postgres
- websocket
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |