diff --git a/package-lock.json b/package-lock.json index cb673fc..d46c423 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,8 @@ "cors": "^2.8.5", "dotenv": "^16.4.7", "express": "^4.21.2", - "mongoose": "^8.9.6" + "mongoose": "^8.9.6", + "uuid": "^11.0.5" }, "devDependencies": { "@types/cors": "^2.8.17", @@ -3027,6 +3028,18 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", + "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", diff --git a/package.json b/package.json index af2a872..c68dd7b 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,8 @@ "cors": "^2.8.5", "dotenv": "^16.4.7", "express": "^4.21.2", - "mongoose": "^8.9.6" + "mongoose": "^8.9.6", + "uuid": "^11.0.5" }, "devDependencies": { "@types/cors": "^2.8.17", @@ -20,13 +21,14 @@ "ts-node": "^10.9.2", "typescript": "^5.7.3" }, + "type": "module", "scripts": { - "dev": "nodemon --exec ts-node src/server.ts", + "dev": "NODE_OPTIONS='--loader ts-node/esm' nodemon src/server.ts", "start": "node dist/server.js", "build": "tsc", "lint": "eslint . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", "prettier": "prettier --write \"src/**/*.ts\"", - "seed": "npx ts-node src/scripts/insertQuiz.ts" + "seed": "node --loader ts-node/esm src/scripts/insertQuiz.ts" } } diff --git a/src/db.ts b/src/db.ts index 2e41044..0aa4a35 100644 --- a/src/db.ts +++ b/src/db.ts @@ -1,5 +1,5 @@ -const mongoose = require('mongoose'); -const dotenv = require('dotenv'); +import mongoose from 'mongoose'; +import dotenv from 'dotenv'; dotenv.config(); diff --git a/src/model/quiz.ts b/src/model/quiz.ts index e8defde..82a7e1e 100644 --- a/src/model/quiz.ts +++ b/src/model/quiz.ts @@ -1,23 +1,33 @@ -const mongoose = require('mongoose'); +import mongoose from 'mongoose'; -const quizSchema = new mongoose.Schema({ - id: { type: Number, required: true, unique: true }, - title: { type: String, required: true }, - description: { type: String, required: true }, - codeTemplate: { type: String, required: true }, - answer: { type: String, required: true }, - hint: { type: String }, - grid: { type: [[Number]], required: true }, - startPosition: { - x: { type: Number, required: true }, - y: { type: Number, required: true }, - }, - commands: [ - { - name: { type: String, required: true }, - functionCode: { type: String, required: true }, +const quizSchema = new mongoose.Schema( + { + id: { type: String, required: true, unique: true }, + title: { type: String, required: true }, + description: { type: String, required: true }, + isFirst: { type: Boolean, required: true }, + prevId: { type: String, default: null, required: false }, + nextId: { type: String, default: null, required: false }, + grid: { type: [[Number]], required: true }, + hint: { type: String }, + startPosition: { + x: { type: Number, required: true }, + y: { type: Number, required: true }, + }, + goalPosition: { + x: { type: Number, required: true }, + y: { type: Number, required: true }, }, - ], -}); + goalAction: { type: String, required: true }, + commands: [ + { + name: { type: String, required: true }, + functionCode: { type: String, required: true }, + _id: false, + }, + ], + }, + { versionKey: false } +); export const Quiz = mongoose.model('Quiz', quizSchema); diff --git a/src/scripts/insertQuiz.ts b/src/scripts/insertQuiz.ts index 775ee02..568d693 100644 --- a/src/scripts/insertQuiz.ts +++ b/src/scripts/insertQuiz.ts @@ -1,6 +1,7 @@ -const mongoose = require('mongoose'); -const { MONGO_URI } = require('../db'); -const { Quiz } = require('../model/quiz'); +import mongoose from 'mongoose'; +import { MONGO_URI } from '../db.ts'; +import { Quiz } from '../model/quiz.ts'; +import { v4 } from 'uuid'; const insertQuiz = async () => { try { @@ -8,137 +9,119 @@ const insertQuiz = async () => { console.log('mongodb성공'); const quizzes = [ { - id: 1, title: '첫 번째 퀴즈', - description: '가데이터로 제공되는 첫 번째 퀴즈 설명입니다.', - codeTemplate: - "function example() {\n console.log('Hello, world!');\n}", - answer: 'Hello, world!', - hint: '코드를 작성하고 결과를 확인하세요.', + description: '목표 지점까지 이동한 후 공격하세요.', grid: [ [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [2, 0, 0, 0], ], + hint: '첫번쨰 힌트', startPosition: { x: 0, y: 0 }, + goalPosition: { x: 0, y: 3 }, + goalAction: 'shoot', commands: [ { name: 'forward', - function: () => { - console.log('move forward'); - }, + functionCode: "console.log('move forward');", }, { name: 'shoot', - function: () => { - console.log('shoot'); - }, + functionCode: "console.log('shoot');", }, ], }, { - id: 2, - title: '조건문과 반복문', - description: '조건문과 반복문을 사용하여 로직을 구현해봅시다.', - codeTemplate: '두번째 codeTemplate', - answer: '2번 정답', - hint: '2번 힌트', + title: '두 번째 퀴즈', + description: '목표 지점까지 이동한 후 공격하세요.', grid: [ - [0, 0, 2, 0], - [0, 1, 2, 0], - [0, 0, 2, 0], - [0, 0, 2, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 2], ], + hint: '두번쨰 힌트 방향을 바꿀수 있어요~', startPosition: { x: 0, y: 0 }, + goalPosition: { x: 3, y: 3 }, + goalAction: 'shoot', commands: [ { name: 'forward', - function: () => { - console.log('move forward'); - }, + functionCode: "console.log('move forward');", }, { name: 'shoot', - function: () => { - console.log('shoot'); - }, + functionCode: "console.log('shoot');", + }, + { + name: 'turnRight', + functionCode: "console.log('turnRight');", }, ], }, { - id: 3, - title: '함수와 스코프', - description: 'JavaScript 함수와 스코프에 대해 알아봅시다.', - codeTemplate: '세번째 codeTemplate', - answer: '3번 정답', - hint: '3번힌트', + title: '세 번째 퀴즈', + description: '목표 지점까지 이동한 후 공격하세요.', grid: [ - [0, 0, 0, 3], - [0, 1, 0, 3], - [0, 0, 2, 0], [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [2, 0, 0, 0], ], + hint: '세번쨰 힌트', startPosition: { x: 0, y: 0 }, + goalPosition: { x: 2, y: 0 }, + goalAction: 'shoot', commands: [ { name: 'forward', - function: () => { - console.log('move forward'); - }, + functionCode: "console.log('move forward');", }, { name: 'shoot', - function: () => { - console.log('shoot'); - }, + functionCode: "console.log('shoot');", }, ], }, { - id: 4, - title: 'ES6+ 문법', - description: '최신 JavaScript 문법(ES6+)을 학습합니다.', - codeTemplate: '네번째 codeTemplate', - answer: '4번정답', - hint: '4번힌트', + title: '네 번째 퀴즈', + description: '목표 지점까지 이동한 후 공격하세요.', grid: [ - [0, 4, 4, 4], - [0, 1, 0, 0], - [0, 0, 2, 0], [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [2, 0, 0, 0], ], + hint: '네번쨰 힌트', startPosition: { x: 0, y: 0 }, + goalPosition: { x: 2, y: 0 }, + goalAction: 'shoot', commands: [ { name: 'forward', - function: () => { - console.log('move forward'); - }, + functionCode: "console.log('move forward');", }, { name: 'shoot', - function: () => { - console.log('shoot'); - }, + functionCode: "console.log('shoot');", }, ], }, ]; - - for (const quiz of quizzes) { - await Quiz.findOneAndUpdate( - { id: quiz.id }, - { $setOnInsert: quiz }, - { upsert: true, new: true } - ); - } + const quizUUID = quizzes.map(() => v4()); + const quizzesLinkedList = quizzes.map((quiz, index) => ({ + ...quiz, + id: quizUUID[index], + isFirst: index === 0, + prevId: index === 0 ? null : quizUUID[index - 1], + nextId: index === quizUUID.length - 1 ? null : quizUUID[index + 1], + })); + await Quiz.insertMany(quizzesLinkedList); process.exit(0); } catch (error) { + console.error('오류 발생:', error); process.exit(1); } }; - insertQuiz(); - -module.exports = { insertQuiz }; diff --git a/src/server.ts b/src/server.ts index 58ff575..7ac43d3 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,10 +1,11 @@ -const express = require('express'); -const cors = require('cors'); -const dotenv = require('dotenv'); -const { connectDB } = require('./db'); +import express, { Response, Request, Application, response } from 'express'; +import cors from 'cors'; +import dotenv from 'dotenv'; +import { connectDB } from './db.ts'; +import { Quiz } from './model/quiz.ts'; dotenv.config(); -import type { Application, Request, Response } from 'express'; + const app: Application = express(); const PORT = process.env.PORT || 5001; app.use(express.json()); @@ -12,10 +13,40 @@ app.use(cors()); app.get('/', (req: Request, res: Response) => { res.send('Express + TypeScript 서버 실행 중!'); }); - +app.get( + `/api/quizzes/firstQuiz`, + async (req: Request, res: Response): Promise => { + try { + const firstQuiz = await Quiz.findOne({ isFirst: true }); + if (!firstQuiz) { + res.status(404).json({ message: '퀴즈없슴' }); + return; + } + res.json(firstQuiz); + } catch (error) { + res.status(500).json({ message: '서버오류발생' }); + } + } +); +app.get( + '/api/quizzes/:id', + async (req: Request, res: Response): Promise => { + try { + const currentQuiz = await Quiz.findOne({ id: req.params.id }); + if (!currentQuiz) { + res.status(404).json({ message: '퀴즈없음' }); + return; + } + res.json({ + currentQuiz, + }); + } catch (error) { + res.status(500).json({ message: '서버오류' }); + } + } +); app.listen(PORT, () => { console.log(`서버 실행: http://localhost:${PORT}`); }); -connectDB(); -module.exports = app; +connectDB(); diff --git a/tsconfig.json b/tsconfig.json index f7181ca..51e46b0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,23 @@ { "compilerOptions": { - "module": "CommonJS", - "moduleResolution": "node", + "target": "ESNext", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "outDir": "dist", + "rootDir": "src", + "strict": true, "esModuleInterop": true, + "allowJs": true, "resolveJsonModule": true, - "outDir": "./dist" - } + "noEmit": true, + "baseUrl": "./", + "paths": { + "@models/*": ["src/models/*"], + "@controllers/*": ["src/controllers/*"], + "@services/*": ["src/services/*"] + }, + "allowImportingTsExtensions": true // ✅ `.ts` 확장자를 포함한 import 허용 + }, + "include": ["src"], + "exclude": ["node_modules", "dist"] }