104 lines
2.7 KiB
Go
104 lines
2.7 KiB
Go
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
|
|
}
|