전역 레이아웃 및 배포
공통 레이아웃을 연결하고 서점의 작은 학습 완료 흐름, 직접 UI 과제, 로컬·배포 확인 항목을 구분합니다.
전역 레이아웃 및 내비게이션
헤더, 푸터 등 모든 페이지에 공통으로 적용될 레이아웃을 구성하고, 내비게이션 바를 추가합니다.
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import type { ReactNode } from 'react';
import './globals.css';
import Header from '@/components/Header'; // Header 컴포넌트
import Footer from '@/components/Footer'; // Footer 컴포넌트
const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = {
title: '나만의 온라인 북스토어',
description: 'Next.js로 만든 간단한 온라인 북스토어 프로젝트',
};
export default function RootLayout({
children,
}: {
children: ReactNode;
}) {
return (
<html lang="ko">
<body className={`${inter.className} flex flex-col min-h-screen bg-gray-100`}>
<Header />
<div className="grow">
{children}
</div>
<Footer />
</body>
</html>
);
}import Link from 'next/link';
export default function Header() {
return (
<header className="bg-white shadow-md py-4">
<div className="container mx-auto px-4 flex justify-between items-center">
<Link href="/" className="flex items-center space-x-2">
<span aria-hidden="true" className="text-2xl">📚</span>
<span className="text-2xl font-bold text-gray-800">My Bookstore</span>
</Link>
<nav>
<ul className="flex space-x-6">
<li>
<Link href="/books" className="text-gray-600 hover:text-blue-600 transition-colors">
모든 책
</Link>
</li>
<li>
<Link href="/cart" className="text-gray-600 hover:text-blue-600 transition-colors">
장바구니
</Link>
</li>
<li>
<Link href="/login" className="text-gray-600 hover:text-blue-600 transition-colors">
로그인
</Link>
</li>
</ul>
</nav>
</div>
</header>
);
}export default function Footer() {
return (
<footer className="border-t bg-white py-6 text-center text-sm text-gray-600">
<p>© {new Date().getFullYear()} My Bookstore</p>
</footer>
);
}작은 서점 흐름의 완료 범위
첫 버전은 로그인 → 도서 목록·상세 → 자기 장바구니 → 가상 주문까지로 정합니다. 생성기의 홈 화면이 남아 있어도 /login과 /books에서 시작할 수 있습니다. 전체 내비게이션까지 완성하려면 아래의 직접 UI 과제도 이어서 마칩니다.
처음 비교할 값은 새 독립 실습 DB에 시드를 처음 넣었고, 다른 주문이나 가격 변경 없이 시작한 경우로 정합니다. Next.js 완벽 가이드의 가격은 35,000원, 재고는 100이며, 계정 A의 장바구니는 비어 있어야 합니다. 기존 데이터로 시작한다면 현재 가격·재고·장바구니를 먼저 기록해 그 값에서 변화를 비교합니다. 결과를 다시 맞추려고 기존 장바구니·주문이 있는 DB에 도서를 재시드하지 않습니다.
/login의 GitHub 버튼으로 로그인합니다. 서버 세션의 소유자 ID는 인증에서 확인한provider:providerAccountId이며 이메일이나 브라우저가 보낸 ID로 바꾸지 않습니다./books에서 해당 도서의 상세 페이지로 이동해 제목·가격·재고를 확인합니다. 도서 목록·상세의 코드와 연결합니다.- 장바구니에 추가를 누르고
/cart에서 수량을 2로 바꿉니다. 합계가 70,000원인지 보고 장바구니의 자기 항목 조건을 확인합니다. 담기·수량 변경만으로 도서 재고를 차감하지는 않습니다. /order에서 같은 항목과 예상 금액을 읽고 가상 주문을 제출합니다. 저장 시점에는 서버가 가격·재고를 다시 읽으므로 앞 화면의 값과 달라질 수 있습니다./order-success의 화면 이동과 DB 변화를 함께 비교합니다. 위 조건이 유지됐다면 Order에 A의 수량 2·구매 가격 35,000원·합계 70,000원·completed가 저장되고, Book 재고는 98, A의 CartItem은 삭제되는 것이 기대 결과입니다.completed는 가상 주문 상태이며 실결제·배송 완료가 아닙니다.
커밋은 트랜잭션 안의 DB 변경을 확정하는 단계입니다. 성공 페이지는 인증이나 주문 ID·DB 조회가 없는 정적 안내입니다. 직접 URL을 열어도 완료 문구가 보이므로 그 화면만으로 주문 커밋을 확정하지 않습니다. 주문 액션의 같은 session 안에서 재고·주문·장바구니를 바꾸는 경계와, 커밋 뒤의 화면 이동을 따로 확인합니다.
제공 코드와 직접 마칠 부분
| 단계 | 현재 제공 코드 | 직접 준비하거나 이후로 남길 것 |
|---|---|---|
| 환경 | Next.js 16 설정, Mongo 연결, 세 모델, 두 권 시드와 표지 SVG 예시 | 잠금 파일·호환 Node·독립 실습 DB·GitHub OAuth 앱을 자신의 환경에 준비 |
| 로그인 | GitHub provider, JWT/session 연결, handlers·getSession, /login | Header의 로그인 상태별 메뉴·로그아웃. 영속 User·계정 통합은 운영 확장 |
| 도서 | 목록·상세·loading·404, 제목/저자 검색과 목록 페이지 교체 코드 | 빈 검색 결과의 맞춤 안내와 대량 검색 성능은 추가 과제 |
| 장바구니 | 소유자 조건, 정수 1~99·재고 검사, 문자열 DTO와 변경 피드백 | UI 최대 10과 서버 최대 99의 차이, 서버 값과 입력 동기화, 누락 도서·경합 정책 |
| 주문 | 같은 session의 재고 차감·주문 생성·장바구니 삭제, 커밋 뒤 이동 | 실결제·배송, 주문 식별자·멱등성·자동 재시도·불명 결과의 확인/복구 |
| 전역 UI·배포 | layout·고정 Header·Footer, 환경 변수·배포 절차 | 홈 화면, 상태별 메뉴·로그아웃, 실제 배포 URL과 DB/OAuth 연결 확인 |
홈은 생성기의 app/page.tsx를 북스토어 시작 화면으로 바꾸는 과제입니다. Header의 메뉴와 로그아웃은 로그인과 로그아웃의 서버 예제를 참고합니다. 그 예제의 src/components 경로와 /account 이동은 여기의 components 경로와 실제 북스토어 주소에 맞춰야 합니다.
검색과 페이지 이동은 기본 흐름 뒤에 확인할 수 있습니다. 현재 두 권 시드와 페이지당 12권 조건에서는 두 번째 페이지가 생기지 않습니다. 설계의 대량 데이터·응답 시간 목표를 이 예제로 달성했다고 판단하지 않습니다.
예상과 다른 결과가 나올 때
아래 표는 직접 비교할 기대 결과와 첫 확인 위치입니다. 실제 환경에서 본 결과는 사용한 데이터·계정과 함께 README에 남깁니다. 아직 확인하지 않은 항목은 미확인으로 기록합니다.
| 경우 | 볼 결과 | 다를 때 먼저 볼 곳 |
|---|---|---|
| 정상 가상 주문 | 위 조건의 Order·Book·CartItem 세 변화와 화면 이동 | Network·서버 응답, 같은 DB의 주문 소유자·금액·재고·장바구니. 성공 URL만 보지 않음 |
| 빈 장바구니 | /cart·/order의 빈 안내와 도서 링크. 직접 액션은 빈 상태를 업무 거절로 반환 | 세션 userId와 CartItem 조회 조건 |
| ID 형식 오류·없는 도서 | 형식 오류를 조회 전에 거절하거나 유효 ID 조회 뒤 404로 연결 | params·isValidObjectId·Book 조회 |
| 재고 부족 | 유효한 도서·수량을 전제로 업무 거절과 오류 안내. DB 값도 별도 비교 | 같은 session·업무 거절/abort 경로. 커밋 결과 불명 오류와 구분 |
| 계정 A/B | 별도 브라우저 프로필의 유효한 두 GitHub 계정에서 각자 장바구니만 조회 | 서버 세션 ID와 조회·수정·삭제의 userId 조건 |
| A 재로그인 | 직접 완성한 로그아웃 뒤 같은 공급자 계정으로 남아 있는 A의 데이터에 접근 | providerAccountId → JWT → session 연결. 토큰·비밀 원문을 기록하지 않음 |
| 빌드·배포 | 배포 환경에서 같은 흐름과 외부 연동을 따로 확인 | 린터·타입·빌드의 실패와 Mongo/OAuth callback·배포 로그의 실패를 구분 |
커밋이 확정된 뒤 화면 갱신만 실패했다고 주문을 다시 제출하지 않습니다. 결과가 불명인 오류도 주문이 없다는 증거는 아닙니다. 현재 수동 트랜잭션은 자동 재시도·멱등성·주문 내역 조회/복구 화면을 제공하지 않습니다. 같은 요청을 반복해도 중복 주문을 만들지 않는 성질을 멱등성이라고 합니다. 운영 확장에서는 이를 위한 주문 식별자와 결과 확인 경로를 먼저 정해야 합니다.
배포 및 테스트
로컬에서 위 학습 흐름과 직접 마친 UI의 범위를 확인한 뒤, 앱을 공개하려면 Vercel 배포로 이어갑니다. 로컬 화면·빌드 성공과 배포 환경의 DB·OAuth 연결은 각각 다른 확인입니다.
로컬 테스트
npm run dev개발 서버가 출력한 실제 접속 주소에서 /login·/books를 열고 위 흐름을 확인합니다. 기본 주소는 http://localhost:3000이지만 사용 중인 서버의 터미널 출력을 기준으로 합니다.
특히 장바구니 추가·수량 변경·삭제·주문을 확인하고, 다른 계정의 데이터가 섞이지 않는지와 재로그인 후 소유자 ID가 유지되는지도 확인합니다. 이 문서는 코드 예시를 제시하며 실제 MongoDB·OAuth·Vercel 검증 결과를 제공하지 않습니다.
홈과 상태별 메뉴·로그아웃을 아직 만들지 않았다면 위 직접 과제로 남겨 둡니다. 고정 Header 코드만으로 그 기능까지 완료했다고 기록하지 않습니다.
배포 전에는 프로젝트에 설정된 린터·타입 검사·production 빌드를 별도로 확인합니다. Next.js 16의 빌드가 ESLint 검사까지 자동으로 대신한다고 가정하지 않습니다.
Vercel 배포
GitHub, GitLab, 또는 Bitbucket에 프로젝트 리포지토리를 생성하고 코드를 푸시합니다.
Vercel 계정에 로그인하고 Add New Project를 통해 해당 Git 리포지토리를 임포트합니다.
Vercel이 Next.js 프로젝트임을 자동으로 감지하고 설정을 제안합니다.
환경 변수 설정: Vercel 대시보드 프로젝트 설정에서 Environment Variables 섹션으로 이동하여 MONGODB_URI, AUTH_SECRET, AUTH_GITHUB_ID, AUTH_GITHUB_SECRET을 Production 환경에 추가합니다.
데이터베이스 값은 해당 배포 환경의 MongoDB Atlas 연결 문자열을 사용하고, AUTH_SECRET에는 충분히 긴 무작위 문자열을 사용합니다. Preview 검증을 한다면 Preview 범위에도 별도 환경 값을 설정하고, 실습용 시드가 운영 DB를 지우지 않도록 대상을 분리합니다.
OAuth 운영 주소 등록: GitHub OAuth 앱에 https://배포도메인/api/auth/callback/github를 Authorization callback URL로 등록합니다.
배포: 설정 확인 후 Deploy 버튼을 클릭하면 Vercel이 자동으로 빌드하고 배포합니다.
이 단계별 가이드는 온라인 북스토어 프로젝트의 핵심 기능을 구현하는 데 필요한 주요 과정과 코드 예시를 제공합니다.
실제 프로젝트에서는 계정 모델과 역할, 사용자용 오류 UI, 관측·복구 절차를 요구사항에 맞춰 확장해야 합니다.
배포 URL에서도 로그인, 목록·검색, 사용자별 장바구니와 가상 주문을 확인합니다. 세션·DB 오류는 배포 환경의 로그와 응답을 대조하며, 빌드 성공만으로 이 외부 연동이 통과했다고 판단하지 않습니다.