graph LR
A[IoT Device] -->|WebSocket| B[Spring Server]
B -->|Cache| C[Redis]
C -->|Scheduled Task| D[MySQL]
C -->|Scheduled Task| E[Kafka]
2.1 WebSocket 데이터 수신 (WebSocketHandler)
// 1. 웹소켓 메시지 수신
handleTextMessage(WebSocketSession session, TextMessage message) {
// JSON 파싱 및 메시지 타입 확인
if (type.equals("SUBSCRIBE")) {
handleSubscribe(session, jsonNode);
} else if (type.equals("SENSOR_DATA")) {
handleSensorData(session, jsonNode.get("payload"));
}
}
// 2. 센서 데이터 처리
handleSensorData(WebSocketSession session, JsonNode payload) {
// DTO 변환 및 SensorDataService로 전달
SensorDataRequestDto dto = convertToDto(payload);
sensorDataService.processSensorData(dto);
}
2.2 Redis 캐싱 (SensorDataService)// 1. 센서 데이터 Redis 캐싱
// 1. 센서 데이터 Redis 캐싱
private void cacheLatestData(SensorData data) {
// 두 가지 키로 저장
// 1) 타임스탬프 포함 키: "device:{deviceId}:{timestamp}"
// 2) 최신 데이터 키: "device:{deviceId}:latest"
String timestampKey = String.format("device:%s:%s", deviceId, timestamp);
String latestKey = String.format("device:%s:latest", deviceId);
redisTemplate.opsForValue().set(timestampKey, data, 24, TimeUnit.HOURS);
redisTemplate.opsForValue().set(latestKey, data, 24, TimeUnit.HOURS);
}
2.3 데이터 영구 저장 처리 (@Scheduled)// 5초마다 실행되는 스케줄러
// 5초마다 실행되는 스케줄러
@Scheduled(fixedRate = 5000)
public void processRedisData() {
// 1. Redis에서 데이터 조회
Set<String> keys = redisTemplate.keys("device:*:latest");
for (String key : keys) {
SensorData data = redisTemplate.opsForValue().get(key);
// 2. MySQL 저장
try {
sensorDataRepository.save(data);
} catch (Exception e) {
log.error("MySQL save failed");
continue;
}
// 3. Kafka 전송
try {
sendToKafka(data);
} catch (Exception e) {
log.error("Kafka send failed");
}
// 4. 처리 완료된 데이터 Redis에서 삭제
redisTemplate.delete(key);
}
}
3.1 데이터 캐싱 전략
3.2 데이터 영구 저장
3.3 에러 처리
4.1 Redis 키 구조
device:{deviceId}:{timestamp} -> 전체 히스토리 데이터
device:{deviceId}:latest -> 최신 데이터
4.2 센서 데이터 구조
{
"deviceId": "device123",
"timestamp": "2024-11-05T15:09:38.157",
"pm25Value": 12.0,
"pm25Level": 1,
"temperature": 24.0,
"humidity": 44.7,
"co2Value": 400.0,
"vocValue": 1.0,
"latitude": 37.3236,
"longitude": 126.8219
}