From 0bf1457318c96d3771d66cddec76f36a81010529 Mon Sep 17 00:00:00 2001 From: JEONG KITAE Date: Fri, 31 Jul 2026 13:11:17 +0900 Subject: [PATCH] fix(collector): filter non-six-digit symbols before name lookup Ranking responses can include ETN-style symbols (e.g. 0197W0) which fetchStockNames() rejects with IllegalArgumentException, failing the entire chunk. Filter to six-digit KRX symbols in refreshSymbols() so ranking rows resolve their display names instead of showing null. --- .../collector/StockReferenceService.java | 3 +++ .../collector/StockReferenceServiceTest.java | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/main/java/com/marketguard/collector/StockReferenceService.java b/src/main/java/com/marketguard/collector/StockReferenceService.java index 8619d38..9aae66c 100644 --- a/src/main/java/com/marketguard/collector/StockReferenceService.java +++ b/src/main/java/com/marketguard/collector/StockReferenceService.java @@ -61,7 +61,10 @@ private synchronized void refreshSymbols(List symbols, boolean missingOn if (symbols.isEmpty() || !hasCredentials()) { return; } + // 토스 종목명 API는 6자리 KRX 종목코드만 허용한다. 랭킹 응답에는 ETN(0197W0) 등 + // 비표준 심볼이 섞일 수 있어, 섞이면 chunk 전체 조회가 실패하므로 먼저 걸러낸다. List requested = symbols.stream() + .filter(symbol -> symbol.matches("\\d{6}")) .filter(symbol -> !missingOnly || !names.containsKey(symbol)) .distinct() .toList(); diff --git a/src/test/java/com/marketguard/collector/StockReferenceServiceTest.java b/src/test/java/com/marketguard/collector/StockReferenceServiceTest.java index 1a26077..d71dfb6 100644 --- a/src/test/java/com/marketguard/collector/StockReferenceServiceTest.java +++ b/src/test/java/com/marketguard/collector/StockReferenceServiceTest.java @@ -53,4 +53,22 @@ void resolvesSupportedMarketIndicatorNamesWithoutAnUpstreamLookup() { assertThat(service.nameOf("KOSPI")).isEqualTo("코스피 시장"); assertThat(service.nameOf("KOSDAQ")).isEqualTo("코스닥 시장"); } + + @Test + void filtersNonSixDigitSymbolsBeforeNameLookup() { + TossApiProperties properties = new TossApiProperties( + "https://example.test", "https://example.test/oauth2/token", + "client-id", "client-secret", List.of()); + when(marketDataClient.fetchStockNames(List.of("005930", "069500"))) + .thenReturn(Map.of("005930", "삼성전자", "069500", "KODEX 200")); + StockReferenceService service = new StockReferenceService( + properties, marketDataClient, symbolUniverse); + + // 랭킹 응답에 섞일 수 있는 ETN 등 비6자리 심볼은 종목명 API 호출에서 제외되어야 한다. + service.refreshMissing(List.of("005930", "0197W0", "069500")); + + assertThat(service.nameOf("005930")).isEqualTo("삼성전자"); + assertThat(service.nameOf("0197W0")).isNull(); + verify(marketDataClient).fetchStockNames(List.of("005930", "069500")); + } }