# Lab Reserve · 연구실 장비 예약

설치 없이 공통 HTTPS 주소에서 사용하는 한국어 장비 예약 앱입니다. HTML/CSS/JavaScript 프런트엔드, Supabase Auth·PostgreSQL·Realtime, Cloudflare Pages를 사용합니다. 예약 원본은 PostgreSQL에 저장합니다. 브라우저 저장소에 예약을 저장하는 데모는 제공하지 않습니다.

## 현재 결과와 빠른 시작

공통 HTTPS 주소는 [https://subvery.pages.dev/](https://subvery.pages.dev/)입니다. Cloudflare Pages와 GitHub `dptmej1116/subvery`의 `main` 연결을 완료하여 같은 주소로 자동 배포합니다. Supabase DB 구성과 공개 설정 연결도 완료했습니다. 기본 로그인은 이메일에 도착한 링크를 누르는 방식이며 프로그램 설치가 필요 없습니다. 최신 앱 배포 후 새 로그인 메일을 요청해 링크를 사용하세요. 선택적인 인증번호 입력은 나중에 운영 SMTP와 OTP 템플릿을 설정하면 코드 변경 없이 사용할 수 있습니다. 운영 SMTP는 아직 설정하지 않았습니다. 사용자가 지정한 인증 완료 계정을 첫 관리자(admin / approved)로 지정했습니다. 실제 브라우저 로그인 완료 확인은 별도입니다. 과거 요청에서 HTTP 429를 확인했지만 현재 소유자는 기본 링크 메일을 받고 있습니다. 두 실제 계정·두 브라우저의 실시간 사용 검증도 아직 미완료입니다. [배포 상태](docs/DEPLOYMENT.md), [현재 연결](docs/CONNECTION.md), [검증 결과](docs/VERIFICATION.md)에서 완료와 남은 작업을 확인하세요.

1. [최초 설정·배포](docs/SETUP.md): Supabase 프로젝트/메일 설정 → SQL 적용 → 관리자 지정 → Cloudflare 자동 배포
2. [사용·운영·업데이트](docs/OPERATIONS.md): 구성원 승인, 장비, 점검, 버전 적용, 백업
3. [실제 서비스 검증 절차](docs/LIVE-TESTS.md): 두 계정/브라우저, 동시 예약, 서버 권한, 복구, 배포 유지

## 파일

| 파일 | 용도 |
| --- | --- |
| `index.html`, `styles.css`, `app.js`, `core.mjs` | 화면·예약·인증·동기화·시간 처리 |
| `supabase/migrations/` | 테이블·제약·RLS·서버 RPC·Realtime를 재현하는 SQL |
| `supabase/email-templates/magic-link.html` | SMTP 설정 후 선택적으로 복사하는 인증번호 메일 템플릿 |
| `supabase/bootstrap_admin.sql` | 최초 관리자를 검증된 이메일로 지정하는 운영자용 SQL |
| `supabase/tests/` | SQL 권한·시간 충돌 검증 |
| `public-config.json` | 제공 Supabase 프로젝트의 공개 URL·publishable key |
| `config.example.js`, `.env.example` | 다른 프로젝트/로컬 덮어쓰기용 공개 설정 예시 |
| `scripts/build.mjs`, `_headers`, `wrangler.jsonc` | 정적 배포 빌드·캐시/보안 헤더·Pages 설정 |
| `.github/workflows/deploy.yml` | 검사·테스트·빌드 자동 검증, 선택적인 Direct Upload 배포 |
| `tests/live.mjs`, `tests/README.md` | 실제 테스트 계정 토큰으로 서버 동작 검증 |

## 내 컴퓨터에서 열기

Node.js 22 이상이 필요합니다. 사용자에게는 Node.js 설치가 필요 없습니다.

```powershell
npm run dev
```

터미널에 표시되는 `http://127.0.0.1:4173`을 여세요. `file://`로 직접 열지 마세요. 기본적으로 포함된 `public-config.json`을 읽으므로 공개 값을 다시 복사하지 않아도 됩니다. 다른 프로젝트로 바꾸려면 `config.example.js`를 `config.js`로 복사해 URL과 publishable key 두 값을 함께 바꾸세요. `config.js`는 커밋되지 않습니다.

```powershell
npm run check
npm test
npm run build
```

일반 `build`는 설정 누락/비밀키를 거부합니다. 서비스가 연결되지 않은 화면 검토를 명시적으로 할 때만 `npm run build:preview`를 사용하세요. `.env.example`은 설명용이며 자동으로 읽지 않습니다. 빌드 설정 우선순위는 환경변수 → 로컬 `config.js` → 포함된 `public-config.json`입니다. 같은 Supabase 프로젝트를 쓸 때 Cloudflare의 공개 환경변수 등록은 선택 사항입니다. 설정 세 곳이 모두 없을 때만 미설정으로 판단합니다.

## 구현 원칙

- 클라이언트는 사용자 JWT와 공개 publishable key만 사용합니다. `service_role`, secret key, DB/SMTP/Cloudflare 비밀값은 HTML과 저장소에 넣지 않습니다.
- 예약·점검은 같은 테이블의 활성 시간 구간을 사용하며 PostgreSQL의 배타 제약이 동시 충돌까지 차단합니다. 종료와 다음 시작이 같으면 허용합니다.
- 예약자·권한은 서버에서 결정합니다. UI를 우회한 요청도 RPC의 인증/승인/소유자 검사를 통과해야 합니다. 직접 테이블 쓰기를 허용하지 않습니다.
- Realtime의 변경 신호와 최신 서버 재조회로 화면을 갱신합니다. 최초 진입·연결 복구·화면 복귀에도 재조회합니다. 예약 취소는 상태 변경으로 전달하여 삭제 이벤트의 접근 제한 문제를 피합니다.
- 코드 버전은 `version.json`, 예약 데이터는 PostgreSQL에서 관리합니다. 재배포가 예약 테이블을 초기화하지 않습니다.

연구실별 독립 데이터베이스 프로젝트를 전제로 한 첫 버전입니다. 단계 템플릿·알림은 추후 별도 테이블/마이그레이션과 서버 작업으로 추가할 수 있습니다.






