WIA-ROB-011의 네 단계는 앞 단계를 기반으로 다음 단계가 쌓이는 구조이므로, 구현도 같은 순서로 진행하는 것이 자연스럽다. 제3장의 준수 수준과 연결하면 다음과 같다.
| 순서 | 구현 대상 | 달성 준수 수준 | 참조 장 |
|---|---|---|---|
| 0 | 현황 분석: 기존 데이터·API와 명세의 차이 파악 | - | 제3장 |
| 1 | 1단계 JSON-LD 데이터 형식과 유효성 검증 | 기본 | 제4장 |
| 2 | 2단계 REST·WebSocket API, 인증, 속도 제한 | 표준 | 제5장 |
| 3 | 3단계 MQTT, TLS 1.3, mDNS, OTA | 고급(일부) | 제6장 |
| 4 | 4단계 스마트 홈·로봇군·클라우드 통합 | 고급 | 제7장 |
| 5 | 적합성 시험과 인증 신청 | - | 이 장 |
각 단계에 걸리는 기간은 기존 제품의 구조와 팀 규모에 따라 크게 달라지므로 이 책에서는 제시하지 않는다.
WIA가 제공하는 출발점은 WIA-Official GitHub 조직의 공개 저장소(wia-standards-public)의 cleaning-robot 디렉터리다.
| 경로 | 내용 |
|---|---|
spec/ | PHASE-1~4 명세 문서 |
api/typescript/ | TypeScript SDK 골격(WiaCleaningRobot 클래스, 1단계 타입 정의) |
cli/ | 요청/응답 계약을 보여 주는 POSIX 셸 클라이언트 |
simulator/ | 브라우저 기반 시뮬레이터 |
git clone https://github.com/WIA-Official/wia-standards-public.git cd wia-standards-public/cleaning-robot/api/typescript
이 밖에 JSON Schema 검증기, MQTT 브로커, TLS 1.3을 지원하는 HTTP 서버 등 일반적인 개발 도구가 필요하다. 명세는 특정 라이브러리를 요구하지 않는다.
1단계 형식을 코드로 옮길 때는 명세의 열거값과 단위를 타입 수준에서 강제하는 것이 좋다. 다음은 RobotState의 일부를 TypeScript로 표현한 예다.
type RobotMode = 'idle' | 'cleaning' | 'charging' | 'returning' | 'error';
type CleaningMode = 'auto' | 'spot' | 'edge' | 'zigzag' | 'spiral';
interface RobotState {
'@context': 'https://wiastandards.com/rob-011/v1';
'@type': 'RobotState';
timestamp: string; // ISO 8601, 시간대 포함
battery: { percentage: number; voltage: number; current: number;
temperature: number; health: number; cycleCount: number };
pose: { x: number; y: number; theta: number; floor: number; confidence: number };
mode: RobotMode;
cleaningMode: CleaningMode;
suctionPower: number; // 0-100
[extension: `x_${string}`]: unknown; // 제조사 확장 필드
}
function toWiaState(internal: InternalState): RobotState {
return {
'@context': 'https://wiastandards.com/rob-011/v1',
'@type': 'RobotState',
timestamp: new Date().toISOString(),
battery: { ...internal.battery },
pose: { x: internal.xMm / 1000, y: internal.yMm / 1000, // mm → m (SI 단위)
theta: internal.headingDeg * Math.PI / 180, // 도 → 라디안
floor: internal.floor, confidence: internal.locConfidence },
mode: internal.mode,
cleaningMode: internal.cleaningMode,
suctionPower: internal.suction
};
}
예시의 toWiaState처럼 기존 내부 형식을 표준 형식으로 바꾸는 변환 계층을 두면, 로봇 펌웨어 내부 구조를 크게 바꾸지 않고도 1단계를 준수할 수 있다. 제3장 3.4절의 "로봇 추상화 계층"이 바로 이 역할을 한다.
다음은 Node.js의 Express 프레임워크로 2단계의 청소 시작 엔드포인트를 구현한 예다. 경로, 오류 형식, 속도 제한은 모두 제5장의 명세를 따른다.
import express from 'express';
import rateLimit from 'express-rate-limit';
const app = express();
const api = express.Router();
api.use(rateLimit({ windowMs: 60_000, limit: 100 })); // IP당 분당 100회, 초과 시 429
api.use(requireBearerJwt); // Authorization: Bearer {token}
function wiaError(res: express.Response, status: number, code: string, message: string) {
return res.status(status).json({
error: { code, message, details: {}, timestamp: new Date().toISOString() }
});
}
api.post('/robot/clean', express.json(), async (req, res) => {
if (robot.mode === 'cleaning') return wiaError(res, 409, 'ROBOT_BUSY', 'Robot is currently cleaning');
if (robot.battery.percentage < 15) return wiaError(res, 409, 'LOW_BATTERY', 'Battery too low for operation');
const { mode = 'auto', rooms, powerLevel } = req.body;
const session = await robot.startCleaning({ mode, rooms, powerLevel });
res.json({ sessionId: session.id, status: 'started', estimatedDuration: session.estimate });
});
app.use('/api/v1', api);
예시에서 HTTP 상태 코드(409)와 배터리 기준값(15%)은 구현자가 정하는 값으로, 명세가 규정한 것이 아니다. 명세가 규정하는 것은 오류 코드 이름과 오류 응답 형식, 그리고 속도 제한 초과 시의 HTTP 429다.
import { WebSocketServer, WebSocket } from 'ws';
const wss = new WebSocketServer({ server: httpsServer, path: '/ws' });
const subscriptions = new Map<WebSocket, Set<string>>();
wss.on('connection', (ws) => {
subscriptions.set(ws, new Set());
ws.on('message', (raw) => {
const msg = JSON.parse(raw.toString());
if (msg.type === 'subscribe') subscriptions.get(ws)!.add(msg.channel);
if (msg.type === 'unsubscribe') subscriptions.get(ws)!.delete(msg.channel);
});
ws.on('close', () => subscriptions.delete(ws));
});
function publish(channel: 'status' | 'sensors' | 'map' | 'logs', data: object): void {
const frame = JSON.stringify({ type: 'event', channel, timestamp: new Date().toISOString(), data });
for (const [ws, channels] of subscriptions) {
if (channels.has(channel)) ws.send(frame);
}
}
명세의 WebSocket 속도 제한(초당 10개 메시지)은 클라이언트가 보내는 메시지에 적용해야 하며, 로봇이 보내는 이벤트도 구독 요청의 interval을 존중해 과도하게 보내지 않도록 한다.
wia/rob/{robot_id}/... 토픽을 사용하고, 상태는 QoS 0, 명령은 QoS 1, 중요 경보는 QoS 2로 발행·구독한다._wia-rob._tcp 서비스를 광고하고, OTA 업데이트에는 SHA-256 검증과 A/B 파티션 롤백을 구현한다.변환 계층이 명세의 유효성 규칙(ISO 8601 시각, SI 단위, UUID v4, 열거값 일치, 필수 필드 비-null)을 지키는지 검사한다.
test('pose는 미터와 라디안으로 변환된다', () => {
const s = toWiaState(sampleInternal({ xMm: 2500, headingDeg: 90 }));
expect(s.pose.x).toBe(2.5);
expect(s.pose.theta).toBeCloseTo(1.5708, 4);
expect(s.timestamp).toMatch(/Z$|[+-]\d\d:\d\d$/); // 시간대 포함
});
명세와 함께 공개되는 테스트 벡터는 요청·응답 쌍의 표준 집합이다. Tier 2 이상을 주장하려면 모든 테스트 벡터를 요청 직렬화와 응답 역직렬화 양방향으로 통과하고, 어떤 벡터를 시험했는지 밝힌 서명된 보고서를 공개해야 한다. 테스트 벡터는 명세 문서와 별도로 버전이 관리된다.
실제 로봇 또는 시뮬레이터를 대상으로 인증 → 청소 시작 → WebSocket 상태 수신 → 정지 → 이력 조회의 전체 흐름을 시험하고, 속도 제한 초과 시 HTTP 429가 반환되는지, TLS 1.2 연결이 거부되는지도 확인한다.
4단계 명세가 정한 인증 절차는 다섯 단계다(제3장 3.8절).
인증 후에는 매년 보안 감사를 받아야 한다(3단계 명세 10.2절). 또한 적합성 등급(Tier)에 따라 감사 주기가 정해져 있다. Tier 1은 연 1회 자체 검토, Tier 2는 24개월마다, Tier 3은 12개월마다 감사를 받는다. 등급은 OpenAPI의 info.x-wia-tier 확장 필드와 공개 인증 페이지에 밝히고, 등급이 내려가면 30일 이내에 WIA 레지스트리에 보고한다.
비용과 유효 기간: WIA는 이 책을 쓰는 시점에 인증 수수료, 시험 항목 수, 인증 유효 기간, 갱신 비용을 명세에 공개하지 않았다. 이러한 조건은 인증을 신청할 때 WIA에 직접 확인해야 한다.
@context와 @type이 있는가x_ 접두사를 붙였는가@version과 schemaVersion을 포함하는가/api/v1 아래에 /robot/status, /robot/clean, /robot/stop, /robot/dock, /robot/map, /robot/history, /robot/schedule을 제공하는가POST /auth/token과 Bearer 토큰 인증을 구현했는가error.code·message·details·timestamp 형식과 표준 오류 코드를 따르는가limit(최대 100)·offset·sort·order를 지원하는가wia/rob/{robot_id}/... 구조와 QoS 규칙(0/1/2)을 따르는가_wia-rob._tcp 광고와 TXT 레코드를 제공하는가/fleet/...)와 구역 할당 형식을 지원하는가GET /health, GET /robot/metrics, GET /diagnostics/logs로 로봇 상태를 관찰한다. 명세 부속서는 지연 시간 p95, 오류율, 위반 시간을 담은 월간 오류 예산 요약 공개를 권장한다(SHOULD).명세 부속서 D는 스키마 버전 관리 정책, 개인정보 보호형 집계, 다국어 오류 메시지 목록, 장기 보존, 지속가능성 공시를 향후 검토 과제로 든다. 이 과제들에는 확정된 일정이 없으며, 공개 논의를 거쳐 규범으로 승격될 수 있다.
WIA-ROB-011은 청소 로봇이 제조사와 플랫폼의 경계를 넘어 함께 일하도록 하는 공통 언어다. 데이터 형식에서 시작해 API, 통신 프로토콜, 시스템 통합으로 한 단계씩 나아가면, 기존 제품도 무리 없이 표준을 받아들일 수 있다. 이것이 弘益人間, 곧 청소 자동화의 혜택을 더 많은 사람에게 넓히는 길이다.
/api/v1/robot/..., error.code, 분당 100회) 구현한다