- EXE project kind next to MSIX: formats.exe, new EXE projects, EXE app info (architecture, UpgradeCode), per-kind workspace; EXE builds and signing are still refused explicitly (#9). - Install configuration tabs: registry grid, shortcuts and installer properties with formatted-text checks (#10). - Per-version .isver files: version list, add dialog, lock/unlock, delete with .isver.bak backups, description (#11). - Major/patch versions with cumulative patch checks and automatic kind selection (#12). - 설치화면 tab: setup steps, theme and scripts per version (#13). - Preferences: theme and display language (#14). - 설치파일 tab as an Explorer-style tree: per-row add/remove, Windows folder install locations (FileRule.targetRoot), picked files placed with FileRule.sourceFolder, unsaved-rule file preview (#17). Checks: cargo fmt/clippy/test, 82 frontend tests, Vite build and the msix-studio build pass. npm ci, GUI click tests and real EXE builds were not run. Refs #9 #10 #11 #12 #13 #14 #17 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
80 lines
8.3 KiB
Markdown
80 lines
8.3 KiB
Markdown
# Installer Studio 프로젝트 파일 형식
|
|
|
|
결정일: 2026-10-26. Installer Studio의 기본 프로젝트 확장자는 **`.isproj`**다. GUI·CLI의 생성·열기·저장에 적용했다. 사용자 요청에 따라 기존 JSON 프로젝트 호환·변환은 제공하지 않는다.
|
|
|
|
## 형식과 용도
|
|
|
|
`.isproj`는 설치 패키지 제작 설정을 보관하는 UTF-8 JSON 파일이다. ZIP·XML·실행 파일이 아니며, 내부 데이터는 기존 `PackageProject v2`와 `schemaVersion: 2`를 유지한다. 확장자 변경만으로 스키마 버전을 올리지 않는다.
|
|
|
|
예: `EG-BIM.isproj`, `BaronViewer.isproj`. MSIX 전용 확장자로 제한하지 않으며 후속 EXE/MSI 제작에도 같은 형식을 사용한다. 최종 배포 파일인 `.msix`, `.appinstaller`, `.exe`, `.msi`, `.msp`와 구분한다.
|
|
|
|
[MSIX 프로젝트 예제](examples/msix.isproj)는 기존 v2 예제의 내용을 유지하고 확장자만 적용한 설계용 파일이다. 미확정 값이 포함되어 있으므로 그대로 배포용 패키지를 만들 수 있다는 의미는 아니다. [EXE 프로젝트 예제](examples/exe.isproj)는 `upgradeCode`가 `null`인 템플릿이며 새 프로젝트를 만들 때 GUID를 채운다.
|
|
|
|
2026-10-27 결정: 별도의 `projectId` 필드를 화면과 저장 모델에서 제거했다. 제작기는 파일 경로로 프로젝트를 열고, MSIX 앱 계열은 `formats.msix.identity.name`과 `publisher`로 식별한다. 파일 이름이나 앱 표시 이름을 바꾸어도 MSIX Identity를 자동 변경하지 않는다. 향후 MSI 식별자도 별도로 관리한다. 새로운 제품으로 복제하는 기능은 별도의 명시적 작업으로 설계한다.
|
|
|
|
개발 중인 v2 계약에서 필드를 제거했으며 기존 호환·자동 변환은 제공하지 않는다. `projectId`가 남아 있는 파일은 알 수 없는 필드 오류로 거부한다. 사용자 파일과 기존 빌드 이력을 일괄 수정하지 않는다.
|
|
|
|
2026-11-09 결정: 같은 `.isproj` 형식으로 **MSIX 프로젝트**와 **EXE 프로젝트**를 만든다. 별도 `kind` 필드를 두지 않고 `formats`에 있는 형식 하나(`msix` 또는 `exe`)로 유형을 판단한다. 열기는 파일 유형에 맞는 작업 화면으로 이어지며, 유형이 모호한 파일은 열지 않고 저장으로 유형을 바꾸지 않는다. 세부 필드는 [프로젝트 모델](02-project-model.md)을 따른다.
|
|
|
|
2026-11-09 추가: 파일 규칙(`files[]`, 버전 파일의 `files[]`)에 선택 필드 `sourceFolder`를 둔다. 패턴이 시작하는 소스 안 폴더이며, 비어 있으면 소스 루트이고 파일에 쓰지 않는다. 그래서 이 필드가 없는 기존 파일은 그대로 열리고 저장해도 바이트가 바뀌지 않는다. 자세한 동작은 [설치파일 탐색기형 트리](../changes/2026-11-09-exe-file-tree.md)를 따른다.
|
|
|
|
2026-11-10 추가: 파일 규칙에 선택 필드 `targetRoot`(EXE만)를 둔다. 설치 폴더 대신 `targetRelativePath`가 시작할 Windows 폴더 속성(`CommonAppDataFolder` 등)이며, 비어 있으면 설치 폴더이고 파일에 쓰지 않는다. [설치파일의 Windows 기본 폴더 위치](../changes/2026-11-10-exe-target-roots.md) 참조.
|
|
|
|
## 파일과 작업 폴더
|
|
|
|
2026-11-09: EXE 프로젝트는 버전마다 `EG-BIM.versions/<버전>.isver` 메타파일을 둔다. 형식은 [프로젝트 모델](02-project-model.md)을 따른다. `.isproj`와 함께 형상 관리하고, 버전 파일의 `.bak`은 제외한다.
|
|
|
|
```text
|
|
project/
|
|
EG-BIM.isproj # 공유 가능한 제품/패키지 설정
|
|
EG-BIM.versions/ # EXE 전용: 버전별 설치파일·레지스트리·바로가기·ProductCode
|
|
1.13.1.isver
|
|
1.14.0.isver
|
|
EG-BIM.isproj.local.json # 해당 PC의 소스·SDK·서명 프로필 참조
|
|
EG-BIM.isproj.bak # 직전 프로젝트 저장본
|
|
EG-BIM.isproj.local.json.bak # 직전 로컬 설정 저장본
|
|
identity.lock.json
|
|
toolchain.lock.json
|
|
.work/
|
|
releases/
|
|
patches/
|
|
attestations/
|
|
```
|
|
|
|
로컬 설정과 백업 이름은 **전체 프로젝트 파일명에 접미사를 추가**하여 계산한다. 예를 들어 `EG-BIM.isproj`에 `.local.json` 또는 `.bak`를 붙인다. `.isproj`를 `.json.bak`로 치환하지 않는다. 로컬 설정·백업·인증서 개인 키는 형상 관리에서 제외한다. 프로젝트에는 개인 키나 비밀번호를 저장하지 않는다.
|
|
|
|
현재 디렉터리 단위의 작업·릴리스·lock 구조를 유지하므로 **작업 폴더 하나에 프로젝트 하나**를 둔다. 다른 이름으로 저장은 별도 작업 폴더를 사용하며, 기존 이력 폴더를 자동 복사하거나 다른 프로젝트와 합치지 않는다. 상대 경로는 대상 폴더 기준으로 다시 계산하고, 연결이 깨지는 소스는 저장 전에 안내한다.
|
|
|
|
## 생성·열기·저장
|
|
|
|
| 동작 | 설계 규칙 |
|
|
| --- | --- |
|
|
| 새 프로젝트 | 시작 화면의 새 MSIX/EXE 프로젝트 버튼 또는 CLI `init --kind msix|exe`. 기본 파일명 `InstallerProject.isproj`, 필터 `Installer Studio 프로젝트 (*.isproj)` |
|
|
| 프로젝트 열기 | `.isproj` 전용 필터. 기존 `.json` 파일은 공통 로더에서도 거부한다. |
|
|
| 확장자 처리 | `.isproj`는 대소문자 구분 없이 허용한다. 저장 이름에 확장자가 없으면 `.isproj`를 붙이고, 다른 확장자가 있으면 수정을 안내한다. `.isproj.isproj` 중복 생성을 금지한다. |
|
|
| 내용 검사 | 확장자뿐 아니라 JSON 파싱, `schemaVersion`, 필수 필드와 지원 대상 검증을 수행한다. 일반 JSON·상위 스키마·손상 파일은 프로젝트로 취급하지 않는다. |
|
|
| 저장 | `expectedRevision` 충돌 검사, 백업, 같은 볼륨의 임시 파일 쓰기와 원자적 교체를 사용한다. 실패 시 원본을 유지한다. |
|
|
| 최근 프로젝트 | 실제 `.isproj` 경로를 저장한다. 기존 JSON 항목은 숨기고 해당 ID로도 열지 못하게 한다. 기존 파일은 삭제하지 않는다. |
|
|
| CLI | `--project .\EG-BIM.isproj`를 표준 예제로 사용한다. GUI와 같은 로더·검증기를 공유한다. |
|
|
|
|
Windows 탐색기 연결은 후속 구현 항목이다. `.isproj`에 Installer Studio 아이콘과 열기 동작을 연결하고, 더블 클릭으로 받은 경로는 일반 프로젝트 열기와 같은 검증 및 미저장 변경 보호를 거친다. 경로를 셸 명령으로 실행하지 않는다. `.json` 전체의 기본 연결은 변경하지 않는다.
|
|
|
|
## 기존 형식 미지원과 구현 범위
|
|
|
|
기존 `.json` 프로젝트는 GUI·CLI·최근 목록을 포함한 모든 열기 경로에서 거부한다. 확장자를 생략한 새 프로젝트 이름에만 `.isproj`를 붙인다. `.json`을 지정한 생성 요청은 자동 변경하지 않는다.
|
|
|
|
기존 `package-project.local.json`으로 폴백하지 않는다. `.isproj.local.json`이 없으면 빈 로컬 설정으로 열고 소스·도구를 사용자가 연결한다. 기존 사용자 파일과 이력은 삭제하거나 이름을 바꾸지 않는다. 실행용 fixture와 새 샘플 생성 스크립트는 `.isproj`로 갱신했다.
|
|
|
|
일반 저장은 로컬 설정을 먼저 원자적으로 교체하고 프로젝트 교체가 실패하면 로컬 설정을 복구한다. 각 파일의 교체는 원자적이지만 프로세스 강제 종료·전원 차단까지 포함한 두 파일의 트랜잭션은 보장하지 않는다. 직전 `.bak` 파일을 보존한다.
|
|
|
|
탐색기 연결, 다른 이름으로 저장, 작업 폴더당 프로젝트 하나의 강제 검사는 후속 항목이다. 현재는 새 프로젝트와 일반 열기·저장을 지원한다.
|
|
|
|
## 구현 시 확인할 항목
|
|
|
|
- GUI의 생성·열기·저장 필터와 CLI가 `.isproj`를 같은 방식으로 처리하는지 확인한다.
|
|
- 한글·공백이 있는 파일명, 대문자 확장자, 확장자 생략·중복 입력을 확인한다.
|
|
- 기존 JSON 거부, 기존 로컬 설정 미참조, `.isproj`의 소스·SDK·서명 참조 저장을 확인한다.
|
|
- 프로젝트 ID 없이 생성·저장·열기·빌드가 가능하고, 일반 저장 전후 패키지 identity가 바뀌지 않는지 확인한다.
|
|
- 백업 이름, 외부 변경 충돌, 중간 저장 실패, 상대 경로 및 최근 목록 갱신을 확인한다.
|
|
- 탐색기 연결은 앱 배포 방식별 등록·제거와 경로 인자 전달을 별도 검증한다.
|