diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index f36c3c4b..9964d8a2 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -4,92 +4,241 @@
+https://daehyunk1m.github.io/front_7th_chapter2-1/
### 기본과제
-#### 1) 라우팅 구현:
-- [ ] History API를 사용하여 SPA 라우터 구현
- - [ ] '/' (홈 페이지)
- - [ ] '/login' (로그인 페이지)
- - [ ] '/profile' (프로필 페이지)
-- [ ] 각 라우트에 해당하는 컴포넌트 렌더링 함수 작성
-- [ ] 네비게이션 이벤트 처리 (링크 클릭 시 페이지 전환)
-- [ ] 주소가 변경되어도 새로고침이 발생하지 않아야 한다.
-
-#### 2) 사용자 관리 기능:
-- [ ] LocalStorage를 사용한 간단한 사용자 데이터 관리
- - [ ] 사용자 정보 저장 (이름, 간단한 소개)
- - [ ] 로그인 상태 관리 (로그인/로그아웃 토글)
-- [ ] 로그인 폼 구현
- - [ ] 사용자 이름 입력 및 검증
- - [ ] 로그인 버튼 클릭 시 LocalStorage에 사용자 정보 저장
-- [ ] 로그아웃 기능 구현
- - [ ] 로그아웃 버튼 클릭 시 LocalStorage에서 사용자 정보 제거
-
-#### 3) 프로필 페이지 구현:
-- [ ] 현재 로그인한 사용자의 정보 표시
- - [ ] 사용자 이름
- - [ ] 간단한 소개
-- [ ] 프로필 수정 기능
- - [ ] 사용자 소개 텍스트 수정 가능
- - [ ] 수정된 정보 LocalStorage에 저장
-
-#### 4) 컴포넌트 기반 구조 설계:
-- [ ] 재사용 가능한 컴포넌트 작성
- - [ ] Header 컴포넌트
- - [ ] Footer 컴포넌트
-- [ ] 페이지별 컴포넌트 작성
- - [ ] HomePage 컴포넌트
- - [ ] ProfilePage 컴포넌트
- - [ ] NotFoundPage 컴포넌트
-
-#### 5) 상태 관리 초기 구현:
-- [ ] 간단한 상태 관리 시스템 설계
- - [ ] 전역 상태 객체 생성 (예: 현재 로그인한 사용자 정보)
-- [ ] 상태 변경 함수 구현
- - [ ] 상태 업데이트 시 관련 컴포넌트 리렌더링
-
-#### 6) 이벤트 처리 및 DOM 조작:
-- [ ] 사용자 입력 처리 (로그인 폼, 프로필 수정 등)
-- [ ] 동적 컨텐츠 렌더링 (사용자 정보 표시, 페이지 전환 등)
-
-#### 7) 라우팅 예외 처리:
-- [ ] 잘못된 라우트 접근 시 404 페이지 표시
+#### 상품목록
+
+**상품 목록 로딩**
+
+- [x] 페이지 접속 시 로딩 상태가 표시된다
+- [x] 데이터 로드 완료 후 상품 목록이 렌더링된다
+- [x] 로딩 실패 시 에러 상태가 표시된다
+- [x] 에러 발생 시 재시도 버튼이 제공된다
+
+**상품 목록 조회**
+
+- [x] 각 상품의 기본 정보(이미지, 상품명, 가격)가 카드 형태로 표시된다
+
+**한 페이지에 보여질 상품 수 선택**
+
+- [x] 드롭다운에서 10, 20, 50, 100개 중 선택할 수 있으며 기본 값은 20개 이다.
+- [x] 선택 변경 시 즉시 목록에 반영된다
+
+**상품 정렬 기능**
+
+- [x] 상품을 가격순/이름순으로 오름차순/내림차순 정렬을 할 수 있다.
+- [x] 드롭다운을 통해 정렬 기준을 선택할 수 있다
+- [x] 정렬 변경 시 즉시 목록에 반영된다
+
+**무한 스크롤 페이지네이션**
+
+- [x] 페이지 하단 근처 도달 시 다음 페이지 데이터가 자동 로드된다
+- [x] 스크롤에 따라 계속해서 새로운 상품들이 목록에 추가된다
+- [x] 새 데이터 로드 중일 때 로딩 인디케이터와 스켈레톤 UI가 표시된다
+- [x] 홈 페이지에서만 무한 스크롤이 활성화된다
+
+**상품을 장바구니에 담기**
+
+- [x] 각 상품에 장바구니 추가 버튼이 있다
+- [x] 버튼 클릭 시 해당 상품이 장바구니에 추가된다
+- [x] 추가 완료 시 사용자에게 알림이 표시된다
+
+**상품 검색**
+
+- [x] 상품명 기반 검색을 위한 텍스트 입력 필드가 있다
+- [ ] 검색 버튼 클릭으로 검색이 수행된다
+- [ ] Enter 키로 검색이 수행된다
+- [ ] 검색어와 일치하는 상품들만 목록에 표시된다
+
+**카테고리 선택**
+
+- [ ] 사용 가능한 카테고리들을 선택할 수 있는 UI가 제공된다
+- [ ] 선택된 카테고리에 해당하는 상품들만 표시된다
+- [ ] 전체 상품 보기로 돌아갈 수 있다
+- [ ] 2단계 카테고리 구조를 지원한다 (1depth, 2depth)
+
+**카테고리 네비게이션**
+
+- [ ] 현재 선택된 카테고리 경로가 브레드크럼으로 표시된다
+- [ ] 브레드크럼의 각 단계를 클릭하여 상위 카테고리로 이동할 수 있다
+- [ ] "전체" > "1depth 카테고리" > "2depth 카테고리" 형태로 표시된다
+
+**현재 상품 수 표시**
+
+- [x] 현재 조건에서 조회된 총 상품 수가 화면에 표시된다
+- [ ] 검색이나 필터 적용 시 상품 수가 실시간으로 업데이트된다
+
+#### 장바구니
+
+**장바구니 모달**
+
+- [ ] 장바구니 아이콘 클릭 시 모달 형태로 장바구니가 열린다
+- [ ] X 버튼이나 배경 클릭으로 모달을 닫을 수 있다
+- [ ] ESC 키로 모달을 닫을 수 있다
+- [ ] 모달에서 장바구니의 모든 기능을 사용할 수 있다
+
+**장바구니 수량 조절**
+
+- [ ] 각 장바구니 상품의 수량을 증가할 수 있다
+- [ ] 각 장바구니 상품의 수량을 감소할 수 있다
+- [ ] 수량 변경 시 총 금액이 실시간으로 업데이트된다
+
+**장바구니 삭제**
+
+- [ ] 각 상품에 삭제 버튼이 배치되어 있다
+- [ ] 삭제 버튼 클릭 시 해당 상품이 장바구니에서 제거된다
+
+**장바구니 선택 삭제**
+
+- [ ] 각 상품에 선택을 위한 체크박스가 제공된다
+- [ ] 선택 삭제 버튼이 있다
+- [ ] 체크된 상품들만 일괄 삭제된다
+
+**장바구니 전체 선택**
+
+- [ ] 모든 상품을 한 번에 선택할 수 있는 마스터 체크박스가 있다
+- [ ] 전체 선택 시 모든 상품의 체크박스가 선택된다
+- [ ] 전체 해제 시 모든 상품의 체크박스가 해제된다
+
+**장바구니 비우기**
+
+- [ ] 장바구니에 있는 모든 상품을 한 번에 삭제할 수 있다
+
+#### 상품 상세
+
+**상품 클릭시 상세 페이지 이동**
+
+- [x] 상품 목록에서 상품 이미지나 상품 정보 클릭 시 상세 페이지로 이동한다
+- [x] URL이 `/product/{productId}` 형태로 변경된다
+- [x] 상품의 자세한 정보가 전용 페이지에서 표시된다
+
+**상품 상세 페이지 기능**
+
+- [x] 상품 이미지, 설명, 가격 등의 상세 정보가 표시된다
+- [x] 전체 화면을 활용한 상세 정보 레이아웃이 제공된다
+
+**상품 상세 - 장바구니 담기**
+
+- [x] 상품 상세 페이지에서 해당 상품을 장바구니에 추가할 수 있다
+- [x] 페이지 내에서 수량을 선택하여 장바구니에 추가할 수 있다
+- [x] 수량 증가/감소 버튼이 제공된다
+
+**관련 상품 기능**
+
+- [ ] 상품 상세 페이지에서 관련 상품들이 표시된다
+- [ ] 같은 카테고리(category2)의 다른 상품들이 관련 상품으로 표시된다
+- [ ] 관련 상품 클릭 시 해당 상품의 상세 페이지로 이동한다
+- [ ] 현재 보고 있는 상품은 관련 상품에서 제외된다
+
+**상품 상세 페이지 내 네비게이션**
+
+- [x] 상품 상세에서 상품 목록으로 돌아가는 버튼이 제공된다
+- [ ] 브레드크럼을 통해 카테고리별 상품 목록으로 이동할 수 있다
+- [x] SPA 방식으로 페이지 간 이동이 부드럽게 처리된다
+
+#### 사용자 피드백 시스템
+
+**토스트 메시지**
+
+- [x] 장바구니 추가 시 성공 메시지가 토스트로 표시된다
+- [x] 장바구니 삭제, 선택 삭제, 전체 삭제 시 알림 메시지가 표시된다
+- [x] 토스트는 3초 후 자동으로 사라진다
+- [x] 토스트에 닫기 버튼이 제공된다
+- [x] 토스트 타입별로 다른 스타일이 적용된다 (success, info, error)
### 심화과제
-#### 1) 해시 라우터 구현
-- [ ] location.hash를 이용하여 SPA 라우터 구현
- - [ ] '/#/' (홈 페이지)
- - [ ] '/#/login' (로그인 페이지)
- - [ ] '/#/profile' (프로필 페이지)
-
-#### 2) 라우트 가드 구현
-- [ ] 로그인 상태에 따른 접근 제어
-- [ ] 비로그인 사용자의 특정 페이지 접근 시 로그인 페이지로 리다이렉션
+#### SPA 네비게이션 및 URL 관리
+
+**페이지 이동**
+
+- [x] 어플리케이션 내의 모든 페이지 이동(뒤로가기/앞으로가기를 포함)은 하여 새로고침이 발생하지 않아야 한다.
+
+**상품 목록 - URL 쿼리 반영**
+
+- [ ] 검색어가 URL 쿼리 파라미터에 저장된다
+- [ ] 카테고리 선택이 URL 쿼리 파라미터에 저장된다
+- [ ] 상품 옵션이 URL 쿼리 파라미터에 저장된다
+- [ ] 정렬 조건이 URL 쿼리 파라미터에 저장된다
+- [ ] 조건 변경 시 URL이 자동으로 업데이트된다
+- [ ] URL을 통해 현재 검색/필터 상태를 공유할 수 있다
+
+**상품 목록 - 새로고침 시 상태 유지**
+
+- [ ] 새로고침 후 URL 쿼리에서 검색어가 복원된다
+- [ ] 새로고침 후 URL 쿼리에서 카테고리가 복원된다
+- [ ] 새로고침 후 URL 쿼리에서 옵션 설정이 복원된다
+- [ ] 새로고침 후 URL 쿼리에서 정렬 조건이 복원된다
+- [ ] 복원된 조건에 맞는 상품 데이터가 다시 로드된다
-#### 3) 이벤트 위임
+**장바구니 - 새로고침 시 데이터 유지**
-- [ ] 이벤트 위임 방식으로 이벤트를 관리하고 있다.
+- [ ] 장바구니 내용이 브라우저에 저장된다
+- [ ] 새로고침 후에도 이전 장바구니 내용이 유지된다
+- [ ] 장바구니의 선택 상태도 함께 유지된다
+
+**상품 상세 - URL에 ID 반영**
+
+- [x] 상품 상세 페이지 이동 시 상품 ID가 URL 경로에 포함된다 (`/product/{productId}`)
+- [ ] URL로 직접 접근 시 해당 상품의 상세 페이지가 자동으로 로드된다
+
+**상품 상세 - 새로고침시 유지**
+
+- [ ] 새로고침 후에도 URL의 상품 ID를 읽어서 해당 상품 상세 페이지가 유지된다
+
+**404 페이지**
+
+- [x] 존재하지 않는 경로 접근 시 404 에러 페이지가 표시된다
+- [x] 홈으로 돌아가기 버튼이 제공된다
+
+#### AI로 한 번 더 구현하기
+
+- [ ] 기존에 구현한 기능을 AI로 다시 구현한다.
+- [ ] 이 과정에서 직접 가공하는 것은 최대한 지양한다.
## 과제 셀프회고
++11-10일
+발제문서와 스터디문서 딥다이브...!
+JS 관련 문서와
+SPA 관련 문서는 내용이 많아서 과제 진행하면서 중간중간 계속 참고하기로..
+
+컴포넌트를 나누고,
+깃헙페이지를 액션 워크플로우에 물려서 배포하는방식을 적용했다.
+
+페이지는 흰 화면이 나오지만, 타이틀은 '상품 쇼핑몰'로 제대로 나오는 것 같으니
+우선 흰 화면만 뜨는건 과제좀 진행하고 해결하는걸로..
+
++11-11일
+
### 기술적 성장
+
-### 코드 품질
+### 자랑하고 싶은 코드
+
+
+
+### 개선이 필요하다고 생각하는 코드
+
### 학습 효과 분석
+
### 과제 피드백
+
+### AI 활용 경험 공유하기
+
+
+
## 리뷰 받고 싶은 내용
+
+궁금한 것.
+
+제가 구현했을 때 생각보다 SPA의 구동 로직이 라우터를 통해 진행되는 것이 많은데요
+SPA를 구성할 때 라우팅도 무시못할 중요한 축 중 하나라고 생각됩니다.
+
+그런데 왜 리액트는 자체적인 라우팅이 없을까?
+라우팅을 사용할 때 react-router-dom 같은 다른 라이브러리에 의존하게 될까??
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 041962e7..5189dd5d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,17 +11,6 @@ on:
jobs:
basic:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- with:
- fetch-depth: 0
- ref: ${{ github.event.pull_request.head.sha }}
- - name: test basic
- run: |
- npm install
- npm run test:basic
- advacned:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
@@ -33,13 +22,13 @@ jobs:
version: latest
- uses: actions/setup-node@v4
with:
- node-version: 20
+ node-version: 22
cache: 'pnpm'
- - name: advanced-test
- run: |
+ - run: |
pnpm install
- pnpm run test:advanced
- e2e:
+ pnpm exec playwright install
+ pnpm run test:e2e:basic
+ advanced:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
@@ -52,10 +41,10 @@ jobs:
version: latest
- uses: actions/setup-node@v4
with:
- node-version: 20
+ node-version: 22
cache: 'pnpm'
- name: Install dependencies
run: |
pnpm install
- npx playwright install --with-deps
- pnpm run test:e2e
+ pnpm exec playwright install
+ pnpm run test:e2e:advanced
diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml
new file mode 100644
index 00000000..24245db3
--- /dev/null
+++ b/.github/workflows/gh-pages.yml
@@ -0,0 +1,32 @@
+name: Deploy to GitHub Pages
+
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write # v4부터 필요
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - uses: pnpm/action-setup@v4
+ with:
+ version: latest
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 22
+ cache: "pnpm"
+ - name: Install dependencies
+ run: |
+ pnpm install
+ pnpm run build
+ - name: Deploy to GitHub Pages
+ uses: peaceiris/actions-gh-pages@v4
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: ./dist
diff --git a/.gitignore b/.gitignore
index e76379da..7cff355f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,5 @@ dist-ssr
*.sw?
/test-results/
/playwright-report/
+coverage
+.coverage
diff --git a/.prettierrc b/.prettierrc
index c3fef9a3..1d2699e4 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,5 +1,6 @@
{
"tabWidth": 2,
"semi": true,
- "singleQuote": false
+ "singleQuote": false,
+ "printWidth": 120
}
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 00000000..475508c4
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,156 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Project Overview
+
+This is a front-end e-commerce shopping mall project ("항해플러스 프론트엔드 쇼핑몰") built with vanilla JavaScript as a Single Page Application (SPA). The project implements a product listing page with filtering, searching, sorting, shopping cart functionality, and product detail pages - all without using frameworks like React, Vue, or Angular.
+
+## Development Commands
+
+### Development Server
+```bash
+pnpm run dev # Start development server on port 5173
+pnpm run dev:hash # Start dev server with hash router (./index.hash.html)
+```
+
+### Build & Preview
+```bash
+pnpm run build # Build for production
+pnpm run preview # Preview production build locally
+```
+
+### Testing
+```bash
+# E2E Tests (Playwright)
+pnpm run test:e2e # Run all e2e tests
+pnpm run test:e2e:basic # Run basic tests only
+pnpm run test:e2e:advanced # Run advanced tests only
+pnpm run test:e2e:ui # Run tests with Playwright UI
+pnpm run test:e2e:report # Show test report
+pnpm run test:generate # Generate test code (codegen on localhost:5173)
+```
+
+Note: Vitest is configured but unit tests are not currently used (only e2e tests).
+
+### Code Quality
+```bash
+pnpm run lint:fix # Fix ESLint errors
+pnpm run prettier:write # Format code with Prettier
+```
+
+Note: Husky and lint-staged are configured to run these checks pre-commit.
+
+### Deployment
+```bash
+pnpm run deploy # Deploy to GitHub Pages (gh-pages -d dist)
+```
+
+## Architecture & Code Structure
+
+### SPA Implementation
+This project is built as a vanilla JavaScript SPA. The main entry point is `src/main.js`, which contains embedded HTML template strings for different UI states. The templates are rendered by setting `document.body.innerHTML`.
+
+**Key Template States (in main.js):**
+- `상품목록_레이아웃_로딩` - Product list loading state
+- `상품목록_레이아웃_로딩완료` - Product list loaded state
+- `상품목록_레이아웃_카테고리_1Depth` - Category 1st depth selected
+- `상품목록_레이아웃_카테고리_2Depth` - Category 2nd depth selected
+- `장바구니_비어있음` - Empty cart modal
+- `장바구니_선택없음` - Cart with no items selected
+- `장바구니_선택있음` - Cart with items selected
+- `상세페이지_로딩` - Product detail loading state
+- `상세페이지_로딩완료` - Product detail loaded state
+- `토스트` - Toast notifications
+- `_404_` - 404 error page
+
+### API Layer
+- **`src/api/productApi.js`** - Contains API calls for fetching product data
+- All API requests go through `/api/products` endpoints
+
+### Mock Service Worker (MSW)
+The project uses MSW for API mocking during development:
+- **`src/mocks/browser.js`** - Browser worker setup
+- **`src/mocks/handlers.js`** - API endpoint handlers with 200ms delay
+- **`src/mocks/items.json`** - Mock product data
+
+**API Endpoints (mocked):**
+- `GET /api/products` - List products with filtering, sorting, pagination
+- `GET /api/products/:id` - Get product detail by ID
+- `GET /api/categories` - Get category hierarchy (1depth & 2depth)
+
+**Query Parameters:**
+- `page` or `current` - Page number (default: 1)
+- `limit` - Items per page (default: 20)
+- `search` - Search term
+- `category1` - 1st level category filter
+- `category2` - 2nd level category filter
+- `sort` - Sorting: `price_asc`, `price_desc`, `name_asc`, `name_desc`
+
+### E2E Test Structure
+Tests are located in `e2e/` directory:
+- **`e2e/e2e.basic.spec.js`** - Basic functionality tests (상품목록, 장바구니, 상품 상세, 사용자 피드백)
+- **`e2e/e2e.advanced.spec.js`** - Advanced tests (SPA navigation, URL management, state persistence)
+- **`e2e/E2EHelpers.js`** - Test helper functions
+
+The Playwright config (`playwright.config.js`) automatically starts the dev server on port 5173 before running tests.
+
+## Important Project Requirements
+
+### Assignment Checklist
+The project is evaluated against a comprehensive checklist in `.github/pull_request_template.md` covering:
+
+**Basic Requirements (기본과제):**
+1. Product list with loading states, error handling, infinite scroll
+2. Shopping cart modal with full CRUD operations, selection, quantity adjustment
+3. Product detail page with related products
+4. Search and filtering (2-depth category hierarchy)
+5. Sorting and pagination
+6. Toast notifications
+
+**Advanced Requirements (심화과제):**
+1. Full SPA navigation without page refresh (including back/forward)
+2. URL state management (all filters, search, sort in query params)
+3. State persistence on refresh (cart in localStorage, URL params restored)
+4. 404 page handling
+5. AI-assisted reimplementation challenge
+
+### Technology Stack
+- **Build Tool:** Vite (using `rolldown-vite` variant)
+- **Styling:** TailwindCSS (loaded via CDN in index.html)
+- **Testing:** Playwright for E2E
+- **Mocking:** MSW (Mock Service Worker)
+- **Language:** Pure JavaScript (no TypeScript, no frameworks)
+- **Code Quality:** ESLint + Prettier with Husky pre-commit hooks
+
+### Key Architectural Patterns
+1. **Template-based rendering** - UI states are defined as template literal strings in main.js
+2. **Event delegation** - Event handlers should be attached to handle dynamically rendered elements
+3. **Manual routing** - SPA routing needs to be implemented without a router library
+4. **LocalStorage integration** - Cart state must persist across page refreshes
+5. **URL as state** - Search/filter/sort state syncs with URL query parameters
+
+## Development Tips
+
+### When Working with Templates
+The current architecture uses large template strings in `main.js`. When modifying UI:
+1. Locate the appropriate template constant (e.g., `상품목록_레이아웃_로딩완료`)
+2. Modify the HTML within that template string
+3. Ensure data attributes (like `data-product-id`) are maintained for event handling
+
+### When Adding New Features
+1. Consider which template states need updates
+2. Add necessary API mocking in `src/mocks/handlers.js` if new endpoints needed
+3. Update E2E tests to cover new functionality
+4. Update the PR template checklist if adding new requirements
+
+### Common Patterns to Follow
+- Use `data-*` attributes for element identification in event handlers
+- Implement debouncing for search inputs
+- Show loading skeletons during data fetches
+- Display toast notifications for user actions
+- Handle error states gracefully with retry options
+
+## GitHub Actions
+- **`.github/workflows/gh-pages.yml`** - Deploys to GitHub Pages on push
+- Uses `peaceiris/actions-gh-pages@v3` to publish the `dist/` directory
diff --git a/README.md b/README.md
deleted file mode 100644
index 6b476381..00000000
--- a/README.md
+++ /dev/null
@@ -1,115 +0,0 @@
-# 상세 기능 요구사항 명세서
-
-## 1. 상품 목록
-
-### 1.1 상품 목록 로딩
-- **초기 로딩**: 페이지 접속 시 로딩 상태 표시
-- **로딩 완료**: 데이터 로드 후 상품 목록 렌더링
-- **로딩 실패**: 에러 발생 시 재시도 옵션 제공
-
-### 1.2 상품 목록 조회
-- **상품 정보 표시**: 각 상품의 기본 정보 (이미지, 상품명, 가격 등) 카드 형태로 표시
-- **목록 레이아웃**: 그리드 형태로 상품들을 정렬하여 표시
-
-### 1.3 한 페이지에 보여질 상품 수 선택 (10, 20, 50, 100)
-- **선택 옵션**: 드롭다운 또는 라디오 버튼으로 10, 20, 50, 100개 중 선택
-- **기본값**: 특정 개수를 기본값으로 설정
-- **적용**: 선택 변경 시 즉시 목록에 반영
-
-### 1.4 무한 스크롤을 이용한 페이지네이션
-- **스크롤 감지**: 페이지 하단 근처 도달 시 다음 페이지 데이터 자동 로드
-- **연속 로딩**: 스크롤에 따라 계속해서 새로운 상품들을 목록에 추가
-- **로딩 표시**: 새 데이터 로드 중일 때 로딩 인디케이터 표시
-
-### 1.5 상품을 장바구니에 담을 수 있음
-- **장바구니 버튼**: 각 상품에 장바구니 추가 버튼 배치
-- **추가 동작**: 버튼 클릭 시 해당 상품이 장바구니에 추가됨
-- **피드백**: 추가 완료 시 사용자에게 알림
-
-### 1.6 상품 검색
-- **검색 입력창**: 상품명 기반 검색을 위한 텍스트 입력 필드
-- **검색 실행**: 입력 후 검색 버튼 클릭 또는 Enter 키로 검색 수행
-- **검색 결과**: 검색어와 일치하는 상품들만 목록에 표시
-
-### 1.7 카테고리 선택
-- **카테고리 목록**: 사용 가능한 카테고리들을 선택할 수 있는 UI 제공
-- **필터링**: 선택된 카테고리에 해당하는 상품들만 표시
-- **카테고리 해제**: 전체 상품 보기로 돌아갈 수 있는 옵션
-
-### 1.8 현재 상품 수
-- **상품 개수 표시**: 현재 조건에서 조회된 총 상품 수를 화면에 표시
-- **실시간 업데이트**: 검색이나 필터 적용 시 상품 수도 함께 업데이트
-
-## 2. 장바구니
-
-### 2.1 장바구니 수량 조절
-- **수량 변경**: 각 장바구니 상품의 수량을 증가/감소할 수 있는 버튼 또는 입력 필드
-- **즉시 반영**: 수량 변경 시 총 금액 등 관련 정보가 실시간으로 업데이트
-
-### 2.2 장바구니 삭제
-- **개별 삭제**: 각 상품에 대해 장바구니에서 제거하는 기능
-- **삭제 버튼**: 각 상품 항목에 삭제 버튼 배치
-
-### 2.3 장바구니 선택 삭제
-- **체크박스**: 각 상품에 선택을 위한 체크박스 제공
-- **선택 삭제 버튼**: 체크된 상품들을 일괄 삭제하는 버튼
-- **선택된 항목만 삭제**: 체크된 상품들만 장바구니에서 제거
-
-### 2.4 장바구니 전체 선택
-- **전체 선택 체크박스**: 모든 상품을 한 번에 선택/해제할 수 있는 마스터 체크박스
-- **일괄 선택**: 전체 선택 시 모든 상품의 체크박스가 선택됨
-- **일괄 해제**: 전체 해제 시 모든 상품의 체크박스가 해제됨
-
-### 2.5 장바구니 비우기
-- **전체 삭제**: 장바구니에 있는 모든 상품을 한 번에 삭제하는 기능
-- **확인 절차**: 전체 삭제 전 사용자 확인 과정
-
-## 3. 상품 상세
-
-### 3.1 상품 클릭시 모달로 조회 가능
-- **모달 오픈**: 상품 목록에서 상품을 클릭하면 상세 정보를 보여주는 모달 창 열림
-- **상세 정보**: 모달 내에서 상품의 자세한 정보 표시
-
-### 3.2 모달
-- **모달 창**: 상품 상세 정보를 담은 오버레이 형태의 팝업 창
-- **상세 내용**: 상품 이미지, 설명, 가격 등의 상세 정보 표시
-
-## 4. 편의성
-
-### 4.1 상품 목록 - URL 쿼리 반영
-- **검색 조건 저장**: 검색어, 카테고리 선택, 상품 옵션을 URL 쿼리 파라미터에 저장
-- **URL 업데이트**: 사용자가 조건을 변경할 때마다 URL이 자동으로 업데이트됨
-- **공유 가능**: URL을 통해 현재 검색/필터 상태를 다른 사람과 공유 가능
-
-### 4.2 상품 목록 - 새로고침 시 상태 유지
-- **상태 복원**: 새로고침 후 URL 쿼리를 읽어서 이전의 검색어, 카테고리, 옵션 설정을 복원
-- **데이터 복원**: 복원된 조건에 맞는 상품 데이터를 다시 로드하여 표시
-
-### 4.3 장바구니 - 새로고침 시 데이터 유지
-- **데이터 저장**: 장바구니 내용을 브라우저에 저장 (로컬스토리지 등)
-- **데이터 복원**: 새로고침 후에도 이전 장바구니 내용을 그대로 유지
-
-### 4.4 상품 상세 - URL 쿼리에 ID 반영
-- **상품 ID 저장**: 상품 상세 모달 열릴 때 해당 상품의 ID를 URL 쿼리에 추가
-- **직접 접근**: URL로 직접 접근 시 해당 상품의 상세 모달이 자동으로 열림
-
-### 4.5 상품 상세 - 새로고침시 유지
-- **모달 상태 유지**: 새로고침 후에도 URL의 상품 ID를 읽어서 해당 상품 모달을 다시 열어줌
-
-### 4.6 상품 상세 - ESC로 닫기
-- **키보드 제어**: ESC 키를 누르면 열린 상품 상세 모달이 닫힘
-
-### 4.7 상품 상세 - 배경 클릭시 닫기
-- **마우스 제어**: 모달 외부 배경 영역을 클릭하면 모달이 닫힘
-
-### 4.8 상품 상세 - 방향키로 다음 상품 선택
-- **키보드 네비게이션**: 좌우 방향키를 사용해서 이전/다음 상품의 상세 모달로 이동
-- **순차 이동**: 현재 상품 목록 순서에 따라 이전/다음 상품으로 전환
-
-### 4.9 상품 상세 - 다음 페이지 상품 접근 시 페이지네이션 실행
-- **자동 페이지 로드**: 현재 페이지의 마지막 상품에서 다음 상품으로 이동 시, 다음 페이지를 자동으로 로드
-- **연속 탐색**: 페이지 경계를 넘나들며 연속적으로 상품 상세를 탐색 가능
-
-### 4.10 상품 상세 - 장바구니 담기
-- **모달 내 장바구니**: 상품 상세 모달 안에서도 해당 상품을 장바구니에 추가할 수 있는 기능
-- **수량 선택**: 모달 내에서 수량을 선택하여 장바구니에 추가
diff --git a/cart-modal.html b/cart-modal.html
new file mode 100644
index 00000000..66455103
--- /dev/null
+++ b/cart-modal.html
@@ -0,0 +1,320 @@
+
+
+
+