perf: 프로필 프런트엔드 자산을 커밋 단위로 공유한다
정적 운영 빌드에서 프로필별 base와 API 설정을 런타임 JSON으로 분리하고, 공용 Vite 번들과 sourcemap을 한 번만 생성·게시한다. Preview와 기존 정적 artifact의 전환 호환 경계는 유지한다.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
| gateway API | `app/gateway-api/src/server.ts` | 계정, session, profile, admin operation |
|
||||
| gateway orchestrator | `app/gateway-api/src/orchestrator/orchestratorServer.ts` | DB queue, build, PM2 reconciliation |
|
||||
| release controller | `app/release-controller/src/index.ts` | Gateway 전체 릴리스와 controller CLI 전환 |
|
||||
| game frontend | Vite preview | profile별 commit frontend artifact |
|
||||
| game frontend | Caddy static | commit 공용 asset + profile runtime wrapper |
|
||||
| game API | `app/game-api/src/server.ts` | profile tRPC, SSE, worker transport |
|
||||
| turn daemon | `app/game-engine/src/turn/cli.ts` | schedule, command, 월간 lifecycle, DB flush |
|
||||
| battle worker | `app/game-api/src/battleSim/worker.ts` | 격리된 전투 시뮬레이션 |
|
||||
@@ -17,12 +17,13 @@
|
||||
Gateway API와 game API는 기본적으로 `0.0.0.0`에 bind합니다. 실제 port와
|
||||
prefix는 환경 변수와 배포 profile이 결정합니다.
|
||||
|
||||
현재 PM2 조립에서 game profile 하나는 frontend, API, turn daemon, auction,
|
||||
battle-sim, tournament worker의 여섯 process를 만듭니다. 각 정의에는
|
||||
`instances`나 cluster `exec_mode`가 없으므로 모두 단일 fork입니다. frontend도
|
||||
Caddy 정적 파일이 아니라 profile별 Vite preview Node process이고, API도 하나의
|
||||
Fastify process입니다. worker 역할 분리는 API event loop의 작업을 줄이지만
|
||||
frontend/API replica나 장애 대체 backend를 제공하지는 않습니다.
|
||||
현재 정적 운영 모드의 PM2 조립에서 game profile 하나는 API, turn daemon, auction,
|
||||
battle-sim, tournament worker의 다섯 process를 만듭니다. 각 정의에는 `instances`나
|
||||
cluster `exec_mode`가 없으므로 모두 단일 fork입니다. Frontend는 Caddy가
|
||||
`frontend-artifacts` volume에서 직접 제공하며 profile별 Vite preview Node process를
|
||||
두지 않습니다. Preview 개발 모드에서만 여섯 번째 frontend process를 유지합니다.
|
||||
API는 하나의 Fastify process입니다. worker 역할 분리는 API event loop의 작업을
|
||||
줄이지만 API replica나 장애 대체 backend를 제공하지는 않습니다.
|
||||
|
||||
Profile은 PostgreSQL schema와 Redis namespace를 분리하지만 같은 database,
|
||||
PostgreSQL instance, runtime cgroup을 공유합니다. 관리되는 PM2 정의는 game API 4,
|
||||
@@ -126,14 +127,17 @@ artifact를 만들며 `Pm2ProcessManager`가 profile process를 조정합니다.
|
||||
재시작 시 DB 상태와 process 상태를 reconciliation합니다.
|
||||
|
||||
Profile `DEPLOY` operation은 현재 game schema와 시즌 데이터를 유지한 채 선택
|
||||
commit의 game API, engine과 profile 전용 frontend artifact를 빌드합니다. 기존
|
||||
commit의 game API, engine과 commit 공용 frontend asset을 빌드합니다. 기존
|
||||
프로세스를 멈춘 뒤 `prisma migrate deploy`만 실행하고 seed는 호출하지 않습니다.
|
||||
새 API·frontend와 모든 worker가 PM2 `online`이고 HTTP readiness가 성공해야
|
||||
build commit을 게시합니다. 실패하면 이전 worktree 프로세스를 다시 시작합니다.
|
||||
Profile frontend build에는 같은 전체 commit SHA를 `VITE_BUILD_COMMIT_SHA`로
|
||||
주입합니다. 이 값은 Turbo의 `VITE_*` cache key에 포함되고 Vite가 bundle 상수로
|
||||
고정하므로, 게임의 `게임 정보` dialog가 실제 선택 build commit을 표시하며 다른
|
||||
commit의 cached artifact를 현재 버전으로 오인하지 않습니다. Orchestrator 밖의
|
||||
주입합니다. 정적 운영 모드는 profile base/API 값을 build에서 제거하고 상대 asset
|
||||
base를 사용하므로 같은 commit의 모든 profile이 하나의 Turbo/Vite 결과를 공유합니다.
|
||||
Profile별 base path, API/SSE URL과 Gateway URL은 각 `current/index.html`에 JSON script로
|
||||
주입되어 router와 client가 시작할 때 읽습니다. 게임의 `게임 정보` dialog가 실제 선택
|
||||
build commit을 표시하며 다른 commit의 cached artifact를 현재 버전으로 오인하지
|
||||
않습니다. Orchestrator 밖의
|
||||
개발 build는 현재 Git checkout의 `HEAD`를 fallback으로 사용하고 Git metadata를
|
||||
읽을 수 없을 때만 `unknown`을 표시합니다.
|
||||
같은 build 단계는 profile root에 `deployment-version.json`을 생성합니다. 이미 열린
|
||||
|
||||
@@ -52,11 +52,15 @@ profile 범위 권한과 별개인 전역 `admin.releases.manage` 권한이 필
|
||||
persistent 경로가 필요하면 controller/orchestrator 환경에 `TURBO_CACHE_DIR`을
|
||||
설정합니다. Cache는 재생성 가능한 build artifact이며 DB/Redis backup이 아닙니다.
|
||||
- Server build 뒤 frontend release는 `typecheck:release`와 Vite bundle을 별도 Turbo
|
||||
task로 실행합니다. 타입검사 hash에는 frontend 자체와 직접 해석하는 common/infra/
|
||||
task로 실행합니다. 정적 운영 모드의 profile은 profile별 base/API 값을 build env에서
|
||||
제거하고 `VITE_ASSET_BASE_PATH=./`인 공용 bundle을 commit당 한 번 생성합니다.
|
||||
타입검사 hash에는 frontend 자체와 직접 해석하는 common/infra/
|
||||
logic/game-engine/game-api/gateway-api source, Prisma schema와 기본 navigation resource가
|
||||
들어가며, bundle hash에는 `NODE_ENV`와 모든 `VITE_*`가 포함됩니다. 따라서 내부 type
|
||||
source, base path나 API URL이 다른 frontend artifact를 cache hit로 잘못 복원하지
|
||||
않습니다. 일반 개발용 `pnpm --filter <frontend> build`의 typecheck 계약은 그대로입니다.
|
||||
source와 공개 build-time 값이 다른 frontend artifact를 cache hit로 잘못 복원하지
|
||||
않습니다. Profile base path와 API/SSE URL은 공용 bundle 입력이 아니라 게시 시점의
|
||||
runtime JSON config이므로 profile 사이에서 의도적으로 같은 cache key를 사용합니다.
|
||||
일반 개발용 `pnpm --filter <frontend> build`의 typecheck 계약은 그대로입니다.
|
||||
`NODE_OPTIONS`와 `RAYON_NUM_THREADS`는 출력에는 영향을 주지 않는 resource 제한으로
|
||||
build child에 전달됩니다.
|
||||
- `TURN_DAEMON_NODE_OPTIONS`가 설정되어 있으면 Gateway orchestrator는 그 값을
|
||||
@@ -135,11 +139,15 @@ Gateway process 전환이 진행 중인 profile migration·seed 실행자를 중
|
||||
데이터를 변환할 수 있으므로 대상 migration의 운영 데이터 영향은 배포 전에
|
||||
별도로 검토해 주세요.
|
||||
|
||||
Profile frontend bundle은 package의 `.release-build`에 고정 생성되어 profile base
|
||||
path별 Turbo cache에 저장됩니다. Orchestrator는 cache 복원 후 이를
|
||||
`.release-dist/<profileName>/game-frontend`에 staging directory를 거쳐 교체합니다.
|
||||
따라서 같은 commit·같은 공개 prefix의 재배포는 `vue-tsc`와 Vite를 다시 실행하지
|
||||
않고, 여러 instance가 같은 prefix를 쓰더라도 각 runtime target은 따로 materialize됩니다.
|
||||
Profile frontend bundle은 package의 `.release-build`에 상대 asset URL로 한 번 생성되어
|
||||
profile과 무관한 Turbo cache에 저장됩니다. Orchestrator는 이를
|
||||
`game-assets/releases/<commit-digest>` 불변 release로 한 번 stage하고, 각 profile에는
|
||||
base path, API/SSE URL과 Gateway URL을 `<script type="application/json">`로 주입한 작은
|
||||
`index.html`, `deployment-version.json`과 manifest만 게시합니다. 브라우저가 다른
|
||||
profile을 열어도 `/gateway/profile-assets/<commit-digest>/assets/*` URL이 같아 JS, CSS와
|
||||
source map 전송 cache를 공유합니다. Source map 생성과 공개 진단 계약은 유지합니다.
|
||||
Preview 개발 모드는 기존 profile별 Vite env와 materialize 경계를 그대로 사용하며,
|
||||
전환 전 profile 전용 정적 artifact도 rollback 호환 경로로 읽습니다.
|
||||
각 artifact의 `deployment-version.json`은 bundle과 같은 full commit SHA만 담습니다.
|
||||
열린 profile 탭은 이 파일의 고정 URL을 ETag로 조건부 재검증해 bundle SHA와 달라졌을
|
||||
때 한 번만 `새 버전이 준비되었습니다. 새로고침하면 변경사항이 반영됩니다.` toast를
|
||||
|
||||
Reference in New Issue
Block a user