GitHub의 비공개(또는 공개) 저장소를 ID/PW 인증 뒤에서 웹으로 보여주는 개인용 문서 뷰어. 마크다운/코드/이미지를 즉석 렌더링하며, 별도 빌드 파이프라인 없이 GitHub에 push만 하면 곧바로 반영된다.
브라우저
│ HTTPS (Let's Encrypt)
▼
nginx (443) ─ reverse proxy ─► Next.js (127.0.0.1:15000, systemd)
│
├─► MongoDB (인증·로그인 시도 기록)
└─► GitHub REST API (트리·파일)
- Next.js 15 App Router (Server Components)
- iron-session 쿠키 기반 세션 (HttpOnly · Secure · SameSite=Lax)
- bcryptjs 비밀번호 해시 (cost 12)
- MongoDB 사용자 + 로그인 시도 카운터
- @octokit/rest GitHub 콘텐츠 페치
- react-markdown + remark-gfm + rehype-highlight (GFM·코드 하이라이팅)
- nginx + certbot 자동 갱신 HTTPS
- DuckDNS 무료 동적 DNS (5분 cron으로 IP 갱신)
- ID/PW 로그인 (이메일 기반)
- 로그인 5회 실패 → 1시간 IP 차단 (X-Forwarded-For 기반, MongoDB 영속)
- repo 트리 폴더형 네비게이션 (펼침/접힘)
- 마크다운 GFM 렌더링 (테이블·체크리스트·각주)
- 코드 파일 신택스 하이라이팅 (highlight.js github-dark)
- 이미지 인라인 (base64)
- 바이너리 파일은 안전하게 거부
- 외부 검색엔진 색인 차단 (
robots: noindex) - 미인증 시 모든 경로 →
/login으로 리디렉트 (middleware) - "GitHub에서 보기" 원본 링크
- GitHub 저장소를 로컬에 클론하지 않는다. 매 요청마다 Octokit으로 트리·파일을 페치 — push 즉시 반영, 별도 sync 불필요. 1인 사용 기준 시간당 5,000 요청 한도는 사실상 무제한.
- Next는 Edge가 아닌 Node 런타임. 미들웨어만 Edge에서 동작하며 절대 URL이 필요해
Host헤더로 구성. 라우트 핸들러는 상대 경로 Location으로 충분. - DB 직접 호출이 안티패턴이 아니다. App Router에선 RSC/Route Handler가 서버에서만 실행되므로 클라이언트가 DB에 도달할 경로가 없다. 별도 API 서버는 단일 도메인 1인 앱엔 overengineering.
- 공개/비공개 repo 모두 가능. GitHub 토큰만 있으면 private도 동작.
- 비밀번호 bcrypt (cost 12)
- 세션 쿠키 HttpOnly + Secure + SameSite=Lax
- 무차별 대입 차단 (5회/1시간/IP)
- HTTPS only (HTTP→HTTPS 301)
- 검색엔진 색인 차단
- open-redirect 방지 (
from은/로 시작·//거부) - CSRF: SameSite=Lax + 폼 POST만 허용
- 로그인 시도 알림 (TODO: 실패 시 메일/웹훅)
- 2FA (TODO)
.env.local:
NODE_ENV=production
MONGODB_URI=mongodb://USER:[email protected]:27017/izdocs?authSource=izdocs
SESSION_SECRET=<48바이트 랜덤 base64>
GITHUB_TOKEN=<repo:contents:read 권한>
GITHUB_REPO=owner/repo
GITHUB_BRANCH=main
[email protected] # 첫 시드용
SEED_PASSWORD=... # 첫 시드용
COOKIE_SECURE=true # 로컬 dev라면 false
# Node 22, MongoDB 8, gh, nginx, certbot 설치 가정
git clone https://github.com/izdev0000/izdocs.git
cd izdocs
cp .env.example .env.local && $EDITOR .env.local
npm install
npm run seed # 첫 사용자 생성
npm run build
npm start # 127.0.0.1:15000systemd 유닛 예시는 docs/izdocs.service, nginx 유닛 예시는 docs/nginx-izdocs.conf 참고.
app/
api/login/ POST /api/login (폼 인증, 시도 카운트)
api/logout/ POST /api/logout
api/health/ GET /api/health (uptime probe)
login/ GET /login
view/[...path]/ GET /view/<repo path> (마크다운/코드/이미지)
page.tsx GET / (트리 네비게이션)
layout.tsx, globals.css
lib/
github.ts Octokit + 파일 인코딩 판별
mongo.ts 전역 풀링된 MongoClient
users.ts findUserByEmail / verifyCredentials / createUser
loginThrottle.ts IP 기반 시도 카운터·1시간 잠금
session.ts iron-session 설정
middleware.ts 미인증 → /login 리디렉트
scripts/
seed-admin.mjs 첫 사용자 생성
MIT