Node-RED 실습 : 가상 센서(온도/진동/전류) 데이터 만들기 (Inject→Function→Debug)



Node-RED 실습 A: 가상 센서(온도/진동/전류) 데이터 만들기 (Inject→Function→Debug)

한눈에 보는 요약

이 실습의 목표는 Node-RED 코어 노드만으로 “1초마다 온도값을 생성”하고, 현실적인 센서 특성(노이즈, 추세 변화, 간헐적 이상치)을 포함한 메시지를 만드는 것입니다.

핵심은 Function 노드에서 상태를 저장/갱신(flow.get/set)하여 랜덤워크(서서히 변하는 추세)를 구현하고, 작은 노이즈와 낮은 확률의 스파이크를 추가해 데이터 품질을 현실에 가깝게 만드는 데 있습니다.

또한 msg.payload를 JSON 형태로 표준화하면, 이후 진동/전류 센서 확장, 저장/시각화/알림 연동, 다중 센서 관리에 유리합니다.

목차


핵심 포인트

  • Inject 노드의 repeat(1초)로 일정 주기 이벤트를 만들고, Function 노드에서 센서 값을 생성합니다.
  • 랜덤워크는 “이전 값 + 작은 변화” 형태로 추세를 만들며, flow 컨텍스트에 값을 저장해야 자연스럽게 이어집니다.
  • 노이즈는 미세한 흔들림을, 스파이크는 간헐적 이상치(갑작스런 튐)를 모사합니다(확률 기반).
  • msg.payload를 JSON으로 표준화하면 타임스탬프/센서ID/다중 채널(진동, 전류) 확장이 쉬워집니다.
  • 범위 제한(클램프)은 데이터가 비현실적으로 폭주하는 것을 막는 안전장치입니다.

상세 설명

1. 실습 목표와 구성 노드

실습 A는 “가상 센서(온도/진동/전류) 데이터”를 생성하는 가장 기본적인 패턴을 다룹니다. 실제 센서를 붙이기 전, 대시보드/저장소/알림 로직이 정상 동작하는지 검증하기 위해 가상 데이터를 많이 사용합니다.

구성은 매우 단순합니다. Inject(repeat: 1 second) → Function(센서 생성) → Debug의 3개 노드만으로 코어 기능을 구현합니다.

inject 노드를 드래그해서 플로우에 가져가면 timestamp로 이름이 변경됩니다.
inject 노드, function 노드, debug 노드 3개를 나란히 놓고 각 노드의 점을 드래그해서 선으로 연결을 하면 됩니다.


2. 랜덤워크·노이즈·스파이크 모델링 이해

현실의 센서 데이터는 단순히 “랜덤 숫자”가 아니라, 보통 다음 3가지 특징을 동시에 가집니다.

  • 추세(랜덤워크): 온도가 서서히 오르거나 내리는 것처럼 이전 값에서 조금씩 이동합니다.
  • 미세 노이즈: 측정 오차나 환경 변화로 인해 작은 폭으로 흔들립니다.
  • 간헐적 이상치(스파이크): 순간적인 전기적 노이즈/충격/통신 오류 등으로 값이 갑자기 튀는 현상이 드물게 발생합니다.

이 실습에서는 랜덤워크와 노이즈를 매 주기마다 누적하고, 2% 확률로 스파이크를 추가해 “정상 데이터 속에 섞인 이상치” 시나리오를 만듭니다.

3. Function 노드 코드 구현(상태 저장 포함)

아래 코드는 “가상 온도 센서: 랜덤워크 + 노이즈 + 스파이크”를 구현한 예시입니다. 핵심은 flow.get("temp")로 이전 값을 가져오고, 계산 후 flow.set("temp", t)로 다시 저장하는 구조입니다.

// 가상 온도 센서: 랜덤워크 + 노이즈 + 스파이크
let t = flow.get("temp") ?? 23.0;

// 랜덤워크(서서히 변함)
t += (Math.random() - 0.5) * 0.2;   // -0.1 ~ +0.1

// 미세 노이즈
t += (Math.random() - 0.5) * 0.05;  // -0.025 ~ +0.025

// 2% 확률로 스파이크(이상치)
if (Math.random() < 0.02) {
  t += (Math.random() < 0.5 ? -1 : 1) * (2 + Math.random() * 3); // ±(2~5)
}

// 범위 제한
t = Math.max(10, Math.min(45, t));

flow.set("temp", t);

// 출력
msg.payload = {
  ts: Date.now(),
  temp: Number(t.toFixed(2)),
  sensor: "TEMP_001"
};

return msg;

운영 관점에서 중요한 포인트는 3가지입니다. 첫째, 랜덤워크와 노이즈는 매번 누적되므로 장시간 실행 시 값이 경계 밖으로 튈 수 있어 범위 제한이 필요합니다. 둘째, 스파이크 확률(예: 0.02)은 테스트 목적에 따라 조절해야 하며 너무 높으면 “정상 패턴”을 보기 어렵습니다. 셋째, payload를 JSON으로 표준화하면 후속 단계(저장, 알림, 이상탐지)에서 파싱/필터링이 쉬워집니다.

function 1 노드를 더블클릭하면 Edit function node 창이 열립니다.
On Message 탭에 위의 코드를 입력하고, Done 버튼을 눌러서 저장합니다.

timestamp 노드를 더블클릭하면 Edit inject node 창이 열립니다.
Repeat : Interval
every 1 seconds로 설정합니다.

timestamp 노드의 왼쪽 사각형을 누르면, debug 창에서 1초마다 온도 데이터가 갱신 되는 것을 확인할 수 있습니다.


4. msg.payload 설계: 숫자 vs JSON

msg.payload는 “숫자 하나”로도 동작합니다. 예를 들어 msg.payload = Number(t.toFixed(2));처럼 만들면 Debug에서 간단히 확인하기 좋습니다.

다만 실무에서는 JSON 형태가 유리합니다. 이유는 다음과 같습니다.

  • 타임스탬프(ts) 포함으로 저장 시계열 데이터 정합성이 좋아집니다.
  • sensor ID로 다중 센서(예: TEMP_001, VIB_001, CUR_001)를 구분할 수 있습니다.
  • 추후 진동(vib), 전류(cur) 등을 한 메시지에 추가하거나, 센서별 토픽 분기에도 유리합니다.

파라미터 튜닝 가이드(추천 범위 표)

아래 표는 실습에서 주로 조절하는 파라미터와 추천 범위를 정리한 것입니다. 목적(정상 시각화, 이상치 테스트, 알림 검증)에 따라 값을 바꾸어 보시면 학습 효과가 큽니다.

항목 코드 위치/의미 추천 범위 값을 키우면 값을 줄이면
랜덤워크 폭 (Math.random()-0.5)*0.2 0.1 ~ 0.6 추세 변화가 빨라짐 완만한 드리프트
노이즈 폭 (Math.random()-0.5)*0.05 0.02 ~ 0.2 잔떨림이 커짐 곡선이 매끈해짐
스파이크 확률 Math.random() < 0.02 0.005 ~ 0.05 이상치가 자주 발생 이상치가 드묾
스파이크 크기 ±(2~5) ±(1~10) 알림/탐지 테스트에 유리 미세 이상치 테스트
값 범위 제한 10 ~ 45 클램프 센서 사양 기반 현실적 범위 유지 폭주 가능(비권장)

따라하기

Inject 노드 추가
플로우 캔버스에 Inject 노드를 배치합니다. Payload는 특별히 필요 없으며(타임 트리거 용도), “repeat”를 1 second로 설정합니다. 이렇게 하면 1초마다 msg가 1개씩 생성됩니다.

Function 노드 추가 및 코드 붙여넣기
Inject 뒤에 Function 노드를 연결하고, 본문에 제시한 코드를 그대로 붙여넣습니다. 여기서 flow.get/set이 동작하려면 Function 노드가 “같은 플로우 컨텍스트”를 유지해야 하므로, 배포(deploy) 후 바로 연속 실행되는지 확인합니다.

Debug 노드로 출력 확인
Function 출력에 Debug 노드를 연결하고, Debug의 출력 대상은 msg.payload로 설정하는 것을 권장합니다. 배포 후 Debug 사이드바에서 1초마다 ts/temp/sensor가 갱신되는지 확인합니다.

(선택) 숫자 payload로 단순화
학습 초기에는 msg.payload를 숫자만 보내도록 바꿔도 좋습니다. 이후 대시보드 차트/DB 적재/알림 분기까지 고려한다면 JSON 표준 형태로 되돌리는 것을 권장합니다.

(확장) 진동/전류 센서로 확장
동일한 패턴을 vib, cur에도 적용할 수 있습니다. flow 키를 각각 "vib", "cur"로 분리하고, payload에 vib, cur 필드를 추가하면 다중 센서 메시지를 만들 수 있습니다. 이때 센서별 범위(예: 전류 0~30A 등)는 현실 사양에 맞춰 재설정합니다.

자주 겪는 문제와 해결 팁

값이 매번 23 근처로 “초기화”되는 것처럼 보입니다.
flow 컨텍스트가 유지되지 않는 경우(예: 노드/플로우 재배포, 컨텍스트 설정 문제)일 수 있습니다. 먼저 배포 후 일정 시간 연속으로 값이 이어지는지 확인하고, Function 노드가 실제로 flow.set을 수행하는지 Debug로 점검합니다.

스파이크가 너무 자주(또는 너무 드물게) 나옵니다.
Math.random() < 0.02의 값을 조정해 확률을 변경하십시오. 알림 검증이 목적이면 0.03~0.05로 높여 빠르게 재현하고, 정상 추세 시각화가 목적이면 0.005~0.01로 낮추는 편이 좋습니다.

데이터가 상한/하한에 붙어서 움직입니다.
랜덤워크 폭이 너무 크거나 범위 제한이 너무 좁을 때 발생합니다. 랜덤워크 계수를 낮추거나(예: 0.2→0.1), 범위를 센서 사양에 맞게 조금 넓히는 방법이 있습니다.

추가로 생각해볼 점

이상치(스파이크)를 “단발”이 아니라 “연속(예: 5초간 과열)” 형태로 모델링하면 경보 로직(지속 시간 조건) 테스트에 더 유리합니다.


센서가 여러 개일 때는 sensor ID뿐 아니라 “라인/설비/위치” 메타데이터를 payload에 넣어두면 운영 단계에서 필터링과 집계가 쉬워집니다.


Debug 확인이 끝나면, 다음 단계로는 차트(대시보드) 시각화, DB 적재, 임계치 알림(이메일/슬랙/웹훅) 순서로 확장하는 것을 권장합니다.



 "이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
Reactions

댓글 쓰기

0 댓글