# 정보 아키텍처 설계서 ## 목차 1. [사이트맵](#1-사이트맵) 2. [프로젝트 구조 설계](#2-프로젝트-구조-설계) --- ## 1. 사이트맵 ### 1.1 전체 사이트 구조 ``` KT 이벤트 마케팅 플랫폼 │ ├── 🔐 인증 영역 (Public) │ ├── /login - 로그인 │ ├── /register - 회원가입 │ └── /profile - 프로필 관리 │ ├── 🏠 대시보드 영역 (Private) │ ├── / - 메인 대시보드 │ │ ├── 진행중 이벤트 현황 │ │ ├── 최근 성과 요약 │ │ └── 빠른 작업 버튼 │ │ │ └── /events - 이벤트 목록 │ ├── 전체 이벤트 조회 │ ├── 상태별 필터링 (진행중/예정/종료) │ └── 검색 기능 │ ├── ✨ 이벤트 생성 플로우 (Private) │ └── /events/create - 이벤트 생성 Funnel │ ├── Step 1: /events/create?step=objective - 목적 선택 │ ├── Step 2: /events/create?step=recommendation - AI 추천 확인 │ ├── Step 3: /events/create?step=content - 콘텐츠 미리보기 │ ├── Step 4: /events/create?step=edit - 콘텐츠 편집 │ ├── Step 5: /events/create?step=channels - 배포 채널 선택 │ └── Step 6: /events/create?step=publish - 최종 승인 │ └── 📊 이벤트 관리 영역 (Private) └── /events/[eventId] ├── /events/[eventId] - 이벤트 상세 ├── /events/[eventId]/participants - 참여자 목록 ├── /events/[eventId]/participate - 고객 참여 화면 (Public) ├── /events/[eventId]/draw - 당첨자 추첨 └── /events/[eventId]/analytics - 성과 분석 ``` ### 1.2 네비게이션 흐름 #### Bottom Navigation (인증 후 모든 화면) ``` ┌─────────────────────────────────────────────────┐ │ 홈 이벤트 분석 프로필 │ │ / /events /analytics /profile │ └─────────────────────────────────────────────────┘ ``` #### 주요 사용자 여정 **여정 1: 신규 이벤트 생성** ``` / (대시보드) → [+ 새 이벤트 생성] 버튼 클릭 → /events/create?step=objective (목적 선택) → /events/create?step=recommendation (AI 추천) → /events/create?step=content (미리보기) → /events/create?step=edit (편집) → /events/create?step=channels (채널 선택) → /events/create?step=publish (승인) → /events/[eventId] (생성 완료, 상세 페이지) ``` **여정 2: 이벤트 관리 및 분석** ``` /events (이벤트 목록) → [이벤트 카드] 클릭 → /events/[eventId] (상세) ├── [참여자 관리] → /events/[eventId]/participants ├── [당첨자 추첨] → /events/[eventId]/draw └── [성과 분석] → /events/[eventId]/analytics ``` **여정 3: 고객 참여** ``` QR 코드 스캔 또는 링크 접속 → /events/[eventId]/participate (참여 화면) → 참여 정보 입력 → 참여 완료 ``` ### 1.3 접근 권한 설정 | 페이지 경로 | 접근 권한 | 인증 필요 | 설명 | |------------|----------|---------|------| | `/login` | Public | ❌ | 로그인 페이지 | | `/register` | Public | ❌ | 회원가입 페이지 | | `/` | Private | ✅ | 메인 대시보드 | | `/events` | Private | ✅ | 이벤트 목록 | | `/events/create` | Private | ✅ | 이벤트 생성 플로우 | | `/events/[eventId]` | Private | ✅ | 이벤트 상세 | | `/events/[eventId]/participants` | Private | ✅ | 참여자 관리 | | `/events/[eventId]/draw` | Private | ✅ | 당첨자 추첨 | | `/events/[eventId]/analytics` | Private | ✅ | 성과 분석 | | `/events/[eventId]/participate` | **Public** | ❌ | 고객 참여 화면 | | `/profile` | Private | ✅ | 프로필 관리 | --- ## 2. 프로젝트 구조 설계 ### 2.1 Next.js 14 App Router 기반 디렉토리 구조 ``` fe-kt-event-marketing/ │ ├── 📁 app/ # Next.js 14 App Router │ ├── (auth)/ # 인증 레이아웃 그룹 │ │ ├── login/ │ │ │ └── page.tsx # 로그인 페이지 │ │ ├── register/ │ │ │ └── page.tsx # 회원가입 페이지 │ │ └── layout.tsx # 인증 전용 레이아웃 │ │ │ ├── (main)/ # 메인 레이아웃 그룹 (인증 필요) │ │ ├── page.tsx # 대시보드 (/) │ │ ├── events/ │ │ │ ├── page.tsx # 이벤트 목록 │ │ │ ├── create/ │ │ │ │ └── page.tsx # 이벤트 생성 Funnel │ │ │ └── [eventId]/ │ │ │ ├── page.tsx # 이벤트 상세 │ │ │ ├── participants/ │ │ │ │ └── page.tsx # 참여자 목록 │ │ │ ├── draw/ │ │ │ │ └── page.tsx # 당첨자 추첨 │ │ │ └── analytics/ │ │ │ └── page.tsx # 성과 분석 │ │ ├── profile/ │ │ │ └── page.tsx # 프로필 관리 │ │ └── layout.tsx # 메인 레이아웃 (Bottom Nav 포함) │ │ │ ├── events/ # Public 이벤트 경로 │ │ └── [eventId]/ │ │ └── participate/ │ │ └── page.tsx # 고객 참여 화면 (인증 불필요) │ │ │ ├── api/ # API Routes (서버 컴포넌트) │ │ └── auth/ │ │ └── [...nextauth]/ │ │ └── route.ts # NextAuth API 라우트 │ │ │ ├── layout.tsx # 루트 레이아웃 │ ├── error.tsx # 전역 에러 핸들링 │ ├── loading.tsx # 전역 로딩 상태 │ └── not-found.tsx # 404 페이지 │ ├── 📁 src/ │ ├── components/ # React 컴포넌트 │ │ ├── common/ # 공통 컴포넌트 │ │ │ ├── Button/ │ │ │ │ ├── Button.tsx │ │ │ │ └── Button.test.tsx │ │ │ ├── Card/ │ │ │ │ └── Card.tsx │ │ │ ├── Input/ │ │ │ │ └── Input.tsx │ │ │ ├── Layout/ │ │ │ │ ├── BottomNavigation.tsx │ │ │ │ ├── Header.tsx │ │ │ │ └── Container.tsx │ │ │ └── Loading/ │ │ │ └── Loading.tsx │ │ │ │ │ ├── auth/ # 인증 관련 컴포넌트 │ │ │ ├── LoginForm.tsx │ │ │ ├── RegisterForm.tsx │ │ │ └── ProfileForm.tsx │ │ │ │ │ ├── dashboard/ # 대시보드 컴포넌트 │ │ │ ├── EventSummaryCard.tsx │ │ │ ├── PerformanceChart.tsx │ │ │ └── QuickActions.tsx │ │ │ │ │ ├── event/ # 이벤트 관련 컴포넌트 │ │ │ ├── EventCard.tsx │ │ │ ├── EventList.tsx │ │ │ ├── EventDetail.tsx │ │ │ ├── ParticipantTable.tsx │ │ │ └── WinnerDrawModal.tsx │ │ │ │ │ └── funnel/ # Funnel 관련 컴포넌트 │ │ ├── ObjectiveStep.tsx │ │ ├── RecommendationStep.tsx │ │ ├── ContentStep.tsx │ │ ├── EditStep.tsx │ │ ├── ChannelsStep.tsx │ │ ├── PublishStep.tsx │ │ └── FunnelLayout.tsx │ │ │ ├── hooks/ # Custom React Hooks │ │ ├── useAuth.ts # 인증 상태 관리 │ │ ├── useEvent.ts # 이벤트 CRUD │ │ ├── useEventList.ts # 이벤트 목록 │ │ ├── useParticipants.ts # 참여자 관리 │ │ ├── useJobPolling.ts # Job 상태 폴링 │ │ └── useToast.ts # Toast 알림 │ │ │ ├── lib/ # 라이브러리 및 유틸리티 │ │ ├── api/ # API 클라이언트 │ │ │ ├── client.ts # Axios 인스턴스 │ │ │ ├── auth.ts # 인증 API │ │ │ ├── events.ts # 이벤트 API │ │ │ └── participants.ts # 참여 API │ │ │ │ │ ├── utils/ # 유틸리티 함수 │ │ │ ├── format.ts # 날짜/숫자 포맷팅 │ │ │ ├── validation.ts # 폼 검증 헬퍼 │ │ │ └── storage.ts # localStorage 헬퍼 │ │ │ │ │ └── constants/ # 상수 정의 │ │ ├── api.ts # API 엔드포인트 │ │ ├── routes.ts # 라우트 경로 │ │ └── event.ts # 이벤트 상수 │ │ │ ├── store/ # 상태 관리 (Zustand) │ │ ├── authStore.ts # 인증 상태 │ │ ├── funnelStore.ts # Funnel 임시 저장 │ │ └── uiStore.ts # UI 상태 (Toast, Modal 등) │ │ │ ├── styles/ # 스타일 │ │ ├── globals.css # 전역 스타일 │ │ └── theme.ts # MUI 테마 설정 │ │ │ └── types/ # TypeScript 타입 정의 │ ├── auth.ts # 인증 관련 타입 │ ├── event.ts # 이벤트 타입 │ ├── participant.ts # 참여자 타입 │ └── api.ts # API 응답 타입 │ ├── 📁 public/ # 정적 파일 │ ├── images/ # 이미지 파일 │ ├── icons/ # 아이콘 파일 │ └── runtime-env.js # 런타임 환경 변수 │ ├── 📁 tests/ # 테스트 파일 │ ├── unit/ # 단위 테스트 │ ├── integration/ # 통합 테스트 │ └── e2e/ # E2E 테스트 (Playwright) │ ├── .env.local # 로컬 환경 변수 ├── .env.development # 개발 환경 변수 ├── .env.production # 프로덕션 환경 변수 ├── next.config.js # Next.js 설정 ├── tsconfig.json # TypeScript 설정 ├── package.json # 의존성 관리 └── README.md # 프로젝트 문서 ``` ### 2.2 주요 파일 설명 #### 2.2.1 레이아웃 구조 **app/layout.tsx** (루트 레이아웃) ```typescript // React Query Provider, MUI ThemeProvider, Toast Provider 설정 export default function RootLayout({ children }) { return ( {children} ); } ``` **app/(main)/layout.tsx** (메인 레이아웃) ```typescript // Bottom Navigation 포함 레이아웃 // 인증 체크 미들웨어 export default function MainLayout({ children }) { return ( <>
{children} ); } ``` **app/(auth)/layout.tsx** (인증 레이아웃) ```typescript // 로고 중심의 심플한 레이아웃 export default function AuthLayout({ children }) { return ( {children} ); } ``` #### 2.2.2 Funnel 구현 **app/(main)/events/create/page.tsx** ```typescript 'use client'; import { useFunnel } from '@use-funnel/next'; import { ObjectiveStep, RecommendationStep, ... } from '@/components/funnel'; export default function EventCreatePage() { const [Funnel, state, setStep] = useFunnel({ id: 'event-creation', initial: 'objective', }); return ( setStep('recommendation')} /> setStep('content')} onBack={() => setStep('objective')} /> {/* ... 나머지 Step들 */} ); } ``` #### 2.2.3 API 클라이언트 **src/lib/api/client.ts** ```typescript import axios from 'axios'; // runtime-env.js에서 환경 변수 로드 declare global { interface Window { __runtime_config__: { API_GROUP: string; USER_HOST: string; EVENT_HOST: string; CONTENT_HOST: string; AI_HOST: string; PARTICIPATION_HOST: string; DISTRIBUTION_HOST: string; ANALYTICS_HOST: string; }; } } const config = window.__runtime_config__; // 1. User Service API Client (인증, 프로필) export const userClient = axios.create({ baseURL: `${config.USER_HOST}${config.API_GROUP}`, timeout: 10000, }); // 2. Event Service API Client (이벤트 생명주기 관리) export const eventClient = axios.create({ baseURL: `${config.EVENT_HOST}${config.API_GROUP}`, timeout: 30000, // AI/이미지 생성 Job 폴링 고려 }); // 3. Content Service API Client (이미지 생성 및 편집) export const contentClient = axios.create({ baseURL: `${config.CONTENT_HOST}${config.API_GROUP}`, timeout: 30000, // 이미지 생성 Job 폴링 }); // 4. AI Service API Client (AI 추천 생성) export const aiClient = axios.create({ baseURL: `${config.AI_HOST}${config.API_GROUP}`, timeout: 30000, // AI 생성 Job 폴링 }); // 5. Participation Service API Client (참여자/당첨자 관리) export const participationClient = axios.create({ baseURL: `${config.PARTICIPATION_HOST}${config.API_GROUP}`, timeout: 10000, }); // 6. Distribution Service API Client (다중 채널 배포) export const distributionClient = axios.create({ baseURL: `${config.DISTRIBUTION_HOST}${config.API_GROUP}`, timeout: 20000, // 다중 채널 배포 시간 고려 }); // 7. Analytics Service API Client (성과 분석 및 대시보드) export const analyticsClient = axios.create({ baseURL: `${config.ANALYTICS_HOST}${config.API_GROUP}`, timeout: 10000, }); ``` ### 2.3 컴포넌트 재사용 전략 #### Atomic Design 기반 컴포넌트 계층 ``` Atoms (원자) └── Button, Input, Icon, Typography ↓ Molecules (분자) └── SearchBar, EventCard, ParticipantRow ↓ Organisms (유기체) └── EventList, ParticipantTable, Dashboard ↓ Templates (템플릿) └── MainLayout, AuthLayout, FunnelLayout ↓ Pages (페이지) └── HomePage, EventListPage, EventCreatePage ``` #### MUI 컴포넌트 커스터마이징 ```typescript // src/components/common/Button/Button.tsx import { Button as MuiButton, ButtonProps } from '@mui/material'; export const Button: React.FC = (props) => { return ( ); }; ``` ### 2.4 상태 관리 전략 | 상태 유형 | 관리 도구 | 사용 사례 | |---------|---------|---------| | 서버 상태 | React Query v5 | API 데이터 캐싱, 자동 재검증 | | 전역 클라이언트 상태 | Zustand | 인증 상태, UI 상태 (Toast, Modal) | | 로컬 상태 | useState | 컴포넌트 내부 상태 | | 폼 상태 | React Hook Form | 폼 입력, 검증 | | Funnel 상태 | @use-funnel/next | Step 전환, 데이터 임시 저장 | ### 2.5 라우팅 및 미들웨어 **middleware.ts** (Next.js Middleware) ```typescript import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { const token = request.cookies.get('accessToken'); const { pathname } = request.nextUrl; // 인증이 필요한 경로 const protectedRoutes = ['/', '/events', '/profile']; const isProtectedRoute = protectedRoutes.some(route => pathname.startsWith(route) ); // 인증되지 않은 사용자가 보호된 경로 접근 시 로그인으로 리다이렉트 if (isProtectedRoute && !token) { return NextResponse.redirect(new URL('/login', request.url)); } // 인증된 사용자가 로그인/회원가입 접근 시 대시보드로 리다이렉트 if ((pathname === '/login' || pathname === '/register') && token) { return NextResponse.redirect(new URL('/', request.url)); } return NextResponse.next(); } export const config = { matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'], }; ``` ### 2.6 환경 변수 관리 **.env.local** ``` # 로컬 개발 환경 NEXT_PUBLIC_USER_HOST=http://localhost:8081 NEXT_PUBLIC_EVENT_HOST=http://localhost:8080 NEXT_PUBLIC_CONTENT_HOST=http://localhost:8082 NEXT_PUBLIC_AI_HOST=http://localhost:8083 NEXT_PUBLIC_PARTICIPATION_HOST=http://localhost:8084 NEXT_PUBLIC_DISTRIBUTION_HOST=http://localhost:8085 NEXT_PUBLIC_ANALYTICS_HOST=http://localhost:8086 NEXT_PUBLIC_API_VERSION=v1 ``` **.env.production** ``` # 프로덕션 환경 NEXT_PUBLIC_USER_HOST=https://api.kt-event-marketing.com/user/v1 NEXT_PUBLIC_EVENT_HOST=https://api.kt-event-marketing.com/event/v1 NEXT_PUBLIC_CONTENT_HOST=https://api.kt-event-marketing.com/content/v1 NEXT_PUBLIC_AI_HOST=https://api.kt-event-marketing.com/ai/v1 NEXT_PUBLIC_PARTICIPATION_HOST=https://api.kt-event-marketing.com/participation/v1 NEXT_PUBLIC_DISTRIBUTION_HOST=https://api.kt-event-marketing.com/distribution/v1 NEXT_PUBLIC_ANALYTICS_HOST=https://api.kt-event-marketing.com/analytics/v1 NEXT_PUBLIC_API_VERSION=v1 ``` **public/runtime-env.js** ```javascript window.__runtime_config__ = { API_GROUP: "/api/v1", // 7개 마이크로서비스 호스트 USER_HOST: process.env.NEXT_PUBLIC_USER_HOST || "http://localhost:8081", EVENT_HOST: process.env.NEXT_PUBLIC_EVENT_HOST || "http://localhost:8080", CONTENT_HOST: process.env.NEXT_PUBLIC_CONTENT_HOST || "http://localhost:8082", AI_HOST: process.env.NEXT_PUBLIC_AI_HOST || "http://localhost:8083", PARTICIPATION_HOST: process.env.NEXT_PUBLIC_PARTICIPATION_HOST || "http://localhost:8084", DISTRIBUTION_HOST: process.env.NEXT_PUBLIC_DISTRIBUTION_HOST || "http://localhost:8085", ANALYTICS_HOST: process.env.NEXT_PUBLIC_ANALYTICS_HOST || "http://localhost:8086", }; ``` --- ## 3. 기술 스택 정리 | 카테고리 | 기술 | 버전 | 용도 | |---------|-----|------|-----| | **Framework** | Next.js | 14.x | App Router, SSR, SSG | | **Library** | React | 18.x | UI 라이브러리 | | **Language** | TypeScript | 5.x | 정적 타입 검사 | | **UI Framework** | Material-UI (MUI) | 6.x | UI 컴포넌트 | | **State (Server)** | React Query | 5.x | 서버 상태 관리 | | **State (Client)** | Zustand | 4.x | 전역 상태 관리 | | **Form** | React Hook Form | 7.x | 폼 관리 | | **Validation** | Zod | 3.x | 스키마 검증 | | **Funnel** | @use-funnel/next | 1.x | Funnel 상태 관리 | | **HTTP Client** | Axios | 1.x | API 통신 | | **Charts** | Chart.js | 4.x | 데이터 시각화 | | **Testing** | Jest, Playwright | - | 단위/E2E 테스트 | --- ## 4. 배포 및 환경 설정 ### 4.1 개발 환경 ```bash npm run dev # 개발 서버 실행 (localhost:3000) npm run build # 프로덕션 빌드 npm run start # 프로덕션 서버 실행 npm run lint # ESLint 검사 npm run test # Jest 단위 테스트 npm run test:e2e # Playwright E2E 테스트 ``` ### 4.2 빌드 최적화 - **Code Splitting**: 동적 import로 번들 크기 최적화 - **Image Optimization**: Next.js Image 컴포넌트 사용 - **Font Optimization**: next/font로 웹폰트 최적화 - **Tree Shaking**: 사용하지 않는 코드 제거 ### 4.3 성능 모니터링 - **Lighthouse**: 성능, 접근성, SEO 점수 - **Web Vitals**: LCP, FID, CLS 측정 - **Bundle Analyzer**: 번들 크기 분석 --- ## 5. 접근성 및 반응형 설계 ### 5.1 반응형 브레이크포인트 ```typescript // src/styles/theme.ts const breakpoints = { xs: 0, // Mobile: 320px ~ 599px sm: 600, // Tablet: 600px ~ 1023px md: 1024, // Desktop: 1024px ~ 1439px lg: 1440, // Large Desktop: 1440px+ }; ``` ### 5.2 접근성 준수 (WCAG 2.1 AA) - **키보드 네비게이션**: Tab, Enter, Space 지원 - **스크린 리더**: aria-label, role 속성 - **색상 대비**: 최소 4.5:1 비율 - **포커스 표시**: 명확한 focus 상태 - **대체 텍스트**: 모든 이미지에 alt 속성 --- **문서 버전**: 1.0 **작성일**: 2025-01-24 **작성자**: Frontend Design Team