SPINON

스피논 / JavaScript API 대응 명세

같은 JavaScript, 다른 실행 환경

V8이 JavaScript 언어를 실행하는 것과 브라우저 API가 존재하는 것은 별개입니다. 스피논이 직접 제공할 함수, 모바일에서 달라지는 동작, 모바일 전용 함수와 초기 제외 항목을 분리합니다.

판정 원칙 · 같은 이름을 노출할 때에는 반환값뿐 아니라 오류, 취소, 이벤트 순서, 백그라운드 동작을 정의합니다. 그 계약을 맞출 수 없으면 웹 API를 흉내 내지 않고 @spinon/platform의 명시적 API로 제공합니다. 실제 조사·구현 진행은 공식 JS API 구현 체크리스트에서 관리합니다.

01 · 언어 엔진 기능

V8에 포함되는 영역

앱에 포함한 V8 버전과 빌드 옵션을 고정한 뒤 확인합니다. 언어 기능의 존재만으로 타이머·네트워크·DOM이 생기지는 않습니다.

API·문법·객체웹과의 관계스피논 계약상태
Promise Map SetECMAScript 언어 객체선택한 V8 빌드에서 제공. 비동기 작업을 돌릴 마이크로태스크 체크포인트는 스피논 호스트가 정합니다.엔진 검증
JSON ArrayBuffer TypedArray언어 수준 데이터 기능JS 객체와 Rust·C++ 경계를 넘을 때 복사·소유권·크기 제한은 별도 계약으로 둡니다.엔진 검증
Intl Date언어 기능이지만 로케일·시간대 데이터에 영향V8/ICU 빌드, OS 시간대와 언어 데이터를 고정해 실제 결과를 비교합니다.조건 검증
globalThisECMAScript 전역 객체 참조전역 객체 자체는 언어 기능입니다. 여기에 어떤 웹식 API를 설치할지는 스피논 호스트 계약으로 구분합니다.엔진 검증

02 · 스피논이 제공할 API

V8 기본 기능이 아님

웹과 같은 이름을 목표로 하지만 구현은 스피논 호스트에 둡니다. 첫 수직 구현에 필요한 최소 기능부터 제공합니다.

API·문법·객체웹에서의 용도스피논 구현·검증 조건첫 목표
setTimeout clearTimeout지연 작업·취소호스트 스케줄러와 JS 이벤트 루프에 연결. 취소 후 콜백 수명과 앱 중단 시 동작을 검증합니다.수직 구현
queueMicrotask현재 작업 뒤의 미세 작업V8 마이크로태스크 큐와 호스트 콜백 경계의 실행 순서를 고정합니다.수직 구현
URL URLSearchParams주소 파싱·조합표준 형태를 목표로 하며 상대 URL의 기준 주소를 모바일 앱에서 명시합니다.도구 확장
TextEncoder TextDecoder문자열·바이트 변환지원 인코딩·오류 동작을 웹과 비교해 호스트 또는 폴리필로 제공합니다.도구 확장
AbortController비동기 작업 취소 신호fetch와 다른 호스트 호출이 취소를 어느 시점에 반영하는지 명시합니다.도구 확장
console로그·오류 조사출력 대상, 오류 스택, 릴리스 로그 정책은 호스트가 정합니다.수직 구현
Blob File FormData바이너리 데이터·업로드메모리 한도, 파일 핸들 수명, fetch 본문·스트림 연동을 정한 뒤 제공하며 초기 존재를 가정하지 않습니다.후속 단계
crypto.getRandomValues() crypto.randomUUID()안전한 난수·식별자OS 난수원을 연결하고 실패 및 백그라운드 동작을 검증합니다. V8 언어 엔진만으로 자동 제공되지 않습니다.도구 확장

03 · 모바일 DOM 호환 façade

제한된 API 제안

모바일의 주 화면은 Rust가 소유하는 UI 트리를 GPU로 그립니다. 일부 DOM 호출 형태를 그 트리에 연결하는 제안이며, 브라우저 DOM 전체나 react-dom 호환을 뜻하지 않습니다. 후보 API와 미정 계약은 공식 DOM 호환 명세를 기준으로 합니다.

API·문법·객체웹에서의 용도스피논 구현·검증 조건상태
document.createElement() document.createTextNode()
appendChild() insertBefore() removeChild()
노드를 만들고 트리에 삽입·이동·제거지원 노드 종류, 태그 이름 대소문자·잘못된 이름 예외, 문서 소속, 기존 부모에서 이동, insertBefore(node, null), 삽입·제거 반환값을 정합니다. 순환·잘못된 참조는 동기 DOMException으로 알리고 실패 시 트리를 보존해야 합니다. 노드 ID·JS wrapper 수명, 앱 루트와 GPU 연결, 프레임워크가 소유한 하위 트리에 직접 DOM 쓰기를 허용할지는 미정입니다.제안 · 계약 미정
nodeType nodeName
parentNode firstChild nextSibling
textContent Text.data nodeValue
노드 종류·관계·텍스트 조회와 변경textContent·Text.data의 getter/setter, 노드 종류별 nodeValue, 노드 이름·종류 상수, 분리된 노드의 수명을 정합니다. 동기 변경 직후 JS는 최신 논리 트리를 읽고 렌더러는 일관된 커밋 revision만 읽어야 합니다.제안 · 계약 미정
getAttribute() setAttribute() removeAttribute()
id className
기본 속성 읽기·쓰기인수 변환, 속성 이름 대소문자, id/className과 id/class 속성의 반영 관계를 정합니다. 값 변경에 따른 선택자 재평가도 계약 대상입니다. style 속성과 CSSOM은 별도 계약 전까지 지원으로 간주하지 않습니다.제안 · 계약 미정
childNodes children
NodeList HTMLCollection classList
자식 컬렉션과 클래스 토큰 조작라이브·정적 여부, 인덱스·반복 규칙, 클래스 토큰 검증과 toggle()의 인수·반환값이 정해지기 전까지 자동 포함하지 않습니다.별도 계약
document.body document.documentElement
getElementById() querySelector(All)
문서 루트와 노드 검색브라우저 페이지 루트를 그대로 제공하지 않습니다. 앱 표시 루트, 선택자 문법·검색 범위·결과 컬렉션을 별도로 정하기 전까지 첫 단계에서 제외하는 제안입니다.첫 단계 제외 제안
addEventListener() removeEventListener()
dispatchEvent() Event
DOM 이벤트 등록·제거·전파·취소이벤트 대상·revision, 전파·캡처 순서, stopPropagation()·preventDefault(), 포인터 취소와 키보드·접근성 활성화를 정해야 합니다. 노드 제거 또는 오래된 이벤트가 도착할 때 콜백을 해제·폐기하는 시점도 미정입니다.별도 계약
getBoundingClientRect() getComputedStyle()레이아웃·계산 스타일 조회레이아웃 동기화, 캐시된 값, 읽기 비용과 반환값의 유효 시점을 정하기 전까지 미정입니다.미정
ShadowRoot customElements MutationObserver
Range Selection iframe
브라우저 문서·커스텀 요소·관찰·선택·중첩 문맥DOM façade의 기본 범위로 약속하지 않습니다. 각 기능의 별도 제품 범위와 동작 계약이 생기기 전까지 지원을 주장하지 않습니다.범위 외 제안
innerHTML outerHTML DOMParserHTML 문자열 파싱·직렬화HTML 파서와 입력 보안 계약이 없으므로 첫 단계에서 제외하는 제안입니다.첫 단계 제외 제안

04 · 이름은 같고 동작은 다름

호환성 차이를 공개

같은 소스가 컴파일되어도 브라우저의 출처·문서·탭 수명주기와 모바일 앱의 권한·백그라운드 규칙은 다릅니다.

API·문법·객체차이의 원인스피논에서 정할 계약첫 목표
fetch()
Request Response Headers
AbortSignal
브라우저 출처·CORS·쿠키·캐시와 앱 네트워크 권한·수명주기가 다릅니다.V8만으로 제공되지 않는 호스트 API 제안입니다. 상대 URL 기준, Request 생성·검증, RequestInit의 최소 필드(method·headers·body·credentials·redirect 등), 요청 본문 형식, Headers 조회·수정·반복, Response.status/ok·헤더·본문 읽기 메서드(예: text()·json()·arrayBuffer()·blob()·formData())와 ReadableStream 여부는 모두 범위 미정입니다. 버전 있는 NetworkHost에서 캐시·리다이렉트·쿠키·TLS·취소·CORS/출처·앱 백그라운드 동작을 정합니다. HTTP 비성공 응답은 Response로, 전송 실패·취소는 별도로 처리합니다. 비동기 결과는 Isolate 소유 실행 경로에 보내고 V8 마이크로태스크 규칙을 따릅니다. 네트워크 스레드는 V8을 직접 만지지 않으며, Isolate 종료·앱 재시작·OTA 교체 시 취소·결과 폐기/거부·콜백 해제와 UI 비차단을 검증해야 합니다. 자세한 경계는 Fetch 호스트 명세를 따릅니다.제안 · 범위 미정
정적 import
import() import.meta
웹 브라우저는 URL 모듈 그래프를 읽습니다. 모바일 첫 수직 구현은 정적 모듈을 단일 번들로 묶고, 이후 청크 그래프로 확장하는 계획입니다.정적 import는 첫 단일 번들에서 번들러가 해결합니다. 청크 그래프의 ESM 로딩과 동적 import(), import.meta 값은 별도 런타임 관문입니다. 활성 매니페스트 밖의 청크를 거부하고 누락·호환 버전 오류를 정의해야 하며 현재 지원으로 간주하지 않습니다. OTA 스냅샷은 앱 재시작에서 바꾸며 실행 중 모듈 교체를 뜻하지 않습니다. HMR·Fast Refresh는 개발 도구 계약으로 분리합니다. 자세한 내용은 실행·빌드·배포 명세를 따릅니다.런타임 계약 미정
WebSocket EventSource연결 유지·재연결이 앱 백그라운드 정책과 충돌할 수 있습니다.첫 목표 범위에는 포함하지 않습니다. 연결 상태, 인증, 중단·재개, 배터리 비용을 별도 명세한 뒤 판정합니다.첫 단계 제외 제안
requestAnimationFrame() cancelAnimationFrame()브라우저 문서 프레임 대신 모바일 GPU 표면의 프레임을 사용합니다.표시 주기, 콜백 시각, 취소 시점, 화면이 가려지거나 앱이 백그라운드일 때의 중단 규칙을 정합니다.렌더러
setInterval() clearInterval()앱 수명주기와 절전 정책에 따라 정지·지연될 수 있습니다.백그라운드에서 실행을 보장하지 않으며 취소와 재개 시 누락된 틱 처리를 정의합니다.도구 확장
performance.now()브라우저의 시간 원점과 앱 프로세스 수명이 다릅니다.단조 시계의 원점·정밀도·앱 재개 후 연속성을 기록합니다. 벤치마크에는 플랫폼 계측도 함께 씁니다.계측
스토리지 API
localStorage sessionStorage
브라우저 출처·탭 단위 저장과 앱 설치·사용자 데이터 수명이 다릅니다.동기 브라우저 저장소 전역을 그대로 복제하지 않고 비동기 저장소 계약, 범위, 용량, 암호화와 삭제 정책을 설계합니다.도구 확장

05 · 모바일 전용 API

명시적 모듈 제안

아래 이름은 @spinon/platform의 API 형태 제안입니다. 웹 빌드에서는 지원 여부를 확인하는 대체 구현 또는 명시적 실패를 제공합니다. 실제 서명은 구현 전에 확정합니다.

제안 함수필요한 이유계약에 포함할 조건첫 목표
getSafeAreaInsets()노치·상태 막대·제스처 영역화면 회전과 창 크기 변경 시 값 갱신, CSS 안전 영역과의 관계실사용 UI
onAppStateChange()전경·백그라운드·복귀 처리구독 해제, 이벤트 순서, 일시 중단된 JS 작업의 재개수직 구현+
onBackPress()Android 시스템 뒤로 가기라우터에 이전 방문 항목이 있는지 먼저 확인하고, 루트 화면의 동작은 플랫폼 정책으로 명시합니다. iOS·웹은 각각의 뒤로 가기 입력에 연결합니다.실사용 UI
dismissKeyboard()모바일 소프트 키보드 제어IME 조합 중 취소·확정, 포커스 이동과 이벤트 순서실사용 UI
requestPermission()카메라·사진·위치 등 OS 권한권한 종류, 거절·재요청·설정 이동, 플랫폼별 상태 차이플랫폼 기능
hapticFeedback()진동·촉각 반응기기 지원 여부와 강도 차이, 무음/절전 상태플랫폼 기능
openExternalURL()앱 밖의 링크·딥링크 열기허용 스킴, 실패 결과, 앱 복귀와 보안 정책실사용 UI

06 · 제외·미검토 API

영구 미지원 판정은 아님

첫 단계 제외 제안과 현재 명세에서 아직 범위를 정하지 않은 API를 함께 기록하되 상태를 구분합니다. 미검토는 지원도 제외도 확정하지 않은 상태입니다. 이름만 있는 빈 함수를 만들지 않으며, 제외 항목은 빌드 진단 또는 실행 시 명시적 오류로 알립니다. 제한 DOM façade의 후보와 미정 기능은 공식 DOM 호환 명세를 확인하세요.

API·문법·객체초기 제외·미검토 이유앱에서의 대안후속 판단
document.body document.documentElement모바일 문서의 표시 루트와 앱 GPU 표면 연결 방식이 아직 정해지지 않았습니다.앱 루트 연결 계약을 정한 뒤 DOM 호환 명세에 추가합니다.미정
getElementById() querySelector() querySelectorAll()선택자 범위와 문법, 결과 컬렉션의 동작이 첫 API 후보에 포함되지 않았습니다.프레임워크 상태 갱신 또는 직접 보유한 노드 참조를 사용합니다.별도 계약
childNodes children NodeList HTMLCollection classList컬렉션의 라이브 여부·반복 계약과 클래스 토큰 메서드가 아직 정해지지 않았습니다.별도 동작 계약과 적합성 사례를 정한 뒤 추가합니다.별도 계약
addEventListener() removeEventListener() dispatchEvent() EventDOM 이벤트 전파·캡처·취소·기본 동작과 콜백 수명이 아직 확정되지 않았습니다.첫 목표에서는 프레임워크별 이벤트 문법을 사용합니다.별도 계약
getBoundingClientRect() getComputedStyle()동기 레이아웃 계산 또는 캐시 조회의 시점·비용·값 유효성이 정의되지 않았습니다.레이아웃과 JS 실행 경계의 계약을 정한 뒤 판정합니다.미정
ShadowRoot customElements MutationObserver Range Selection iframe별도 브라우저·DOM 기능 계약이 필요합니다.각 기능의 제품 범위가 정해지기 전까지 DOM façade 지원에 포함하지 않습니다.범위 외 제안
innerHTML outerHTML DOMParserHTML 문자열 파싱과 입력 보안 계약이 없습니다.프레임워크 상태 갱신이나 명시적 노드 API 후보를 사용합니다.첫 단계 제외 제안
window (브라우저 전역) window.open()
location history
브라우저의 페이지·탭 전역과 문서 탐색 모델이 모바일 앱에 그대로 존재하지 않습니다.선택형 스피논 라우터의 위치·push·replace·back 계약과 openExternalURL()을 사용합니다. ECMAScript 전역 객체인 globalThis는 브라우저 window 호환을 뜻하지 않습니다.별도 계약
navigator.serviceWorker브라우저 Service Worker의 등록 범위·수명·Cache API 계약을 제공하지 않습니다.OTA는 앱 JS API가 아니라 런타임·CLI 배포 경로입니다. 서명·해시·호스트 호환성을 검증하고 한 릴리스 스냅샷을 원자적으로 활성화하며, 기본 적용은 앱 시작 또는 안전한 재시작입니다. 실패 시 이전 스냅샷으로 롤백합니다. 서명 형식은 미정입니다. 실행·빌드·배포 명세를 따릅니다.브라우저 API 제외
navigator.mediaDevices브라우저 미디어 권한과 앱 OS 권한 계약이 다릅니다.명시적 카메라·마이크 플랫폼 컴포넌트플랫폼 기능
Node.js fs process Buffer setImmediate앱 런타임은 Node.js가 아닙니다. setImmediate는 일부 패키지가 Node 경로를 선택하게 할 수 있습니다.파일 선택·저장소 등 스피논 플랫폼 API. React 스케줄러 의존성은 Node 전역을 무조건 추가하지 않고 실제 번들 경로로 확인합니다.후속 검토
navigator.gpu / 브라우저 WebGPU스피논 내부 GPU 렌더러가 WebGPU의 앱 공개 API를 뜻하지 않습니다.공개 GPU API는 독립 제안으로 검토후속 검토
Worker SharedWorker BroadcastChannel분리된 JS 실행 문맥과 메시지·전송 규약이 아직 없습니다.메인 JS 실행 문맥에만 의존하는 초기 범위로 한정하고 병렬 JS는 별도 설계합니다.후속 검토
MessageChannel MessagePort
requestIdleCallback() cancelIdleCallback()
작업 큐와 유휴 시간 예약 API입니다. React scheduler 원본은 먼저 setImmediate를 확인하고, 없으면 DOM/Worker 경로에서 MessageChannel, 마지막으로 타이머를 선택합니다. 시계는 performance.now가 있으면 이를 사용합니다. React Native 또는 모바일 번들러가 어떤 경로를 선택할지는 별도 확인이 필요합니다.프레임워크 지원에 필요한 최소 작업 큐 계약만 조사합니다. 이를 추가해도 Worker·SharedWorker 지원을 뜻하지 않으며, 유휴 콜백의 백그라운드 보장도 약속하지 않습니다.미검토
canvas OffscreenCanvas WebGL내부 GPU 표면만으로 웹의 Canvas 객체·명령 모델이 생기지 않습니다.일반 HTML 태그 또는 전역 API로 노출하지 않고 별도 그래픽 API를 검토합니다.후속 검토
XMLHttpRequestfetch()와 다른 콜백·업로드 진행률·응답 형식·이벤트 계약이 있습니다.현재 Fetch 제안이 XHR을 대체하거나 XHR 기반 라이브러리를 지원한다는 뜻은 아닙니다. 사용 라이브러리 요구를 확인해 별도 어댑터/API 범위를 정합니다.미검토
ResizeObserver IntersectionObserver레이아웃 결과와 GPU 프레임 사이의 관찰 시점·콜백 순서가 정해지지 않았습니다.필요한 라이브러리를 확인한 뒤 레이아웃 revision·화면 가시성·해제 규칙을 별도 계약으로 정합니다.미검토
navigator.geolocation navigator.clipboard navigator.share위치 권한·좌표 조회, 시스템 클립보드, 공유 시트는 서로 다른 OS 권한·수명주기 계약이 필요합니다.requestPermission()은 권한 요청만 나타내며 위치 읽기·구독을 제공하지 않습니다. 세 기능 모두 현재 API 제안에 포함되지 않았습니다.미검토

호환성 표의 단위

함수마다 웹·Android·iOS의 존재 여부, 입력과 반환값, 오류, 취소, 권한, 백그라운드 동작을 기록합니다. fetch()처럼 같은 이름을 쓸 때에는 차이를 문서화하고, 동작이 크게 다르면 플랫폼 API로 분리합니다.

JSI와 사용자 확장 경계

V8을 연결하는 엔진 내부 어댑터는 필요하지만 React Native의 JSI를 가져오거나 V8 핸들을 앱 API로 공개할 필요는 없습니다. 앱에서 자체 Kotlin·Swift·Rust·C++ 기능을 JS로 쓰게 하려면 별도의 버전 있는 플랫폼 모듈 계약이 필요합니다. JS 타입 선언, 빌드 시 연결, 플랫폼 구현 등록, 비동기 오류·취소, 권한, 스레드와 객체 수명을 계약하고 일반 데이터 전달과 고용량 zero-copy 자원 경로를 분리합니다. 이 기능은 아직 지원되지 않으며 J15 사용자 정의 네이티브 모듈 작업에서 추적합니다.

현재 검증 상태

기존 V8 동적 트리 PoC는 JS 호출과 이벤트 연결을 확인한 자료입니다. 이 문서의 제한 DOM façade, fetch(), 타이머, 저장소, 모바일 전용 함수가 실제 앱에서 동작한다는 증거는 아닙니다. 먼저 작은 카운터 앱에 필요한 타이머·마이크로태스크 계약을 구현합니다. 기준 자료: V8 임베딩 문서, DOM 표준, Fetch 표준.