package services import ( "fmt" "stocksearch/models" "time" ) // StockService 주식 비즈니스 로직 (캐시 + 키움 API 조합) type StockService struct { kiwoom *KiwoomClient cache *CacheService } var stockSvc *StockService // GetStockService 주식 서비스 싱글턴 반환 func GetStockService() *StockService { if stockSvc == nil { stockSvc = &StockService{ kiwoom: GetKiwoomClient(), cache: GetCacheService(), } } return stockSvc } // GetCurrentPrice 현재가 조회 (1초 캐시 적용) func (s *StockService) GetCurrentPrice(stockCode string) (*models.StockPrice, error) { cacheKey := "price:" + stockCode if cached, ok := s.cache.Get(cacheKey); ok { if price, ok := cached.(*models.StockPrice); ok { return price, nil } } price, err := s.kiwoom.GetCurrentPrice(stockCode) if err != nil { return nil, fmt.Errorf("현재가 조회 실패 [%s]: %w", stockCode, err) } s.cache.Set(cacheKey, price, 30*time.Second) return price, nil } // GetDailyChart 일봉 데이터 조회 (5분 캐시 적용) func (s *StockService) GetDailyChart(stockCode string) ([]models.CandleData, error) { cacheKey := "chart:daily:" + stockCode if cached, ok := s.cache.Get(cacheKey); ok { if candles, ok := cached.([]models.CandleData); ok { return candles, nil } } candles, err := s.kiwoom.GetDailyChart(stockCode) if err != nil { return nil, fmt.Errorf("일봉 조회 실패 [%s]: %w", stockCode, err) } s.cache.Set(cacheKey, candles, 5*time.Minute) return candles, nil } // GetMinuteChart 분봉 데이터 조회 (30초 캐시 적용) func (s *StockService) GetMinuteChart(stockCode string, minutes int) ([]models.CandleData, error) { cacheKey := fmt.Sprintf("chart:minute%d:%s", minutes, stockCode) if cached, ok := s.cache.Get(cacheKey); ok { if candles, ok := cached.([]models.CandleData); ok { return candles, nil } } candles, err := s.kiwoom.GetMinuteChart(stockCode, minutes) if err != nil { return nil, fmt.Errorf("분봉 조회 실패 [%s]: %w", stockCode, err) } s.cache.Set(cacheKey, candles, 30*time.Second) return candles, nil } // GetTopFluctuation 상위 등락률 종목 조회 (1분 캐시 적용) func (s *StockService) GetTopFluctuation(market string, ascending bool, count int) ([]models.StockPrice, error) { dir := "up" if ascending { dir = "down" } cacheKey := fmt.Sprintf("fluctuation:%s:%s:%d", market, dir, count) if cached, ok := s.cache.Get(cacheKey); ok { if stocks, ok := cached.([]models.StockPrice); ok { return stocks, nil } } stocks, err := s.kiwoom.GetTopFluctuation(market, ascending, count) if err != nil { return nil, fmt.Errorf("등락률 조회 실패: %w", err) } s.cache.Set(cacheKey, stocks, 1*time.Minute) return stocks, nil }