Code
Search code…
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LINKS
LINKS Is Not Kloud Streaming. 게임을 서버에서 돌려 영상으로 보내지 않는다. 브라우저가 직접 실행한다.
마지막 수정: 2026-10-31
LINKS는 NAS 같은 개인 서버에 쌓아 둔 게임 폴더를 한 바이트도 바꾸지 않고 한국어 게임 라이브러리로 만드는 self-hosted 서비스다. 폴더 구조와 작은 식별 파일만 읽어 설치본을 찾고, VNDB·DLsite 같은 외부 공급자의 정보를 출처와 함께 붙인다. 지원 범위의 RPG Maker 게임은 원격 화면 스트리밍 대신, 원본에서 봉인한 실행 사본을 브라우저 안의 격리된 sandbox에서 HTML5 또는 WebAssembly로 실행하고 세이브는 서버에 사용자별로 보관한다.
왜 흥미로운가
- 원본은 손대지 않는다. 게임 library는
read_onlymount로만 연결한다. 이름 변경·이동·삭제·압축 해제·patch·save 기록이 없고, 게임 실행 파일과 script도 서버에서 실행하지 않는다. - 같은 번호라고 같은 게임은 아니다. 같은 RJ 번호가 붙은 두 폴더의 내용이 서로 다른 경우가 실제로 있다. 그래서 작품(
Work)·판본(Edition)·설치본(Installation)·외부 ID(ExternalIdentity)를 분리하고, 외부 ID 하나로 설치본을 합치거나 지우지 않는다. 자동 판정에는 근거와 점수를 남기고 애매하면 관리자가 검토한다. - 스트리밍 서버가 아니라 정적 파일 서버다. MV/MZ는 게임에 들어 있는 HTML/JavaScript를, XP/VX/VX Ace는 외부 RGSS 호환 WebAssembly 런타임 ARCA를 브라우저에서 실행한다. 서버에는 GPU도 영상 인코더도 필요 없다.
- 게임 코드는 손님이다. 게임은
allow-same-origin없는 opaque sandbox iframe에서 돈다. catalog 세션 cookie·DB credential·원본 library에는 닿지 못하고, 신뢰된 부모 화면이 허용된 자산과 세이브 요청만 중계한다. - "된다"고 쉽게 말하지 않는다. 패키지 생성이나 타이틀 화면 한 장으로 지원을 선언하지 않는다. 실제 입력·오디오·저장 후 재시작·불러오기를 같은 build와 browser에서 통과한 범위만 지원으로 기록한다.
주요 기능
현재 구현된 기능이다. 기능별 검증 범위와 한계는 완료 기준선을 따른다.
| 영역 | 제공 범위 |
|---|---|
| 라이브러리 스캔 | 읽기 전용 root의 증분 스캔·중단/재개, 대량 누락 보호, 누락 설치본 보존, 관리자 재판정 |
| 식별 | 폴더명·sidecar의 DLsite·VNDB·Steam·Getchu 정확한 ID, payload별 엔진 근거(RPG Maker MV·MZ·VX·VX Ace·XP, WOLF, Unity, KiriKiri, GameMaker, Alice, LiveMaker, Artemis) |
| 검토 | 작품 연결 후보의 승인·거절, 경로가 바뀐 설치본의 재연결 후보, 형태가 같거나 비슷한 중복·판본 후보, 최근 스캔 변경 |
| 메타데이터 | 공급자·상품 ID별 snapshot과 필드 정책·출처 보존, 표지·제작사·발매일·태그·샘플 이미지와 검증된 썸네일, 수집 실패에도 이전 정상 정보 유지 |
| 한국어 표시 | 한국어 UI와 원문 fallback, 공급자 태그 한국어 사전, 번역 작업 파일 export와 서버 번역 사전 적용(운영자 번역 배지)·원문 보기 |
| 탐색 | 검색·상세 필터·정렬·페이지, 제작사·태그 모아보기, 작품별 판본·설치본 목록, 이미지 뷰어 |
| 계정과 개인 라이브러리 | WebAuthn 패스키 전용 로그인(비밀번호 없음), 관리자 공유 링크로 로그인 없이 한 게임 실행(세이브는 그 브라우저에만, 게스트는 목록을 볼 수 없음), 저장한 게임 검색, 마지막 실행 시작과 플레이 시간 |
| 브라우저 실행 | 여러 사용자가 공유하는 실행 준비(두 번 관찰 → 봉인 사본 → build), 일회용 launch grant, 재시작·음량·화면 크기·전체화면, 실행 실패 신고 |
| 세이브 | 사용자·설치본별 서버 세이브, slot별 이전 버전 복원, 다른 실행 버전 세이브 가져오기 |
| 관리자 | 스캔·정보 수집·작업 취소와 재개, 수집 사이트 상태, 실행 빌드 관리, 초대 기반 사용자 관리, 운영 경고, 버그 신고, 컨테이너 로그·감사 기록 |
| 운영 | 역할별 Compose service·DB role·mount 분리, health/readiness, registry 이미지 배포와 forward migration 적용 |
동작 원리
flowchart LR
L[("게임 라이브러리<br/>read-only")] --> S["Scanner"]
L --> R["Runtime stager /<br/>package stager"]
S --> DB[("PostgreSQL")]
M["Metadata worker"] -->|"허용된 공급자만"| DB
R -->|"봉인된 입력"| B["Runtime builder /<br/>ARCA Builder OCI"]
B --> CAS[("Artifact CAS")]
U["브라우저"] --> G["Gateway<br/>단일 hostname"]
G --> C["Catalog API + Web"]
G -->|"/player/*"| P["Player bridge"]
C --> DB
C -. "일회용 launch grant" .-> K["Launch broker"]
P --> K
P --> CAS
P --> SV[("Save store")]
- 스캔: scanner가 read-only library에서 번호 폴더와 작은 sentinel 파일만 읽어 설치본 후보와 엔진 근거를 기록한다.
- 보강: metadata worker가 운영자가 허용한 공급자에서 정확한 ID로 정보를 수집하고 원문·출처·수집 시각을 보존한다.
- 준비: 로그인 사용자가 처음 실행하면 해당 설치본만 두 번 관찰해 안정된 사본을 봉인하고, network 없는 builder가 불변 실행 artifact를 만든다. XP/VX/VX Ace는 package coordinator가 digest로 고정된 ARCA Builder OCI를 호출한다.
- 실행: catalog가 짧은 일회용 grant를 발급하고, Player는 broker로 이를 검증한 뒤 해당 build의 artifact와 그 사용자의 세이브만 제공한다. 게임 코드는 opaque sandbox 안에서만 동작한다.
서비스별 mount·network·DB 권한은 아키텍처, 위협 모델은 보안·격리 정책을 따른다.
엔진 지원 현황
요약이다. 정확한 build·browser·표본 범위는 최신 검증 기준선, 상태 vocabulary는 런타임 계약을 따른다.
| 엔진 | 실행 방식 | 합성 fixture | 실제 게임 |
|---|---|---|---|
| RPG Maker MV/MZ | 게임의 HTML/JS를 sandbox에서 실행 | Chromium·Firefox의 입력·이벤트·BGM/SE·저장 후 재시작·불러오기 PASS | 표본별 타이틀·입력·BGM 일부 확인, 전체 PARTIAL. 실제 게임 전체 acceptance NOT RUN |
| RPG Maker VX/VX Ace | ARCA WebAssembly 런타임 | Player 로딩·캐시·재시작 경계의 합성 회귀 PASS(엔진 지원 근거 아님). 합성 RGSS2 VX gate는 Chromium·Firefox fixture PASS이며 Firefox는 페이지를 떠난 뒤 session 종료 단계가 간헐적으로 FAIL하는 알려진 경쟁이 있어 후속으로 추적 |
표본별 타이틀·한글 메뉴·게임 내 메뉴·기존 세이브 불러오기 확인, 전체 PARTIAL. 실제 게임 전체 acceptance NOT RUN. 남은 문제는 호환성 진단 |
| RPG Maker XP | ARCA WebAssembly 런타임(RGSS1) | 합성 XP gate의 입력·BGM/SE·서버 세이브 후 재시작·불러오기 Chromium·Firefox fixture PASS(최대 EXPERIMENTAL, Firefox는 페이지를 떠난 뒤 session 종료 단계가 간헐적으로 FAIL하는 알려진 경쟁이 있어 후속으로 추적) |
실제 게임·live RPGXP RTP 준비·사용자 acceptance NOT RUN. RTP를 둘 이상 선언한 XP는 NOT SUPPORTED. 범위는 XP 검증 범위 |
| WOLF·Unity·KiriKiri·GameMaker·Alice·LiveMaker·Artemis | 엔진 인식과 catalog만 | — | 브라우저 실행 없음 |
현재 어떤 엔진도 "지원"으로 표시하지 않는다. 한 fixture나 표본의 성공은 그 build·browser의 결과일 뿐 엔진 전체 지원이 아니다. 남은 acceptance와 NAS 운영 검증은 개발 계획이 소유한다.
빠른 시작
개발·빌드·검증·운영은 모두 Docker Compose 안에서만 수행한다. host의 node·pnpm·python으로 프로젝트 코드를 실행하지 않는다.
로컬 개발(Windows + Docker Desktop)
powershell -NoProfile -ExecutionPolicy Bypass -File .\ops\start-develop.ps1
기본 주소는 https://localhost:8443이다. 게임 폴더(.env.develop의 LINKS_LIBRARY_SOURCE)·준비·CA 신뢰는 로컬 HTTPS 개발 서버, 첫 관리자 패스키는 최초 관리자 등록을 따른다.
운영(NAS 등): 소스 checkout 없이 배포 디렉터리의 sh update.sh(갱신·migration)와 sh reset.sh(전체 초기화)로 운영한다(운영 배포).
검증: 변경 종류별 gate와 runner는 테스트 전략을 따른다.
저장소 구조
| 경로 | 책임 |
|---|---|
apps/api |
Fastify catalog API와 web static 제공 |
apps/web |
React/Vite catalog·관리자·Player 부모 화면 |
apps/player |
session에 묶인 artifact·save bridge |
apps/launch-broker |
일회용 launch grant 발급·소비(backend 전용) |
apps/worker |
scanner·metadata·번역 사전 적용·runtime·GC·로그 수집 역할 |
packages/ |
공유 계약(contracts)·domain·DB query·scanner·provider·runtime·runtime-builder |
infra/ |
Dockerfile·Caddy gateway 설정, 도메인별 기준 SQL schema(infra/schema)와 forward migration(infra/migrations), browser 검증 runner 의존성(infra/browser) |
ops/ |
개발 기동, registry 배포·초기화, ARCA package coordinator와 image build의 ARCA release 번들 검증 |
tests/ |
합성 fixture, Compose 검증 runner, 통합·browser 검사 |
compose.yaml / compose.develop.yaml / compose.test.yaml |
운영 registry image / 로컬 build·HTTPS / 검증 전용 service |
games/, data/, state/, 비밀 값과 운영자 입력은 Git과 image build 입력에서 제외한다. state/는 개발·검증 산출물 전용이며 운영 배포 디렉터리에는 없다.
설계 원칙
- 읽기 전용 원본: library는
read_only: true로만 mount하고 scanner·inspector는 root 밖 경로와 symlink/junction을 따라가지 않는다. - 역할별 최소 권한: 하나의 image를 역할별 command·DB role·mount·network로 나눈다. catalog에는 원본 library가 없고, builder에는 network가 없으며, Player에는 DB credential이 없다.
- provenance 보존: 공급자 원문, 정규화 값, 한국어 표시값과 사용자 수정은 서로 덮어쓰지 않고 출처와 수집 시각을 함께 남긴다.
- 불변 artifact와 분리된 세이브: 실행 artifact는 content hash로 식별하고 원자적으로 게시한다. 세이브는
사용자 + 설치본단위로 build cache와 분리해 보존한다. - migration 사슬을 갖는 기준 schema: 물리 schema는
infra/schema의 기준 SQL이 현재 전체를 소유하고, 배포된 DB의 schema 변경은 1.0.0 기준 schema에서 시작하는 forward migration 사슬(infra/migrations)로 적용한다. 사슬 안 DB는 한 transaction으로 갱신하고 사슬 밖 DB만 초기화하며, migration이 적용된 DB는 이전 image로 되돌릴 수 없다. - 정직한 상태 표기: 실행 결과는
PASS·PARTIAL·FAIL·BLOCKED·NOT RUN만 쓰고 합성 fixture·실제 표본·운영 환경을 구분한다.
ARCA와의 관계
XP/VX/VX Ace 브라우저 엔진·SDK·RTP 준비·Builder는 외부 핵심 라이브러리 ARCA(npm @arca/rgss123)가 소유한다. LINKS는 exact version으로 고정한 정식 배포본의 공개 API만 소비하며, ARCA 소스를 복사·수정·vendor하거나 내부 hook으로 기능을 대신 구현하지 않는다. ARCA 소관 결함은 ARCA에 개선을 요청하고, 정식 배포 뒤 버전 갱신과 공개 API 연결로 재개한다. 버전 pin은 package.json, 경계와 절차는 런타임 계약을 따른다.
문서 안내
| 문서 | 읽을 때 |
|---|---|
| 제품 범위 | 무엇을 하고 무엇을 하지 않는지 |
| 아키텍처 | 서비스·신뢰 경계와 데이터 흐름 |
| 완료 기준선 | 지금 실제로 되는 것과 최신 검증 결과 |
| 개발 계획 | 남은 작업과 완료 gate |
| 운영 가이드 | 기동·배포·장애 대응 |
| 테스트 전략 | Docker 검증 진입점 |