설정 관리와 핫리로드: config.ini/YAML 실전

English version

TECH INSIGHT / EXPLAINED

핫리로드는 설정을 읽고 전체를 검증한 뒤 일관된 한 버전을 공개하는 트랜잭션입니다. 파일을 고치는 동안 주문 판단이 옛 설정과 새 설정을 섞어 읽어서는 안 됩니다.

동료 세 명이 설정 전체 검증과 불변 버전 적용 주제를 그림으로 설명하는 모습
이해를 돕기 위한 AI 생성 설명 일러스트. 실제 운영 화면이나 실적 자료가 아닙니다.

INI와 YAML보다 먼저 단위를 정한다

이 예제의 50bp는 0.50%이고 평가 간격은 밀리초, MaxNotional은 계좌 통화의 정수 금액입니다. 필수 항목 누락·잘못된 숫자·알 수 없는 키 처리 정책을 명시하고 파서에서 검증합니다. Go 표준 라이브러리에는 INI·YAML 파서가 없으므로 적절한 라이브러리가 필요합니다. 비밀 키는 예제 설정에 넣지 않습니다.

[COMMON]
GapEvalIntervalMs=1000
EntryDebounceSec=30

[PAIR_01]
EntryGapBps=50
MaxNotional=100000
Enabled=true

검증한 불변 스냅샷을 한 번에 공개한다

아래는 INI 파서가 아닌 적용 단계를 분리한 실행 가능한 Go 예제입니다. 리로드 고루틴 하나만 쓰기를 담당합니다. 시작 설정이 성공해야 작업자를 시작하고, 거절된 업데이트는 기존 버전 1을 유지합니다. 독자는 판단 시작 시 한 버전을 복사해 사용하고 필드마다 따로 읽지 않습니다.

package main

import (
    "fmt"
    "sync/atomic"
)

type Config struct {
    Version uint64
    EntryGapBps int64
    MaxNotional int64 // integer account-currency units
    Enabled bool
}

var active atomic.Pointer[Config]

// One reload goroutine owns all calls to install.
// Config has value fields only; published objects are immutable.
func install(next Config) error {
    if next.Version == 0 || next.EntryGapBps <= 0 || next.MaxNotional <= 0 {
        return fmt.Errorf("invalid config")
    }
    if old := active.Load(); old != nil && next.Version <= old.Version {
        return fmt.Errorf("version must increase")
    }
    active.Store(&next) // next is a private value copy
    return nil
}

func snapshot() (Config, bool) {
    p := active.Load()
    if p == nil { return Config{}, false }
    return *p, true
}

func main() {
    if err := install(Config{1, 50, 100000, true}); err != nil {
        panic(err) // no valid startup configuration
    }
    err := install(Config{2, 60, 0, true})
    cfg, ok := snapshot()
    fmt.Println("rejected:", err != nil, "ready:", ok, "version:", cfg.Version)
}

출력은 rejected: true ready: true version: 1입니다. 이 설정은 값 필드만 가집니다. 나중에 map·slice·pointer를 넣으면 내부의 가변 데이터까지 복제하고 공개 후 변경하지 않아야 합니다. 슬라이스 헤더만 복사해서는 충분하지 않습니다.

오류를 일부 적용하지 않고 드러낸다

필수 페어나 필드 간 제약 하나라도 틀리면 후보 전체를 거절합니다. 잘못된 페어만 조용히 건너뛰면 기존 포지션 관리가 끊길 수 있습니다. 후보 버전과 민감 정보 없는 사유를 기록하고 마지막 승인 버전을 표시하며 알립니다. 단순 편집 오류에는 마지막 정상 설정 유지가 적절하지만, 자격 증명 폐기나 안전 정지는 별도의 차단 정책으로 다뤄야 합니다.

숫자 변경과 자원 변경을 구분한다

임계값은 다음 판단 경계부터 적용할 수 있습니다. 종목·계좌·구독 변경은 신규 진입 중지, 미체결 확인, 구독 전환, 새 데이터 확인이 필요합니다. 페어 비활성화가 보유 포지션 관리까지 끊어서는 안 됩니다. 폴링은 context로 종료하고 ticker를 정리합니다. 파일 감시는 편집기의 연속 이벤트를 합치고 완성된 후보만 읽습니다. 파일 교체의 원자성과 장애 시 보존은 운영체제·파일시스템에 따라 달라 실제 배포 경로에서 시험해야 합니다.

공식 문서와 이어 읽기

내용·예제 검토: 2026-09-29

댓글