공연 좌석 예매 시스템 풀스택 구현
- 본 레포지토리를 fork하여 과제를 수행하고, 완료시 PR을 보냅니다.
- 과제의 소스코드는 본인의 GitHub 레포지토리에 Public으로 올려주세요.
- 진행 간 문의사항은 이 레포지토리의 Issue로 등록해주세요.
- 구현 내용은 README.md 하단에 이어서 작성해 주세요.
공연 좌석 예매 시스템 구현
- Backend: 자유 선택 (Spring Boot, Node.js, Django, FastAPI 등)
- Frontend: 자유 선택 (React, Vue, Svelte, Vanilla JS 등)
- Database: 자유 선택
- 선택한 기술 스택에 대한 이유를 README에 간단히 설명해주세요
- 문제 해결 접근 방식에서 기술적 의사결정
- 구현 완성도와 문서화 수준
아래 목표들을 달성하기 위한 구현 방법은 자유롭게 선택하세요.
- 좌석 현황 표시
- 3x3 격자 형태로 총 9개의 좌석 표시
- 각 좌석의 예약 가능/불가능 상태를 시각적으로 구분
- 좌석 예약 기능
- 사용자가 빈 좌석을 클릭하여 선택
- 페이지를 이동하여 예약자 정보 입력
- 정보 입력 완료 후 예약 확정 시도
- 99% 확률로 예약 성공 처리
- 1% 확률로 의도적 실패 처리
- 예약 성공/실패에 대한 명확한 피드백 제공
- API 엔드포인트
- 좌석 목록 조회 API
- 좌석 예약 요청 API
- HTTP 통신을 통한 데이터 교환
- 코드 품질 보장
- 테스트 코드
- 타입 체크
- 린팅
아래 목표들을 달성하기 위한 구현 방법은 자유롭게 선택하세요.
각 목표를 어떻게 해결했는지 README에 설명해주세요.
- 사용자 경험 개선
- 목표: 사용자가 서비스를 이용할 때 발생할 수 있는 불편함 최소화
- 예시
- 직관적인 UI
- 네트워크 지연이 발생했을 때 편의성
- 예약이 실패했을 때 편의성
- 모바일에서 접속했을 때 편의성
- 안정적인 서비스 운영
- 목표: 예상치 못한 상황에서도 서비스가 안정적으로 동작
- 예시
- 잘못된 요청이 들어왔을 때
- 존재하지 않는 좌석을 예약하려 할 때
- 서버 에러가 발생했을 때
- 데이터 정합성 보장
아래 목표들을 달성하기 윈한 구현 방법은 자유롭게 선택하세요.
각 목표를 달성했음을 검증할 방법을 마련하세요.
시도한 방법이 어떤 방식으로 문제를 해결했으며 보유한 한계점에 대해 상세히 README에 설명해주세요.
- 동시성 제어
- 상황: 여러 사용자가 동시에 같은 좌석을 예약하려고 시도하는 경우
- 목표: 한 좌석에 대해 단 한 명만 예약에 성공하도록 보장
- 실시간 좌석 상태 동기화
- 상황: UI에서 사용자들이 이미 선택된 좌석을 선택하게 되는 경우
- 목표: 실시간 좌석 예약 상태를 확인할 수 있도록 실시간 동기화 제공
- 선택한 좌석에 대한 우선순위 제공
- 상황 : 좌석 선택 후 예약자 정보를 입력하는 동안 다른 사용자가 좌석을 예약하게 되는 경우
- 목표: 동일 좌석에 대해 먼저 선택을 한 사용자에게 예약 우선순위 제공
- 최소 요구사항을 먼저 완성한 후 기본 기능을 구현해주세요
- 심화 요구사항은 구현에 실패해도 고민한 해결 방법이 있으면 작성해주세요.
- README.md: 다음 내용을 반드시 포함
- 프로젝트 실행 방법 (상세하게)
- 기술 스택 선택 이유
- 구현한 요구사항 체크리스트
- 각 요구사항별 해결 방법 설명
- 아키텍처 다이어그램
- 시연 영상 또는 GIF
- Frontend: Next.js (App Router) + TypeScript + Tailwind CSS
Next.js(App Router): 파일/페이지 기반 라우팅으로 예약 흐름 단순화, 초기 로딩 UX 우수
TypeScript: 컴파일 타임 타입 체크로 런타임 오류 예방, 리팩터링 안정성↑
Tailwind CSS: 유틸리티 클래스 기반, 반응형 UI를 빠르게 구현
- Backend: Node.js + Express
Express: 러닝커브 낮고 REST API 구현 용이
Node.js: 프론트/백 모두 JS/TS로 통일 → 생산성↑
Good-Night-4th-Hackathon/
├── backend/ # Express API 서버
│ ├── server.js
│ └── __tests__/ # API 테스트
├── frontend/ # Next.js 프론트엔드
│ ├── src/
│ └── src/app/__tests__/ # 컴포넌트/UX 테스트
└── README.md
- 의존성 설치
프론트
cd frontend && npm install
백엔드
cd ../backend && npm install
- 개발 서버 실행
백엔드
cd backend
node server.js
프론트
cd frontend
npm run dev
- Frontend
cd frontend
npm run lint # ESLint
npm run typecheck # TypeScript 타입 체크
npm test # Jest + React Testing Library
- Backend
cd backend
npm test # Jest + Supertest
✅ 최소 요구사항
- 3x3 격자 형태로 총 9개의 좌석 표시
- 각 좌석의 예약 가능/불가능 상태를 시각적으로 구분
- 사용자가 빈 좌석을 클릭하여 선택
- 페이지를 이동하여 예약자 정보 입력
- 99% 성공 / 1% 실패 처리 + 명확한 피드백
- 좌석 목록 조회 API
- 좌석 예약 API
- HTTP 통신을 통한 데이터 교환
- 테스트 코드
- 타입 체크
- 린팅
✅ 기본 요구사항
- 사용자 경험 개선(사용자가 서비스를 이용할 때 발생할 수 있는 불편함 최소화)
- 안정적인 운영(예상치 못한 상황에서도 서비스가 안정적으로 동작)
✅ 심화 요구사항 (필요 시 진행 & README에 검증 방법 추가)
-
동시성 제어: 동일 좌석 동시 경쟁 시 단 한 명만 성공 보장
-
실시간 좌석 동기화: WebSocket/SSE로 상태 브로드캐스트
-
우선순위 제공: 좌석 선택 후 입력 중 우선권 부여(홀드/타임아웃)
-
좌석현황표시 SeatGrid가 3×3 그리드로 렌더링, 좌석 상태에 따라 스타일을 명확히 구분(예약됨=회색, 선택됨=파랑, 선택 가능=초록)
-
좌석 예약 기능 좌석 클릭 시 이미 예약된 좌석은 차단하고, 선택 좌석을 /reservation로 전달해 폼 페이지로 이동. 백엔드에서는 Math.random() > 0.01 조건으로 99% 성공·1% 실패를 시뮬레이션하며, 실패 시 예외를 던지지 않고 좌석 상태를 변경하지 않은 채 201과 status: "failed" 응답을 반환합니다. (검증/장애 재현을 위해 ?force=fail, ?force500=1 및 x-force-fail, x-force-500 헤더를 지원합니다.)
-
API
-
GET /seats : 모든 좌석의 현재 상태를 JSON 배열로 반환합니다.
-
GET /seats/:id :특정 좌석의 상태를 반환합니다. 잘못된/없는 ID는 400 Bad Request로 응답합니다.
-
POST /seats/reserve : 예약자 정보를 받아 좌석을 예약 처리합니다.
- 코드 품질 보장 SeatGrid.test.tsx: 3×3 그리드 렌더링, 로딩 문구, 클릭 이벤트 전달 등 UI 기본 동작 검증 ReservationForm.test.tsx: 폼 렌더·검증(필수값/형식), 제출 시 payload(좌석 정보 포함) 생성, 제출 중 버튼 비활성화/스피너 노출 검증
app/tests/reservation.test.tsx(페이지 테스트):
즉시 피드백: 제출 직후 “요청 중…”/스피너/버튼 비활성화 지연 알림: 1.5초 이상 지연 시 “조금만 기다려 주세요.” 배지 노출 요청 취소: AbortController로 취소 시나리오(취소 메시지 확인) 폼 보존: localStorage 저장/복원 및 성공 시 삭제 낙관적 업데이트 금지: 성공 확정 전까지 좌석 상태 변화 없음(간접 검증) 에러 처리/재시도: 서버 오류/실패 응답 시 메시지 노출, “다시 시도/다른 좌석 보기” 동작 확인
모든 테스트 통과 로컬 최신 실행 기준 테스트 스위트가 통과함.
- 사용자 경험 개선
- UX 개선 직관적 좌석 UI(3×3) / 상태별 색상(예약됨/선택됨/가능) 지연 대응: 제출 즉시 로딩, 1.5초 후 “조금만 기다려 주세요.” 배지, 요청 취소(AbortController) 실패 대응: 명확한 원인 메시지 + “다시 시도/다른 좌석 보기” CTA 폼 보존: localStorage로 입력값 자동 저장/복원 낙관적 업데이트 금지: 성공 확정 전까지 좌석 상태 미변경 모바일 반응형 최적화(Tailwind)
- 안정적인 서비스 운영
-
입력 가드 & 에러 코드 표준화 필수 필드/형식 오류 → 400 에러 응답 포맷 통일: {"error": true, "code": "<에러코드>", "message": "<설명>"}
-
데이터 정합성 보장 성공일 때만 seat.isReserved = true로 상태 전이 실패/서버 오류 시 좌석 상태 변경 없음 이미 예약된 좌석 재요청 시 409로 차단
-
서버 장애/오류 대비 중앙 에러 핸들러로 예기치 못한 예외를 500으로 통일 응답
-
헬스체크 제공

