[Spring Boot] 공기질 모니터링 서비스 BE 코드 구현 (블루투스 연동)

Sungjin Cho·2024년 11월 12일
0

Spring Boot

목록 보기
16/16

1. 데이터 흐름도

graph LR
    A[IoT Device] -->|WebSocket| B[Spring Server]
    B -->|Cache| C[Redis]
    C -->|Scheduled Task| D[MySQL]
    C -->|Scheduled Task| E[Kafka]

2. 주요 컴포넌트 설명

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. 주요 기능 설명

3.1 데이터 캐싱 전략

  • 모든 센서 데이터는 먼저 Redis에 저장
  • 24시간 TTL(Time To Live) 설정
  • 디바이스별 최신 데이터는 별도 키로 관리

3.2 데이터 영구 저장

  • 5초마다 Redis의 데이터를 검사
  • MySQL: 히스토리 데이터 저장
  • Kafka: 실시간 데이터 스트리밍

3.3 에러 처리

  • MySQL 저장 실패: 해당 데이터만 스킵하고 다음 처리
  • Kafka 전송 실패: 무시하고 계속 진행
  • Redis 삭제 실패: 로그 기록

4. 데이터 구조

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
}

5. 성능 고려사항

  • Redis 캐싱으로 빠른 데이터 접근
  • 배치 처리로 DB 부하 감소
  • 비동기 Kafka 전송으로 응답 시간 최소화
  • 각 저장소 독립적 에러 처리로 안정성 확보

0개의 댓글