프로젝트 기획 및 설계
온라인 북스토어의 사용자·문제·MVP를 정의하고 기술 스택, 화면·API 경계, 도서·주문 데이터 모델을 설계합니다.
이 장에서는 앞선 챕터에서 학습한 Next.js 핵심 개념과 고급 주제를 종합해, 실제 웹 애플리케이션을 기획하고 설계하는 과정을 다룹니다.
이론 정리를 넘어 프로젝트 시작 방식, 구조화 방법, 기술 스택 선택, 기능 구현 순서를 실전 기준으로 안내합니다.
이번 절에서는 프로젝트 기획 및 설계에 초점을 맞춰 아이디어 구체화, 요구사항 정의, 기술 스택 선정, 아키텍처 설계, 데이터 모델링까지의 흐름을 정리합니다.
프로젝트 아이디어 구체화 및 목표 설정
프로젝트 시작 단계에서는 아이디어와 목표를 명확히 해야 합니다.
어떤 종류의 애플리케이션을 만들지, 누가 사용할지, 어떤 문제를 해결할지 먼저 정리합니다.
아이디어 도출 및 선정
- 관심 분야 탐색: 자신이 관심 있거나 잘 아는 분야에서 아이디어를 찾습니다. (예: 독서 기록 앱, 재료 관리 앱, 스터디 그룹 매칭 서비스, 간단한 이커머스 스토어)
- 문제점 인식: 일상생활이나 업무에서 불편함을 느꼈던 점, 개선이 필요하다고 생각하는 점을 찾아봅니다.
- 기존 서비스 분석: 유사한 기존 서비스가 있다면, 그들의 장단점을 분석하고 차별화될 수 있는 요소를 모색합니다.
- 실현 가능성 고려: 주어진 시간과 기술 역량 내에서 구현 가능한 아이디어를 선정합니다. 너무 거창한 아이디어보다는 작고 핵심적인 기능부터 시작하는 것이 좋습니다.
예시 프로젝트 아이디어: 간단한 온라인 북스토어 (Online Bookstore)
- 문제 정의: 사용자들이 쉽게 책을 검색하고, 상세 정보를 확인하며, 장바구니에 담아 주문할 수 있는 간단한 플랫폼이 필요하다.
- 대상 사용자: 책 구매에 관심 있는 일반 사용자.
- 핵심 가치: 사용자 친화적인 인터페이스, 빠른 검색, 간편한 구매 프로세스.
프로젝트 목표 설정 (SMART 원칙)
선정된 아이디어를 바탕으로 구체적인 목표를 설정합니다.
SMART 원칙(Specific, Measurable, Achievable, Relevant, Time-bound)을 적용하면 좋습니다.
- S (Specific): 사용자가 책을 검색하고, 상세 페이지를 보고, 장바구니에 담아 가상으로 주문할 수 있는 웹 애플리케이션 개발.
- M (Measurable): 최소 50권의 책 데이터 구축, 검색 기능 응답 시간 1초 이내, 장바구니 및 주문 프로세스 구현.
- A (Achievable): Next.js와 기본적인 웹 기술 스택(MongoDB/PostgreSQL, Route Handlers/Server Actions)만으로 구현 가능.
- R (Relevant): Next.js 학습 내용을 총체적으로 적용하며, 실제 서비스 개발 경험 습득에 기여.
- T (Time-bound): 4주 이내에 핵심 기능 개발 및 배포 완료.
50권·1초·4주는 계획의 목표값입니다. 뒤의 시드는 2권 예시이며 검색 응답 시간을 측정한 결과를 제시하는 것은 아닙니다. 측정할 때는 데이터 규모와 기기·네트워크 조건도 함께 정합니다.
요구사항 정의 및 기능 목록 작성
프로젝트의 목표를 달성하기 위해 필요한 기능들을 구체적으로 정의합니다.
사용자 관점에서 어떤 기능을 제공해야 하는지 상세하게 나열합니다.
핵심 기능 (MVP)
최소 기능 제품(MVP - Minimum Viable Product)은 프로젝트의 핵심 가치를 전달할 수 있는 최소한의 기능 집합입니다.
MVP를 먼저 개발하여 빠르게 피드백을 받고 점진적으로 기능을 확장합니다.
- 사용자 인증: 장바구니와 주문을 사용자별로 분리하기 위한 로그인, 로그아웃, 서버 세션 확인.
- 도서 목록 조회: 모든 도서 목록을 페이지네이션과 함께 표시.
- 도서 검색: 도서 제목, 저자 등으로 검색.
- 도서 상세 정보: 특정 도서의 상세 정보(제목, 저자, 설명, 가격, 이미지 등) 표시.
- 장바구니 기능: 도서 추가, 수량 변경, 도서 삭제.
- 주문 기능 (가상): 장바구니의 도서를 가상으로 주문 (결제 시스템 연동은 MVP에서 제외).
추가 기능 (향후 확장 고려)
MVP 이후 확장할 수 있는 기능들을 미리 구상해 봅니다.
- 사용자 리뷰 및 평점 시스템.
- 위시리스트 기능.
- 추천 도서 기능 (개인화).
- 관리자 페이지 (도서 추가/수정/삭제, 주문 관리).
- 실제 결제 시스템 연동 (Stripe, Toss Payments 등).
- 국제화 (i18n) 지원.
- 푸시 알림.
기술 스택 선정
Next.js를 기반으로 하지만, 백엔드, 데이터베이스, 스타일링, 배포 등 전반적인 기술 스택을 결정합니다.
프론트엔드 (Next.js 기반)
- 프레임워크: Next.js (React 기반)
- 렌더링: 정적 렌더링(정적인 정보 페이지), 동적 렌더링(검색 결과, 사용자별 장바구니), 클라이언트 컴포넌트(장바구니, 주문, 검색 입력)를 적절히 활용.
- 데이터 페칭:
fetchAPI, SWR 또는 React Query.
- 타입스크립트: 안정성과 개발 생산성 향상을 위해 TypeScript 사용.
- 스타일링:
- CSS Modules: 컴포넌트별 스코프 CSS.
- Tailwind CSS: 유틸리티 우선 CSS 프레임워크 (빠른 UI 개발).
- Styled-components / Emotion (선택 사항): 컴포넌트 기반 스타일링. (이 프로젝트에서는 Tailwind CSS를 주력으로 사용)
- 폼 관리: React Hook Form (폼 유효성 검사 및 상태 관리).
백엔드 및 API
- API 구현 방식: App Router 기준의 Route Handlers 또는 Server Actions.
- 간단한 애플리케이션이므로 별도의 백엔드 서버 없이 Next.js 서버 기능을 활용.
- 인증: Auth.js(소셜 로그인 및 세션 관리). 장바구니와 주문 Server Action은 인증된 사용자 ID를 기준으로 동작.
- 데이터베이스: NoSQL 또는 RDB
- MongoDB (NoSQL): 유연한 스키마, 빠른 개발 (Mongoose ODM).
- PostgreSQL (RDB): 관계형 데이터, 안정성 (Prisma ORM 또는 raw SQL).
- (예시 프로젝트에서는 MongoDB와 Mongoose를 선택)
배포
- 호스팅: Vercel (Next.js에 최적화된 배포 플랫폼).
- 데이터베이스 호스팅: MongoDB Atlas (클라우드 MongoDB 서비스).
아키텍처 설계
애플리케이션의 전체적인 구조와 데이터 흐름을 시각화합니다.
시스템 아키텍처
북스토어의 화면·서버·저장소
기능의 책임을 나타낸 구조입니다. 정적 자산·캐시 응답은 CDN에서 처리할 수 있고, 렌더링과 Server Action이 별도 서버로 분리된다는 뜻은 아닙니다.
Auth.js는 서버 세션에서 사용자 식별 정보를 제공하고, 장바구니·주문 액션은 이 ID로 조회 대상을 제한합니다. 데이터베이스 연결 문자열과 권한 검사는 서버 경계에 둡니다.
폴더/파일 구조 설계
App Router 기반으로 프로젝트 구조를 설계합니다. 아래 트리에서 # 뒤는 설명이며 실제 파일·폴더 이름에는 포함하지 않습니다.
데이터 모델링
애플리케이션이 다룰 데이터의 구조를 정의합니다.
NoSQL (MongoDB)을 기준으로 예시를 들어보겠습니다.
주요 엔티티 식별
- Book: 도서 정보.
- User: Auth.js 공급자와 세션이 관리하는 사용자 식별 정보. 이 MVP는 별도
User모델을 만들지 않습니다. - CartItem: 장바구니에 담긴 도서 항목.
- Order: 주문 정보.
CartItem은 bookId와 수량을 저장해 도서의 현재 정보와 연결합니다. Order의 각 항목은 bookId와 구매 시점 가격인 priceAtPurchase를 함께 저장하므로, 이후 도서 가격이 바뀌어도 주문 금액을 현재 가격으로 다시 계산하지 않습니다. userId 문자열은 각 장바구니·주문의 소유자를 구분합니다.
스키마 정의 (MongoDB/Mongoose 예시)
각 스키마는 폴더 구조에서 정한 models 파일에 하나씩 분리합니다.
다음 Book 모델은 그대로 복사할 수 있는 예시이며, CartItem과 Order 모델은 다음 절에서 같은 방식으로 구현합니다.
import mongoose, { Schema, type Model } from 'mongoose';
// Book 스키마 정의
export interface IBook {
_id: mongoose.Types.ObjectId;
title: string;
author: string;
description: string;
price: number;
imageUrl: string;
isbn: string;
publishedDate: Date;
genre: string[];
stock: number;
}
const BookSchema = new Schema<IBook>({
title: { type: String, required: true },
author: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true },
imageUrl: { type: String, required: true },
isbn: { type: String, required: true, unique: true },
publishedDate: { type: Date, default: Date.now },
genre: [{ type: String }],
stock: { type: Number, default: 0 },
}, { timestamps: true });
const Book = (mongoose.models.Book as Model<IBook> | undefined)
?? mongoose.model<IBook>('Book', BookSchema);
export default Book;unique: true는 Mongoose 검증기가 아니라 MongoDB의 고유 인덱스를 만들기 위한 선언입니다. 실제 인덱스가 있어야 중복 ISBN을 막을 수 있습니다. 현재 Book 스키마에는 제목·저자 검색 인덱스나 가격·재고의 음수·정수 검증이 없으므로, 선언한 제약과 추가할 정책을 구분합니다.
다음 절에서 CartItem과 Order를 정의하고 이 구조를 실제 화면과 연결합니다.