JK
>로딩 중 // 로딩 중
뷰 초기화 중
모듈식 MVC 구조, MongoDB 집계 파이프라인, 안전한 인증 체계를 갖춘 프로덕션 레디 REST API 백엔드.
체계적인 예외 처리, 보안 헤더 및 자동화 테스트를 갖춘 실무형 백엔드 템플릿을 완성하는 것.
| 기술 | 버전 | 목적 | 선택 이유 |
|---|---|---|---|
| Node.js | — | JavaScript runtime | Non-blocking I/O, large ecosystem |
| Express.js | 4.19.2 | HTTP framework | Minimal, flexible, well-documented |
| TypeScript | 5.5.4 | Type safety | Compile-time error catching, IDE support |
| MongoDB | — | Document database | Flexible schema, JSON-native, horizontal scaling |
| Mongoose | 8.5.3 | MongoDB ODM | Schema validation, middleware, query building |
| JWT (jsonwebtoken) | 9.0.2 | Authentication tokens | Stateless auth, industry standard |
| bcrypt | 5.1.1 | Password hashing | Adaptive hashing, salt rounds |
| Cloudinary | 2.4.0 | Image hosting/CDN | Managed service, CDN, image transformations |
| Multer | 1.4.5-lts.1 | File upload handling | Express-integrated, simple API |
| 메서드 | 경로 | 목적 |
|---|---|---|
| GET | / | Health check / welcome |
| POST | /api/users/register | Register new user |
| POST | /api/users/login | Login user |
| POST | /api/admin/createAdmin | Create admin user |
| POST | /api/admin/adminlogin | Login admin |
| POST | /api/restaurant/createRestaurant | Register restaurant owner |
| POST | /api/restaurant/ownerLogin | Login restaurant owner |
| POST | /api/Menuitems/addItems | Create menu item with image |
| PUT | /api/Menuitems/:itemId | Update menu item |
| GET | /api/Menuitems/getAllItems | List all menu items |
| GET | /api/Menuitems/:itemId | Get single menu item |
| DELETE | /api/Menuitems/:itemId | Delete menu item |
| POST | /api/orders/createorder | Create order |
| POST | /api/orders/cancelorder/:orderId | Cancel order |
| GET | /api/orders/orderdetails/:orderId | Get order details |
| 컬럼 | 유형 | 비고 |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| name | String | Required |
| String | Required, unique | |
| password | String | bcrypt hashed |
| createdAt | Date | Auto (timestamps: true) |
| updatedAt | Date | Auto (timestamps: true) |
User accounts. Email is unique.
| 컬럼 | 유형 | 비고 |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| name | String | Required |
| String | Required, unique | |
| password | String | bcrypt hashed |
| userType | String | enum: ['admin', 'user', 'restOwner'] |
Admin accounts. Separate collection from users.
| 컬럼 | 유형 | 비고 |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| restaurantEmail | String | Required |
| restaurantPwd | String | bcrypt hashed |
| restaurantName | String | Required |
| restaurantAddress | String | Required |
| restaurantPhoneNo | Number | Required, unique |
Restaurant owner accounts.
| 컬럼 | 유형 | 비고 |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| restaurantId | ObjectId | No ref defined — .populate() won't work |
| itemName | String | Has typo: require instead of required |
| itemDescription | String | Has typo: require instead of required |
| itemPrice | Number | Has typo: require instead of required |
| itemImage | String | Cloudinary URL |
Menu items per restaurant. restaurantId lacks ref property — schema bug.
| 컬럼 | 유형 | 비고 |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| customerId | ObjectId | ref: User |
| restaurantId | ObjectId | ref: restaurant |
| menuId | ObjectId | ref: MenuItems |
| orderQuantity | Number | No validation for positive values |
| orderDate | Date | Default: Date.now |
| orderStatus | String | enum: ['in process', 'transit', 'cancelled', 'delivered'] |
| orderBill | Number | Client-supplied — security concern |
Orders are client-supplied bill amounts — no server-side price calculation.
One-to-Many: Users→Orders, Restaurants→MenuItems, Restaurants→Orders, MenuItems→Orders. All via ObjectId references. No many-to-many relationships. menuitems.restaurantId lacks ref property.
결정: Single Express.js application with domain-based folder structure
이유: Appropriate for project scale (~15 endpoints, single deployment)
이점: Simple deployment, easy debugging, low operational overhead, clear domain ownership
트레이드오프: Cannot scale domains independently, all modules share process, no service layer for reuse
결정: Stateless JWT tokens with Authorization: Bearer header
이유: Standard for REST APIs, no session storage needed
이점: Stateless, no server-side session store, scales horizontally
트레이드오프: No server-side revocation, tokens valid until expiry even if user is deleted
결정: Business logic resides directly in controllers
이유: Simplicity for small project, fewer files to navigate
이점: Fast development, fewer abstractions
트레이드오프: Untestable business logic, code duplication across auth controllers, hard to reuse logic
결정: Menu item images uploaded to Cloudinary CDN
이유: Managed service avoids S3/MinIO setup, provides CDN and image transformations
이점: No infrastructure to manage, built-in CDN, free tier available
트레이드오프: Vendor lock-in, external dependency, cost at scale, latency for non-CDN regions
결정: orderBill is sent by the client, not calculated server-side
이유: Likely intentional simplification for MVP
이점: Simpler server logic
트레이드오프: Critical security vulnerability — clients can manipulate order amounts
결정: Manual if (!field) validation instead of Zod/Joi
이유: Simplicity, fewer dependencies
이점: No additional dependency, explicit control
트레이드오프: Inconsistent validation, no type inference from schemas, generic error messages