Skip to content

Commit 1b71bc5

Browse files
SimoKiiclaude
andcommitted
Refactor: 데이터 변환 계층을 인터페이스로 추상화
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 1da0209 commit 1b71bc5

2 files changed

Lines changed: 129 additions & 4 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.rabbittick.streamer.converter;
2+
3+
import com.rabbittick.streamer.global.dto.MarketDataMessage;
4+
import com.rabbittick.streamer.global.dto.OrderBookPayload;
5+
import com.rabbittick.streamer.global.dto.TickerPayload;
6+
import com.rabbittick.streamer.global.dto.TradePayload;
7+
8+
/**
9+
* 거래소 WebSocket 수신 데이터를 시스템 표준 DTO로 변환하는 컨버터의 표준 계약을 정의하는 인터페이스.
10+
*
11+
* <p>주요 책임:
12+
* <ul>
13+
* <li>거래소별 원시 JSON 메시지를 표준 {@link MarketDataMessage}로 변환</li>
14+
* <li>거래소 식별자 제공 (라우팅 키 생성에 사용)</li>
15+
* </ul>
16+
*
17+
* <p>각 거래소 구현체는 이 인터페이스를 통해 거래소별 JSON 포맷 차이를 캡슐화한다.
18+
* 변환된 {@link MarketDataMessage}는 거래소 종류에 관계없이 동일한 구조를 가지므로
19+
* 하위 계층(발행, 저장)은 거래소에 대한 지식 없이 데이터를 처리할 수 있다.
20+
*
21+
* <p>새로운 거래소를 추가하려면 이 인터페이스를 구현하고
22+
* {@code AbstractExchangeConnector}의 {@code handleMessage()} 안에서 호출한다.
23+
*/
24+
public interface ExchangeDataConverter {
25+
26+
/**
27+
* 거래소 식별자를 반환한다.
28+
*
29+
* <p>반환값은 {@link com.rabbittick.streamer.global.dto.Metadata}의
30+
* {@code exchange} 필드에 기록되며, RabbitMQ 라우팅 키 생성에 사용된다.
31+
*
32+
* @return 대문자 거래소 식별자 (예: "UPBIT", "BINANCE")
33+
*/
34+
String getExchangeName();
35+
36+
/**
37+
* 원시 JSON 문자열을 파싱하여 표준 ticker {@link MarketDataMessage}로 변환한다.
38+
*
39+
* @param rawJson 거래소 WebSocket으로부터 수신된 원시 JSON 문자열
40+
* @return 표준화된 ticker MarketDataMessage
41+
* @throws IllegalArgumentException JSON 파싱 실패 또는 필수 필드 누락 시
42+
*/
43+
MarketDataMessage<TickerPayload> convertTicker(String rawJson);
44+
45+
/**
46+
* 원시 JSON 문자열을 파싱하여 표준 trade {@link MarketDataMessage}로 변환한다.
47+
*
48+
* @param rawJson 거래소 WebSocket으로부터 수신된 원시 JSON 문자열
49+
* @return 표준화된 trade MarketDataMessage
50+
* @throws IllegalArgumentException JSON 파싱 실패 또는 필수 필드 누락 시
51+
*/
52+
MarketDataMessage<TradePayload> convertTrade(String rawJson);
53+
54+
/**
55+
* 원시 JSON 문자열을 파싱하여 표준 orderbook {@link MarketDataMessage}로 변환한다.
56+
*
57+
* @param rawJson 거래소 WebSocket으로부터 수신된 원시 JSON 문자열
58+
* @return 표준화된 orderbook MarketDataMessage
59+
* @throws IllegalArgumentException JSON 파싱 실패 또는 필수 필드 누락 시
60+
*/
61+
MarketDataMessage<OrderBookPayload> convertOrderBook(String rawJson);
62+
}

src/main/java/com/rabbittick/streamer/converter/UpbitDataConverter.java

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import org.springframework.stereotype.Component;
88

9+
import com.fasterxml.jackson.core.JsonProcessingException;
10+
import com.fasterxml.jackson.databind.ObjectMapper;
911
import com.rabbittick.streamer.connector.dto.upbit.UpbitOrderBookDto;
1012
import com.rabbittick.streamer.connector.dto.upbit.UpbitTickerDto;
1113
import com.rabbittick.streamer.connector.dto.upbit.UpbitTradeDto;
@@ -16,11 +18,13 @@
1618
import com.rabbittick.streamer.global.dto.TickerPayload;
1719
import com.rabbittick.streamer.global.dto.TradePayload;
1820

21+
import lombok.RequiredArgsConstructor;
22+
1923
/**
20-
* Upbit 외부 API DTO를 시스템 표준 DTO로 변환하는 컨버터.
24+
* Upbit WebSocket 수신 데이터를 시스템 표준 DTO로 변환하는 컨버터.
2125
*
22-
* <p>각 데이터 타입별로 명시적인 변환 메서드를 제공하여
23-
* 타입 안전성과 코드 가독성을 확보한다.
26+
* <p>{@link ExchangeDataConverter}를 구현하여 원시 JSON 문자열을 직접 수신하고,
27+
* Upbit 전용 DTO로 파싱한 후 거래소 독립적인 {@link MarketDataMessage}로 변환한다.
2428
*
2529
* <p>지원하는 데이터 타입:
2630
* <ul>
@@ -30,11 +34,70 @@
3034
* </ul>
3135
*/
3236
@Component
33-
public class UpbitDataConverter {
37+
@RequiredArgsConstructor
38+
public class UpbitDataConverter implements ExchangeDataConverter {
39+
40+
private final ObjectMapper objectMapper;
3441

3542
private static final String EXCHANGE_NAME = "UPBIT";
3643
private static final String VERSION = "1.0";
3744

45+
@Override
46+
public String getExchangeName() {
47+
return EXCHANGE_NAME;
48+
}
49+
50+
/**
51+
* 원시 JSON 문자열을 {@link UpbitTickerDto}로 파싱하여 표준 ticker 메시지로 변환한다.
52+
*
53+
* @param rawJson Upbit WebSocket으로부터 수신된 원시 JSON 문자열
54+
* @return 표준화된 ticker MarketDataMessage
55+
* @throws IllegalArgumentException JSON 파싱 실패 시
56+
*/
57+
@Override
58+
public MarketDataMessage<TickerPayload> convertTicker(String rawJson) {
59+
try {
60+
UpbitTickerDto dto = objectMapper.readValue(rawJson, UpbitTickerDto.class);
61+
return convertTickerData(dto);
62+
} catch (JsonProcessingException e) {
63+
throw new IllegalArgumentException("Ticker JSON 파싱 실패: " + e.getMessage(), e);
64+
}
65+
}
66+
67+
/**
68+
* 원시 JSON 문자열을 {@link UpbitTradeDto}로 파싱하여 표준 trade 메시지로 변환한다.
69+
*
70+
* @param rawJson Upbit WebSocket으로부터 수신된 원시 JSON 문자열
71+
* @return 표준화된 trade MarketDataMessage
72+
* @throws IllegalArgumentException JSON 파싱 실패 시
73+
*/
74+
@Override
75+
public MarketDataMessage<TradePayload> convertTrade(String rawJson) {
76+
try {
77+
UpbitTradeDto dto = objectMapper.readValue(rawJson, UpbitTradeDto.class);
78+
return convertTradeData(dto);
79+
} catch (JsonProcessingException e) {
80+
throw new IllegalArgumentException("Trade JSON 파싱 실패: " + e.getMessage(), e);
81+
}
82+
}
83+
84+
/**
85+
* 원시 JSON 문자열을 {@link UpbitOrderBookDto}로 파싱하여 표준 orderbook 메시지로 변환한다.
86+
*
87+
* @param rawJson Upbit WebSocket으로부터 수신된 원시 JSON 문자열
88+
* @return 표준화된 orderbook MarketDataMessage
89+
* @throws IllegalArgumentException JSON 파싱 실패 시
90+
*/
91+
@Override
92+
public MarketDataMessage<OrderBookPayload> convertOrderBook(String rawJson) {
93+
try {
94+
UpbitOrderBookDto dto = objectMapper.readValue(rawJson, UpbitOrderBookDto.class);
95+
return convertOrderBookData(dto);
96+
} catch (JsonProcessingException e) {
97+
throw new IllegalArgumentException("OrderBook JSON 파싱 실패: " + e.getMessage(), e);
98+
}
99+
}
100+
38101
/**
39102
* UpbitTickerDto를 표준 MarketDataMessage로 변환한다.
40103
*

0 commit comments

Comments
 (0)