Cocos Creator 지원
상태: 스펙 — 구현 전. 결정 2개에 권고안이 있고, 확인 항목이 §4입니다
결론부터 적습니다. 새 타깃을 만들지 않습니다. Creator의 게임 코드는 TypeScript이므로
소비 경로는 이미 있는 typescript 타깃입니다. 부족한 것은 파일 바이트를 어디서 가져올지
갈아끼울 이음매입니다.
다만 이음매를 추가하는 것으로 끝나지 않습니다. 생성된 TypeScript가 Node를 전제하고 있어서, 이 지원의 본체는 그 전제를 걷어내는 일입니다(§3). 그리고 그것은 Creator만을 위한 작업이 아닙니다 — 브라우저·Deno·번들러가 전부 같은 자리에 걸립니다.
1. 대상
| 대상 | 상태 |
|---|---|
| Cocos Creator 3.x | 현행. 이 문서의 대상입니다. 웹 빌드와 네이티브 빌드가 같은 TypeScript를 씁니다 |
| Cocos Creator 2.x | 스크립트가 JavaScript이고 자산 로딩 API가 다릅니다. 포함할지는 §7의 미결정 항목입니다 |
| Cocos Studio | 지원하지 않습니다. 2016년 4월에 지원이 종료되어 Creator로 대체되었고, 그 구성품 중 표 데이터를 다루던 Data Editor는 이 도구와 기능이 중복됩니다. 남은 .csd·.csb는 UI·씬·애니메이션 데이터이므로 표가 아닙니다 |
2. 범위 — 바뀌지 않는 것
| 무엇 | 상태 |
|---|---|
| 와이어 형식(v106)·변환기·익스포터 | 무변경. 리더가 바이트를 어디서 받는지만 달라집니다 |
| 새 타깃 | 없습니다. typescript 그대로이고 recipe에 Type이 추가되지 않습니다 |
| 코어의 엔진 이름 | 없습니다. 훅은 「이름을 받아 바이트를 돌려주는 함수」이고, cocos라는 낱말은 문서와 예제에만 나타납니다(CLAUDE.md의 규칙) |
| 다른 언어 | 무변경. §3은 typescript 타깃 안에서 끝납니다 |
| 골든 트리 | 움직입니다. 골든 시나리오에 typescript가 포함되므로, 생성물의 import가 바뀌면 골든 diff가 발생합니다. 동작 보존 리팩터링이 아니라 의도된 변경이고, 그 diff가 리뷰 대상입니다 |
3. 결정 1 — TypeScript 생성물의 Node 전제 제거
3.1 측정된 사실 3개
| 번호 | 사실 | 자리 |
|---|---|---|
| ① | 모든 테이블 모듈이 fs를 무조건 import합니다. 사용은 메서드 안이지만 import는 파일 최상단에 있어, 번들러가 빌드 시점에 그 모듈을 해석합니다 | ts-table.sbn:13 |
| ② | 접근자가 path를 import하고 경로 조립에 씁니다 | ts-tables-set.sbn:3 |
| ③ | 접근자의 공개 읽기 3개가 전부 경로 기반이고, 로드를 게시하는 publish와 solveCrossReferences가 private입니다 | ts-tables-set.sbn:120·135 |
③의 결과가 이 절의 핵심입니다. 엔진이 바이트를 공급하는 방식으로는 전량 로드와 참조
연결에 도달할 방법이 없습니다. 테이블에 readBinaryFrom(Uint8Array)가 있으나
(ts-table.sbn:364) 그것은 테이블 하나짜리 경로이고,
참조는 모든 테이블이 메모리에 있어야 연결됩니다.
문서가 이미 이 자리를 가리키고 있으나 안내가 성립하지 않습니다.
typescript.md의 트러블슈팅은 「브라우저에서는
readBinaryFrom(bytes)를 쓰세요」로 안내하는데, 그 경로로는 참조가 연결되지 않습니다.
①도 함께 걸립니다 — 바이트를 직접 넘기더라도 fs import는 파일에 남아 있습니다.
3.2 결정
| 번호 | 무엇 | 이유 |
|---|---|---|
| A | 바이트 로더 훅 — 접근자의 정적 필드 하나. 이름을 받아 바이트를 돌려주는 비동기 함수이고, 기본값은 지금의 fs 구현입니다 | C#의 ReadAllBytesAsync와 같은 형태입니다. 언어마다 다른 설명이 되지 않는 것이 이 선택의 값입니다 |
| B | 전량 로드의 바이트 진입점 1개 — 로더를 거쳐 모든 테이블을 읽고 publish까지 가는 공개 메서드 | ③의 해결입니다. private을 공개로 바꾸는 것이 아니라, 부분 로드를 노출하지 않으면서 전량 로드만 열어 두는 쪽입니다 — 참조가 연결되지 않은 상태를 소비 코드가 볼 수 없어야 합니다 |
| C | fs·path 의존을 로더 기본값 한 곳으로 격리 — 테이블 모듈에서 import를 제거하고, 경로 조립도 그쪽으로 | ①·②의 해결입니다. 번들러가 해석할 Node 모듈이 생성물에 남지 않는 것이 목표이므로, 기본값 자신도 지연 로드가 되어야 합니다 |
Creator에서의 사용은 다음과 같은 형태가 됩니다. API 이름은 §4의 확인 항목입니다.
GameData.readBytesAsync = async (name: string) => {
const asset = await load(`data/${name}`, BufferAsset)
return new Uint8Array(asset.buffer())
}
await tables.readAllBinaryFromLoader()
비동기인 이유는 엔진이 그렇기 때문입니다. Creator의 자산 로딩은 callback 또는
Promise이고, 동기 진입점만 두면 그 경로가 닫힙니다. C#이 훅을 비동기로 둔 것과 같은
판단입니다.
3.3 게이트
엔진 없이 검 증할 수 있는 범위가 넓습니다 — 로더를 대입해 메모리에서 바이트를 공급하고,
파일에서 읽은 결과와 값을 대조하면 ③이 해결되었음이 확인됩니다. ①·②는 생성물에
from 'fs'·from 'path'가 없는지로 확인되고, 이것은 골든이 판정합니다. 실물 에디터
게이트는 §7의 미결정 항목입니다.
4. 결정 2 — Creator의 자산 경로 (확인 항목)
데이터 파일이 Creator의 자산 파이프라인에 어떻게 들어가는지는 문서를 읽어 판단할 항목이 아니라 실제 에디터에서 확인할 항목입니다. 후보가 3개이고, 어느 쪽이어도 §3의 훅으로 흡수됩니다.
| 후보 | 내용 | 확인할 것 |
|---|---|---|
BufferAsset | 3.8 API에 클래스가 존재합니다. 원시 바이너리를 자산으로 임포트하는 경로입니다 | 어느 확장자가 이것으로 임포트되는지, 그리고 바이트 접근자의 정확한 이름 |
| 커스텀 핸들러 등록 | assetManager의 downloader·parser에 확장자별 핸들러를 등록하는 방법이 문서화되어 있습니다 | .tcb를 그대로 쓸 수 있는지 |
loadRemote·쓰기 가능 경로 | 내려받은 데이터를 읽는 경로. 데이터 갱신과 짝입니다 | 바이너리에 쓸 수 있는지 |
확장자 에 제약이 있으면 BinaryTableFileExtension으로 해결되므로 코드 변경은
없습니다. 유니티가 .bytes만 TextAsset으로 포함하는 것과 같은 종류이고, recipe에
한 줄입니다.
웹 빌드와 네이티브 빌드가 같은지도 여기서 확인합니다. 네이티브 빌드도 게임 코드는 TypeScript이므로 같은 경로일 것으로 보이나, 자산이 실제로 놓이는 위치는 다릅니다.
5. 데이터 갱신
1차 범위에서 제외합니다. §3의 훅이 있으면 게임이 자기 방식으로 받아 읽을 수 있고,
Creator에는 원격 자산을 다루는 수단이 이미 있습니다. typescript 타깃의 업데이터가
Creator에서 그대로 동작하는지는 §3이 끝난 뒤에 판단할 항목입니다.
6. 위험과 대응
| 항목 | 내용 | 대응 |
|---|---|---|
| 골든 재기록 | §3은 기존 typescript 생성물의 import를 바꾸므로 골든이 움직입니다 | 의도된 변경이므로 diff를 리뷰하고 재기록합니다. 생성기·템플릿을 건드리는 변경이므로 CLAUDE.md의 순서가 그대로 적용됩니다 — 골든 재기록 → 전 언어 비교본 재생성 → 샘플 재생성 → 기록 없이 재검증 |
| 게이트의 신뢰도 | 엔진 없이 검증하면 언리얼에서 겪은 종류가 남습니다 — 스텁으로는 검출되지 않는 것 | 1차는 엔진 없이 검증되는 것만 봅니다(로더가 실제로 대체되는지, 대체된 로더로 값이 일치하는지, 생성물에 Node 모듈 import가 없는지). 나머지는 §4의 확인으로 대신합니다 |
| 기존 소비 코드 | readAllSync·readAllBinarySync를 쓰는 Node 프로젝트가 있습니다 | 공개 API는 유지합니다. §3의 A·B는 추가이고, C는 그 API의 구현 위치만 옮기는 것이라 호출 쪽이 바뀌지 않아야 합니다. 골든이 그것을 판정합니다 |
| 암호화 키의 노출 | 봉인한 파일을 읽으려면 키가 클라이언트에 있어야 하고, 웹 빌드에서는 번들에서 추출됩니다 | 새 위험이 아니라 이미 ts-tables-set.sbn의 주석이 적어 둔 것입니다. 무엇을 방어하는 수단이 아닌지를 Creator 문서에도 같은 문구로 적습니다 |
7. 단계와 미결정
| 순서 | 무엇 | 왜 이 순서인지 |
|---|---|---|
| 1 | §3 — 바이트 로더 훅·전량 로드 진입점·Node 의존 격리 | Creator 지원의 전제이고, 엔진 없이 검증됩니다. 셋을 한 번에 하는 이유는 하나만 해도 골든이 움직이므로 나누면 재기록을 세 번 하게 되기 때문입니다 |
| 2 | §4 — 실제 에디터에서 자산 경로 확인 | 1번이 없으면 확인해도 쓸 자리가 없습니다. 결과는 문서의 예제로만 반영됩니다 |
| 3 | 문서 — doc/languages/cocos-creator.md 새 페이지. 언어별 가이드의 표에 한 줄이 함께 들어갑니다 | 1·2의 결과가 그대로 들어갑니다. 생성물은 typescript와 같지만 소비 절차가 전부 Creator 고유입니다 — 자산 임포트, 확장자, 로더 대입, 비동기 진입점. 그것을 typescript.md의 절로 넣으면 Node 프로젝트가 읽을 문서에 엔진 절차가 섞입니다. 유니티가 csharp.md에 얹혀 있는 것은 어댑터가 스스로 설치되어 소비 쪽 절차가 없는 경우이므로 선례가 되지 않습니다 |
doc/roadmap.md의 「다음에 할 것」에는 1번의 착수 시점이 정해진 뒤 항목을 추가합니다.
| 번호 | 미결정 | 누가 정하는지 |
|---|---|---|
| ① | Creator 2.x를 포함할지 | 확인 필요. 포함하면 §4의 확인이 두 번입니다 |
| ② | 실물 에디터 게이트를 둘지 | 1차 범위에서는 두지 않습니다 |
EOD