개발 문서
Immercy 개발자 도구
게임은 정적 HTML·CSS·JavaScript 빌드로 배포합니다. 플랫폼은 PC 화면과 스마트폰 한 대의 연결을 처리하고, 게임은 SDK의 입력 이벤트를 받습니다. Unity 및 별도 서버 프로세스가 필요한 빌드는 지원하지 않습니다.
packages/sdk, packages/cli, packages/mcp의 로컬 소스를 포함합니다. npm 공개 배포나 외부 레지스트리의 이름 확보는 아직 하지 않았습니다. 준비 전에는 저장소의 도구 경로를 직접 사용하고, 아래 공개 패키지 설치 명령은 npm 게시를 완료한 뒤에만 사용합니다.
1. 프로젝트와 인증
Immercy에 Google 계정으로 로그인하고 프로젝트를 만듭니다. 발급된 프로젝트 ID와 API 키를 확인합니다. API 키는 생성 또는 교체 시에만 전체 값을 표시하므로 안전한 개발 환경에 보관합니다. 키는 해당 프로젝트에만 사용할 수 있습니다.
게임 소스에 immercy.config.json을 작성합니다. buildDir은 프로젝트 루트 안의 별도 출력 폴더이며 루트에 index.html이 있어야 합니다. controller는 JSON 파일의 상대 경로입니다.
{
"projectId": "대시보드에서_발급된_실제_ID",
"buildDir": "dist",
"controller": "controller.json",
"origin": "https://immercy.eturnalove.com"
}
실제 프로젝트 ID에는 발급된 영문 식별자를 그대로 사용합니다. API 키는 위 파일에 넣지 않습니다. 운영체제/CI의 비밀 환경 변수 IMMERCY_API_KEY를 사용하거나, Git에서 제외한 .immercy.local.json에 저장합니다.
{ "apiKey": "실제_프로젝트_API_키" }
프로젝트 .gitignore에 다음을 추가합니다. 키 파일과 .env를 웹 빌드의 public 또는 dist 폴더에 복사하지 않습니다.
.immercy.local.json
.env
.env.local
키를 교체하면 이전 키로 업로드할 수 없습니다. Vercel Blob 토큰, MongoDB 비밀번호, Google OAuth 비밀은 플랫폼 운영자의 서버 설정이며 게임 개발자 API 키와 다릅니다.
2. 게임에서 입력 받기
SDK는 브라우저에서 초기화합니다. 로컬 개발에서는 이 저장소의 packages/sdk를 파일 의존성으로 연결할 수 있습니다. npm에 게시한 이후에는 게임 프로젝트에서 npm install @immercy/sdk@1.0.0으로 설치합니다.
import { createImmercy } from '@immercy/sdk';
const immercy = createImmercy();
const movement = { x: 0, y: 0 };
const stopMove = immercy.on('move', (value) => {
movement.x = value.active ? value.x : 0;
movement.y = value.active ? value.y : 0;
});
const stopFire = immercy.on('fire', (value) => {
if (value.pressed) fire();
});
const stopConnection = immercy.onConnection((connected) => {
if (!connected) {
movement.x = 0;
movement.y = 0;
}
});
function dispose() {
stopMove();
stopFire();
stopConnection();
immercy.destroy();
}
fire()는 게임 자체의 행동 함수로 구현합니다. React라면 컴포넌트 effect 안에서 초기화하고 cleanup에서 destroy()를 호출합니다. on()은 해당 이벤트를 해제하는 함수를 반환합니다. onInput()으로 전체 입력을 관찰할 수 있고 connected, sessionId는 읽기 전용 상태입니다.
기본 신뢰 주소는 https://immercy.eturnalove.com입니다. 별도 Preview 플랫폼을 사용할 때에만 createImmercy({ parentOrigin: 'https://고정된-preview-주소' })처럼 명시합니다. 임의의 메시지 출처나 URL 쿼리로 신뢰 주소를 결정하지 않습니다. SDK에 프로젝트 API 키나 QR 토큰을 전달할 필요가 없습니다.
컨트롤러의 event 이름과 on()의 첫 인자를 일치시킵니다. 모든 콜백의 두 번째 인자는 { event, value, componentId, timestamp }입니다.
| 입력 컴포넌트 | value |
|---|---|
| Button | { pressed: boolean } |
| Joystick / DPad / TouchPad | { x, y, active }, 축 범위 -1~1 |
| Gyro | { alpha, beta, gamma } |
| Accelerometer | { x, y, z, interval } |
| Swipe | { direction, distance, velocity }, 방향 left/right/up/down |
| MultiTouch | { points: [{ id, x, y }], active }, 최대 10점 |
센서 값의 기기별 품질과 권한 허용은 브라우저/기기에 따라 실제 확인이 필요합니다. 접근이 거부되거나 장치가 지원하지 않을 때 게임이 멈추지 않도록 게임 규칙에서 처리합니다.
3. 컨트롤러 JSON과 코드 조립
웹 에디터에서 만든 컨트롤러를 사용하거나 SDK의 builder로 조립한 뒤 JSON으로 저장합니다. 플랫폼은 컨트롤러를 데이터로 검증하며 업로드된 임의의 컨트롤러 코드를 실행하지 않습니다.
import { writeFile } from 'node:fs/promises';
import { defineController, Joystick, Button } from '@immercy/sdk/controller';
const controller = defineController({
version: 1,
name: '이동과 발사',
orientation: 'landscape',
background: '#111820',
accent: '#A9F072',
components: [
Joystick({ id: 'movement', event: 'move', label: '이동', x: 7, y: 20, w: 38, h: 65 }),
Button({ id: 'action', event: 'fire', label: '발사', x: 64, y: 26, w: 27, h: 52 }),
],
});
await writeFile('controller.json', JSON.stringify(controller, null, 2) + '\n', 'utf8');
추가 builder는 DPad, TouchPad, Gyro, Accelerometer, Swipe, MultiTouch입니다. validateControllerConfig(value)는 { valid, errors }를 반환합니다. 모든 builder 결과는 같은 데이터 스키마를 사용합니다.
좌표와 크기는 0100의 백분율입니다. 각 컴포넌트의 폭/높이는 최소 4이며 화면 바깥으로 나갈 수 없습니다. 124개 컴포넌트, 중복 없는 ID, 영문으로 시작하는 1~64자 이벤트 식별자를 사용합니다. 배경·강조·개별 색은 #RRGGBB 형식입니다.
4. 빌드와 배포
번들러를 사용한다면 에셋 경로가 실행 디렉터리에 상대적이어야 합니다. Vite는 base: './'로 빌드하고, HTML의 /assets/... 같은 루트 절대 경로는 피합니다. 소스 폴더 전체 대신 dist 같은 완성된 정적 출력 폴더를 지정합니다.
빌드 루트의 index.html에서 게임을 시작합니다. 활성 세션 안의 HTML 재요청, 정적 페이지 이동, 게임 내부 재시작은 같은 Play로 처리합니다. 독립된 새로운 실행 세션의 시작이 승인될 때만 Play가 추가됩니다. 다른 HTML과 에셋으로 이동할 때도 현재 빌드 기준의 상대 경로를 사용합니다.
현재 로컬 checkout에서는 저장소 루트에서 npm ci를 완료한 뒤, 게임 프로젝트 폴더에서 CLI 파일을 직접 실행할 수 있습니다. 아래 C:/Projects/Immercy는 예시이므로 실제 저장소 경로로 바꿉니다.
node C:/Projects/Immercy/packages/cli/src/index.js validate
node C:/Projects/Immercy/packages/cli/src/index.js deploy
validate는 경로, 크기, 파일 해시, 컨트롤러를 로컬에서 읽어 확인합니다. deploy는 실제 원격 업로드와 최신 빌드 교체를 수행합니다. 이 문서 작성 과정에서는 두 명령을 실행하지 않았습니다.
npm 게시 후에는 npm install --save-dev @immercy/cli@1.0.0으로 설치하고 다음 명령을 사용할 수 있습니다.
npx immercy validate
npx immercy deploy
npx immercy deploy --config immercy.config.json
npx immercy help
CLI는 manifest를 등록하고 각 파일을 Private Blob에 업로드한 다음 commit API를 호출합니다. 일부 파일만 올라간 상태로 최신 빌드를 교체하지 않습니다. 검사 후 파일 내용이 바뀌면 다시 빌드·검사해야 합니다. API 키 자체가 출력 파일에 포함된 경우에도 배포를 중단합니다. 제한은 파일 500개, 합계 100 MiB, 파일당 25 MiB이며 각 HTML 파일(.html, .htm)은 2 MiB까지입니다. 빌드 루트의 index.html은 필수입니다. 빈 파일, .env, 소스맵, 서버 파일, 심볼릭 링크 등은 허용하지 않습니다.
CLI 배포 결과의 게임 주소를 열어 실제 연결을 확인합니다. 비공개 프로젝트는 권한 있는 개발자만 접근하며, 공개 요청은 검토 상태에 따라 게재됩니다. 개발자 Preview도 주간 Play 사용량을 소모합니다.
5. AI 도구에서 MCP 연결
MCP 서버는 로컬 stdio 방식입니다. MCP를 지원하는 클라이언트에 아래 실행 정보를 등록합니다. IMMERCY_PROJECT_DIR는 게임 소스 폴더이며 그 안에 immercy.config.json이 있어야 합니다. command는 PATH의 Node.js 24 실행 파일 또는 절대 경로를 사용합니다.
{
"mcpServers": {
"immercy": {
"command": "node",
"args": ["C:/Projects/Immercy/packages/mcp/src/index.js"],
"env": {
"IMMERCY_PROJECT_DIR": "C:/Projects/Immercy/examples/starter",
"IMMERCY_CONFIG": "immercy.config.json"
}
}
}
}
위 JSON은 mcpServers 형식을 사용하는 클라이언트의 예시입니다. 다른 클라이언트에서는 같은 command/args/env 값을 해당 설정 형식으로 옮깁니다. API 키는 클라이언트의 안전한 환경 변수 전달 기능 또는 게임 폴더의 Git 제외 .immercy.local.json에 넣습니다. 서버는 지정된 폴더와 프로젝트 ID에 묶이며 도구 인자로 임의 쉘 명령을 받지 않습니다.
| MCP 도구 | 동작 |
|---|---|
immercy_help | SDK/컨트롤러/배포 계약 설명 |
immercy_validate_controller | 전달된 컨트롤러 데이터 검증 |
immercy_inspect_build | 지정된 로컬 빌드의 manifest·해시·크기 검토 |
immercy_get_project | 해당 프로젝트의 실제 서버 메타데이터 조회 |
immercy_preview_links | 에디터/Integration Preview/게임 링크 반환 |
immercy_update_controller | 서버의 컨트롤러 데이터 변경 |
immercy_deploy | 완성된 정적 빌드 업로드와 최신 빌드 교체 |
가이드 resource는 immercy://guide, 게임 제작 prompt는 immercy-game입니다. 재사용 안내는 packages/mcp/skills/immercy-game/SKILL.md에 포함됩니다. 이 파일을 포함한 패키지는 준비되어 있으며 사용자의 MCP 클라이언트에 자동 설치하거나 시작하지 않았습니다.
조회/검증과 원격 변경 도구를 구분합니다. immercy_preview_links는 브라우저를 열거나 Play를 시작하지 않습니다. immercy_update_controller와 immercy_deploy는 실제 서버 자료를 바꾸므로 개발 도구에 요청한 작업 범위 안에서 사용합니다. 게임 빌드는 MCP가 쉘로 자동 실행하지 않으며 배포는 이미 완성된 출력물을 사용합니다.
6. 포함된 starter로 첫 프로젝트 만들기
examples/starter의 Orbit Garden은 조이스틱과 대시 버튼으로 60초 동안 빛을 모으는 게임입니다. SDK 이벤트, 코드 조립 컨트롤러, 정적 출력, CLI 설정이 함께 들어 있습니다. 저장소 루트에서 의존성을 설치한 다음 아래 명령으로 출력물을 만듭니다.
npm run build --workspace @immercy/starter
빌드 스크립트는 controller.mjs를 controller.json으로 직렬화하고 게임과 로컬 SDK 모듈을 dist에 복사합니다. 외부 CDN에서 SDK를 가져올 필요가 없습니다. examples/starter/immercy.config.json의 프로젝트 ID를 대시보드에서 만든 실제 ID로 바꾸고, 그 예제 폴더에 .immercy.local.json을 만들거나 IMMERCY_API_KEY를 전달합니다.
Set-Location examples/starter
npx immercy validate
npx immercy deploy
배포한 게임 주소는 /g/<projectId>입니다. 개발자 Integration Preview는 /play/<projectId>?preview=1, 컨트롤러 에디터는 /dashboard/projects/<projectId>/controller로 연결됩니다. PC에서 Play(Integration Preview에서는 미리보기 시작)를 누르면 QR이 표시됩니다. 스마트폰으로 QR을 읽고 연결을 누르면, 연결 완료 후 게임이 자동으로 시작됩니다. 게임 내 대시 버튼으로 다음 라운드를 시작하며 PC의 플레이 종료는 연결 세션을 닫습니다.
이 starter는 소스로 제공하며 빌드·배포·실기기 플레이를 이번 작업에서 실행하지 않았습니다. 최초 운영 확인은 서버와 외부 서비스 설정 이후 진행합니다.
7. SDK·CLI·MCP 공개 게시 준비
npm 계정과 immercy scope의 소유/게시 권한을 먼저 확보합니다. 저장소의 패키지 이름이 npm에서 사용 가능한지는 아직 확인하거나 예약하지 않았습니다. 다른 이름이 필요하면 세 패키지의 이름·의존성과 문서 명령을 함께 변경합니다.
배포 담당자는 package 파일 목록과 비밀 포함 여부를 검토하고 SDK → CLI → MCP 순서로 게시합니다. CLI가 SDK에, MCP가 CLI에 의존하기 때문입니다. root 패키지는 private: true이며 게시 대상이 아닙니다. 게시 명령은 npm 인증과 이름 소유권 준비를 마친 후에만 수행합니다.
npm publish --workspace @immercy/sdk --access public
npm publish --workspace @immercy/cli --access public
npm publish --workspace @immercy/mcp --access public
패키지 공개 게시, 신규 이름 확보, 버전 태그, 실제 설치·실행 검증은 이번 구현에서 수행하지 않았습니다. 공개 전에는 로컬 도구 소스를 기준으로 사용합니다.