[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CBWZSGRR9R3YJZB3177667":3,"skill-same:01M6CBWZSGRR9R3YJZB3177667":51},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":20,"linkOnly":21,"markdownContent":22,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":13,"repositoryHtmlUrl":27,"repositoryHomepageUrl":6,"ownerHtmlUrl":28,"ownerBlogUrl":6,"ownerDescription":29,"updatedAt":30,"install":31,"resources":44},"01M6CBWZSGRR9R3YJZB3177667","30-env-management",null,"devwinsoft\u002Fdevian","devwinsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F22570160?v=4","01M6C6RR8W05NH8NPKQNCE3Q72","maoshy","01M6C6RRDJ5TJJCZXRTY801YDH",0,"MIT","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F30-env-management\u002FSKILL.md",[],[18,19],"management","30 env management","2026-11-10 10:12:30",false,"# 30-env-management — Environment Variable Management Policy\n\nStatus: ACTIVE\nAppliesTo: v10\nType: POLICY\n\n---\n\n## Verification Target\n\n- **검증 대상**: main branch (현재 커밋)\n- **포함**: `framework-ts\u002Fapps\u002F*`, `framework-ts\u002Ftools\u002Fenv\u002F*`\n- **제외**: Unity build, WebGL runtime, framework-cs\n- **관련 SSOT**:\n  - `{appRoot}\u002Fenv.spec.json` (환경변수 정본)\n  - `framework-ts\u002Ftools\u002Fenv\u002Fenv-sync.mjs` (생성 도구)\n  - `framework-ts\u002Ftools\u002Fenv\u002Fenv-check.mjs` (검증 도구)\n\n---\n\n## Scope\n\n모든 framework-ts 앱의 환경변수 정의 및 `.env.example` 생성 정책\n\n**포함**: WebGLServer, GameServer, 향후 추가되는 모든 framework-ts 앱\n**제외**: Unity 프로젝트, C# 코드, 빌드 산출물\n\n---\n\n## SSOT\n\n| 구분 | 경로 |\n|------|------|\n| **정본 (SSOT)** | `{appRoot}\u002Fenv.spec.json` |\n| **생성물** | `{appRoot}\u002F.env.example` (자동 생성, 수동 편집 금지) |\n| **공통 도구** | `framework-ts\u002Ftools\u002Fenv\u002Fenv-sync.mjs`, `env-check.mjs` |\n\n---\n\n## Rules (MUST\u002FFAIL)\n\n1. **SSOT 고정**: 각 앱의 환경변수 정의는 `{appRoot}\u002Fenv.spec.json` 하나로 고정 — 분산 정의 FAIL\n2. **생성물 보호**: `.env.example`는 수동 편집 금지, 오직 `env:sync`로만 생성\u002F갱신 — 수동 수정 FAIL\n3. **검증 필수**: `env:check`가 `.env.example`이 최신이 아니면 `exit 1`로 실패 — 검증 없이 완료 선언 FAIL\n4. **.env 커밋 금지**: `.env` 파일은 절대 커밋하지 않음 — 커밋 시 FAIL\n5. **코드 동기화**: 코드에서 env 키 추가 시 반드시 `env.spec.json`에도 추가 — 누락 FAIL\n\n---\n\n## env.spec.json Schema\n\n```json\n[\n  {\n    \"key\": \"ENV_KEY\",\n    \"default\": \"value\",\n    \"description\": \"Description of the variable\",\n    \"required\": false\n  }\n]\n```\n\n| 필드 | 타입 | 필수 | 설명 |\n|------|------|------|------|\n| `key` | string | O | 환경변수 이름 |\n| `default` | string \\| number \\| boolean | O | 기본값 |\n| `description` | string | O | 설명 |\n| `required` | boolean | X | 필수 여부 (기본: false) |\n\n---\n\n## Workflow (고정 절차)\n\n환경변수 추가\u002F변경 시 반드시 아래 순서를 따른다:\n\n```bash\n# 1. env.spec.json 수정 (에디터에서)\n\n# 2. .env.example 생성\u002F갱신\nnpm -w \u003Cworkspace> run env:sync\n\n# 3. 검증\nnpm -w \u003Cworkspace> run env:check\n\n# 4. 커밋 (env.spec.json + .env.example 함께)\ngit add apps\u002F\u003Capp>\u002Fenv.spec.json apps\u002F\u003Capp>\u002F.env.example\ngit commit -m \"env: add\u002Fupdate \u003CKEY> for \u003Capp>\"\n```\n\n---\n\n## DoD (Hard=0 체크리스트)\n\n- [ ] `env.spec.json`이 정본으로 존재\n- [ ] `.env.example`이 `env:sync`로 생성됨\n- [ ] `npm -w \u003Cworkspace> run env:check` → exit 0\n- [ ] `package.json`에 `env:sync`, `env:check` 스크립트 존재\n- [ ] `prestart` 또는 `prestart:dev`에서 `env:check` 호출\n- [ ] 코드에서 사용하는 env 키가 모두 `env.spec.json`에 정의됨\n\n---\n\n## Anti-patterns (금지사항)\n\n1. **`.env.example` 수동 수정** — regen 시 되돌아오는 패치, 근본 해결 없음\n2. **`.env` 파일 커밋** — 비밀 유출 위험\n3. **코드에서 env 키 추가 후 `env.spec.json` 누락** — 문서\u002F코드 불일치\n4. **앱별 개별 env 스크립트 생성** — 공통 tool로 통일 필수\n5. **`env:check` 없이 \"완료\" 선언** — 검증 누락\n6. **문서 경로와 실제 경로 불일치** — 복붙 시 흔한 실수\n\n---\n\n## Commands\n\n```bash\n# .env.example 생성\u002F갱신\nnpm -w \u003Cworkspace> run env:sync\n\n# .env.example 최신 여부 검증\nnpm -w \u003Cworkspace> run env:check\n\n# 전체 앱 검증 (예시)\nnpm -w webgl-server run env:check && npm -w game-server run env:check\n```\n\n---\n\n## Related\n\n- [03-ssot](..\u002F03-ssot\u002FSKILL.md) — Tools SSOT\n- [22-game-server-webgl](..\u002F..\u002F..\u002Fdevian-examples\u002F22-game-server-webgl\u002FSKILL.md) — WebGL 서버 예제\n",{},"main","8cb5bd877a3a7004867d2f55697cb9e4ff2f1734","skills\u002Fdevian\u002F80-tools\u002F30-env-management","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian","https:\u002F\u002Fgithub.com\u002Fdevwinsoft","Kim Hyong Joon","2026-04-12 18:44:10",{"source":7,"skillName":5,"commands":32,"prompt":42,"zipAvailable":43},[33,36,39],{"tool":34,"command":35},"npx","npx skills add devwinsoft\u002Fdevian --skill 30-env-management",{"tool":37,"command":38},"bunx","bunx skills add devwinsoft\u002Fdevian --skill 30-env-management",{"tool":40,"command":41},"pnpm","pnpm dlx skills add devwinsoft\u002Fdevian --skill 30-env-management","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F30-env-management\u002FSKILL.md",true,[45],{"path":46,"resourceType":47,"resourceTypeDesc":48,"sizeBytes":49,"sourceHtmlUrl":50},"agents\u002Fopenai.yaml","REFERENCE","参考文档",161,"https:\u002F\u002Fgithub.com\u002Fmalinskibeniamin\u002Fskills\u002Fblob\u002Fmain\u002Fcodex-skills\u002Fmatt-codebase-design\u002Fagents\u002Fopenai.yaml",[52,58,66,75,82,89],{"skillNo":53,"name":54,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":55,"categories":56,"keywords":57,"publishedAt":20},"01M6CBX3K2JJV38ANHVGCAT8A0","devian","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002FSKILL.md",[],[54],{"skillNo":59,"name":60,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":61,"categories":62,"keywords":63,"publishedAt":20},"01M6CBX210BFMM8AMN770J9WY8","90-project-archive","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F90-project-archive\u002FSKILL.md",[],[64,65],"archive","90 project archive",{"skillNo":67,"name":68,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":69,"categories":70,"keywords":71,"publishedAt":20},"01M6CBWYD3TGWBQV7V35551THF","19-page-push-send","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F19-page-push-send\u002FSKILL.md",[],[72,73,74],"push","page","19 page push send",{"skillNo":76,"name":77,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":78,"categories":79,"keywords":80,"publishedAt":20},"01M6CBWWRQ05A7604GHJKTPJTF","18-page-savedata","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F18-page-savedata\u002FSKILL.md",[],[73,81],"18 page savedata",{"skillNo":83,"name":84,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":20},"01M6CBWVH4S2VF1V7B2GBTESCT","17-page-deobfuscate","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F17-page-deobfuscate\u002FSKILL.md",[],[73,88],"17 page deobfuscate",{"skillNo":90,"name":91,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":94,"publishedAt":20},"01M6CBWSZG5BN4YTA8SRXXF8YP","16-page-obfuscate","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F16-page-obfuscate\u002FSKILL.md",[],[73,95],"16 page obfuscate"]