result = (market != null && !market.isBlank())
+ ? service.listByMarket(userId, deviceId, market)
+ : service.list(userId, deviceId);
+ return ResponseEntity.ok(result);
+ }
+
+ private Long parseUserId(String h) {
+ if (h == null || h.isBlank()) return null;
+ try { return Long.parseLong(h); } catch (NumberFormatException e) { return null; }
+ }
+}
diff --git a/backend/src/main/java/com/goldenchart/controller/WatchlistController.java b/backend/src/main/java/com/goldenchart/controller/WatchlistController.java
new file mode 100644
index 0000000..83b7bed
--- /dev/null
+++ b/backend/src/main/java/com/goldenchart/controller/WatchlistController.java
@@ -0,0 +1,133 @@
+package com.goldenchart.controller;
+
+import com.goldenchart.entity.GcWatchlist;
+import com.goldenchart.entity.GcHoldings;
+import com.goldenchart.repository.GcHoldingsRepository;
+import com.goldenchart.repository.GcWatchlistRepository;
+import com.goldenchart.service.WatchlistService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 관심종목 / 보유종목 REST API.
+ *
+ * 관심종목 추가/삭제 시 {@link WatchlistService} 가 실시간 전략 체크 대상과 자동 연동한다.
+ */
+@RestController
+@RequiredArgsConstructor
+@Transactional
+public class WatchlistController {
+
+ private final WatchlistService watchlistService;
+ private final GcWatchlistRepository watchlistRepo;
+ private final GcHoldingsRepository holdingsRepo;
+
+ private Long userId(Map h) {
+ String v = h.get("x-user-id"); return v != null ? Long.parseLong(v) : null;
+ }
+ private String deviceId(Map h) {
+ return h.getOrDefault("x-device-id", "anonymous");
+ }
+
+ // ── 관심종목 ──────────────────────────────────────────────────────────────
+
+ @GetMapping("/watchlist")
+ @Transactional(readOnly = true)
+ public ResponseEntity> getWatchlist(@RequestHeader Map h) {
+ return ResponseEntity.ok(watchlistService.list(userId(h), deviceId(h)));
+ }
+
+ @PostMapping("/watchlist")
+ public ResponseEntity addWatchlist(
+ @RequestHeader Map h,
+ @RequestBody Map body) {
+ Long uid = userId(h);
+ String symbol = (String) body.get("symbol");
+ GcWatchlist item = watchlistService.add(
+ uid,
+ deviceId(h),
+ symbol,
+ (String) body.get("koreanName"),
+ (String) body.get("englishName"),
+ body.containsKey("displayOrder") ? (Integer) body.get("displayOrder") : null
+ );
+ return ResponseEntity.ok(item);
+ }
+
+ @DeleteMapping("/watchlist/{symbol}")
+ public ResponseEntity removeWatchlist(
+ @RequestHeader Map h,
+ @PathVariable String symbol) {
+ watchlistService.remove(userId(h), deviceId(h), symbol);
+ return ResponseEntity.noContent().build();
+ }
+
+ @PutMapping("/watchlist/order")
+ public ResponseEntity reorderWatchlist(
+ @RequestHeader Map h,
+ @RequestBody List