Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,50 @@ jobs:

- name: Build
run: pnpm run build

app:
name: App
runs-on: ubuntu-latest
defaults:
run:
working-directory: app
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
package_json_file: app/package.json

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: app/pnpm-lock.yaml

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Check Expo dependencies
run: pnpm exec expo install --check

- name: Lint
run: pnpm run lint

- name: Typecheck
run: pnpm run typecheck

- name: Unit test
run: pnpm run test

- name: Build iOS bundle
run: pnpm run build:ios
env:
EXPO_PUBLIC_WEBVIEW_BASE_URL: https://example.com

- name: Build Android bundle
run: pnpm run build:android
env:
EXPO_PUBLIC_WEBVIEW_BASE_URL: https://example.com
40 changes: 28 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@
- 함께한 사람, 감정, 내용, 날짜·시간, 날씨, 사진을 나눠 입력하는 기록 작성
- 기록 상세 조회·수정과 1년 전 오늘 회고
- 홈 기본 기간, 개인 태그, 다크 모드 설정
- 모바일 브라우저와 설치형 PWA를 고려한 스택 내비게이션
- 모바일 브라우저·PWA의 Stackflow 내비게이션과 모바일 앱의 RN 멀티 WebView 스택

## 저장소 구성

| 경로 | 구성 | 설명 |
| -------------------------------- | ----------------------------------------- | ---------------------------------- |
| [`frontend/`](frontend/) | React 19, Vite, Stackflow, TanStack Query | 모바일 우선 웹·PWA |
| [`app/`](app/) | Expo Router, React Native WebView | RN 스택 기반 모바일 앱 |
| [`backend/`](backend/) | Kotlin, Spring Boot, JPA | 인증, 사람, 기록, 타임라인, 칩 API |
| [`docs/prd/`](docs/prd/) | Markdown | 화면별 제품 요구사항 |
| [`backend/docs/`](backend/docs/) | Markdown | mustpass와 로컬·배포·운영 절차 |
Expand All @@ -53,11 +54,11 @@

### 준비물

| 도구 | 버전 |
| ------- | ------------------ |
| Node.js | 20.19+ 또는 22.12+ |
| pnpm | 10+ |
| Docker | Compose v2 포함 |
| 도구 | 버전 |
| ------- | --------------------------------------- |
| Node.js | frontend 20.19+ 또는 22.12+, app 22.13+ |
| pnpm | 10+ |
| Docker | Compose v2 포함 |

### 1. 백엔드

Expand Down Expand Up @@ -98,11 +99,26 @@ BACKEND_URL=http://localhost:8080 pnpm dev:vite

사진 업로드까지 확인하려면 Vercel 프로젝트와 Blob 환경변수가 필요합니다. 설정 방법은 [프런트엔드 README](frontend/README.md#사진-업로드)에 있습니다.

### 3. 모바일 앱

프런트엔드를 실행한 상태에서 별도 터미널을 사용합니다.

```bash
cd app
cp .env.example .env.local
pnpm install
pnpm ios
# 또는 pnpm android
```

Android 에뮬레이터와 실기기의 WebView 주소 설정은 [앱 README](app/README.md)를 참고합니다.

## 문서

| 문서 | 내용 |
| ---------------------------------------------------- | ------------------------------- |
| [프런트엔드 README](frontend/README.md) | 실행 모드, 구조, API 생성, 검증 |
| [백엔드 README](backend/README.md) | API와 화면별 엔드포인트 |
| [로컬 백엔드 Runbook](backend/docs/runbook/local.md) | Docker·H2 실행과 데이터 리셋 |
| [제품 PRD](docs/prd/README.md) | 제품 범위와 화면별 기준 |
| 문서 | 내용 |
| ---------------------------------------------------- | -------------------------------- |
| [프런트엔드 README](frontend/README.md) | 실행 모드, 구조, API 생성, 검증 |
| [앱 README](app/README.md) | Expo 앱 실행과 WebView 주소 설정 |
| [백엔드 README](backend/README.md) | API와 화면별 엔드포인트 |
| [로컬 백엔드 Runbook](backend/docs/runbook/local.md) | Docker·H2 실행과 데이터 리셋 |
| [제품 PRD](docs/prd/README.md) | 제품 범위와 화면별 기준 |
3 changes: 3 additions & 0 deletions app/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# WebView에서 로드할 frontend origin
# Android 에뮬레이터는 localhost 대신 10.0.2.2 사용
EXPO_PUBLIC_WEBVIEW_BASE_URL=http://localhost:3000
7 changes: 7 additions & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules/
.expo/
dist/
ios/
android/
.env*.local
*.tsbuildinfo
1 change: 1 addition & 0 deletions app/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node-linker=hoisted
26 changes: 26 additions & 0 deletions app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Mongle App

Expo Router의 네이티브 스택 위에 Mongle frontend를 여러 WebView로 띄우는 모바일 앱입니다.

- 첫 화면은 `/home`을 로드하는 루트 WebView입니다.
- 웹에서 activity를 push하면 RN 스택에 새 WebView가 추가됩니다.
- 웹의 replace와 여러 단계 pop도 RN 스택에서 처리합니다.
- 하단 +·기록 수정은 아래에서 올라오는 full-screen modal, 인물에서 시작한 기록은 일반 push로 표시합니다.
- 상세 화면에서 돌아오면 아래 WebView의 활성 query를 다시 조회합니다.
- 모바일 브라우저에서는 이 브리지가 활성화되지 않고 기존 Stackflow가 계속 내비게이션을 담당합니다.
- WebView는 설정한 frontend와 같은 origin만 로드하고, 허용한 외부 URL은 시스템 앱으로 엽니다.

## 실행

Node.js 22.13 이상과 pnpm 10이 필요합니다.

```bash
cp .env.example .env.local
pnpm install
pnpm ios
# 또는 pnpm android
```

`EXPO_PUBLIC_WEBVIEW_BASE_URL`에는 frontend 주소를 지정합니다. iOS 시뮬레이터는
`http://localhost:3000`, Android 에뮬레이터는 `http://10.0.2.2:3000`, 실기기는 같은
네트워크에서 접근 가능한 개발 머신 주소를 사용합니다.
14 changes: 14 additions & 0 deletions app/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"expo": {
"name": "Mongle",
"slug": "mongle",
"version": "1.0.0",
"orientation": "portrait",
"scheme": "mongle",
"userInterfaceStyle": "automatic",
"plugins": ["expo-router"],
"experiments": {
"typedRoutes": true
}
}
}
4 changes: 4 additions & 0 deletions app/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const { defineConfig } = require('eslint/config')
const expoConfig = require('eslint-config-expo/flat')

module.exports = defineConfig([expoConfig, { ignores: ['dist/*'] }])
40 changes: 40 additions & 0 deletions app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "@mongle/app",
"version": "1.0.0",
"private": true,
"main": "expo-router/entry",
"packageManager": "pnpm@10.30.1",
"engines": {
"node": ">=22.13.0"
},
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"build:android": "expo export --platform android --output-dir dist/android",
"build:ios": "expo export --platform ios --output-dir dist/ios",
"lint": "expo lint",
"test": "vitest run",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"expo": "~57.0.7",
"expo-constants": "~57.0.6",
"expo-linking": "~57.0.3",
"expo-router": "~57.0.7",
"react": "19.2.3",
"react-dom": "19.2.3",
"react-native": "0.86.0",
"react-native-gesture-handler": "~2.32.0",
"react-native-safe-area-context": "~5.7.0",
"react-native-screens": "4.25.2",
"react-native-webview": "13.16.1"
},
"devDependencies": {
"@types/react": "^19.2.0",
"eslint": "^9.39.4",
"eslint-config-expo": "~57.0.0",
"typescript": "~6.0.3",
"vitest": "^4.1.5"
}
}
Loading
Loading