데이터 형식과 JS·Arduino 호환성
JS와 Arduino의 지원 범위
데이터 없음(EMPTY), 문자열(TEXT), 바이너리(BINARY)는 JS와 Arduino가 함께 사용하는 기본 유형입니다. JS(Node.js와 browser)는 객체 하나나 여러 인자를 보내는 기능도 제공합니다.
JS의 signal(tag, ...args)는 인자 개수와 자료형을 인식하여 payload 유형을 자동으로 선택합니다. 수신 JS는 패킷의 유형값에 따라 데이터를 해석하고 (tag, ...args)로 핸들러에 전달합니다. 객체 하나는 객체 하나로, 여러 인자는 각각의 인자로 복원하므로 사용자가 유형 번호를 직접 지정하거나 수신 바이트를 파싱할 필요가 없습니다.
| 유형 | 보내는 데이터 | JS 지원 | Arduino 지원 |
|---|---|---|---|
| 0 EMPTY (데이터 없음) | 인자 없음 | 송신·수신 (payload 인자 생략) | 송신·수신 (길이 0) |
| 1 TEXT | 문자열 하나 | 송신·수신 | 송신·수신 |
| 2 BINARY | 바이너리 하나 | 송신·수신 | 송신·수신 |
| 3 OBJECT | 객체 또는 배열 하나 | 자동 선택·복원 | 기본 송신·자동 복원 없음 |
| 4 MJSON | 바이너리 없는 여러 인자 | 자동 선택·각 인자로 복원 | 문자열 2개 송신만 제공 |
| 5 MBA | 바이너리를 포함한 여러 인자 | 자동 선택·각 인자로 복원 | 기본 송신·자동 복원 없음 |
Arduino도 OBJECT/MJSON/MBA 메시지를 받을 수 있지만, 콜백에는 유형값·원시 바이트·길이가 전달됩니다. 객체나 여러 인자로 자동 복원하지 않으므로 앱에서 별도 JSON/MBP 파싱을 구현해야 합니다. 유형 enum이 정의되어 있다는 것과 고수준 송신·자동 복원 API를 지원한다는 것은 구분해야 합니다.
JS 송신 인자에 따른 선택 예시는 다음과 같습니다. 수신 인자는 태그 이름 이벤트나 직접 수신용 '@' 이벤트 핸들러에 전달되는 값입니다.
io.signal('room'); // EMPTY → (tag)
io.signal('room', 'hello'); // TEXT → (tag, 'hello')
io.signal('room', new Uint8Array([0, 255])); // BINARY → (tag, 바이너리)
io.signal('room', { value: 42 }); // OBJECT → (tag, { value: 42 })
io.signal('room', [1, 2]); // OBJECT → (tag, [1, 2])
io.signal('room', 'value', 42); // MJSON → (tag, 'value', 42)
io.signal('room', 'data', new Uint8Array([7])); // MBA → (tag, 'data', 바이너리)
인자 복원의 예외와 지원 범위는 다음과 같습니다.
- 숫자 하나는 TEXT로 변환됩니다.
signal('room', 42)의 수신값은 숫자42가 아니라 문자열'42'입니다. - 데이터 없음은
signal(tag)입니다. JS는 핸들러에tag만 전달합니다.(tag, payload)로 선언한 핸들러에서 생략된payload는undefined이며,(tag, ...args)의args는[]입니다.undefined를 두 번째 인자로 명시적으로 전달하는 방식이 아닙니다.signal(tag, null)은 OBJECT 유형으로 보내고 수신도(tag, null)이므로 EMPTY와 구별됩니다. Arduino는 기존대로payloadType = EMPTY,payloadSize = 0이며 이때 payload 바이트를 읽지 않습니다. - JS 호환성 안내: 2026-09-26 개발 소스에서 EMPTY 수신을
(tag, null)에서(tag)로 변경했습니다. 기존에payload === null로 EMPTY를 판별했다면payload === undefined또는args.length === 0으로 변경하세요. 명시적인 null 데이터 처리는 그대로 유지합니다. 패킷 형식과 Arduino 동작은 변경하지 않았으며, 공개 배포본 반영 여부는 사용하는 버전에서 확인해야 합니다. - 바이너리는 원시 바이트로 전달됩니다. 원래 TypedArray 생성자나 요소의 바이트 순서까지 자동 복원하는 것은 아닙니다.
- 복잡한 계층형 payload의 자동 복원은 지원 범위에 포함하지 않습니다. 단순 객체·배열과 평평한 인자 목록을 사용하고, 바이너리는 독립된 인자로 전달하세요. 중첩 JSON이 직렬화될 수 있다는 것과 내부 바이너리·사용자 정의 자료형까지 원형대로 복원된다는 것은 다릅니다.
- 바이너리 포함 여부는 최상위 인자에서 검사합니다.
{ data: buffer }는 OBJECT이며 내부 버퍼를 자동으로 분리하여 MBA로 전송하지 않습니다. OBJECT/MJSON에는 JSON으로 표현 가능한 데이터를 사용해야 합니다.
Arduino에는 다음과 같이 문자열 두 개를 MJSON으로 보내는 오버로드가 있습니다.
io.signal("room", "left", "right"); // MJSON → JS 수신: (tag, "left", "right")
2026-09-26 수정 소스에서는 이 오버로드가 따옴표·역슬래시와 개행·탭 등의 제어문자를 JSON 규칙에 맞게 이스케이프하고, 변환 후 길이로 버퍼를 할당합니다. 유효한 UTF-8 문자열은 JS에서 원래 문자열 두 개로 복원됩니다. C 문자열의 NUL은 입력 종료이므로 문자열 내부 NUL 데이터는 지원하지 않습니다. 이전 라이브러리는 escaping을 하지 않으므로 수정된 소스 또는 반영된 배포본을 사용해야 합니다. 반면 JSON 모양의 문자열 하나를 보내는 signal(tag, jsonText)는 OBJECT가 아닌 TEXT이며, 수신 앱에서 JSON으로 해석하려면 별도 파싱이 필요합니다.
버전 차이
호환성과 검증 기록을 함께 확인하세요. JS 7.2.0에서 EMPTY와 명시적 null은 구별됩니다. Arduino 과거 배포본의 반영 여부는 사용하는 라이브러리 버전과 소스로 확인하세요.