From 799b975406c33e8ecfdacb8052c30bba00f802fd Mon Sep 17 00:00:00 2001
From: ian
Date: Thu, 16 Apr 2026 13:54:11 +0900
Subject: [PATCH] =?UTF-8?q?=EA=B3=B5=EA=B0=9C:=20=ED=94=8C=EB=9E=AB?=
=?UTF-8?q?=ED=8F=BC=20=EA=B2=B0=EB=A1=A0=EA=B3=BC=20=EB=A6=B4=EB=A6=AC?=
=?UTF-8?q?=EC=A6=88=20=EB=85=B8=ED=8A=B8=20=EA=B7=9C=EC=B9=99=20=EB=B0=98?=
=?UTF-8?q?=EC=98=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/release-portable.yml | 54 ++--
CHANGELOG.md | 5 +
CLIENT_PLATFORM_DECISION.md | 160 ++++++++++
DEVELOPMENT.md | 29 +-
PROJECT_STATUS.md | 21 +-
PhysOn.sln | 7 +
README.md | 18 +-
RELEASING.md | 12 +-
ROADMAP.md | 18 +-
deploy/Caddyfile | 4 +-
docs/assets/latest/README.md | 1 +
docs/assets/latest/kotalk-android-mockup.png | Bin 0 -> 80622 bytes
packaging/windows/KoTalkInstaller.nsi | 85 +++++
release-assets/README.md | 21 +-
release-assets/templates/RELEASE_NOTES.ko.md | 4 +-
.../branding/generate_android_icon_assets.py | 50 +++
scripts/release/build-android-apk.sh | 119 +++++++
.../release/build-windows-distributions.sh | 130 ++++++++
scripts/release/release-prepare-assets.sh | 296 ++++++++++++++++--
scripts/release/release-publish-forge.sh | 8 +-
scripts/release/release-publish-github.sh | 8 +-
src/PhysOn.Desktop/PhysOn.Desktop.csproj | 8 +-
.../ViewModels/MainWindowViewModel.cs | 2 +-
src/PhysOn.Mobile.Android/AndroidManifest.xml | 14 +
src/PhysOn.Mobile.Android/MainActivity.cs | 268 ++++++++++++++++
.../PhysOn.Mobile.Android.csproj | 37 +++
.../Resources/AboutResources.txt | 44 +++
.../drawable/retry_button_background.xml | 6 +
.../Resources/layout/activity_main.xml | 52 +++
.../Resources/mipmap-anydpi-v26/appicon.xml | 4 +
.../mipmap-anydpi-v26/appicon_round.xml | 4 +
.../Resources/mipmap-hdpi/appicon.png | Bin 0 -> 1328 bytes
.../mipmap-hdpi/appicon_background.png | Bin 0 -> 229 bytes
.../mipmap-hdpi/appicon_foreground.png | Bin 0 -> 1374 bytes
.../Resources/mipmap-mdpi/appicon.png | Bin 0 -> 940 bytes
.../mipmap-mdpi/appicon_background.png | Bin 0 -> 142 bytes
.../mipmap-mdpi/appicon_foreground.png | Bin 0 -> 1010 bytes
.../Resources/mipmap-xhdpi/appicon.png | Bin 0 -> 1721 bytes
.../mipmap-xhdpi/appicon_background.png | Bin 0 -> 295 bytes
.../mipmap-xhdpi/appicon_foreground.png | Bin 0 -> 1859 bytes
.../Resources/mipmap-xxhdpi/appicon.png | Bin 0 -> 2528 bytes
.../mipmap-xxhdpi/appicon_background.png | Bin 0 -> 436 bytes
.../mipmap-xxhdpi/appicon_foreground.png | Bin 0 -> 2749 bytes
.../Resources/mipmap-xxxhdpi/appicon.png | Bin 0 -> 3267 bytes
.../mipmap-xxxhdpi/appicon_background.png | Bin 0 -> 594 bytes
.../mipmap-xxxhdpi/appicon_foreground.png | Bin 0 -> 3387 bytes
.../Resources/values/colors.xml | 8 +
.../values/ic_launcher_background.xml | 4 +
.../Resources/values/strings.xml | 4 +
.../Resources/values/styles.xml | 8 +
.../Resources/xml/network_security_config.xml | 4 +
src/PhysOn.Web/package-lock.json | 4 +-
src/PhysOn.Web/package.json | 2 +-
src/PhysOn.Web/src/App.tsx | 2 +-
문서/33-platform-capability-matrix.md | 28 +-
55 files changed, 1439 insertions(+), 114 deletions(-)
create mode 100644 CLIENT_PLATFORM_DECISION.md
create mode 100644 docs/assets/latest/kotalk-android-mockup.png
create mode 100644 packaging/windows/KoTalkInstaller.nsi
create mode 100755 scripts/branding/generate_android_icon_assets.py
create mode 100755 scripts/release/build-android-apk.sh
create mode 100755 scripts/release/build-windows-distributions.sh
create mode 100644 src/PhysOn.Mobile.Android/AndroidManifest.xml
create mode 100644 src/PhysOn.Mobile.Android/MainActivity.cs
create mode 100644 src/PhysOn.Mobile.Android/PhysOn.Mobile.Android.csproj
create mode 100644 src/PhysOn.Mobile.Android/Resources/AboutResources.txt
create mode 100644 src/PhysOn.Mobile.Android/Resources/drawable/retry_button_background.xml
create mode 100644 src/PhysOn.Mobile.Android/Resources/layout/activity_main.xml
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-anydpi-v26/appicon.xml
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-anydpi-v26/appicon_round.xml
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-hdpi/appicon.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-hdpi/appicon_background.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-hdpi/appicon_foreground.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-mdpi/appicon.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-mdpi/appicon_background.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-mdpi/appicon_foreground.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-xhdpi/appicon.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-xhdpi/appicon_background.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-xhdpi/appicon_foreground.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-xxhdpi/appicon.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-xxhdpi/appicon_background.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-xxhdpi/appicon_foreground.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-xxxhdpi/appicon.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-xxxhdpi/appicon_background.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/mipmap-xxxhdpi/appicon_foreground.png
create mode 100644 src/PhysOn.Mobile.Android/Resources/values/colors.xml
create mode 100644 src/PhysOn.Mobile.Android/Resources/values/ic_launcher_background.xml
create mode 100644 src/PhysOn.Mobile.Android/Resources/values/strings.xml
create mode 100644 src/PhysOn.Mobile.Android/Resources/values/styles.xml
create mode 100644 src/PhysOn.Mobile.Android/Resources/xml/network_security_config.xml
diff --git a/.github/workflows/release-portable.yml b/.github/workflows/release-portable.yml
index d12184b..9ad929d 100644
--- a/.github/workflows/release-portable.yml
+++ b/.github/workflows/release-portable.yml
@@ -31,7 +31,7 @@ permissions:
jobs:
build-windows:
- runs-on: windows-latest
+ runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -42,21 +42,30 @@ jobs:
with:
global-json-file: global.json
- - name: Restore desktop project
- run: dotnet restore src/PhysOn.Desktop/PhysOn.Desktop.csproj
+ - name: Install NSIS
+ run: sudo apt-get update && sudo apt-get install -y nsis
- - name: Publish portable desktop build
- run: dotnet publish src/PhysOn.Desktop/PhysOn.Desktop.csproj -c Release -r win-x64 --self-contained true -o out/win-x64
+ - name: Build Windows release assets
+ env:
+ VERSION_INPUT: ${{ github.event_name == 'workflow_dispatch' && inputs.version || github.ref_name }}
+ run: |
+ chmod +x scripts/release/build-windows-distributions.sh
+ ./scripts/release/build-windows-distributions.sh \
+ --version "$VERSION_INPUT" \
+ --output out
- - name: Create portable ZIP
- shell: pwsh
- run: Compress-Archive -Path out/win-x64/* -DestinationPath out/KoTalk-windows-x64.zip
+ cp out/KoTalk-windows-x64-"$VERSION_INPUT".zip out/KoTalk-windows-x64.zip
+ cp out/KoTalk-windows-x64-onefile-"$VERSION_INPUT".exe out/KoTalk-windows-x64-onefile.exe
+ cp out/KoTalk-windows-x64-installer-"$VERSION_INPUT".exe out/KoTalk-windows-x64-installer.exe
- name: Upload Windows artifact
uses: actions/upload-artifact@v4
with:
- name: windows-portable
- path: out/KoTalk-windows-x64.zip
+ name: windows-release
+ path: |
+ out/KoTalk-windows-x64.zip
+ out/KoTalk-windows-x64-onefile.exe
+ out/KoTalk-windows-x64-installer.exe
build-android:
if: ${{ hashFiles('src/PhysOn.Mobile.Android/*.csproj') != '' }}
@@ -80,23 +89,16 @@ jobs:
- name: Install Android workload
run: dotnet workload install android
- - name: Restore Android project
- run: dotnet restore src/PhysOn.Mobile.Android/PhysOn.Mobile.Android.csproj
-
- name: Publish Android APK
+ env:
+ VERSION_INPUT: ${{ github.event_name == 'workflow_dispatch' && inputs.version || github.ref_name }}
run: |
- dotnet publish src/PhysOn.Mobile.Android/PhysOn.Mobile.Android.csproj \
- -c Release \
- -f net8.0-android \
- -p:AndroidPackageFormat=apk \
- -p:AndroidKeyStore=false \
- -o out/android
+ chmod +x scripts/release/build-android-apk.sh
+ ./scripts/release/build-android-apk.sh \
+ --version "$VERSION_INPUT" \
+ --output out
- - name: Collect Android artifact
- run: |
- apk_path="$(find out/android -type f -name '*.apk' | head -n 1)"
- test -n "$apk_path"
- cp "$apk_path" out/KoTalk-android-universal.apk
+ cp out/KoTalk-android-universal-"$VERSION_INPUT".apk out/KoTalk-android-universal.apk
- name: Upload Android artifact
uses: actions/upload-artifact@v4
@@ -118,7 +120,7 @@ jobs:
- name: Download Windows artifact
uses: actions/download-artifact@v4
with:
- name: windows-portable
+ name: windows-release
path: incoming/windows
- name: Download Android artifact
@@ -149,6 +151,8 @@ jobs:
--version "$VERSION_INPUT"
--channel "$channel"
--windows-zip incoming/windows/KoTalk-windows-x64.zip
+ --windows-portable-exe incoming/windows/KoTalk-windows-x64-onefile.exe
+ --windows-installer-exe incoming/windows/KoTalk-windows-x64-installer.exe
--force
)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 759302b..32968ab 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,9 @@
### Added
+- Android WebView 기반 첫 APK 프로젝트와 `KoTalk-android-universal-*.apk` 산출물 경로 추가
+- Windows `installer exe + onefile exe + zip` 3종 배포 체인 추가
+- 모바일/iOS/Linux 프레임워크 결론 문서 `CLIENT_PLATFORM_DECISION.md` 추가
- 공개 원격용 버전 태그 생성 스크립트 `scripts/release/release-create-tag.sh`
- GitHub 릴리즈 게시 스크립트 `scripts/release/release-publish-github.sh`
- 제2·제3 공개 원격 순차 게시 스크립트 `scripts/release/release-publish-public.sh`
@@ -53,6 +56,8 @@
### Changed
+- 공개 릴리즈 Assets에서 스크린샷과 릴리즈 노트 첨부를 제거하고, 최신 화면은 변경 노트 본문에서 직접 확인하도록 조정
+- Android 상태를 `계획`에서 `첫 APK 기준선 확보` 단계로 상향하고, iOS/Linux 계획을 공개 문서에 명시
- 데스크톱/웹 스크린샷 캡처를 앱 창·앱 셸 기준으로 정리하고, README·SHOWCASE 이미지를 실제 종횡비에 맞춘 `width/height` 기준으로 재배치
- 공개 원격 배포 정책을 `public/* 브랜치 + 버전 태그 + 릴리즈 페이지 + 자산` 기준으로 고정
- Gitea/GitHub 릴리즈 게시 스크립트가 지정 원격 기준으로 동작하고 최신 스크린샷 자산도 함께 첨부하도록 확장
diff --git a/CLIENT_PLATFORM_DECISION.md b/CLIENT_PLATFORM_DECISION.md
new file mode 100644
index 0000000..18904bd
--- /dev/null
+++ b/CLIENT_PLATFORM_DECISION.md
@@ -0,0 +1,160 @@
+# Client Platform Decision
+
+마지막 정리일: `2026-04-16`
+
+## 결론
+
+KoTalk의 장기적인 네이티브 클라이언트 기준선은 **Avalonia 중심**으로 유지하는 편이 맞습니다.
+현재 Android의 WebView 셸은 `alpha` 단계의 빠른 APK 배포를 위한 전술적 경로로 유지하되, iOS와 Linux까지 포함하는 장기 클라이언트 전략은 Avalonia를 축으로 정리합니다.
+
+## 왜 다시 판단했는가
+
+초기에는 `Windows + mobile web + Android APK`만 빨리 닫는 것이 우선이었습니다. 그런데 이제 조건이 바뀌었습니다.
+
+- Android만이 아니라 iOS도 예정돼 있습니다.
+- Linux 공식 지원도 예정돼 있습니다.
+- Windows는 이미 네이티브 데스크톱 축으로 유지해야 합니다.
+- 저장소와 공식 서비스 모두에서 UI/UX 일관성을 더 강하게 요구받고 있습니다.
+
+즉, Android만 빨리 붙이는 기준이 아니라 `Windows + Android + iOS + Linux`를 함께 수용하는 클라이언트 구조가 필요해졌습니다.
+
+## 현재 기준선
+
+### 지금 이미 있는 것
+
+- Windows 네이티브 데스크톱 앱: Avalonia 기반
+- Mobile web: 실제 운영 중
+- Android: WebView 기반 첫 APK 셸 생성 가능
+
+### 지금 없는 것
+
+- iOS 클라이언트
+- Linux 네이티브 패키징
+- Android/iOS 전용 네이티브 경험을 공용 UI 축으로 가져가는 체계
+
+## 검토한 선택지
+
+### 1. Android/iOS를 계속 각각 별도 네이티브 셸로 유지
+
+장점:
+
+- 지금 당장 APK를 빠르게 배포하기 쉽다
+- 모바일 웹을 감싸는 방식이라 초기 유지 비용이 낮다
+
+한계:
+
+- Windows와 Linux 쪽 UI 자산을 재사용하기 어렵다
+- iOS까지 같은 방식으로 늘어나면 표면은 빠르게 늘지만 제품 일관성은 약해진다
+- 장기적으로는 플랫폼마다 다른 껍데기를 유지하게 된다
+
+판단:
+
+- **전술적으로는 유효**
+- **장기 기준선으로는 부적합**
+
+### 2. .NET MAUI로 장기 축 전환
+
+장점:
+
+- Android와 iOS, Windows까지 한 프레임워크로 묶기 좋다
+- 모바일 장치 API 접근이 익숙한 생태계다
+
+한계:
+
+- Microsoft 공식 문서 기준 `.NET MAUI`의 기본 지원 플랫폼은 Android, iOS, macOS, Windows다. Linux는 기본 축에 없다.
+- 현재 저장소의 Windows 클라이언트는 이미 Avalonia 기반이라, MAUI로 옮기면 데스크톱 축을 다시 크게 재구성해야 한다.
+
+판단:
+
+- **Linux 공식 지원 예정 조건과 현재 코드베이스 기준을 함께 놓고 보면, 주 프레임워크로 선택하기 어렵다**
+
+참고:
+
+- Microsoft Learn, “What is .NET MAUI?”:
+- Microsoft Learn, “Supported platforms for .NET MAUI apps”:
+
+### 3. Uno Platform으로 장기 축 전환
+
+장점:
+
+- 공식 문서 기준 Android, iOS, Web, macOS, Linux, Windows를 포괄한다
+- 광범위한 플랫폼 표면 자체는 매력적이다
+
+한계:
+
+- 현재 Windows 클라이언트가 Avalonia 기반이라, Uno로 가면 데스크톱 UI 자산과 운영 경험을 다시 맞춰야 한다
+- 지금 시점의 저장소 기준으로는 전환 비용이 작지 않다
+
+판단:
+
+- **대안으로는 충분히 검토 가능**
+- **하지만 현재 코드베이스를 고려하면 1순위는 아님**
+
+참고:
+
+- Uno Platform, “Supported platforms”:
+
+### 4. Avalonia를 장기 축으로 유지
+
+장점:
+
+- 현재 Windows 클라이언트가 이미 Avalonia 기반이다
+- 공식 문서 기준 Windows, Linux, iOS, Android, WebAssembly까지 포괄한다
+- 데스크톱 밀도, 멀티 윈도우, 플랫한 커스텀 UI를 유지하기 유리하다
+- Linux 공식 지원 예정이라는 조건과 가장 자연스럽게 맞는다
+
+전제 조건:
+
+- Avalonia 공식 문서 기준 데스크톱은 `.NET 8` 이상이지만, 모바일인 iOS/Android는 `.NET 10` 기준을 따른다
+- 따라서 현재 저장소의 `.NET 8` 기준선을 유지한 채 즉시 Android/iOS를 Avalonia로 통합하는 것은 현실적이지 않다
+
+주의:
+
+- 모바일은 데스크톱과 같은 방식으로 밀어붙이면 안 된다
+- 작은 화면, 제스처, OS 관례를 반영한 모바일 전용 UX 조정은 별도로 필요하다
+- 현재 Android alpha 셸을 곧바로 폐기할 필요는 없지만, 장기적으로는 공용 UI 구조와의 관계를 분명히 해야 한다
+
+판단:
+
+- **현 시점 KoTalk의 가장 현실적인 장기 기준선**
+
+참고:
+
+- Avalonia Docs, “Supported platforms”:
+- Avalonia Docs, “Welcome / What is Avalonia?”:
+
+## 최종 결정
+
+### 전술
+
+- Android는 당분간 현재 WebView 셸을 유지합니다.
+- 이유는 APK 배포, 설치 동선 검증, 알파 피드백 수집을 빠르게 계속하기 위해서입니다.
+- 현재 저장소가 `.NET 8` 기준선이므로, 모바일 공용 UI로 바로 넘어가기 전까지는 이 경로가 가장 안전합니다.
+
+### 전략
+
+- 장기적인 네이티브 클라이언트 축은 **Avalonia 기반 공유 구조**로 정리합니다.
+- 다만 이 단계는 `.NET 10` 모바일 기준선을 감당할 준비가 됐을 때 들어갑니다.
+- Windows와 Linux는 같은 데스크톱 계열 기준으로 묶습니다.
+- Android와 iOS는 같은 제품 경험 원칙 아래로 수렴시키되, 모바일 전용 UX 조정은 별도 계층으로 둡니다.
+
+## 배포 원칙
+
+- 자체 미러와 공개 저장소 Assets:
+ - Windows installer / onefile / zip
+ - Android APK
+- Apple 배포 채널:
+ - iOS는 저장소 Assets나 자체 미러 직접 배포가 아니라 Apple 채널을 전제로 준비합니다
+
+## 지금 바로 바뀌는 문장
+
+- `Android는 계획 단계`라고 쓰지 않습니다.
+- `Android APK 기준선은 확보됐고, 장기 모바일 전략은 재정의 중`이라고 씁니다.
+- `iOS와 Linux는 예정`이라고 공개적으로 적되, 아직 완성된 것처럼 쓰지 않습니다.
+
+## 다음 실행 항목
+
+1. Android alpha 셸을 유지하면서 배포와 설치 루프를 먼저 안정화
+2. `.NET 10` 전환 부담과 시점을 포함해 Avalonia 기반 공유 클라이언트 구조를 설계
+3. Linux 패키징 기준선 정리
+4. iOS 배포 준비 문서와 빌드 전제 정리
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index 581d5f9..ea47375 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -80,22 +80,21 @@ dotnet test PhysOn.sln -c Debug
Windows:
```bash
-dotnet publish src/PhysOn.Desktop/PhysOn.Desktop.csproj \
- -c Release \
- -r win-x64 \
- --self-contained true \
- -o artifacts/release/v0.1.0-alpha.1-win-x64
+./scripts/release/build-windows-distributions.sh \
+ --version 2026.04.16-alpha.6
```
+생성물:
+
+- `KoTalk-windows-x64-.zip`
+- `KoTalk-windows-x64-onefile-.exe`
+- `KoTalk-windows-x64-installer-.exe`
+
Android:
```bash
-dotnet workload install android
-dotnet publish src/PhysOn.Mobile.Android/PhysOn.Mobile.Android.csproj \
- -c Release \
- -f net8.0-android \
- -p:AndroidPackageFormat=apk \
- -o artifacts/release/android
+./scripts/release/build-android-apk.sh \
+ --version 2026.04.16-alpha.6
```
공개 산출물 네이밍은 `KoTalk-*` 기준으로 정리하는 방향이고, 현재 내부 스크립트와 프로젝트명은 별도 정렬 단계에 있습니다.
@@ -104,10 +103,12 @@ dotnet publish src/PhysOn.Mobile.Android/PhysOn.Mobile.Android.csproj \
```bash
./scripts/release/release-prepare-assets.sh \
- --version v0.1.0-alpha.1 \
+ --version 2026.04.16-alpha.6 \
--channel alpha \
- --windows-zip artifacts/release/PhysOn-win-x64-v0.1.0-alpha.1.zip \
- --android-apk artifacts/release/PhysOn-android-universal-v0.1.0-alpha.1.apk \
+ --windows-zip artifacts/builds/2026.04.16-alpha.6/KoTalk-windows-x64-2026.04.16-alpha.6.zip \
+ --windows-portable-exe artifacts/builds/2026.04.16-alpha.6/KoTalk-windows-x64-onefile-2026.04.16-alpha.6.exe \
+ --windows-installer-exe artifacts/builds/2026.04.16-alpha.6/KoTalk-windows-x64-installer-2026.04.16-alpha.6.exe \
+ --android-apk artifacts/builds/2026.04.16-alpha.6/KoTalk-android-universal-2026.04.16-alpha.6.apk \
--screenshots artifacts/screenshots \
--force
```
diff --git a/PROJECT_STATUS.md b/PROJECT_STATUS.md
index 320cb42..2c6081c 100644
--- a/PROJECT_STATUS.md
+++ b/PROJECT_STATUS.md
@@ -9,7 +9,7 @@
| Public brand | `KoTalk` |
| Stage | `Alpha` |
| Most usable surface | Mobile web live + Windows build |
-| Biggest current gap | Android 실빌드와 데스크톱 멀티윈도우 완성도 |
+| Biggest current gap | 네이티브 모바일 공용 UI 수렴과 데스크톱 멀티윈도우 완성도 |
| Signup direction | 공개형 1회성 인증 중심으로 재설계 중 |
| Tone of this repo | 현재 동작 범위와 남은 갭을 함께 적는 제품형 저장소 |
@@ -19,6 +19,7 @@ KoTalk는 아직 모든 플랫폼이 완성된 상태는 아니지만, “문서
- Windows 데스크톱 클라이언트 빌드
- 모바일 웹 실서비스 채널
+- Android APK 빌드 기준선
- 기본 인증, 최근 대화, 메시지 전송, 읽기 커서, 세션 복구 루프
- 최신 기준 스크린샷 세트
- 릴리즈 경로와 다운로드 경로 문서
@@ -29,8 +30,10 @@ KoTalk는 아직 모든 플랫폼이 완성된 상태는 아니지만, “문서
|---|---|---|---|
| Windows desktop | 저장소 빌드 / 릴리즈 산출물 | Buildable | 핵심 메시징 루프 검증 가능 |
| Mobile web | [vstalk.phy.kr](https://vstalk.phy.kr) | Live | 가입, 대화, 검색, 보관 1차 흐름 제공 |
-| Android | 저장소 릴리즈 예정 | In progress | 문서와 배포 구조 우선 정리 중 |
-| Official mirror | [download-vstalk.phy.kr](https://download-vstalk.phy.kr) | Live | Windows latest와 version manifest를 HTTPS로 제공 |
+| Android | 저장소 APK / 릴리즈 파이프라인 | Buildable | alpha WebView 셸과 APK 산출물 생성 가능 |
+| iOS | Apple 배포 채널 예정 | Planned | 자체 미러가 아닌 Apple 채널 전제 |
+| Linux | 저장소 빌드 예정 | Planned | Windows와 같은 공유 UI 축으로 준비 |
+| Official mirror | [download-vstalk.phy.kr](https://download-vstalk.phy.kr) | Live | Windows latest, Android latest, version manifest를 HTTPS로 제공 |
## Verified Now
@@ -38,6 +41,7 @@ KoTalk는 아직 모든 플랫폼이 완성된 상태는 아니지만, “문서
- Windows 클라이언트는 저장소 기준으로 빌드 가능한 상태입니다.
- 모바일 웹은 [vstalk.phy.kr](https://vstalk.phy.kr)에서 공개 중입니다.
+- Android APK는 저장소 기준으로 생성 가능한 상태입니다.
- 기본 메시징 루프와 세션 복구 흐름은 구현돼 있습니다.
- 검색, 보관, 빈 상태 UX는 1차 개편이 반영돼 있습니다.
- 최신 스크린샷은 저장소에 함께 보관됩니다.
@@ -66,7 +70,9 @@ KoTalk는 아직 모든 플랫폼이 완성된 상태는 아니지만, “문서
## In Progress
-- Android 첫 실사용 빌드
+- Android APK 서명과 배포 품질 정리
+- iOS 채널 준비와 Apple 배포 절차 정리
+- Linux 네이티브 패키징 기준선
- 릴리즈 페이지와 미러 간 latest 라우트 통합
- 검색 범위 확장
- 파일 전송
@@ -76,10 +82,12 @@ KoTalk는 아직 모든 플랫폼이 완성된 상태는 아니지만, “문서
아직 부족한 부분도 그대로 남깁니다.
-- Android 실사용 빌드는 아직 제공되지 않습니다.
+- Android는 현재 WebView 셸 중심의 첫 APK 기준선으로, 네이티브 모바일 경험은 더 다듬어야 합니다.
+- iOS 클라이언트는 아직 시작되지 않았습니다.
+- Linux 클라이언트는 장기 목표로만 정리돼 있습니다.
- 파일 전송은 미구현입니다.
- 검색은 전역 파일/링크/사람 범위까지 확장되지 않았습니다.
-- 공식 다운로드 미러는 현재 Windows latest와 version manifest 기준으로 동작합니다.
+- 공식 다운로드 미러는 현재 Windows latest, Android latest, version manifest 기준으로 동작합니다.
- 데스크톱 멀티 윈도우는 방향은 잡혀 있지만, 실제 생산성 흐름은 더 다듬어야 합니다.
## Download And Release Paths
@@ -111,3 +119,4 @@ KoTalk는 아직 모든 플랫폼이 완성된 상태는 아니지만, “문서
- 라이브 우선순위: [문서/35-live-user-review-and-priority-backlog.md](문서/35-live-user-review-and-priority-backlog.md)
- 가입/온보딩 정책: [문서/10-signup-onboarding-and-auth-policy.md](문서/10-signup-onboarding-and-auth-policy.md)
- 신뢰와 보안 표면: [TRUST_CENTER.md](TRUST_CENTER.md), [SECURITY.md](SECURITY.md)
+- 클라이언트 플랫폼 결론: [CLIENT_PLATFORM_DECISION.md](CLIENT_PLATFORM_DECISION.md)
diff --git a/PhysOn.sln b/PhysOn.sln
index 2e37bd4..6d0ff60 100644
--- a/PhysOn.sln
+++ b/PhysOn.sln
@@ -23,6 +23,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{04EBE1E2
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhysOn.Api.IntegrationTests", "tests\PhysOn.Api.IntegrationTests\PhysOn.Api.IntegrationTests.csproj", "{38821CD9-915B-4C96-8A35-11BDE991C16E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhysOn.Mobile.Android", "src\PhysOn.Mobile.Android\PhysOn.Mobile.Android.csproj", "{FD4774AB-47F7-4C47-BCC7-FD97BCBF4101}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -64,6 +66,10 @@ Global
{38821CD9-915B-4C96-8A35-11BDE991C16E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{38821CD9-915B-4C96-8A35-11BDE991C16E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{38821CD9-915B-4C96-8A35-11BDE991C16E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FD4774AB-47F7-4C47-BCC7-FD97BCBF4101}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FD4774AB-47F7-4C47-BCC7-FD97BCBF4101}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FD4774AB-47F7-4C47-BCC7-FD97BCBF4101}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FD4774AB-47F7-4C47-BCC7-FD97BCBF4101}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{DD8A5885-9647-4248-A0B2-C8695BBFB54E} = {BD1AEF6A-5B59-4DAC-82C9-1983916200FB}
@@ -74,5 +80,6 @@ Global
{925D92EC-965D-44D9-A3FF-011E1815C9EE} = {BD1AEF6A-5B59-4DAC-82C9-1983916200FB}
{90EF510F-E338-45C4-9EF4-0A4916725EF0} = {BD1AEF6A-5B59-4DAC-82C9-1983916200FB}
{38821CD9-915B-4C96-8A35-11BDE991C16E} = {04EBE1E2-D374-4F58-A0D5-5062BB4674FA}
+ {FD4774AB-47F7-4C47-BCC7-FD97BCBF4101} = {BD1AEF6A-5B59-4DAC-82C9-1983916200FB}
EndGlobalSection
EndGlobal
diff --git a/README.md b/README.md
index 7f0179e..e1b9a78 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,10 @@
짧은 답장, 빠른 복귀, 설명 가능한 제품 표면, 그리고 한국어 사용 습관에 맞는 조용한 UI를 핵심 기준으로 삼습니다.
+
+ 현재는 Windows, 모바일 웹, Android APK 기준선을 운영하고 있으며, iOS와 Linux 네이티브 채널은 같은 제품 경험 안으로 수렴시키는 방향을 공개적으로 준비 중입니다.
+
+
@@ -31,6 +35,7 @@
Showcase ·
Background ·
Alternative Gap ·
+ Platform Strategy ·
Brand Guide ·
FAQ ·
Releases ·
@@ -61,8 +66,8 @@
| Layer | Current read |
|---|---|
| What this is | 한국어 UI, 낮은 피로도, 업무형 메시징 복귀 흐름을 중심에 둔 Windows-first 오픈소스 메신저 |
-| What works now | Windows 빌드, 모바일 웹 라이브, 기본 인증/대화/세션 루프 |
-| What is still moving | Android 첫 실빌드, 파일 전송, 검색 확장, 공개 다운로드 미러 정합성 |
+| What works now | Windows 빌드, 모바일 웹 라이브, Android APK 기준선, 기본 인증/대화/세션 루프 |
+| What is still moving | 파일 전송, 검색 확장, 네이티브 모바일 공용 UI 수렴, 공개 다운로드 미러 정합성 |
| What this repo tries to show | 화면, 빌드 산출물, 릴리즈 경로, 상태 문서, 배경 문서를 한 눈에 읽히게 정리한 제품형 저장소 |
## Why Now
@@ -156,14 +161,16 @@ KoTalk는 바로 그 비어 있는 결합점을 목표로 둡니다. 이 항목
|---|---|---|---|
| Windows desktop | 저장소 빌드와 버전별 산출물 | Buildable | 핵심 메시징 루프와 데스크톱 레이아웃 실험 진행 중 |
| Mobile web | [vstalk.phy.kr](https://vstalk.phy.kr) | Live | 가입, 대화, 검색, 보관 1차 흐름 검증 |
-| Android | 저장소 릴리즈 예정 | In progress | 문서와 배포 구조 우선 정리 중 |
-| Official download mirror | [download-vstalk.phy.kr](https://download-vstalk.phy.kr) | Live | Windows latest와 version manifest를 HTTPS로 제공 |
+| Android | 저장소 APK / 릴리즈 파이프라인 | Buildable | WebView 기반 alpha 셸과 APK 산출물 기준선 확보 |
+| iOS | Apple 배포 채널 예정 | Planned | 자체 미러 대신 App Store/TestFlight 전제 |
+| Linux | 저장소 빌드 예정 | Planned | 장기적으로 Windows와 같은 네이티브 클라이언트 축 |
+| Official download mirror | [download-vstalk.phy.kr](https://download-vstalk.phy.kr) | Live | Windows latest, Android latest, version manifest를 HTTPS로 제공 |
## Architecture Snapshot
KoTalk의 현재 구조는 지나치게 복잡한 플랫폼보다, 작은 조각을 조합해 실서비스와 로컬 빌드를 함께 검증하는 쪽에 가깝습니다.
-- 클라이언트: Windows 데스크톱 + 모바일 웹 + Android 예정
+- 클라이언트: Windows 데스크톱 + 모바일 웹 + Android APK 기준선 + iOS/Linux 예정
- API: 인증, 최근 대화, 메시지 전송, 읽기 커서, 세션 루프
- 배포: VPS 기반 same-origin 웹앱과 API 운영
- 공개 증거: 저장소 스크린샷, 빌드 산출물, 상태 문서, 릴리즈 경로
@@ -211,6 +218,7 @@ KoTalk의 현재 구조는 지나치게 복잡한 플랫폼보다, 작은 조각
- [ROADMAP.md](ROADMAP.md)
- [BUSINESS_MODEL.md](BUSINESS_MODEL.md)
- [ALTERNATIVE_GAP.md](ALTERNATIVE_GAP.md)
+- [CLIENT_PLATFORM_DECISION.md](CLIENT_PLATFORM_DECISION.md)
- [문서/01-product-strategy-and-mvp.md](문서/01-product-strategy-and-mvp.md)
- [문서/18-white-material-compact-ui-system.md](문서/18-white-material-compact-ui-system.md)
- [문서/22-work-communication-ux-playbook.md](문서/22-work-communication-ux-playbook.md)
diff --git a/RELEASING.md b/RELEASING.md
index b7a84ce..5d8a1a7 100644
--- a/RELEASING.md
+++ b/RELEASING.md
@@ -15,7 +15,7 @@ KoTalk의 릴리즈는 단순한 파일 업로드가 아니라, 산출물과 공
## Current Note
2026-04-16 기준 [download-vstalk.phy.kr](https://download-vstalk.phy.kr)는 DNS와 HTTPS가 정상입니다.
-현재는 Windows latest와 version manifest를 제공하고, 저장소 릴리즈 경로를 함께 유지합니다.
+현재 기준선은 Windows installer / onefile / zip, Android latest APK, version manifest를 함께 제공하는 구조입니다.
## Minimum Release Contract
@@ -25,13 +25,16 @@ KoTalk의 릴리즈는 단순한 파일 업로드가 아니라, 산출물과 공
4. 최신 스크린샷이 현재 UI를 대표해야 합니다.
5. 다운로드 경로와 릴리즈 링크가 함께 갱신돼야 합니다.
6. 공개 원격은 `브랜치 + 태그 + 릴리즈 페이지 + 자산`을 한 세트로 맞춥니다.
-7. 공개 릴리즈 페이지에는 산출물과 최신 스크린샷을 함께 게시합니다.
+7. 공개 릴리즈 페이지의 Assets는 실행 파일, 체크섬, 메타데이터처럼 실제 배포에 필요한 파일만 남깁니다.
+8. 최신 스크린샷은 Assets 첨부 대신 변경 노트 안에 담고, 다운로드 미러의 정적 경로를 이미지 소스로 사용합니다.
## Platform Policy
-- Windows: 빌드 산출물, 스크린샷, 체크섬을 함께 남깁니다.
+- Windows: installer, onefile portable, zip, 체크섬을 기본 산출물로 유지합니다.
- Mobile web: 라이브 반영이 있으면 스크린샷과 상태 문서를 함께 갱신합니다.
- Android: APK 공개 시 공식 미러와 저장소 릴리즈를 함께 맞춥니다.
+- iOS: 자체 미러나 저장소 Assets로 직접 배포하지 않고, Apple 배포 채널을 전제로 준비합니다.
+- Linux: Windows와 함께 장기적인 네이티브 클라이언트 축으로 다루며, 공유 UI 프레임워크 기준선을 유지합니다.
## Public Release Sequence
@@ -41,7 +44,8 @@ KoTalk의 릴리즈는 단순한 파일 업로드가 아니라, 산출물과 공
4. 제2 공개 레포에 브랜치와 태그를 푸시합니다.
5. 제2 공개 레포 릴리즈 페이지에 자산과 노트를 게시합니다.
6. 명시적 요청이 있을 때만 같은 태그와 자산을 제3 공개 레포에 게시합니다.
-7. `download-vstalk.phy.kr`는 최신 포인터만 유지합니다.
+7. `download-vstalk.phy.kr`는 `Windows latest landing`, `Android latest landing`, `latest/version.json` 포인터를 유지합니다.
+8. 공개 릴리즈 노트에는 최신 스크린샷을 포함하고, 공개 릴리즈 Assets에는 스크린샷을 첨부하지 않습니다.
## Release Scripts
diff --git a/ROADMAP.md b/ROADMAP.md
index dae7837..8485f15 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -3,7 +3,8 @@
## 현재 상태
- Alpha 가입, 대화 목록, 대화창, 텍스트 전송이 동작하는 첫 사용 가능 프로토타입 확보
-- Windows x64 portable build 생성 가능
+- Windows x64 installer / onefile / zip 생성 가능
+- Android APK alpha 기준선 생성 가능
- `vstalk.phy.kr` 모바일 웹앱과 API를 VPS에 실제 배포
- 원격 저장소에 최신 기준 스크린샷 포함 시작
- `vstalk.phy.kr` 모바일 웹앱 MVP 빌드 및 same-origin API 검증 완료
@@ -15,9 +16,11 @@
- [x] 메시지 전송
- [x] 읽기 커서 갱신
- [x] Windows portable zip 생성
+- [x] Windows installer / onefile / zip 생성
- [x] 모바일 웹앱 PWA 셸/가입/대화/전송
- [x] VPS 공개 API 상시 구동
- [x] `vstalk.phy.kr` same-origin 웹앱 배포
+- [x] Android WebView 셸과 첫 APK 생성
- [ ] 데스크톱 WebSocket 실시간 반영
## v0.2 Collaboration Basics
@@ -30,12 +33,19 @@
## v0.2 Android First-class
-- [ ] Android 셸/네비게이션 골격
-- [ ] Android 로그인/대화 목록/대화 진입 MVP
+- [x] Android 셸/네비게이션 골격
+- [x] Android 로그인/대화 목록/대화 진입 MVP 기준선
- [ ] APK 서명 및 산출물 규칙 확정
- [ ] Windows/Android 동시 릴리즈 메타데이터 검증
- [ ] Forge Releases + VPS 미러 동시 게시
+## v0.3 Shared Client Expansion
+
+- [ ] Avalonia 기반 공유 클라이언트 구조를 Android/iOS/Linux 관점으로 재정리
+- [ ] iOS 배포 채널 준비 문서와 빌드 체인 검증
+- [ ] Linux 패키징 기준선 확보
+- [ ] Android WebView 셸에서 네이티브 공용 UI 단계로 이행할 범위 정의
+
## v0.2 Mobile Web Entry
- [x] `vstalk.phy.kr` 모바일 웹 IA와 핵심 사용자 흐름 확정
@@ -89,6 +99,6 @@
- 하나의 태그는 하나의 릴리즈 레코드를 뜻합니다.
- 같은 버전 번호 아래에 Windows와 Android 자산을 함께 게시합니다.
-- 원격 저장소에는 최신 기준 스크린샷도 함께 포함합니다.
+- 원격 저장소 릴리즈 Assets에는 실행 파일과 체크섬만 두고, 최신 스크린샷은 변경 노트 안에서 참조합니다.
- 다운로드 미러와 원격 Releases는 같은 자산 이름과 같은 노트를 기준으로 맞춥니다.
- 모바일 웹은 설치형 산출물 대신 `https://vstalk.phy.kr`를 기준 진입점으로 관리합니다.
diff --git a/deploy/Caddyfile b/deploy/Caddyfile
index 5009816..96b0ad0 100644
--- a/deploy/Caddyfile
+++ b/deploy/Caddyfile
@@ -7,8 +7,8 @@
root * /srv/download
redir /windows /windows/latest 302
redir /android /android/latest 302
- redir /windows/latest /latest/KoTalk-windows-x64.zip 302
- redir /android/latest /latest/KoTalk-android-universal.apk 302
+ redir /windows/latest /latest/windows/index.html 302
+ redir /android/latest /latest/android/index.html 302
redir /latest /latest/version.json 302
header {
Content-Security-Policy "default-src 'none'; frame-ancestors 'none'; base-uri 'none'"
diff --git a/docs/assets/latest/README.md b/docs/assets/latest/README.md
index 9c6a8a5..478c8f9 100644
--- a/docs/assets/latest/README.md
+++ b/docs/assets/latest/README.md
@@ -13,4 +13,5 @@
- 현재 포함:
- Windows 데스크톱 셸
- Windows 온보딩/대화 화면
+ - Android APK shell 목업
- `vstalk` 모바일 웹 온보딩/목록/검색/보관/대화 화면
diff --git a/docs/assets/latest/kotalk-android-mockup.png b/docs/assets/latest/kotalk-android-mockup.png
new file mode 100644
index 0000000000000000000000000000000000000000..adbab6de2a63ff13216a0c7ba6c18c8ff26279d4
GIT binary patch
literal 80622
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