# KPN 추천 시스템 UX 상세 설계서 > 참조 프로젝트 기반 UX 구현 가이드 > 작성일: 2025-01-XX > 기준: KPN Recommendation System 참조 프로젝트 --- ## 📋 목차 1. [UX 설계 철학](#1-ux-설계-철학) 2. [메뉴 구조](#2-메뉴-구조) 3. [페이지별 상세 설계](#3-페이지별-상세-설계) 4. [네비게이션 플로우](#4-네비게이션-플로우) 5. [API 연동 명세](#5-api-연동-명세) 6. [컴포넌트 재사용 전략](#6-컴포넌트-재사용-전략) 7. [모바일 반응형 가이드](#7-모바일-반응형-가이드) --- ## 1. UX 설계 철학 ### 1.1 핵심 원칙 #### **양방향 탐색 지원** - **KPN → 소**: "이 KPN을 누구한테 쓸 수 있지?" - **소 → KPN**: "이 소한테 뭘 써야 하지?" - **농장 전체**: "우리 농장엔 어떤 KPN이 필요하지?" #### **3가지 독립적 진입점** ``` 사용자 니즈별 진입점: ├── KPN 중심 사고 → KPN 관리 메뉴 ├── 소 중심 사고 → 내 소보기 메뉴 └── 전략적 사고 → 홈 또는 KPN 관리 > 농장 추천 ``` #### **정보 아키텍처** ``` 일관된 3-패널 레이아웃 (Desktop): ┌────────┬──────────────┬──────────────┐ │사이드바 │ 메인 콘텐츠 │ 상세 패널 │ │(고정) │ (목록/그리드)│ (슬라이드) │ └────────┴──────────────┴──────────────┘ ``` --- ## 2. 메뉴 구조 ### 2.1 사이드바 메뉴 (최종안) ```typescript interface MenuItem { label: string; href: string; icon: React.ReactNode; badge?: string; // 알림 배지 } const menuItems: MenuItem[] = [ { label: "홈", href: "/home", icon: }, { label: "내 소보기", href: "/cow", icon: }, { label: "KPN 관리", // ⭐ 추가 href: "/kpn", icon: }, { label: "교배 계획", // ⭐ 추가 (선택사항) href: "/breeding", icon: } ] ``` ### 2.2 PRD vs 최종 메뉴 비교 | 구분 | PRD (기능요구사항20.md) | 최종 구현안 | 사유 | |------|----------------------|-----------|------| | 메뉴 개수 | 2개 (홈, 내 소보기) | 4개 (홈, 내 소보기, KPN 관리, 교배 계획) | 사용성 개선 | | KPN 접근 | 홈 섹션 / 소 상세 서브 | 독립 메뉴 | 양방향 탐색 지원 | | 구매 계획 | 홈 섹션 | KPN 관리 > 농장 추천 | 전용 페이지로 분리 | | 교배 이력 | 미정의 | 독립 메뉴 (선택사항) | 저장된 계획 관리 | --- ## 3. 페이지별 상세 설계 ### 3.1 KPN 목록 페이지 (`/kpn`) #### **페이지 목적** - 전체 KPN 한눈에 조망 - 보유/미보유 KPN 필터링 - KPN 상세 정보 및 적합한 소 확인 #### **핵심 기능** ##### 1) 필터 상태 (3가지) ```typescript type FilterStatus = 'all' | 'owned' | 'needed'; // 전체: 모든 KPN // 보유: 농가가 보유 중인 KPN (초록 배지) // 필요: 구매가 필요한 KPN ``` ##### 2) 정렬 옵션 ```typescript type SortBy = 'matching' | 'inbreeding'; // matching: 매칭률 (우량형확률) 높은 순 // inbreeding: 근친도 낮은 순 ``` ##### 3) 액션 버튼 (2개) ```typescript ``` #### **API 연동** ```typescript // 1. KPN 목록 조회 const response = await fetch('/api/kpn/ranking', { method: 'POST', body: JSON.stringify({ filterOptions: { filters: [ // 필터 조건 (선택사항) ] }, rankingOptions: { criteriaType: 'GENE', order: 'DESC', weights: {} } }) }); // 2. 보유 KPN 확인 const ownedKpns = await fetch('/api/kpn/owned'); // Response: { isOwned: boolean } 각 KPN별 ``` #### **UI 구성** ```tsx
{/* 헤더 */}
{/* 통계 카드 */} {/* 액션 버튼 */} {/* 필터 & 정렬 */} {/* KPN 그리드 */}
``` #### **KPN 카드 디자인** ```tsx {/* 헤더 */}
#{rank} {isOwned && 보유}

{kpn.pkKpnNo}

{kpn.origin}

{/* 주요 유전자 */}
{kpn.genes.map(gene => ( {gene} ))}
{/* 통계 */}
{/* 추천 이유 */}

{kpn.recommendationReason}

``` --- ### 3.2 KPN 보유 등록 페이지 (`/kpn/inventory`) #### **페이지 목적** - 농가가 보유한 KPN 등록 및 관리 - 보유 KPN 목록 조회 - 보유 수량 및 메모 관리 #### **핵심 기능** ##### 1) KPN 검색 및 등록 ```typescript // KPN 검색 const kpns = await fetch(`/api/kpn/search?keyword=${keyword}`); // 보유 등록 await fetch('/api/kpn/owned', { method: 'POST', body: JSON.stringify({ kpnNo: 'KPN1385', quantity: 5, memo: '2024년 구매' }) }); ``` ##### 2) 보유 KPN 목록 ```typescript const ownedList = await fetch('/api/kpn/owned'); // Response: { totalCount: 3, ownedKpns: [ { id: 1, kpnNo: 'KPN1385', quantity: 5, memo: '2024년 구매', registeredAt: '2024-03-15', kpnInfo: { /* KPN 상세 정보 */ } } ] } ``` ##### 3) 수정 및 삭제 ```typescript // 수정 await fetch(`/api/kpn/owned/${id}`, { method: 'PATCH', body: JSON.stringify({ quantity: 3, memo: '사용 중' }) }); // 삭제 await fetch(`/api/kpn/owned/${id}`, { method: 'DELETE' }); ``` #### **UI 구성** ```tsx
{/* 헤더 */}
{/* 등록 폼 */}

새 KPN 등록