package com.goldenchart.controller; import com.goldenchart.dto.CandleBarDto; import com.goldenchart.service.HistoricalDataService; import com.goldenchart.websocket.DynamicSubscriptionManager; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; /** * 캔들 데이터 REST API 컨트롤러. * * context-path: /api * endpoint: GET /api/candles/history * * 명세서 5.1 포맷: * Query Params: market=KRW-BTC, type=1m, to=2026-05-20T10:17:00Z, count=200 * Response: CandleBarDto[] (time, open, high, low, close, volume, rsi) */ @RestController @RequestMapping("/candles") @RequiredArgsConstructor @Slf4j public class CandleController { private final HistoricalDataService historicalDataService; private final DynamicSubscriptionManager subscriptionManager; /** * 과거 캔들 데이터 조회. * * @param market 업비트 마켓 코드 (e.g. "KRW-BTC") * @param type 캔들 타입 (e.g. "1m", "5m", "1h", "1d") * @param to 기준 시간 이전(exclusive) ISO-8601 (e.g. "2026-05-20T10:00:00" 또는 "...Z") * @param count 요청 캔들 수 (기본값 200, 최대 200) * @return 시간 오름차순 CandleBarDto 배열 */ @GetMapping("/history") public ResponseEntity> getHistory( @RequestParam String market, @RequestParam(defaultValue = "1d") String type, @RequestParam(required = false) String to, @RequestParam(defaultValue = "200") int count) { log.info("[CandleController] history 요청: market={}, type={}, to={}, count={}", market, type, to, count); List bars = historicalDataService.getHistory(market, type, to, count); return ResponseEntity.ok(bars); } /** * 차트 실시간용 — 업비트 WS·Ta4j warm-up 고정 (STOMP 구독과 병행). */ @PostMapping("/watch") public ResponseEntity watch( @RequestParam String market, @RequestParam(defaultValue = "1m") String type) { subscriptionManager.ensureMarketPinned(market, type); subscriptionManager.ensureMarketPinned(market, "1m"); return ResponseEntity.ok().build(); } }