설정 관리와 핫리로드: config.ini/YAML 실전
돌아가는 봇의 파라미터를 바꾸려고 매번 재시작하면, 그 사이 시장은 기다려주지 않습니다. 재시작 없이 설정을 갈아끼우는 핫리로드 패턴을, 자동매매 봇을 운영하며 정리했습니다. 핵심은 세 가지 — 주기적 재로드, 동시성 안전, 그리고 검증입니다.
설정 파일에는 민감 정보(API 키 등)가 들어가기 쉽습니다. 절대 저장소에 커밋하지 말고, 예시 파일(
config.example.ini)만 공유하세요.
왜 INI/YAML인가
봇 설정은 사람이 손으로 자주 고칩니다. 그래서 사람이 읽고 쓰기 쉬운 형식이 유리합니다. INI는 섹션 구조가 단순해 페어·종목별 설정을 나누기 좋고, YAML은 중첩 구조에 강합니다. 둘 다 주석을 달 수 있어 "이 값이 뭔지"를 파일 안에 남길 수 있습니다.
[COMMON]
GapEvalIntervalMs = 1000 ; 갭 평가 주기(ms)
EntryDebounceSec = 30 ; 중복 진입 방지 시간(초)
[PAIR_01]
EntryGapPct = 0.50 ; 진입 임계치(%)
Enabled = true
5분 자동 reload
가장 단순하면서 실전에서 잘 도는 패턴은 일정 주기로 파일을 다시 읽는 것입니다. 파일 변경 감시(inotify 등)보다 구현이 단순하고 예측 가능합니다.
func configReloader() {
ticker := time.NewTicker(5 * time.Minute)
for range ticker.C {
if err := reloadConfig(); err != nil {
logCh <- "[설정] 자동 reload 실패: " + err.Error()
continue // 실패해도 기존 설정 유지
}
logCh <- "[설정] 자동 reload 완료"
}
}
포인트는 continue입니다. reload에 실패해도 봇을 멈추지 않고 직전의 정상 설정으로 계속 돕니다. 오타 하나로 봇 전체가 죽으면 안 되니까요.
동시성 — 스냅샷으로 읽는다
여기서 초보가 놓치는 함정이 있습니다. reload는 설정을 쓰고(write), 봇의 여러 goroutine은 그 설정을 읽습니다(read). 아무 보호 없이 하면 읽는 도중 값이 바뀌는 경쟁 상태(race)가 납니다.
해법은 sync.RWMutex와 스냅샷 복사입니다. 읽는 쪽은 설정 전체를 오래 잡고 있지 말고, 독립된 복사본을 잠깐 떠서 그걸로 일합니다.
var cfgMu sync.RWMutex
// 활성 설정의 독립 복사본을 반환 — reload가 원본을 바꿔도 영향 없음
func snapshotPairs() []Pair3Config {
cfgMu.RLock()
defer cfgMu.RUnlock()
out := make([]Pair3Config, len(cfg.Pairs))
copy(out, cfg.Pairs) // 값 복사
return out
}
이러면 reader들은 락을 짧게만 잡고, 그 뒤로는 자기 사본으로 자유롭게 일합니다. reload가 원본을 통째로 갈아끼워도 진행 중이던 계산은 안전합니다. "락을 잡은 채로 오래 일하지 않는다"가 핵심 원칙입니다.
검증 — 나쁜 값은 걸러낸다
핫리로드의 가장 큰 위험은 잘못된 설정이 즉시 반영되는 것입니다. 그래서 reload 시 반드시 검증합니다.
- 타입·범위 검사: 임계치가 음수거나 0이면 해당 항목 skip.
- 필수 값 확인: 종목 코드가 비었으면 그 페어는 비활성 처리.
- 핫리로드 대상 제한: 임계치·활성여부처럼 안전하게 바꿀 수 있는 것만 핫리로드하고, 종목 코드나 WebSocket 구독처럼 재구독이 필요한 항목은 재시작을 권고합니다.
if pair.EntryGapPct <= 0 || pair.MaxInvestPerLeg <= 0 {
continue // 이상값 → 이 페어는 이번 reload에서 무시
}
검증을 통과하지 못한 항목은 조용히 무시하되 로그는 반드시 남깁니다. "왜 내 설정이 안 먹지?"를 나중에 추적할 수 있어야 하니까요.
정리
- 설정은 사람이 읽기 쉬운 INI/YAML, 민감정보는 커밋 금지
- 주기적 재로드(예: 5분)가 파일 감시보다 단순·예측 가능
- reload는 write, 봇은 read → RWMutex + 스냅샷 복사로 race 차단
- 검증을 통과한 안전한 항목만 핫리로드, 나머지는 재시작 권고
- 실패·무시는 봇을 멈추지 말고 로그로 남긴다
핫리로드가 잘 되면 운영 감각이 완전히 달라집니다. 시장을 보며 파라미터를 실시간으로 조율하되, 그 편의가 안정성을 해치지 않도록 검증이라는 안전벨트를 꼭 채우세요.
댓글
댓글 쓰기