WORK EXPERIENCE

실시간 센서 데이터 전송 시스템

선박에서 수집되는 센서 데이터를 외부 서버로 실시간 전송하는 데이터 연동 시스템

Java · Spring · MQTT

아키텍처

온습도 센서화재 센서도어 센서API Server센서 데이터 수신 핸들러MQTT 전송 스레드풀MQTT PublisherMQTT Broker외부 서버

개요

  • 선박의 온습도·화재·도어 센서 데이터를 외부 서버로 실시간 전송하는 시스템
  • API Server가 수신한 센서 데이터를 MQTT 메시지로 변환해 발행
  • WMS·API·ADMIN·SOCKET으로 분리된 네 애플리케이션과 MySQL·Redis가 8코어 단일 서버에서 함께 동작하는 국방 폐쇄망 환경

기술 선택 이유

  • HTTP Polling — 제외

    • 주기적 요청으로 실시간성이 떨어지고, 작은 센서 메시지마다 요청·헤더 오버헤드 발생
  • Kafka — 제외

    • 이벤트 영속성·재처리보다 단순 실시간 전달이 우선인 요구사항
    • Broker·파티션·컨슈머 그룹까지 운영해야 해 요구사항 대비 복잡도 큼
  • MQTT — 채택

    • 작은 센서 상태 메시지를 반복 전송하기에 적합한 경량 Pub/Sub 방식
    • MQTT Broker를 사이에 두어 API Server와 외부 서버의 직접 연결 제거
    • 온습도·화재·도어 센서의 평상값은 일부 누락돼도 다음 값으로 상태가 갱신되므로 QoS 0 적용
    • 실제 화재 이벤트는 유실을 막기 위해 QoS 1 적용, 중복 메시지는 수신 측에서 멱등 처리

문제

  • MQTT 전송을 @Async로 처리하며 pool-size="100"인 공통 스레드풀 사용
  • 400 req/s 부하가 이어지자 스레드가 최대 100개까지 늘고, 서버 CPU가 90~95%까지 상승하며 처리량이 유입량 아래로 감소
  • 처리하지 못한 작업이 상한 없는 큐에 쌓이면서 대기시간이 최대 6–7초까지 증가
  • 같은 서버의 위치 측위 요청도 함께 지연돼 서비스 운용에 영향

해결 전략

  • MQTT 전송 전용 스레드풀을 분리하고 CorePoolSize 8, MaxPoolSize 16, Queue Capacity 200으로 제한
  • Queue와 MaxPoolSize가 모두 차면 CallerRunsPolicy로 호출 스레드가 직접 처리해 추가 적체 억제

튜닝 기준

  • CorePoolSize 8 · MaxPoolSize 16: 평상시 8개로 처리하고 순간적인 부하나 전송 지연이 겹칠 때만 16개까지 확장
  • Queue Capacity 200: 운영 유입량의 약 0.5초분만 대기시켜 무제한 적체 방지

검증

테스트 설정

  • Locust로 센서 400개의 데이터 수신 트래픽과 선원 300명의 위치 측위 트래픽을 함께 재현해 공통 풀과 MQTT 전용 풀을 30분씩 비교
  • 완료 처리량·큐 적재량·대기시간을 측정하고 4·6·8개 스레드에서 큐 포화 여부 확인
  • 8·16·32개 스레드의 처리량·서버 CPU·API 프로세스 Context Switching을 비교해 과도한 스레드의 비용 확인

동일 부하 전후 결과

지표기존 공통 풀MQTT 전용 풀
최대 activeCount1008
30분 시점 queueSize2,80060
큐 대기시간 p955s150ms
최대 큐 대기시간7s500ms
8코어 서버 CPU90–95%55–65%

최소 스레드 수 검증

스레드 수평균 완료 처리량큐 상태
4약 320 msg/s200건 도달 후 포화 지속
6약 390 msg/s순간 전송 지연 시 200건 반복 도달
8약 400 msg/s30분 시점 60건, 지속 증가 없음
  • 8개부터 평균 400 msg/s를 유지하고 큐가 지속해서 늘지 않아 최소 스레드 수로 결정

8개 이상 스레드 수 비교

스레드 수평균 처리량서버 평균 CPUAPI CS/s
8약 400 msg/s60%3.0K
16약 400 msg/s64%4.2K
32약 400 msg/s73%6.5K
  • 세 설정 모두 약 400 msg/s를 처리했지만, 스레드가 늘수록 CPU 사용량과 Context Switching 증가