[MED-003] WIA 생체신호 스트리밍 표준 전자책 | 제6장 (총 8장)


[MED-003] 제6장: Phase 3 - 통신 프로토콜

"보안 없는 통신은 위험한 통신이다"

Phase 3은 생체신호 데이터의 안전하고 효율적인 전송을 보장하는 통신 프로토콜을 정의합니다.


6.1 Bluetooth LE 프로토콜

6.1.1 GATT 서비스 정의

WIA-MED-003 전용 Bluetooth LE GATT 서비스:

Service UUID: 00001820-0000-1000-8000-00805f9b34fb
Service Name: WIA-MED-003 Vital Sign Service

Characteristics:

1. 기기 정보 (Read)
   UUID: 00002a1e-0000-1000-8000-00805f9b34fb
   - 제조사, 모델, 펌웨어 버전

2. 신호 구성 (Read/Write)
   UUID: 00002a1f-0000-1000-8000-00805f9b34fb
   - 샘플링 레이트, 필터 설정

3. 데이터 스트림 (Notify)
   UUID: 00002a20-0000-1000-8000-00805f9b34fb
   - 실시간 생체신호 데이터

4. 제어 명령 (Write)
   UUID: 00002a21-0000-1000-8000-00805f9b34fb
   - START, STOP, PAUSE, RESUME

5. 상태 (Notify)
   UUID: 00002a22-0000-1000-8000-00805f9b34fb
   - 배터리, 신호 품질, 오류

6.1.2 데이터 패킷 구조

BLE 패킷 (최대 20 bytes):

[Header 4 bytes][Payload N bytes][CRC 2 bytes]

Header:
- Byte 0: 패킷 유형 (0x01=ECG, 0x02=SpO2, etc.)
- Byte 1: 시퀀스 번호
- Byte 2-3: 페이로드 길이

Payload:
- 신호 데이터 (압축 또는 원본)

CRC:
- CRC-16 체크섬

예제 (ECG 데이터):
01 3A 00 0C 05 12 18 0A 15 1C 09 14 1B 08 A3 4F
│  │  │  │  └─────────────────────┘        └──┘
│  │  │  │       ECG 샘플 (12 bytes)       CRC
│  │  │  └─ 길이 (12)
│  │  └─ 길이 MSB
│  └─ 시퀀스 #58
└─ ECG (0x01)

6.1.3 연결 파라미터 최적화

파라미터 최소 최대 권장 용도
Connection Interval 7.5 ms 4000 ms 20-50 ms 실시간 스트리밍
Slave Latency 0 500 0-2 배터리 절약
Supervision Timeout 100 ms 32000 ms 2000 ms 연결 유지

6.2 WiFi/TCP 프로토콜

6.2.1 TCP 소켓 통신

// 서버 (기기)
const server = net.createServer((socket) => {
  console.log('클라이언트 연결:', socket.remoteAddress);

  // TLS 업그레이드
  const secureSocket = new tls.TLSSocket(socket, {
    cert: deviceCertificate,
    key: devicePrivateKey,
    ca: [caCertificate]
  });

  // 데이터 전송
  const interval = setInterval(() => {
    const data = getVitalSignData();
    const packet = encodeWIA(data);
    secureSocket.write(packet);
  }, 20);  // 50Hz 전송

  secureSocket.on('close', () => {
    clearInterval(interval);
  });
});

server.listen(8883);

// 클라이언트 (앱)
const client = tls.connect(8883, deviceIP, {
  ca: [caCertificate],
  checkServerIdentity: (host, cert) => {
    // 기기 인증서 검증
    return verifyDeviceCertificate(cert);
  }
}, () => {
  console.log('안전한 연결 확립');

  // 데이터 수신
  client.on('data', (packet) => {
    const data = decodeWIA(packet);
    processVitalSignData(data);
  });
});

6.2.2 HTTP/2 스트리밍

// Server-Sent Events (SSE)
app.get('/stream/ecg/:deviceId', (req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  });

  const stream = device.startStream('ECG');

  stream.on('data', (data) => {
    res.write(`event: ecg-data\n`);
    res.write(`data: ${JSON.stringify(data)}\n\n`);
  });

  req.on('close', () => {
    stream.stop();
  });
});

// 클라이언트
const eventSource = new EventSource('/stream/ecg/device-123');

eventSource.addEventListener('ecg-data', (event) => {
  const data = JSON.parse(event.data);
  updateECGChart(data);
});

6.3 MQTT 프로토콜

6.3.1 토픽 구조

WIA-MED-003 MQTT 토픽 계층:

wia-med-003/
  ├─ {deviceId}/
  │   ├─ info                   # 기기 정보 (retained)
  │   ├─ status                 # 상태 업데이트
  │   ├─ data/
  │   │   ├─ ecg               # ECG 데이터
  │   │   ├─ spo2              # SpO2 데이터
  │   │   ├─ bp                # 혈압 데이터
  │   │   └─ hrv               # HRV 데이터
  │   ├─ alerts                # 알림
  │   └─ control               # 제어 명령
  └─ broadcast/
      └─ discovery             # 기기 발견

예제:
발행: wia-med-003/ECG-12345/data/ecg
구독: wia-med-003/+/data/ecg (모든 기기의 ECG)

6.3.2 QoS 레벨 선택

토픽 QoS 이유
data/* 0 실시간 데이터, 다음 샘플이 곧 도착
alerts 1 중요하지만 중복 허용
control 2 정확히 한 번 실행 필요
info 1 + retained 새 구독자가 즉시 확인 필요

6.3.3 MQTT 보안

// TLS/SSL 연결
const mqttClient = mqtt.connect('mqtts://broker.example.com:8883', {
  ca: fs.readFileSync('ca.crt'),
  cert: fs.readFileSync('client.crt'),
  key: fs.readFileSync('client.key'),
  rejectUnauthorized: true
});

// 사용자 인증
const mqttClient = mqtt.connect('mqtts://broker.example.com:8883', {
  username: 'device-12345',
  password: generateDeviceToken(),  // 시간 제한 토큰
  clientId: 'ECG-12345'
});

// 토픽 ACL
// broker.conf:
acl:
  - pattern: wia-med-003/{clientid}/data/#
    access: write
  - pattern: wia-med-003/{clientid}/control
    access: read
  - pattern: wia-med-003/+/data/#
    access: read

6.4 WebSocket 프로토콜

6.4.1 WebSocket 서버 구현

// 서버 (Node.js + ws)
const WebSocket = require('ws');

const wss = new WebSocket.Server({
  port: 8080,
  verifyClient: (info, callback) => {
    // JWT 토큰 검증
    const token = new URL(info.req.url, 'ws://base').searchParams.get('token');
    jwt.verify(token, SECRET_KEY, (err, decoded) => {
      callback(!err, 200, 'OK');
    });
  }
});

wss.on('connection', (ws, req) => {
  const deviceId = new URL(req.url, 'ws://base').searchParams.get('deviceId');

  // 기기 스트림 시작
  const stream = startDeviceStream(deviceId);

  stream.on('data', (data) => {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify(data));
    }
  });

  ws.on('message', (message) => {
    const command = JSON.parse(message);
    handleCommand(stream, command);
  });

  ws.on('close', () => {
    stream.stop();
  });
});

6.4.2 WebSocket 클라이언트

// 브라우저 클라이언트
const token = await getAuthToken();
const ws = new WebSocket(`wss://api.example.com/stream?deviceId=ECG-12345&token=${token}`);

ws.onopen = () => {
  console.log('WebSocket 연결됨');

  // 스트림 시작 요청
  ws.send(JSON.stringify({
    command: 'start',
    signalType: 'ECG',
    samplingRate: 512
  }));
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);

  if (data.signalType === 'ECG') {
    updateECGChart(data);
  }
};

ws.onerror = (error) => {
  console.error('WebSocket 오류:', error);
};

ws.onclose = (event) => {
  console.log('WebSocket 닫힘:', event.code, event.reason);

  // 자동 재연결
  setTimeout(() => reconnect(), 5000);
};

// Ping/Pong으로 연결 유지
setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ type: 'ping' }));
  }
}, 30000);

6.5 프로토콜 선택 가이드

프로토콜 장점 단점 적합한 용도
Bluetooth LE 저전력, 근거리, 널리 지원됨 제한된 범위, 낮은 대역폭 웨어러블, 휴대용 기기
WiFi/TCP 높은 대역폭, 안정적 높은 전력 소모 가정용 모니터, 병원 기기
MQTT 경량, IoT 최적화, Pub/Sub 중앙 브로커 필요 원격 모니터링, 다중 기기
WebSocket 양방향, 브라우저 지원 방화벽 문제 가능 웹 대시보드, 원격의료

6.6 보안 및 암호화

6.6.1 종단간 암호화

// AES-256-GCM 암호화
const crypto = require('crypto');

function encryptData(data, key) {
  const iv = crypto.randomBytes(12);
  const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);

  let encrypted = cipher.update(JSON.stringify(data), 'utf8', 'hex');
  encrypted += cipher.final('hex');

  const authTag = cipher.getAuthTag();

  return {
    iv: iv.toString('hex'),
    data: encrypted,
    authTag: authTag.toString('hex')
  };
}

function decryptData(encryptedData, key) {
  const decipher = crypto.createDecipheriv(
    'aes-256-gcm',
    key,
    Buffer.from(encryptedData.iv, 'hex')
  );

  decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'hex'));

  let decrypted = decipher.update(encryptedData.data, 'hex', 'utf8');
  decrypted += decipher.final('utf8');

  return JSON.parse(decrypted);
}

6.6.2 인증 및 권한 부여

// OAuth 2.0 Device Flow
async function authenticateDevice(deviceId) {
  // 1. 기기 코드 요청
  const response = await fetch('https://auth.wialive.smilestory.ai/device/code', {
    method: 'POST',
    body: JSON.stringify({
      client_id: 'wia-med-003',
      scope: 'vital-signs:read vital-signs:write'
    })
  });

  const { device_code, user_code, verification_uri } = await response.json();

  // 2. 사용자에게 코드 표시
  displayUserCode(user_code, verification_uri);

  // 3. 폴링으로 토큰 대기
  const token = await pollForToken(device_code);

  return token;
}

// JWT 토큰 검증
function verifyToken(token) {
  try {
    const decoded = jwt.verify(token, PUBLIC_KEY, {
      algorithms: ['RS256'],
      issuer: 'https://auth.wialive.smilestory.ai',
      audience: 'wia-med-003'
    });

    return {
      valid: true,
      deviceId: decoded.sub,
      permissions: decoded.scope.split(' ')
    };
  } catch (error) {
    return { valid: false, error: error.message };
  }
}

6.6.3 의료 규정 준수

HIPAA 준수:

GDPR 준수:

// 감사 로그 예제
{
  "timestamp": "2025-01-15T10:30:00.000Z",
  "eventType": "data_access",
  "userId": "doctor-456",
  "patientId": "patient-123",
  "dataType": "ECG",
  "action": "view",
  "ipAddress": "192.168.1.100",
  "userAgent": "Mozilla/5.0...",
  "purpose": "medical_consultation",
  "consentId": "consent-789"
}

6.7 장 요약

[OK] 핵심 내용:

  1. Bluetooth LE: 웨어러블에 최적, GATT 서비스 정의
  2. WiFi/TCP: 높은 대역폭, 안정적 연결
  3. MQTT: IoT 최적화, Pub/Sub 모델
  4. WebSocket: 웹 실시간 통신, 양방향
  5. 프로토콜 선택: 용도에 따른 적절한 선택
  6. 보안: 종단간 암호화, 인증, 규정 준수

6.8 다음 장 미리보기

제7장에서는 Phase 4인 생태계 통합을 다룹니다. EHR/EMR, 원격의료, 클라우드 스토리지, AI/ML 분석 플랫폼과의 통합 방법을 학습합니다.


이전: 제5장 | 다음: 제7장 - Phase 4: 생태계 통합