본 가이드는 Go 기반 AI API 게이트웨이에서 GoModel 라이브러리를 사용하여 Rate Limiting을 구성하는 방법을 설명합니다. 특히 공식 OpenAI/Anthropic API나 타사 릴레이 서비스에서 HolySheep AI로 마이그레이션하는 시나리오를 중점적으로 다룹니다.

들어가며: 왜 Rate Limiting이 중요한가

프로덕션 환경에서 AI API를 운영할 때 Rate Limiting은 단순한 설정이 아닌 시스템 안정성의 근간입니다. 적절한 Rate Limiting 없이 운영하면:

제가 실제 운영에서 경험한 사례입니다. 한 스타트업 팀이 Rate Limiting 없이 GPT-4 API를 호출했더니, 개발자 한 명이 순수한 디버깅 작업 중 3시간 만에 $2,400 이상의 비용이 발생했습니다. 이러한悲剧를 막기 위해 GoModel과 HolySheep의 조합은 견고한 솔루션을 제공합니다.

GoModel 라이브러리 개요

GoModel은 Go 언어에서 AI 모델 호출을 간소화하는 라이브러리입니다. 주요 특징:

HolySheep AI vs 기존 서비스 비교

구분 공식 OpenAI API 기존 릴레이 서비스 HolySheep AI
결제 방식 해외 신용카드 필수 해외 신용카드 필수 국내 결제 가능, 해외 카드 불필요
GPT-4.1 비용 $8/MTok $8~12/MTok $8/MTok (동일)
Claude Sonnet 4 $15/MTok $15~18/MTok $15/MTok (동일)
Gemini 2.5 Flash $2.50/MTok $3~5/MTok $2.50/MTok (동일)
DeepSeek V3.2 지원 안함 $0.50~1/MTok $0.42/MTok (최저가)
Rate Limiting 기본 제공, 커스터마이징 제한 서비스마다 상이 완전한 커스터마이징 지원
단일 API 키 불가 (별도 키 필요) 부분 지원 모든 모델 통합 관리
무료 크레딧 $5 제공 없거나 소액 가입 시 제공
연결 안정성 지역에 따라 상이 불안정 보고 많음 전 세계 최적화 라우팅

이런 팀에 적합 / 비적합

✅ HolySheep AI가 적합한 팀

❌ HolySheep AI가 비적합한 팀

가격과 ROI

비용 비교 시나리오

월 1,000만 토큰 사용 시 모델별 비용 비교:

모델 공식 API HolySheep AI 절감액
DeepSeek V3.2 (50%) - $21 -
Gemini 2.5 Flash (30%) $75 $75 -
Claude Sonnet 4 (20%) $300 $300 -
합계 $375 $396 -

ROI 관점의 실제 이점:

왜 HolySheep AI를 선택해야 하나

  1. 개발자 친화적 결제: 해외 신용카드 없이 로컬 결제 지원으로 즉각적인 서비스 시작 가능
  2. 단일 키 다중 모델: 모든 주요 AI 모델(GPT-4.1, Claude Sonnet 4, Gemini 2.5 Flash, DeepSeek V3.2)을 하나의 API 키로 관리
  3. 비용 최적화: HolySheep의 최적화 라우팅으로 지연 시간 감소 및 요청 실패율 최소화
  4. 안정적인 연결: 글로벌 최적화 인프라로 해외 직접 연결 대비 안정성 향상
  5. GoModel 완벽 호환: 기존 코드를 거의 수정하지 않고 마이그레이션 가능

마이그레이션 준비

사전 검토 체크리스트

마이그레이션 전 필수 확인 사항:

□ 현재 API 사용량 분석 (월별/모델별 토큰 소비량)
□ Rate Limiting 요구사항 문서화
  - 사용자별 RPM (Requests Per Minute)
  - 모델별 TPM (Tokens Per Minute)
  - 일일/월간 사용량 한도
□ 현재 코드베이스의 API 호출 패턴 파악
□ 롤백 시나리오 준비 완료
□ HolySheep API 키 발급 및 기본 연결 테스트

현재 환경 진단

기존 설정 파일(config.yaml)의 구조를 먼저 파악하세요:

# 기존 환경 설정 예시 (공식 API 또는 타사 릴레이)
api:
  provider: "openai"  # 또는 "relay-service"
  base_url: "https://api.openai.com/v1"
  api_key: "sk-xxxx...xxxx"
  timeout: 60

rate_limit:
  requests_per_minute: 60
  tokens_per_minute: 120000
  retry_attempts: 3
  retry_delay: 1000  # milliseconds

GoModel Rate Limiting 기본 설정

1단계: 프로젝트 초기화

// 프로젝트 디렉토리 생성 및 초기화
mkdir gomodel-rate-limit && cd gomodel-rate-limit
go mod init gomodel-rate-limit

// 필요한 의존성 설치
go get github.com/sashabaranov/go-openai
go get github.com/holysheep/gomodel  # HolySheep 호환 모듈
go get golang.org/x/time/rate
go get github.com/spf13/viper

2단계: HolySheep AI 연결 설정

package config

import (
    "os"
    "sync"
    "time"

    "golang.org/x/time/rate"
    "github.com/spf13/viper"
)

// RateLimitConfig Rate Limiting 설정 구조체
type RateLimitConfig struct {
    // 사용자별 제한
    UserRPM int           // Requests Per Minute per user
    UserTPM int           // Tokens Per Minute per user (예측치)

    // 글로벌 제한
    GlobalRPM int         // 전체 시스템 RPM
    GlobalTPM int         // 전체 시스템 TPM

    // 버스트 설정
    BurstSize int         // 순간 허용 burst 크기
    WarmupTime time.Duration  // 워밍업 시간
}

// APIConfig HolySheep API 설정
type APIConfig struct {
    BaseURL    string
    APIKey     string
    Timeout    time.Duration
    RateLimit  RateLimitConfig
}

// Global singleton instances
var (
    cfg     *APIConfig
    cfgOnce sync.Once
)

// LoadConfig 설정 로드
func LoadConfig() *APIConfig {
    cfgOnce.Do(func() {
        viper.SetConfigName("config")
        viper.SetConfigType("yaml")
        viper.AddConfigPath(".")
        viper.AddConfigPath("$HOME/.gomodel/")
        viper.SetDefault("base_url", "https://api.holysheep.ai/v1")
        viper.SetDefault("timeout", 60)
        viper.SetDefault("rate_limit.user_rpm", 60)
        viper.SetDefault("rate_limit.user_tpm", 120000)
        viper.SetDefault("rate_limit.global_rpm", 1000)
        viper.SetDefault("rate_limit.global_tpm", 10000000)
        viper.SetDefault("rate_limit.burst_size", 10)

        if err := viper.ReadInConfig(); err != nil {
            // 환경변수에서 로드
            cfg = &APIConfig{
                BaseURL: getEnv("HOLYSHEEP_BASE_URL", "https://api.holysheep.ai/v1"),
                APIKey:  getEnv("HOLYSHEEP_API_KEY", ""),
                Timeout: time.Duration(60) * time.Second,
                RateLimit: RateLimitConfig{
                    UserRPM:    60,
                    UserTPM:    120000,
                    GlobalRPM:  1000,
                    GlobalTPM:  10000000,
                    BurstSize:  10,
                },
            }
            return
        }

        cfg = &APIConfig{
            BaseURL: viper.GetString("base_url"),
            APIKey:  viper.GetString("api_key"),
            Timeout: time.Duration(viper.GetInt("timeout")) * time.Second,
            RateLimit: RateLimitConfig{
                UserRPM:    viper.GetInt("rate_limit.user_rpm"),
                UserTPM:    viper.GetInt("rate_limit.user_tpm"),
                GlobalRPM:  viper.GetInt("rate_limit.global_rpm"),
                GlobalTPM:  viper.GetInt("rate_limit.global_tpm"),
                BurstSize:  viper.GetInt("rate_limit.burst_size"),
            },
        }
    })
    return cfg
}

func getEnv(key, defaultValue string) string {
    if value := os.Getenv(key); value != "" {
        return value
    }
    return defaultValue
}

3단계: Rate Limiter 구현

package ratelimit

import (
    "context"
    "sync"
    "time"

    "golang.org/x/time/rate"
    "errors"
)

// RateLimitError Rate Limit 초과 에러
type RateLimitError struct {
    UserID      string
    RetryAfter  time.Duration
    CurrentRate float64
}

func (e *RateLimitError) Error() string {
    return "rate limit exceeded"
}

// MultiTierLimiter 다중 계층 Rate Limiter
type MultiTierLimiter struct {
    // 사용자별 제한
    userLimiters map[string]*rate.Limiter
    userMu        sync.RWMutex

    // 글로벌 제한
    globalLimiter *rate.Limiter

    // 모델별 제한
    modelLimiters map[string]*rate.Limiter
    modelMu        sync.RWMutex

    // 설정값
    userRPM   rate.Limit
    userBurst int
    globalRPM rate.Limit
    globalBurst int

    // 토큰 추적 (TPM용)
    tokenUsage    map[string]int64
    tokenMu       sync.RWMutex
    tokenLastReset time.Time
    tpmLimit      int64
}

var (
    ErrRateLimitExceeded = errors.New("rate limit exceeded")
    ErrGlobalLimitExceeded = errors.New("global rate limit exceeded")
)

// NewMultiTierLimiter Rate Limiter 생성
func NewMultiTierLimiter(userRPM, globalRPM int, burstSize int, tpmLimit int64) *MultiTierLimiter {
    return &MultiTierLimiter{
        userLimiters:  make(map[string]*rate.Limiter),
        globalLimiter: rate.NewLimiter(rate.Limit(globalRPM)/60, burstSize),
        modelLimiters: make(map[string]*rate.Limiter),
        userRPM:       rate.Limit(userRPM) / 60,
        userBurst:     burstSize,
        globalRPM:     rate.Limit(globalRPM) / 60,
        globalBurst:   burstSize,
        tokenUsage:    make(map[string]int64),
        tokenLastReset: time.Now(),
        tpmLimit:      tpmLimit,
    }
}

// GetUserLimiter 사용자별 Limiter 획득
func (m *MultiTierLimiter) GetUserLimiter(userID string) *rate.Limiter {
    m.userMu.RLock()
    limiter, exists := m.userLimiters[userID]
    m.userMu.RUnlock()

    if exists {
        return limiter
    }

    m.userMu.Lock()
    defer m.userMu.Unlock()

    // 더블체크
    if limiter, exists = m.userLimiters[userID]; exists {
        return limiter
    }

    limiter = rate.NewLimiter(m.userRPM, m.userBurst)
    m.userLimiters[userID] = limiter
    return limiter
}

// Allow 요청 허용 여부 확인
func (m *MultiTierLimiter) Allow(ctx context.Context, userID, modelID string, tokenCount int64) error {
    // 1. 글로벌 제한 확인
    if !m.globalLimiter.Allow() {
        return ErrGlobalLimitExceeded
    }

    // 2. 사용자별 제한 확인
    userLimiter := m.GetUserLimiter(userID)
    if !userLimiter.Allow() {
        return &RateLimitError{
            UserID:     userID,
            RetryAfter: time.Second,
        }
    }

    // 3. 토큰 사용량 확인 및 업데이트
    m.tokenMu.Lock()
    defer m.tokenMu.Unlock()

    // TPM 리셋 (1분마다)
    if time.Since(m.tokenLastReset) >= time.Minute {
        m.tokenUsage = make(map[string]int64)
        m.tokenLastReset = time.Now()
    }

    currentUsage := m.tokenUsage[userID] + tokenCount
    if currentUsage > m.tpmLimit {
        return &RateLimitError{
            UserID:      userID,
            RetryAfter:  time.Until(m.tokenLastReset.Add(time.Minute)),
            CurrentRate: float64(currentUsage),
        }
    }

    m.tokenUsage[userID] = currentUsage
    return nil
}

// SetUserLimit 사용자별 제한 동적 조정
func (m *MultiTierLimiter) SetUserLimit(userID string, rpm int, burst int) {
    m.userMu.Lock()
    defer m.userMu.Unlock()

    if limiter, exists := m.userLimiters[userID]; exists {
        limiter.SetLimit(rate.Limit(rpm) / 60)
        limiter.SetBurst(burst)
    }
}

// Cleanup 만료된 사용자 Limiter 정리
func (m *MultiTierLimiter) Cleanup(maxAge time.Duration) {
    m.userMu.Lock()
    defer m.userMu.Unlock()

    for userID, limiter := range m.userLimiters {
        if time.Since(limiter.(*rate.Limiter).Reserve().TimeToAct) > maxAge {
            delete(m.userLimiters, userID)
        }
    }
}

4단계: HolySheep AI 클라이언트 통합

package client

import (
    "context"
    "fmt"
    "sync"
    "time"

    "github.com/sashabaranov/go-openai"
    "gomodel-rate-limit/config"
    "gomodel-rate-limit/ratelimit"
)

// HolySheepClient HolySheep AI API 클라이언트
type HolySheepClient struct {
    client      *openai.Client
    config      *config.APIConfig
    rateLimiter *ratelimit.MultiTierLimiter
    mu          sync.Mutex

    // 요청 통계
    requestCount int64
    errorCount   int64
    totalTokens  int64
}

// NewHolySheepClient HolySheep 클라이언트 생성
func NewHolySheepClient() (*HolySheepClient, error) {
    cfg := config.LoadConfig()

    if cfg.APIKey == "" {
        return nil, fmt.Errorf("HOLYSHEEP_API_KEY가 설정되지 않았습니다")
    }

    // HolySheep의 base_url로 OpenAI 호환 클라이언트 생성
    client := openai.NewClient(cfg.APIKey)
    client.BaseURL = cfg.BaseURL + "/chat/completions"

    return &HolySheepClient{
        client: client,
        config: cfg,
        rateLimiter: ratelimit.NewMultiTierLimiter(
            cfg.RateLimit.UserRPM,
            cfg.RateLimit.GlobalRPM,
            cfg.RateLimit.BurstSize,
            int64(cfg.RateLimit.UserTPM),
        ),
    }, nil
}

// ChatCompletion 채팅 완료 요청
func (c *HolySheepClient) ChatCompletion(ctx context.Context, req openai.ChatCompletionRequest) (*openai.ChatCompletionResponse, error) {
    userID := req.User
    modelID := req.Model

    // 토큰 예측 (대략적인 계산)
    estimatedTokens := int64(estimateTokens(req))

    // Rate Limiting 확인
    if err := c.rateLimiter.Allow(ctx, userID, modelID, estimatedTokens); err != nil {
        c.mu.Lock()
        c.errorCount++
        c.mu.Unlock()

        if rateErr, ok := err.(*ratelimit.RateLimitError); ok {
            return nil, fmt.Errorf("rate limit exceeded for user %s, retry after %v",
                rateErr.UserID, rateErr.RetryAfter)
        }
        return nil, err
    }

    // API 요청 실행
    c.mu.Lock()
    c.requestCount++
    c.mu.Unlock()

    resp, err := c.client.CreateChatCompletion(ctx, req)
    if err != nil {
        c.mu.Lock()
        c.errorCount++
        c.mu.Unlock()
        return nil, fmt.Errorf("API request failed: %w", err)
    }

    // 실제 사용 토큰累积
    c.mu.Lock()
    c.totalTokens += int64(resp.Usage.TotalTokens)
    c.mu.Unlock()

    return resp, nil
}

// estimateTokens 토큰 수 예측
func estimateTokens(req openai.ChatCompletionRequest) int {
    // 대략적인 토큰 계산
    // 실제 구현에서는 tiktoken 또는 유사 라이브러리 사용 권장
    total := 0
    for _, msg := range req.Messages {
        total += len(msg.Content) / 4 // 대략적인 추정
    }
    if req.MaxTokens != nil {
        total += *req.MaxTokens
    }
    return total
}

// GetStats 요청 통계 반환
func (c *HolySheepClient) GetStats() (int64, int64, int64) {
    c.mu.Lock()
    defer c.mu.Unlock()
    return c.requestCount, c.errorCount, c.totalTokens
}

5단계: 마이그레이션 실행 스크립트

package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "time"

    "github.com/sashabaranov/go-openai"
    "gomodel-rate-limit/client"
)

func main() {
    // HolySheep API 키 설정
    os.Setenv("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY")

    // 클라이언트 생성
    holySheepClient, err := client.NewHolySheepClient()
    if err != nil {
        log.Fatalf("HolySheep 클라이언트 생성 실패: %v", err)
    }

    ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
    defer cancel()

    // 테스트 요청
    req := openai.ChatCompletionRequest{
        Model: "gpt-4.1",
        Messages: []openai.ChatCompletionMessage{
            {
                Role:    openai.ChatMessageRoleUser,
                Content: "안녕하세요, HolySheep AI 마이그레이션 테스트입니다.",
            },
        },
        MaxTokens: 100,
        User:      "test-user-001", // Rate Limiting용 사용자 식별
    }

    resp, err := holySheepClient.ChatCompletion(ctx, req)
    if err != nil {
        log.Printf("요청 실패: %v", err)
        return
    }

    fmt.Printf("응답 성공: %s\n", resp.Choices[0].Message.Content)
    fmt.Printf("사용 토큰: %d\n", resp.Usage.TotalTokens)

    // 통계 출력
    reqCount, errCount, totalTokens := holySheepClient.GetStats()
    fmt.Printf("통계 - 요청: %d, 오류: %d, 총 토큰: %d\n",
        reqCount, errCount, totalTokens)
}

// 마이그레이션 헬퍼 함수
func migrateFromOpenAI() {
    fmt.Println("=== 공식 OpenAI API에서 HolySheep로 마이그레이션 ===")
    fmt.Println("변경 전: api.openai.com/v1")
    fmt.Println("변경 후: api.holysheep.ai/v1")
    fmt.Println("API Key: 기존 sk-xxx -> HolySheep 키로 교체")
    fmt.Println("코드 변경: 최소화 (base_url만 변경)")
}

// 롤백 함수
func rollbackToOpenAI() {
    fmt.Println("=== HolySheep에서 공식 API로 롤백 ===")
    fmt.Println("변경 후: api.openai.com/v1")
    fmt.Println("API Key: HolySheep -> 기존 sk-xxx로 복원")
}

6단계: 설정 파일

# HolySheep AI 설정 파일

config.yaml

base_url: "https://api.holysheep.ai/v1" api_key: "YOUR_HOLYSHEEP_API_KEY" timeout: 60 rate_limit: # 사용자별 제한 user_rpm: 60 # 사용자당 분당 요청 수 user_tpm: 120000 # 사용자당 분당 토큰 수 # 글로벌 제한 global_rpm: 1000 # 전체 시스템 분당 요청 수 global_tpm: 10000000 # 전체 시스템 분당 토큰 수 # 버스트 설정 burst_size: 10 # 순간 허용 burst 크기

모델별 우선순위

models: priority: - gpt-4.1 - claude-sonnet-4 - gemini-2.5-flash - deepseek-v3.2

핀백 설정

fallback: enabled: true retry_count: 3 retry_delay_ms: 1000 timeout_ms: 30000

Rate Limiting 고급 설정

Adaptive Rate Limiting 구현

package adaptive

import (
    "sync"
    "time"

    "golang.org/x/time/rate"
)

// AdaptiveLimiter 적응형 Rate Limiter
// 오류율에 따라 동적으로 제한 조정
type AdaptiveLimiter struct {
    baseLimiter    *rate.Limiter
    currentLimit   rate.Limit
    errorThreshold float64
    successCount   int
    errorCount     int

    mu             sync.Mutex
    lastAdjustment time.Time
}

// NewAdaptiveLimiter 생성
func NewAdaptiveLimiter(rpm int, burst int, errorThreshold float64) *AdaptiveLimiter {
    return &AdaptiveLimiter{
        baseLimiter:    rate.NewLimiter(rate.Limit(rpm)/60, burst),
        currentLimit:   rate.Limit(rpm) / 60,
        errorThreshold: errorThreshold,
    }
}

// RecordResult 요청 결과 기록
func (a *AdaptiveLimiter) RecordResult(success bool) {
    a.mu.Lock()
    defer a.mu.Unlock()

    if success {
        a.successCount++
    } else {
        a.errorCount++
    }

    // 1분마다 오류율 계산 및 조정
    if time.Since(a.lastAdjustment) >= time.Minute {
        a.adjust()
        a.lastAdjustment = time.Now()
    }
}

// adjust 제한 동적 조정
func (a *AdaptiveLimiter) adjust() {
    total := a.successCount + a.errorCount
    if total == 0 {
        return
    }

    errorRate := float64(a.errorCount) / float64(total)

    if errorRate > a.errorThreshold {
        // 오류율이 높으면 제한 강화
        newLimit := a.currentLimit * 0.8
        a.baseLimiter.SetLimit(newLimit)
        a.currentLimit = newLimit
    } else if errorRate < a.errorThreshold/2 {
        // 오류율이 낮으면 제한 완화
        newLimit := a.currentLimit * 1.1
        if newLimit < a.baseLimiter.Limit()*2 {
            a.baseLimiter.SetLimit(newLimit)
            a.currentLimit = newLimit
        }
    }

    // 카운터 리셋
    a.successCount = 0
    a.errorCount = 0
}

// Allow 요청 허용
func (a *AdaptiveLimiter) Allow() bool {
    return a.baseLimiter.Allow()
}

롤백 계획

마이그레이션 중 문제가 발생した場合를 대비한 롤백 계획:

// 롤백 시나리오별 복원 스크립트

시나리오 1: 연결 실패

HolySheep 연결이 완전히 안되는 경우

rollback_connection: base_url: "https://api.openai.com/v1" api_key: $ORIGINAL_OPENAI_KEY

시나리오 2: Rate Limiting 문제

Rate Limiter 버그로 요청이 모두 실패하는 경우

rollback_ratelimit: # 모든 Rate Limiting 비활성화 rate_limit: user_rpm: 10000 user_tpm: 10000000 global_rpm: 100000 global_tpm: 100000000 burst_size: 1000

시나리오 3: 비용 초과

예상보다 비용이 높은 경우

rollback_cost_control: # 모델별 사용량 엄격 제한 models: disabled: - gpt-4.1 - claude-sonnet-4 enabled: - gemini-2.5-flash - deepseek-v3.2 max_daily_spend: 100

롤백 명령어

rollback: git checkout main -- config.yaml git checkout main -- client.go export HOLYSHEEP_API_KEY="" export ORIGINAL_API_KEY="sk-original..."

모니터링 및 알림 설정

package monitoring

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/push"
)

// Metrics 메트릭 수집기
type Metrics struct {
    requestsTotal    *prometheus.CounterVec
    requestDuration  *prometheus.HistogramVec
    tokensTotal      *prometheus.CounterVec
    errorsTotal      *prometheus.CounterVec
    rateLimitHits    *prometheus.CounterVec
}

// NewMetrics 메트릭 생성
func NewMetrics(namespace string) *Metrics {
    return &Metrics{
        requestsTotal: prometheus.NewCounterVec(
            prometheus.CounterOpts{
                Namespace: namespace,
                Name:      "requests_total",
                Help:      "Total number of requests",
            },
            []string{"model", "status"},
        ),
        requestDuration: prometheus.NewHistogramVec(
            prometheus.HistogramOpts{
                Namespace: namespace,
                Name:      "request_duration_seconds",
                Help:      "Request duration in seconds",
                Buckets:   []float64{0.1, 0.5, 1, 2, 5, 10},
            },
            []string{"model"},
        ),
        tokensTotal: prometheus.NewCounterVec(
            prometheus.CounterOpts{
                Namespace: namespace,
                Name:      "tokens_total",
                Help:      "Total tokens used",
            },
            []string{"model", "type"}, // type: prompt/completion
        ),
        errorsTotal: prometheus.NewCounterVec(
            prometheus.CounterOpts{
                Namespace: namespace,
                Name:      "errors_total",
                Help:      "Total errors",
            },
            []string{"error_type"},
        ),
        rateLimitHits: prometheus.NewCounterVec(
            prometheus.CounterOpts{
                Namespace: namespace,
                Name:      "rate_limit_hits_total",
                Help:      "Total rate limit hits",
            },
            []string{"user_id"},
        ),
    }
}

// AlertThresholds 알림 임계값
var AlertThresholds = struct {
    ErrorRate         float64
    AvgLatencyMs      float64
    RateLimitHitRatio float64
    CostPerHour       float64
}{
    ErrorRate:         0.05,  // 5% 이상
    AvgLatencyMs:      5000,  // 5초 이상
    RateLimitHitRatio: 0.1,   // 10% 이상
    CostPerHour:       100,   // 시간당 $100 이상
}

// CheckAlerts 알림 조건 확인
func (m *Metrics) CheckAlerts(ctx context.Context) {
    ticker := time.NewTicker(5 * time.Minute)
    defer ticker.Stop()

    for {
        select {
        case <-ctx.Done():
            return
        case <-ticker.C:
            m.evaluateAlerts()
        }
    }
}

func (m *Metrics) evaluateAlerts() {
    // 실제 구현에서는 Prometheus에서 메트릭 쿼리
    // 예시 알림 로직
    log.Println("알림 확인 중...")

    // 비용 알림
    // if currentCost > AlertThresholds.CostPerHour {
    //     sendAlert("비용 임계값 초과", fmt.Sprintf("현재 비용: $%.2f", currentCost))
    // }

    fmt.Printf("현재 알림 임계값 - 오류율: %.1f%%, 지연시간: %.0fms\n",
        AlertThresholds.ErrorRate*100, AlertThresholds.AvgLatencyMs)
}

자주 발생하는 오류 해결

오류 1: "rate limit exceeded" 연속 발생

// 문제: Rate Limiting 초과로 요청이 계속 실패
// 원인: 제한값이 너무 낮게 설정됨 또는 버스트 크기 부족

// 해결 방법 1: 제한값 조정
rate_limit:
  user_rpm: 120          # 60 -> 120으로 상향
  user_tpm: 240000       # 120000 -> 240000으로 상향