Duckport | 포트폴리오

현재 배포된 포트폴리오 사이트 입니다

기간: 2026-01 ~ 진행중인원: 1 명

Stack: Next.js, Cloudflare, TypeScript, JavaScript

#Portfolio#Blog

DuckPort

Next.js 15 (App Router) 기반 포트폴리오 CMS. Cloudflare D1(SQLite) + R2(Object Storage) 위에서 동작하며, 관리자 대시보드를 통해 프로젝트/포스트/프로필/사이트 설정을 관리합니다.

Tech Stack

LayerTechnology
FrameworkNext.js 15 (App Router), React 19, TypeScript (strict)
StylingTailwind CSS 4
VisualizationD3.js 7 (버블 차트)
Math RenderingKaTeX (LaTeX 수식)
HostingCloudflare Pages
DatabaseCloudflare D1 (SQLite)
StorageCloudflare R2 (이미지 + 마크다운 콘텐츠)
BuildOpenNext.js (@opennextjs/cloudflare)

Features

Public Pages

  • Home — 3페이지 플립북 인트로 (프로필 소개, About, 스킬 버블 차트)
  • Projects — 리스트 / 그리드 / 간략 보기 전환, 카테고리 필터, 키워드 검색, 정렬
  • Project Detail — Markdown + KaTeX 수식, 기간/팀/스택/링크, 사이드바 네비게이션
  • Posts — 리스트 / 그리드 / 간략 보기 전환, 카테고리 필터, 키워드 검색, 정렬
  • Post Detail — Markdown + KaTeX 수식, 태그, 사이드바 네비게이션
  • Dark / Light Theme — 토글 + 시스템 설정 감지

Admin Dashboard

  • Projects 관리 — CRUD, 썸네일 업로드, Markdown 편집기 + 실시간 미리보기, 발행/임시저장
  • Posts 관리 — CRUD, 썸네일 업로드, Markdown 편집기 + 실시간 미리보기, 발행/임시저장
  • Profile 편집 — 이름, 태그라인, 소개글, 아바타, 소셜 링크 (11종 아이콘 + 커스텀 아이콘)
  • Site Settings — 사이트명, SEO, 폰트 (16종 + 5단계 크기), 버블 차트 설정
  • Categories 관리 — 프로젝트/포스트별 카테고리 추가/삭제

Typography

16종 Google Fonts 선택 가능. 설정 페이지에서 실시간 미리보기 후 저장하면 전체 사이트에 적용됩니다. 폰트 크기(xs~xl)는 root font-size를 변경하여 모든 rem 기반 사이즈가 비례 스케일링됩니다.

분류폰트
Sans-serifInter, Roboto, Open Sans, Lato, Poppins, Nunito, Montserrat, DM Sans, Work Sans
SerifPlayfair Display, Lora, Noto Serif KR, Nanum Myeongjo
KoreanNoto Sans KR, Noto Serif KR, Nanum Gothic, Nanum Myeongjo
MonospaceSource Code Pro

Architecture

src/
├── app/
│   ├── (public)/              # 공개 페이지 (홈, 프로젝트, 포스트)
│   ├── ad/                    # 관리자 대시보드
│   └── api/                   # REST API
├── components/                # React 컴포넌트
│   ├── layout/                # Header, Footer
│   ├── ui/                    # 재사용 UI 컴포넌트
│   ├── PageFlipBook.tsx       # 홈 플립북
│   ├── StackBubbles.tsx       # D3 버블 차트
│   ├── DetailSidebar.tsx      # 상세 페이지 사이드바
│   ├── PostListView.tsx       # 포스트 목록 (검색, 필터, 뷰 전환)
│   ├── ProjectListView.tsx    # 프로젝트 목록 (검색, 필터, 뷰 전환)
│   └── *Form.tsx              # 관리자 폼 컴포넌트
├── lib/
│   ├── db/                    # D1 데이터베이스 헬퍼
│   ├── r2/                    # R2 스토리지 헬퍼
│   ├── auth/                  # 인증 모듈
│   └── markdown.ts            # Markdown → HTML 변환 (KaTeX 포함)
└── middleware.ts              # 라우트 보호

Key Patterns

PatternDescription
인증서명 기반 세션 토큰, HttpOnly 쿠키
콘텐츠 저장D1에 메타데이터 + R2에 Markdown 파일 분리 저장
이미지 업로드R2 직접 저장 후 asset 메타 기록
폰트 시스템Google Fonts 동적 로드, root font-size 비례 스케일링
라우트 보호미들웨어 기반 세션 검증

Data Model

D1 Tables

  • projects — 프로젝트 (제목, 슬러그, 카테고리, 스택, 태그, 기간, 팀, 링크)
  • posts — 포스트 (제목, 슬러그, 카테고리, 태그)
  • profile — 프로필 단일 행 (이름, 소개, 아바타)
  • site_settings — 사이트 설정 단일 행 (브랜딩, 폰트, 카테고리, 소셜 링크)
  • assets — 업로드 파일 메타데이터
  • tags — 태그 관계 테이블

R2 Storage

  • 업로드된 이미지 파일
  • 프로젝트/포스트 본문 마크다운 파일

Getting Started

Prerequisites

  • Node.js 18+
  • Wrangler CLI (npm install -g wrangler)
  • Cloudflare 계정 (D1 + R2 설정)

Setup

bash# 의존성 설치
npm install

# D1 로컬 마이그레이션 적용
npm run db:migrate

# 관리자 계정 생성
npm run db:seed-admin

# 개발 서버 실행
npm run dev

Commands

bashnpm run dev              # 개발 서버 (localhost:3000)
npm run build            # Next.js 빌드
npm run preview          # Cloudflare 로컬 프리뷰
npm run deploy           # Cloudflare Pages 배포
npm run db:migrate       # D1 로컬 마이그레이션
npm run db:migrate:prod  # D1 프로덕션 마이그레이션
npm run db:seed-admin    # 관리자 계정 생성
npm run lint             # ESLint

Environment Variables

VariableDescriptionRequired
SESSION_SECRETJWT 서명 키Production
SITE_URL사이트 기본 URL (메타데이터용)Optional