Skip to content

05 서비스 개발 Spec 예(생성)

포스트잇형 개인 노트 관리 웹 서비스. 사용자가 메모를 포스트잇 형태로 작성하고, 자유 배치(Freeform) 또는 칸반(Kanban) 방식으로 관리할 수 있는 반응형 웹 애플리케이션입니다.

  • 직관적인 포스트잇 UX (파스텔 톤, 끝 말림 효과)
  • Markdown 지원으로 풍부한 메모 작성
  • AI 기반 메모 요약 및 중요 알림
  • Desktop/Mobile 반응형 지원

구분기술버전
FrontendNext.js + React최신 (App Router)
스타일링Tailwind CSS최신 (v4+)
BackendPython + FastAPI최신
DatabaseSQLite3-
AI/LLMGoogle Geminigemini-3-flash-preview
인증JWT (JSON Web Token)-
API 문서Swagger UI (FastAPI 내장)-

참고: 모든 라이브러리는 Context7 MCP를 통해 최신 API 기준으로 구현합니다.


┌─────────────────────────────────────────────────┐
│ Client (Browser) │
│ ┌───────────────────────────────────────────┐ │
│ │ Next.js Frontend (React) │ │
│ │ - Pages (App Router) │ │
│ │ - Components (Freeform, Kanban, etc.) │ │
│ │ - Tailwind CSS │ │
│ └──────────────────┬────────────────────────┘ │
└─────────────────────┼────────────────────────────┘
│ REST API (JSON)
┌─────────────────────┼────────────────────────────┐
│ ┌──────────────────┴────────────────────────┐ │
│ │ FastAPI Backend (Python) │ │
│ │ - Auth Router (JWT) │ │
│ │ - Notes Router (CRUD) │ │
│ │ - AI Router (Gemini 요약/알림) │ │
│ └──────────┬──────────────┬─────────────────┘ │
│ │ │ │
│ ┌──────────┴───┐ ┌──────┴──────────────┐ │
│ │ SQLite3 │ │ Gemini API │ │
│ │ Database │ │ (gemini-3-flash- │ │
│ │ │ │ preview) │ │
│ └──────────────┘ └─────────────────────┘ │
└──────────────────────────────────────────────────┘
post-note/
├── frontend/ # Next.js 프로젝트
│ ├── src/
│ │ ├── app/ # App Router 페이지
│ │ │ ├── layout.tsx # 루트 레이아웃
│ │ │ ├── page.tsx # 메인 (로그인 리다이렉트)
│ │ │ ├── login/ # 로그인 페이지
│ │ │ ├── register/ # 회원가입 페이지
│ │ │ └── notes/ # 메모 메인 페이지
│ │ │ └── page.tsx # Freeform/Kanban 전환 뷰
│ │ ├── components/ # 재사용 컴포넌트
│ │ │ ├── common/ # 공통 컴포넌트
│ │ │ │ ├── Header.tsx
│ │ │ │ ├── Modal.tsx
│ │ │ │ └── MarkdownRenderer.tsx
│ │ │ ├── notes/ # 메모 관련 컴포넌트
│ │ │ │ ├── NoteCard.tsx # 포스트잇 카드
│ │ │ │ ├── NoteCreateModal.tsx # 메모 생성 팝업
│ │ │ │ ├── NoteDetailModal.tsx # 메모 상세 보기
│ │ │ │ ├── FreeformView.tsx # 자유 배치 뷰
│ │ │ │ ├── KanbanView.tsx # 칸반 뷰
│ │ │ │ └── KanbanColumn.tsx # 칸반 컬럼
│ │ │ ├── ai/ # AI 관련 컴포넌트
│ │ │ │ ├── AiSummaryPanel.tsx
│ │ │ │ └── AiAlertBadge.tsx
│ │ │ └── auth/ # 인증 컴포넌트
│ │ │ ├── LoginForm.tsx
│ │ │ └── RegisterForm.tsx
│ │ ├── hooks/ # 커스텀 훅
│ │ │ ├── useAuth.ts
│ │ │ ├── useNotes.ts
│ │ │ └── useDragDrop.ts
│ │ ├── lib/ # 유틸리티
│ │ │ ├── api.ts # API 클라이언트
│ │ │ └── constants.ts
│ │ └── types/ # TypeScript 타입 정의
│ │ └── index.ts
│ ├── public/
│ ├── tailwind.config.ts
│ ├── next.config.ts
│ └── package.json
├── backend/ # FastAPI 프로젝트
│ ├── main.py # FastAPI 앱 진입점
│ ├── config.py # 설정 (DB, API Key 등)
│ ├── database.py # SQLite3 연결 관리
│ ├── models/ # Pydantic 모델
│ │ ├── user.py
│ │ └── note.py
│ ├── routers/ # API 라우터
│ │ ├── auth.py # 인증 API
│ │ ├── notes.py # 메모 CRUD API
│ │ └── ai.py # AI 요약/알림 API
│ ├── services/ # 비즈니스 로직
│ │ ├── auth_service.py
│ │ ├── note_service.py
│ │ └── ai_service.py # Gemini 연동
│ ├── utils/ # 유틸리티
│ │ └── security.py # JWT 토큰 관리
│ └── requirements.txt
├── test/ # 테스트 코드 (GEMINI.md 규칙)
│ ├── backend/
│ │ ├── test_auth.py
│ │ ├── test_notes.py
│ │ └── test_ai.py
│ └── frontend/
├── scripts/ # 유틸리티 스크립트 (GEMINI.md 규칙)
├── docs/ # 문서
│ ├── requirement.md
│ ├── spec.md # 이 문서
│ ├── backend-wiki.md # 백엔드 위키 (GEMINI.md 규칙)
│ └── frontend-wiki.md # 프론트엔드 위키 (GEMINI.md 규칙)
└── GEMINI.md # 프로젝트 규칙

컬럼명타입제약조건설명
idINTEGERPK, AUTOINCREMENT사용자 고유 ID
emailTEXTUNIQUE, NOT NULL이메일 (로그인 ID)
password_hashTEXTNOT NULL비밀번호 해시 (bcrypt)
nicknameTEXTNOT NULL사용자 닉네임
created_atTEXTNOT NULL, DEFAULT CURRENT_TIMESTAMP가입일시
updated_atTEXTNOT NULL, DEFAULT CURRENT_TIMESTAMP수정일시
컬럼명타입제약조건설명
idINTEGERPK, AUTOINCREMENT메모 고유 ID
user_idINTEGERFK(users.id), NOT NULL작성자 ID
titleTEXTNOT NULL메모 제목
contentTEXTNOT NULL, DEFAULT ”메모 내용 (Markdown)
note_typeTEXTNOT NULL, CHECK(‘free’,‘kanban’)메모 타입
colorTEXTNOT NULL, DEFAULT ‘#FFEAA7’메모 색상 (파스텔 HEX)
kanban_statusTEXTCHECK(‘plan’,‘progress’,‘done’), DEFAULT NULL칸반 상태
progress_percentINTEGERDEFAULT 0, CHECK(0~100)진척도 (%) - progress 상태 시
due_dateTEXTDEFAULT NULL마감일 (YYYY-MM-DD, D-Day용)
position_xREALDEFAULT 0Freeform X 좌표
position_yREALDEFAULT 0Freeform Y 좌표
widthREALDEFAULT 240카드 너비
heightREALDEFAULT 200카드 높이
z_indexINTEGERDEFAULT 0겹침 순서 (Freeform overlap용)
kanban_orderINTEGERDEFAULT 0칸반 내 정렬 순서
is_archivedINTEGERDEFAULT 0보관 여부 (0/1)
created_atTEXTNOT NULL, DEFAULT CURRENT_TIMESTAMP생성일시
updated_atTEXTNOT NULL, DEFAULT CURRENT_TIMESTAMP수정일시
-- 사용자별 메모 조회 최적화
CREATE INDEX idx_notes_user_id ON notes(user_id);
-- 칸반 상태별 조회
CREATE INDEX idx_notes_kanban ON notes(user_id, note_type, kanban_status);
-- 마감일 기준 조회
CREATE INDEX idx_notes_due_date ON notes(user_id, due_date);

MethodEndpoint설명Request BodyResponse
POST/api/auth/register회원가입{ email, password, nickname }{ id, email, nickname }
POST/api/auth/login로그인{ email, password }{ access_token, token_type }
GET/api/auth/me내 정보 조회- (Authorization Header){ id, email, nickname }
MethodEndpoint설명Request Body / ParamsResponse
GET/api/notes메모 목록 조회Query: ?type=free|kanban[Note]
POST/api/notes메모 생성{ title, content, note_type, color, kanban_status?, progress_percent?, due_date?, position_x?, position_y? }Note
GET/api/notes/{id}메모 상세 조회-Note
PUT/api/notes/{id}메모 수정{ title?, content?, color?, kanban_status?, progress_percent?, due_date? }Note
PATCH/api/notes/{id}/position메모 위치 변경 (Freeform){ position_x, position_y, z_index? }Note
PATCH/api/notes/{id}/kanban칸반 상태 변경{ kanban_status, kanban_order?, progress_percent? }Note
DELETE/api/notes/{id}메모 삭제-{ message }
MethodEndpoint설명Request BodyResponse
POST/api/ai/summary전체 메모 요약- (Authorization Header){ summary: string }
POST/api/ai/alerts중요 알림 생성- (Authorization Header){ alerts: [{ note_id, message, priority }] }
// 성공 응답
{
"status": "success",
"data": { ... }
}
// 에러 응답
{
"status": "error",
"detail": "에러 메시지"
}
  • Bearer Token (JWT): 모든 인증 필요 API에 Authorization: Bearer <token> 헤더 필수
  • JWT Payload: { sub: user_id, email, exp }
  • 토큰 만료: 24시간

Stitch MCP 프로젝트 post-note (ID: 2027687418161249866) 기반

속성설명
Color ModeLight밝은 배경
Primary Color#b6e6fc파스텔 하늘색
FontSpline Sans메인 폰트
Border Radius12px모든 카드/버튼에 적용
Saturation2 (Medium)중간 채도의 파스텔 톤

6.2 포스트잇 색상 팔레트 (파스텔)

Section titled “6.2 포스트잇 색상 팔레트 (파스텔)”
색상명HEX용도/미리보기
노란색#FFEAA7기본 포스트잇
분홍색#FDCFE8중요 메모
하늘색#B6E6FC아이디어
연두색#C4E9B2완료/긍정
보라색#D5C6F0개인 메모
주황색#FFDAB9긴급
민트색#B2E6D4프로젝트
라벤더#E8D5F5참고

6.3 스크린 구성 (Stitch 디자인 기준)

Section titled “6.3 스크린 구성 (Stitch 디자인 기준)”
  • Stitch Screen: 로그인 페이지 (개선) / Desktop 2560×2048
  • 구성: 좌측 브랜딩 영역 + 우측 로그인 폼
  • 요소:
    • 이메일 입력 필드
    • 비밀번호 입력 필드
    • 로그인 버튼 (Primary Color)
    • “회원가입” 링크
  • Stitch Screen: 회원 가입 페이지 (파스텔 블루) / Desktop 2560×2048
  • 구성: 로그인과 동일한 레이아웃
  • 요소:
    • 이메일 입력
    • 닉네임 입력
    • 비밀번호 입력
    • 비밀번호 확인 입력
    • 가입 버튼
    • “로그인으로 돌아가기” 링크

스크린 3: 메인 자유 배치 모드 (Freeform)

Section titled “스크린 3: 메인 자유 배치 모드 (Freeform)”
  • Stitch Screen: 메인 자유 배치 모드 (AI 아이콘 및 메뉴 정리) / Desktop 2560×2058
  • 구성:
    • 상단 헤더바: 로고, 뷰 전환(Freeform/Kanban) 토글, AI 요약 버튼, 사용자 메뉴
    • 메인 캔버스: 자유 배치 가능한 포스트잇 노트 영역
    • 플로팅 버튼: 메모 추가 (+) 버튼
  • 인터랙션:
    • Drag & Drop으로 메모 위치 이동
    • 메모 간 Overlap (z-index 관리) 허용
    • 메모 클릭 → 상세 보기 모달
  • Stitch Screen: 심플 칸반 보드 뷰 (상태 중심) / Desktop 2560×2048
  • 구성:
    • 동일한 상단 헤더바
    • 3개 컬럼: Plan(계획)Progress(실행중)Done(완료)
    • 각 컬럼에 해당 상태의 포스트잇 나열
  • 인터랙션:
    • Drag & Drop으로 컬럼 간 이동 (상태 변경)
    • Progress 컬럼의 메모에는 진척도 표시 (% 바)
  • Stitch Screen: 상세 메모 생성 팝업 / Desktop 2560×2048
  • 구성: 중앙 모달 팝업
  • 입력 필드:
    1. 메모 타입: Free / Kanban 라디오 선택
      • Kanban 선택 시: Plan/Progress/Done 상태 선택 드롭다운
      • Progress 선택 시: 진척도 % 슬라이더 (0~100)
    2. 메모 색상: 파스텔 색상 팔레트 선택 (원형/사각 색상 버튼)
    3. 메모 제목: 텍스트 입력
    4. 메모 내용: Markdown 에디터 (미리보기 지원)
    5. 마감날짜 (옵션): 날짜 선택기 (Date Picker)
  • Stitch Screen: 모바일 심플 칸반 보드 / Mobile 780×2012
  • 구성:
    • 탭 방식으로 Plan/Progress/Done 전환
    • 세로 스크롤로 메모 나열
    • 하단 플로팅 추가 버튼
  • Stitch Screen: 모바일 메이슨리 뷰 (이미지 제거 및 텍스트 수정) / Mobile 780×1782
  • 구성:
    • 2열 메이슨리(Masonry) 레이아웃으로 포스트잇 나열
    • Freeform의 모바일 대응 뷰
    • 터치 탭으로 상세 보기
┌────────────────────────┐ ─┐
│ 📌 메모 제목 │ │ 끝 말림 효과
│ │ │ (CSS box-shadow +
│ 메모 내용 미리보기 │ │ gradient)
│ 최대 10줄 표시 │ │
│ ... │ │
│ │ │
│ 📅 D-3 ■■■■□ 70% │ │ 마감일 + 진척도
└────────────────────────┘ ─┘
↗ 말린 모서리

CSS 포스트잇 효과(참고):

.note-card {
border-radius: 2px 2px 2px 12px; /* 좌하단만 둥글게 */
box-shadow:
2px 2px 5px rgba(0,0,0,0.1), /* 기본 그림자 */
inset 0 -30px 30px -20px rgba(0,0,0,0.03); /* 내부 말림 효과 */
position: relative;
}
.note-card::after {
content: '';
position: absolute;
bottom: 0; right: 0;
width: 30px; height: 30px;
background: linear-gradient(135deg, transparent 50%, rgba(0,0,0,0.04) 50%);
border-radius: 0 0 0 12px; /* 모서리 말림 */
}
Breakpoint디바이스Freeform 뷰Kanban 뷰
≥1280pxDesktop자유 드래그 배치 (캔버스)3컬럼 나란히
768~1279pxTablet그리드 레이아웃 (3열)3컬럼 (좁게)
<768pxMobile메이슨리 2열탭 전환 방식

  1. 이메일 형식 검증 (프론트 + 백엔드)
  2. 비밀번호 최소 8자, 영문+숫자 조합 검증
  3. 비밀번호 확인 일치 검증
  4. 이메일 중복 확인 (DB 조회)
  5. bcrypt 해싱 후 DB 저장
  6. 성공 → 로그인 페이지로 리다이렉트
  1. 이메일/비밀번호 입력
  2. DB 조회 + bcrypt 비교
  3. JWT 토큰 발급 (24시간 유효)
  4. LocalStorage에 토큰 저장
  5. 메인 페이지로 리다이렉트
  • 페이지 새로고침 시 LocalStorage의 JWT 토큰으로 /api/auth/me 호출하여 인증 상태 복원
  • 넓은 캔버스 영역에 포스트잇 자유 배치
  • Drag & Drop: 마우스로 포스트잇 위치 이동
  • Overlap: 포스트잇 간 겹침 허용 (z-index 관리, 클릭 시 맨 앞으로)
  • Resize: 포스트잇 크기 변경 (우하단 핸들)
  • 배치 정보(x, y, z_index, width, height)는 DB에 자동 저장
  • 2열 메이슨리(Masonry) 레이아웃
  • 자유 배치는 불가, 자동 배열
  • 터치 탭으로 상세 보기
컬럼설명색상 아이콘
Plan (계획)계획 단계의 메모📋
Progress (실행중)진행 중인 메모🔄
Done (완료)완료된 메모
  • 포스트잇을 컬럼 간 끌어 놓으면 상태 자동 변경
  • Progress 컬럼으로 이동 시 진척도 입력 프롬프트 표시
  • Progress 상태의 메모에 진척도 바 표시 (0~100%)
  • 색상: 030% 빨간색, 3170% 노란색, 71~100% 초록색
  • 제목 표시
  • 내용 최대 10줄 표시 (11줄 이상이면 ... 말줄임 처리)
  • Markdown 렌더링된 형태로 표시
  • 마감일 D-Day 배지 표시 (예: D-3, D-Day, D+2)
  • Kanban인 경우 진척도 % 바 표시
  • 전체 내용 Markdown 렌더링
  • 편집 모드 전환 가능
  • 메모 타입, 색상, 마감일 등 메타 정보 표시 및 수정
  • 삭제 기능
조건표시스타일
마감일 미설정표시 안 함-
마감일 > 오늘D-N일반 텍스트
마감일 = 오늘D-Day빨간색 강조 + 깜빡임
마감일 < 오늘D+N빨간색 + 취소선
  • 사용자의 모든 메모를 Gemini에 전달 → 종합 요약 생성
  • 프롬프트 예시:
    다음은 사용자의 메모 목록입니다. 전체적인 요약과 키워드를 한국어로 만들어주세요.
    [메모 데이터]
  • UI: 사이드 패널 또는 모달에 요약 결과 표시
  • 마감일 임박 메모, 오래된 미완료 메모 등을 Gemini가 분석
  • 프롬프트 예시:
    현재 날짜: {today}
    다음 메모 목록을 분석하여 지금 시점에서 가장 중요하고 긴급한 알림을
    우선순위와 함께 한국어로 생성해주세요.
    [메모 데이터 (제목, 상태, 마감일, 진척도)]
  • UI: 알림 배지 + 알림 목록 드롭다운
문법지원 여부설명
# 제목H1~H6
**굵게**Bold
*기울임*Italic
~~취소선~~Strikethrough
- 목록Unordered list
1. 순서 목록Ordered list
[ ] 체크박스Task list
`코드`Inline code
``` 코드블록 ```Code block
[링크](url)Link
> 인용Blockquote
---구분선
![이미지](url)이미지 미지원 (텍스트 전용)

8.1 SQL Injection 방지 (GEMINI.md 규칙 준수)

Section titled “8.1 SQL Injection 방지 (GEMINI.md 규칙 준수)”
# ✅ 올바른 방법 - 파라미터 바인딩
cursor.execute(
"SELECT * FROM notes WHERE user_id = ? AND note_type = ?",
(user_id, note_type)
)
# ❌ 금지 - 문자열 포맷팅
cursor.execute(f"SELECT * FROM notes WHERE user_id = {user_id}")
  • 모든 쿼리는 파라미터 바인딩 사용 (SQLite3 ? 플레이스홀더)
  • 동적 컬럼 (정렬, 필터)은 화이트리스트 매핑으로 검증:
# 정렬 컬럼 화이트리스트
ALLOWED_SORT_COLUMNS = {
"created_at": "created_at",
"updated_at": "updated_at",
"title": "title",
"due_date": "due_date",
}
  • bcrypt 사용 (salt rounds: 12)
  • 평문 비밀번호 절대 저장 금지
  • Algorithm: HS256
  • 만료 시간: 24시간
  • Secret Key: 환경변수 SECRET_KEY로 관리
# FastAPI CORS 설정
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"], # Next.js dev server
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

# 서버 설정
HOST=0.0.0.0
PORT=8000
# 데이터베이스
DATABASE_URL=sqlite:///./post_note.db
# JWT
SECRET_KEY=your-secret-key-change-in-production
ACCESS_TOKEN_EXPIRE_MINUTES=1440 # 24시간
# Gemini AI
GEMINI_API_KEY=your-gemini-api-key
GEMINI_MODEL=gemini-3-flash-preview
NEXT_PUBLIC_API_URL=http://localhost:8000

  1. 프로젝트 초기 세팅 (Next.js + FastAPI)
  2. 데이터베이스 스키마 생성
  3. 인증 시스템 (회원가입/로그인/JWT)
  4. 메모 CRUD API + 기본 UI
  1. Freeform 뷰 (Drag & Drop, 자유 배치)
  2. Kanban 뷰 (3컬럼, 상태 변경)
  3. 메모 생성 팝업 (전체 입력 필드)
  1. Markdown 렌더링/편집
  2. D-Day 표시 기능
  3. 반응형 디자인 (Mobile 대응)
  1. Gemini API 연동 (전체 요약)
  2. 중요 알림 기능
  1. UI 디테일 (포스트잇 말림 효과, 애니메이션)
  2. 테스트 작성 (단위 테스트 + API 테스트)
  3. 문서 업데이트 (Wiki)

11. 코드 규칙 (GEMINI.md 준수 사항)

Section titled “11. 코드 규칙 (GEMINI.md 준수 사항)”
규칙적용
테스트 코드 → /test 디렉토리
스크립트 → /scripts 디렉토리
SQL Injection 방지 (파라미터 바인딩)
소스 코드 주석 → 한국어
프론트엔드 수정 후 빌드 에러 확인
새 API 추가 시 CURL + 테스트 검증
백엔드 변경 → docs/backend-wiki.md 업데이트
프론트엔드 변경 → docs/frontend-wiki.md 업데이트
Sequential Thinking MCP 사용 (단순 수정 제외)
Context7 MCP로 최신 API 확인

항목
Stitch Project ID2027687418161249866
Project Titlepost-note
총 스크린 수7개
#Screen ID제목디바이스해상도
1051e257cb7da4537b857ca013f38f902로그인 페이지 (개선)Desktop2560×2048
29d23a039776748fe841f56db263f1ede회원 가입 페이지 (파스텔 블루)Desktop2560×2048
39d25a07d47334c43b20969947358c4f5메인 자유 배치 모드 (AI 아이콘 및 메뉴 정리)Desktop2560×2058
40e29e32df0b74f45a8ba3232370685a2심플 칸반 보드 뷰 (상태 중심)Desktop2560×2048
549651950c5bc43a5b2ab7ca4b5fd73ca상세 메모 생성 팝업Desktop2560×2048
676ff876cf0214ea5a5aadb1278af1925모바일 심플 칸반 보드Mobile780×2012
7bfd36c44c0df40dca819d4bbceaabdd7모바일 메이슨리 뷰 (이미지 제거 및 텍스트 수정)Mobile780×1782

개발 시 각 스크린의 HTML 코드를 Stitch MCP get_screen API로 가져와 디자인 참조로 활용합니다.