xNote 개발 명세서 v1.0
다중사용자 파일관리 · 자료관리 · 자료공유 솔루션
작성일: 2026-06-19
1. 프로젝트 개요
1.1 핵심 포지셔닝
| 항목 | 내용 |
|---|---|
| 제품명 | xNote |
| 포지셔닝 | DSM Note Station 대체 · 독립형 자료관리 솔루션 |
| 경쟁 회피 | 노션·옵시디언과 직접 경쟁 안 함 → 파일 특화 뷰어 + 공유가 차별점 |
| 배포 방식 | 어느 서버든 설치 가능 (XAMPP, VPS, Synology 등) |
| 대상 | 팀/조직 단위 다중 사용자 |
1.2 핵심 차별화 기능
- 특화 뷰어: PDF → 이북뷰어, 오디오 → 플레이어, 이미지 → 슬라이드쇼
- 대용량 첨부: 파일당 최대 100MB, 청크 업로드로 서버 과부하 방지
- 외부 임베드 공유: 이북뷰어 등 링크 공유로 외부 사이트에서 바로 서비스 가능
- 클라우드 연동: 구글 드라이브 파일공유 + 네이버 클라우드 폴더 파일관리
2. 기술 스택
2.1 Frontend
Vue 3 (Composition API)
├── 에디터: TipTap v2 (ProseMirror 기반)
├── 상태관리: Pinia
├── 라우팅: Vue Router 4
├── 스타일: CSS Variables (다크/라이트 테마)
├── 파일 업로드: Uppy (청크 업로드 지원)
├── PDF 뷰어: PDF.js
├── 오디오 플레이어: Howler.js
└── 이미지 슬라이더: Swiper.js
2.2 Backend
Node.js (Express)
├── DB: SQLite (better-sqlite3)
├── 인증: JWT (Access Token + Refresh Token)
├── 파일저장: 로컬 스토리지 (/data/files/)
├── 썸네일: Sharp (이미지), pdf-thumbnail (PDF)
├── 청크 업로드: Multer + 자체 청크 병합 로직
└── 클라우드 연동: Google Drive API v3, Naver Cloud API
2.3 인프라
서버: XAMPP / Node.js 독립 실행
DB: SQLite (단일 파일 → 백업 용이)
파일: /data/files/{userId}/{year}/{month}/
설정: .env 파일 기반
3. UI 레이아웃 구조
3.1 메인 3단 레이아웃
┌─────────────────────────────────────────────────────────────────┐
│ HEADER: 로고 · 검색바 · 계정정보(쿼터) · 다크/라이트 토글 · 로그인 │
├──────────────┬──────────────────────────────┬───────────────────┤
│ LEFT PANEL │ CENTER (메인뷰) │ RIGHT PANEL │
│ 220px │ flex: 1 (전체 화면) │ 220px │
│ │ │ │
│ 썸네일 목록 │ ┌─────────────────────────┐ │ 카테고리 목록 │
│ (12개, 최신순)│ │ 제목 │ │ (계정관리자 무제한) │
│ │ │ 메타정보 (날짜·카테고리) │ │ │
│ [카테고리명] │ │ │ │ 전체 검색 │
│ [썸네일] │ │ 유튜브/쇼츠 임베드 │ │ │
│ [제목] │ │ │ │ 태그 목록 │
│ [내용 일부] │ │ 본문 내용 │ │ (박스형 20개) │
│ │ │ │ │ │
│ (스크롤) │ │ 파일 첨부 목록 │ │ 라이브러리 미리보기 │
│ │ │ │ │ (이미지 2열 3줄) │
│ │ │ 공유 버튼 │ │ │
│ │ │ 이전글 / 다음글 │ │ [라이브러리 →] │
│ │ │ 댓글 · 답변 │ │ │
│ │ └─────────────────────────┘ │ │
└──────────────┴──────────────────────────────┴───────────────────┘
3.2 반응형 브레이크포인트
| 구간 | 레이아웃 |
|---|---|
| ≥ 1280px | 3단 (좌220 · 중앙flex · 우220) |
| 768px ~ 1279px | 2단 (좌목록 접힘 · 중앙 · 우패널) |
| < 768px | 1단 (모바일: 목록 → 상세 → 에디터 순차) |
3.3 모바일 네비게이션
하단 탭바 (모바일 전용)
[홈] [목록] [글쓰기] [라이브러리] [설정]
4. 핵심 기능 명세
4.1 게시글 (Note)
목록 화면 (Left Panel)
- 최신 등록 순 12개, 무한 스크롤
- 썸네일: 첫 번째 이미지 첨부 또는 카테고리 아이콘 자동 적용
- 표시 정보: 카테고리명 · 제목 · 내용 앞 60자 · 날짜
- 클릭 → 중앙 상세보기 즉시 로드 (SPA, 페이지 전환 없음)
상세 화면 (Center)
[제목]
[카테고리] [날짜] [작성자] [조회수]
[유튜브 또는 쇼츠 임베드] ← 링크 입력시 자동 표시
[본문 렌더링]
[첨부파일 목록]
- 이미지: 썸네일 클릭 → 슬라이드 뷰어
- PDF: 클릭 → 이북뷰어 (모달 또는 새 탭)
- 오디오: 인라인 플레이어 렌더링
- 기타: 다운로드 링크
[공유] [수정] [삭제]
[← 이전글] [다음글 →]
[댓글 목록]
└ [답변 입력]
편집 화면
[카테고리 선택 드롭다운]
[제목 입력]
[TipTap 웹에디터]
- 텍스트 서식 (볼드·이탤릭·취소선·코드)
- 제목 H1~H3
- 표 삽입
- 이미지 삽입 (드래그 앤 드롭)
- 체크박스 / 할 일 목록
- 코드 블록 (하이라이팅)
- 구분선
[태그 입력] (엔터로 추가, X로 삭제)
[유튜브/쇼츠 링크 입력]
[파일 첨부 영역]
- + 버튼으로 개수 무제한 추가
- 파일당 최대 100MB (청크 업로드)
- 업로드 진행바 개별 표시
- 첨부된 파일 목록 + 삭제 버튼
[임시저장] [발행]
4.2 라이브러리
라이브러리 메인 화면
┌─────────────────────────────────────────────────────┐
│ [이미지] [PDF] [오디오] [동영상] [기타] ← 탭 필터 │
├─────────────────────────────────────────────────────┤
│ │
│ 이미지 탭: │
│ [→ 슬라이드쇼로 보기] 버튼 │
│ 썸네일 3열 그리드, 클릭 → 라이트박스 │
│ │
│ PDF 탭: │
│ [→ 이북뷰어로 보기] 버튼 │
│ PDF 목록 (파일명·크기·등록일) │
│ │
│ 오디오 탭: │
│ [→ 오디오 플레이어] 버튼 │
│ 트랙 목록 (아티스트·제목·길이) │
│ │
└─────────────────────────────────────────────────────┘
이북뷰어 (PDF Viewer)
- PDF.js 기반 페이지 렌더링
- 좌우 페이지 넘기기 (book flip 애니메이션)
- 썸네일 사이드바, 페이지 점프
- 외부 공유 링크 생성:
/viewer/ebook/{token}→ 외부 사이트 임베드 가능 - 임베드 코드 생성:
<iframe src="...">복사 버튼
오디오 플레이어
- 폴더/카테고리 기준 플레이리스트 자동 구성
- 재생·정지·다음·이전·셔플·반복
- 배경 재생 (페이지 이동해도 유지)
- 트랙 커버 이미지 (없으면 기본 아이콘)
이미지 슬라이드쇼
- Swiper.js 풀스크린 슬라이드
- 자동재생 · 슬라이드 간격 설정
- 공유 링크 생성: 슬라이드쇼 단독 URL 공유 가능
4.3 파일 업로드 시스템 (100MB 청크)
[클라이언트]
파일 선택
→ 5MB 단위 청크 분할
→ 청크 순서대로 POST /api/upload/chunk
→ 진행률 표시 (청크 단위)
→ 마지막 청크 → POST /api/upload/merge
→ 서버 응답: 파일 URL + 메타데이터
[서버]
청크 임시 저장: /data/tmp/{uploadId}/chunk_001 ...
병합 완료 → /data/files/{userId}/{year}/{month}/{uuid}.ext
썸네일 자동 생성 (이미지·PDF)
DB 파일 레코드 저장
4.4 클라우드 연동
구글 드라이브 연동
- OAuth2 인증 후 드라이브 파일 목록 탐색
- 드라이브 파일 → xNote 첨부파일로 가져오기 (복사 저장)
- xNote 파일 → 드라이브로 내보내기
네이버 클라우드 연동
- 네이버 클라우드 API 연동
- 폴더 구조 탐색 + 파일 가져오기/내보내기
4.5 사용자 및 권한 관리
역할 (Role)
| 역할 | 권한 |
|---|---|
| admin | 모든 기능 + 카테고리 무제한 추가 + 사용자 관리 + 쿼터 설정 |
| editor | 글쓰기·수정·삭제(본인글) + 파일 업로드 |
| viewer | 읽기 + 댓글 |
| guest | 공개 게시물 읽기만 |
쿼터 관리
- 사용자별 저장 용량 상한 설정 (관리자 지정)
- 헤더에 사용량 표시:
사용중 1.2GB / 10GB - 쿼터 초과시 업로드 차단 + 경고 메시지
JWT 인증
Access Token: 15분 만료
Refresh Token: 30일 만료 (HttpOnly Cookie)
자동 갱신: axios 인터셉터로 무중단 처리
4.6 검색
- 전문 검색 (제목 + 본문 + 태그 + 파일명)
- SQLite FTS5 (Full-Text Search) 활용
- 카테고리 필터 + 날짜 범위 필터
- 태그 클릭 → 해당 태그 게시물 목록
4.7 댓글 시스템
- 1단계 답변 (댓글 → 답변, 대댓글 없음)
- 마크다운 경량 지원 (볼드·이탤릭·코드)
- 작성자 수정·삭제 + 관리자 삭제
5. DB 스키마
-- 사용자
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
email TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
role TEXT DEFAULT 'editor', -- admin/editor/viewer/guest
quota_mb INTEGER DEFAULT 1024, -- 사용 가능 용량 (MB)
used_mb REAL DEFAULT 0,
theme TEXT DEFAULT 'dark',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 카테고리
CREATE TABLE categories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
slug TEXT UNIQUE NOT NULL,
parent_id INTEGER REFERENCES categories(id),
sort_order INTEGER DEFAULT 0,
created_by INTEGER REFERENCES users(id)
);
-- 게시글
CREATE TABLE notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT, -- HTML (TipTap 출력)
category_id INTEGER REFERENCES categories(id),
author_id INTEGER REFERENCES users(id),
youtube_url TEXT,
status TEXT DEFAULT 'published', -- draft/published
view_count INTEGER DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 태그
CREATE TABLE tags (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE NOT NULL
);
CREATE TABLE note_tags (
note_id INTEGER REFERENCES notes(id) ON DELETE CASCADE,
tag_id INTEGER REFERENCES tags(id) ON DELETE CASCADE,
PRIMARY KEY (note_id, tag_id)
);
-- 첨부파일
CREATE TABLE files (
id INTEGER PRIMARY KEY AUTOINCREMENT,
note_id INTEGER REFERENCES notes(id) ON DELETE CASCADE,
uploader_id INTEGER REFERENCES users(id),
original_name TEXT NOT NULL,
stored_name TEXT NOT NULL,
file_path TEXT NOT NULL,
file_type TEXT, -- image/pdf/audio/video/other
mime_type TEXT,
size_bytes INTEGER,
thumbnail_path TEXT,
share_token TEXT UNIQUE, -- 이북뷰어 등 외부 공유용
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 댓글
CREATE TABLE comments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
note_id INTEGER REFERENCES notes(id) ON DELETE CASCADE,
parent_id INTEGER REFERENCES comments(id),
author_id INTEGER REFERENCES users(id),
content TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- FTS 검색 인덱스
CREATE VIRTUAL TABLE notes_fts USING fts5(
title, content, tokenize='unicode61'
);
6. API 설계
6.1 인증
| Method | Path | 설명 |
|---|---|---|
| POST | /api/auth/login | 로그인 (JWT 발급) |
| POST | /api/auth/logout | 로그아웃 |
| POST | /api/auth/refresh | 토큰 갱신 |
| GET | /api/auth/me | 내 정보 조회 |
6.2 게시글
| Method | Path | 설명 |
|---|---|---|
| GET | /api/notes | 목록 (페이지네이션·필터) |
| GET | /api/notes/:id | 상세 조회 |
| POST | /api/notes | 생성 |
| PUT | /api/notes/:id | 수정 |
| DELETE | /api/notes/:id | 삭제 |
| GET | /api/notes/search | 전문 검색 |
6.3 파일
| Method | Path | 설명 |
|---|---|---|
| POST | /api/upload/chunk | 청크 업로드 |
| POST | /api/upload/merge | 청크 병합 완료 |
| GET | /api/files/:id | 파일 다운로드 |
| DELETE | /api/files/:id | 파일 삭제 |
| POST | /api/files/:id/share | 공유 토큰 생성 |
6.4 라이브러리
| Method | Path | 설명 |
|---|---|---|
| GET | /api/library | 파일 타입별 목록 |
| GET | /api/library/images | 이미지 목록 |
| GET | /api/library/pdf | PDF 목록 |
| GET | /api/library/audio | 오디오 목록 |
6.5 공개 뷰어 (비인증)
| Method | Path | 설명 |
|---|---|---|
| GET | /viewer/ebook/:token | 이북뷰어 공개 접근 |
| GET | /viewer/slideshow/:token | 슬라이드쇼 공개 접근 |
| GET | /api/public/file/:token | 공개 파일 스트리밍 |
7. 테마 시스템
/* 다크모드 (기본) */
:root[data-theme="dark"] {
--bg-primary: #0f0f0f;
--bg-secondary: #1a1a1a;
--bg-panel: #141414;
--text-primary: #e8e8e8;
--text-secondary: #999;
--border: #2a2a2a;
--accent: #4f9cf9;
--accent-hover: #3d85e0;
}
/* 라이트모드 */
:root[data-theme="light"] {
--bg-primary: #ffffff;
--bg-secondary: #f5f5f5;
--bg-panel: #fafafa;
--text-primary: #1a1a1a;
--text-secondary: #666;
--border: #e0e0e0;
--accent: #2563eb;
--accent-hover: #1d4ed8;
}
8. 개발 Phase 계획
Phase 1 — 코어 (4주)
- 미완료프로젝트 세팅 (Vue3 + Express + SQLite)
- 미완료JWT 인증 (로그인·로그아웃·갱신)
- 미완료카테고리 CRUD
- 미완료게시글 CRUD (TipTap 에디터 통합)
- 미완료기본 파일 첨부 (5MB 이하 단순 업로드)
- 미완료3단 레이아웃 + 다크/라이트 테마
Phase 2 — 파일 특화 (3주)
- 미완료청크 업로드 (100MB)
- 미완료이미지 슬라이드쇼 뷰어
- 미완료PDF 이북뷰어 (PDF.js)
- 미완료오디오 플레이어 (Howler.js)
- 미완료라이브러리 화면
Phase 3 — 공유 & 검색 (2주)
- 미완료SQLite FTS5 전문 검색
- 미완료태그 시스템
- 미완료공유 토큰 + 외부 임베드 URL
- 미완료댓글·답변 시스템
- 미완료이전글/다음글 네비게이션
Phase 4 — 다중 사용자 & 클라우드 (2주)
- 미완료사용자 관리 (역할·쿼터)
- 미완료관리자 대시보드
- 미완료구글 드라이브 연동
- 미완료네이버 클라우드 연동
- 미완료모바일 최적화 완성
Phase 5 — 배포 & 완성 (1주)
- 미완료보안 점검 (XSS·SQL Injection·파일 업로드 검증)
- 미완료성능 최적화 (이미지 레이지 로딩·페이지네이션)
- 미완료설치 가이드 (XAMPP / VPS / Synology)
- 미완료백업·복원 스크립트
9. 보안 고려사항
| 항목 | 대책 |
|---|---|
| 파일 업로드 | MIME 타입 검증 + 확장자 화이트리스트 + 실행파일 차단 |
| XSS | TipTap 출력 → DOMPurify 새니타이징 |
| 인증 | JWT + HttpOnly Cookie + CSRF 토큰 |
| 파일 접근 | DB 토큰 기반 접근 제어 (직접 경로 노출 금지) |
| 쿼터 | 업로드 전 용량 사전 검증 |
| SQL | Prepared Statement 전용 사용 |
10. 설치 구조
xnote/
├── client/ # Vue 3 앱
│ ├── src/
│ │ ├── views/ # Home, Note, Editor, Library, Viewer
│ │ ├── components/
│ │ ├── stores/ # Pinia
│ │ └── api/ # axios 래퍼
│ └── dist/ # 빌드 결과물
├── server/ # Express API
│ ├── routes/
│ ├── middleware/
│ ├── models/
│ └── utils/
├── data/
│ ├── files/ # 업로드된 파일
│ ├── tmp/ # 청크 임시 저장
│ └── xnote.db # SQLite DB
├── .env
└── package.json
xNote v1.0 명세서 끝 — Phase 1 착수 시 이 문서를 기준으로 세부 태스크 분해 진행

댓글 (0)
댓글 쓰기