제품명·헤더 로고 이미지 통일, 덱 이름 변경·조회 수 제거, 썸네일 홀드 미리보기를 누르는 동안만 표시하도록 수정하고 Tailwind CSS를 재빌드했다. Co-authored-by: Cursor <cursoragent@cursor.com>
6.0 KiB
6.0 KiB
NAS 배포 가이드 (UNIARE v4)
1. 사전 준비
- Ugreen NAS에 Docker(또는 Container Manager) 설치
- 프로젝트를 NAS에 클론 또는 동기화
Git LFS로 이미지 자산 pull 완료 확인
2. 환경변수 설정
cp .env.example .env
| 변수 | 설명 |
|---|---|
JWT_SECRET |
32자 이상 랜덤 문자열 (필수) |
ADMIN_EMAIL |
최초 관리자 이메일 |
ADMIN_PASSWORD |
최초 관리자 비밀번호 (8자+) |
WEB_PORT |
웹 노출 포트 (기본 44082, 기존 정적 사이트 포트 유지) |
CORS_ORIGINS |
옆 프로젝트 도메인 포함, 쉼표 구분 |
예시:
JWT_SECRET=your-random-secret-at-least-32-chars
ADMIN_EMAIL=admin@uniare.sori.studio
ADMIN_PASSWORD=your-secure-password
WEB_PORT=44082
CORS_ORIGINS=https://uniare.sori.studio,https://your-other-app.sori.studio,http://localhost:44082,http://127.0.0.1:44082,http://localhost:5500,http://127.0.0.1:5500
3. 로컬 테스트
한 줄 요약: 프로젝트 루트에서
npm start→ 브라우저 http://localhost:44082
회원가입·로그인·덱 저장은 API 서버가 떠 있어야 합니다.
HTML만 Live Server 등으로 열면 저장·로그인이 405 로 실패합니다.
빠른 시작 (권장)
npm start # 백그라운드 실행 (터미널 점유 안 함)
# 브라우저: http://localhost:44082
npm run logs # 로그 보기 (종료: Ctrl+C)
npm stop # 서버 종료
| 명령 | 설명 |
|---|---|
npm start |
Docker로 웹+API 백그라운드 기동 (일상 개발용) |
npm stop |
서버 종료 |
npm run logs |
API·Nginx 로그 스트리밍 |
npm run dev |
포그라운드 실행 (로그 붙어 있음, Ctrl+C로 서버도 종료) |
npm run api:dev |
API만 Node로 실행 (Live Server 병행 시) |
저장이 안 될 때
curl http://localhost:44082/api/v1/health→{"ok":true,...}가 나와야 함- 안 나오면
npm start다시 실행 npm run dev후Healthy에서 멈춘 것처럼 보여도 정상이지만,Ctrl+C하면 서버가 꺼짐 →npm start사용 권장- Live Server(
:5500)로 HTML만 연 경우 → 아래 방법 B 또는 반드시:44082사용
방법 A — Docker (npm start와 동일)
npm start
브라우저: http://localhost:44082 (Live Server 포트가 아님)
방법 B — API만 로컬 실행 (Live Server / Cursor 미리보기 사용 시)
터미널 1 — API:
cd api && npm install # 최초 1회
cd .. && npm run api:dev
터미널 2 — HTML은 Live Server 등으로 열기 (예: :5500)
.env의 CORS_ORIGINS에 Live Server 포트를 추가하세요:
CORS_ORIGINS=...,http://localhost:5500,http://127.0.0.1:5500
확인:
curl http://localhost:3000/api/v1/health
# → {"ok":true,"version":"4.0.0"}
405 오류가 나올 때
| 원인 | 해결 |
|---|---|
| API 미실행 | npm start (또는 npm run dev) |
| Live Server로 HTML만 연 경우 | POST /api/v1/...가 정적 서버로 가서 405 발생 → 방법 A 또는 B 사용 |
| Docker 미기동 | docker ps로 uniare-api, uniare-web 확인 |
4. Docker 기동 (NAS / 프로덕션)
# 프로덕션 스택 (Nginx + API)
docker compose -f docker-compose.prod.yml up -d --build
# API만 단독 (기존 웹서버가 정적 파일 서빙 중일 때)
docker compose up -d --build
확인:
curl http://localhost:44082/api/v1/health
# → {"ok":true,"version":"4.0.0"}
5. 기존 리버스 프록시 연동
이미 NAS에서 Nginx Proxy Manager, Traefik, Caddy 등을 쓰는 경우:
옵션 A — uniare-web 포트만 프록시 (권장)
https://uniare.sori.studio → http://NAS_IP:44082
uniare-web 컨테이너가 /api/와 정적 파일을 모두 처리합니다.
docker-compose.prod.yml은 프로젝트 루트 전체를 웹 루트로 열지 않고, 필요한 HTML·정적 폴더만 read-only로 마운트합니다.
따라서 .env, .git, api/, docs/ 같은 내부 파일은 Nginx에서 직접 노출되지 않습니다.
옵션 B — 기존 정적 호스팅 + API만 Docker
docker compose up -d(API만, 포트 3000)- 기존 웹서버에
nginx/uadeck.conf규칙 추가:
location ~ ^/d/([A-Za-z0-9]+)$ {
return 302 /cardList.html?d=$1;
}
location /api/ {
proxy_pass http://127.0.0.1:3000;
# proxy_set_header ... (uadeck.conf 참고)
}
6. 최초 관리자 로그인
https://uniare.sori.studio/login.html접속.env의ADMIN_EMAIL계정으로 로그인- API 최초 기동 시 해당 이메일이 없으면
ADMIN_PASSWORD로 계정이 자동 생성된다. - 이미
ADMIN_EMAIL로 회원가입한 경우 API 재시작 시 해당 계정이admin으로 승격된다. (가입 시 설정한 비밀번호 그대로 사용)
- API 최초 기동 시 해당 이메일이 없으면
- 프로필 메뉴 → 관리자 →
/admin.html
관리자 메뉴가 안 보이면 로그아웃 후 다시 로그인하세요. 브라우저에 이전
role이 캐시되어 있을 수 있습니다.
7. 운영 명령
# 로그
docker compose -f docker-compose.prod.yml logs -f uniare-api
# 재시작
docker compose -f docker-compose.prod.yml restart
# DB 백업 (볼륨 내 SQLite)
docker cp uniare-api:/data/uadeck.db ./backup/uadeck-$(date +%Y%m%d).db
8. 카드/이미지 업데이트
datas/, images/, HTML 파일은 허용된 경로만 read-only 볼륨 마운트이므로:
- Git pull (또는 파일 동기화)
- 재빌드 불필요 — 브라우저 새로고침만으로 반영
API 컨테이너는 datas/를 read-only 마운트하므로 새 시리즈 파일 추가 후 API 재시작만 하면 됩니다:
docker compose -f docker-compose.prod.yml restart uniare-api
9. 트러블슈팅
| 증상 | 확인 |
|---|---|
| 로그인 안 됨 | JWT_SECRET 설정, API health 확인 |
| 공유 링크 404 | Nginx /d/ 리다이렉트 규칙 |
| CORS 오류 | CORS_ORIGINS에 옆 프로젝트 도메인 추가 |
| 덱 카드 메타 누락 | datas/<series>.js 존재 여부, API DATAS_PATH |