From c0f5eccc433a3e8c238a0911e9549384f51f0992 Mon Sep 17 00:00:00 2001 From: tanonkim Date: Sat, 4 Nov 2023 19:45:28 +0900 Subject: [PATCH 1/5] Refactor : Fix app.js -> index.js --- index.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 index.js diff --git a/index.js b/index.js new file mode 100644 index 0000000..06dadce --- /dev/null +++ b/index.js @@ -0,0 +1,48 @@ +const serverless = require("serverless-http"); // Lambda + +const dotenv = require("dotenv"); + +const express = require("express"); +const cors = require("cors"); +const morgan = require("morgan"); + +dotenv.config(); + +const dataSource = require("./models/appDataSource"); +const routes = require("./routes"); +const baseResponse = require("./utils/baseResponse"); + +const initializeDataSource = async () => { + try { + await dataSource.initialize(); + console.log("Data Source has been initialized!"); + } catch (error) { + console.error(`Initialize Error: ${error}`); + } +}; + +// 데이터 소스를 즉시 초기화하려는 경우 여기서 호출 +initializeDataSource(); + +const app = express(); + +app.use(express.json()); +app.use(cors()); +app.use(morgan("dev")); +app.use(routes); +app.get("/ping", (req, res) => { + return res.status(200).json({ message: "pong" }); +}); +// app.get("/", (req, res) => { +// return res.status(200).json({ message: "Welcome to the API" }); +// }); + +const PORT = process.env.PORT; + +const start = async () => { + app.listen(PORT, () => console.log(`server is listening on ${PORT}`)); +}; + +start(); + +module.exports.handler = serverless(app); From c3b30a9c0e35c300af86114ab5a3f293ec38c841 Mon Sep 17 00:00:00 2001 From: tanonkim Date: Sat, 4 Nov 2023 19:46:20 +0900 Subject: [PATCH 2/5] Feature : Add engines 20 -> 18 && install serverless-https --- package-lock.json | 12 ++++++++++++ package.json | 8 ++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8bd90d9..f1b9fae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,10 +21,14 @@ "multer": "^1.4.5-lts.1", "multer-s3": "^3.0.1", "mysql2": "^3.6.1", + "serverless-http": "^3.2.0", "typeorm": "^0.3.17" }, "devDependencies": { "nodemon": "^3.0.1" + }, + "engines": { + "node": "18.x" } }, "node_modules/@aws-crypto/crc32": { @@ -3902,6 +3906,14 @@ "node": ">= 0.8.0" } }, + "node_modules/serverless-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/serverless-http/-/serverless-http-3.2.0.tgz", + "integrity": "sha512-QvSyZXljRLIGqwcJ4xsKJXwkZnAVkse1OajepxfjkBXV0BMvRS5R546Z4kCBI8IygDzkQY0foNPC/rnipaE9pQ==", + "engines": { + "node": ">=12.0" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", diff --git a/package.json b/package.json index 4759078..c01fa4c 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,9 @@ "name": "assign-code", "version": "1.0.0", "description": "", - "main": "app.js", + "main": "index.js", "scripts": { - "start": "nodemon app.js", + "start": "nodemon index.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], @@ -23,9 +23,13 @@ "multer": "^1.4.5-lts.1", "multer-s3": "^3.0.1", "mysql2": "^3.6.1", + "serverless-http": "^3.2.0", "typeorm": "^0.3.17" }, "devDependencies": { "nodemon": "^3.0.1" + }, + "engines": { + "node": "18.x" } } From f731900673bb6fd99e7c92d9c8b53f0831ba97dc Mon Sep 17 00:00:00 2001 From: tanonkim Date: Sat, 4 Nov 2023 19:47:24 +0900 Subject: [PATCH 3/5] Refactor : Add CircularReplacer --- utils/baseResponse.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/utils/baseResponse.js b/utils/baseResponse.js index 39c6d1b..584d1a4 100644 --- a/utils/baseResponse.js +++ b/utils/baseResponse.js @@ -1,6 +1,21 @@ const baseResponseStatus = require("./baseResponseStatus"); const CustomException = require("./handler/customException"); +// 순환 참조를 제거하는 함수 +function getCircularReplacer() { + const seen = new WeakSet(); + return (key, value) => { + if (typeof value === "object" && value !== null) { + if (seen.has(value)) { + // 순환 참조가 발견되면 대체 값(예: undefined)을 반환합니다. + return; + } + seen.add(value); + } + return value; + }; +} + const baseResponse = (dataOrError, res) => { if (dataOrError instanceof CustomException) { return res.status(200).json({ @@ -12,11 +27,14 @@ const baseResponse = (dataOrError, res) => { // 데이터 반환 처리 if (dataOrError) { + const responseData = JSON.parse( + JSON.stringify(dataOrError, getCircularReplacer()) + ); return res.status(200).json({ isSuccess: baseResponseStatus.SUCCESS.isSuccess, responseCode: baseResponseStatus.SUCCESS.responseCode, responseMessage: baseResponseStatus.SUCCESS.responseMessage, - data: dataOrError, + data: responseData, }); } From 78f91a0a4ccf012ca52b732442e5d9eeeb723d4d Mon Sep 17 00:00:00 2001 From: tanonkim Date: Sat, 4 Nov 2023 19:47:52 +0900 Subject: [PATCH 4/5] Refactor : Fix minor --- app.js | 40 ----- models/community/controller/index.js | 2 +- models/community/service/index.js | 184 +++++++++++----------- models/publicData/publicDataController.js | 3 - models/user/service/index.js | 2 - utils/s3/imageUploader.js | 15 +- 6 files changed, 101 insertions(+), 145 deletions(-) delete mode 100644 app.js diff --git a/app.js b/app.js deleted file mode 100644 index 4c1c1d2..0000000 --- a/app.js +++ /dev/null @@ -1,40 +0,0 @@ -const dotenv = require("dotenv"); - -const express = require("express"); -const cors = require("cors"); -const morgan = require("morgan"); - -dotenv.config(); - -const dataSource = require("./models/appDataSource"); -const routes = require("./routes"); -const baseResponse = require("./utils/baseResponse"); - -dataSource - .initialize() - .then(() => { - console.log("Data Source has been initialized!"); - }) - .catch((error) => { - console.err(`Initialize Error ${error}`); - }); - -const app = express(); - -app.use(express.json()); -app.use(cors()); -app.use(morgan("dev")); -app.use(routes); -app.use(baseResponse); - -app.get("/ping", (req, res) => { - return res.status(200).json({ message: "pong" }); -}); - -const PORT = process.env.PORT; - -const start = async () => { - app.listen(PORT, () => console.log(`server is listening on ${PORT}`)); -}; - -start(); \ No newline at end of file diff --git a/models/community/controller/index.js b/models/community/controller/index.js index 9b28654..1ca436f 100644 --- a/models/community/controller/index.js +++ b/models/community/controller/index.js @@ -38,7 +38,7 @@ class CommunityController { try { const { id } = req.params; const result = await this.communityService.findPost(id); - console.log(res); + baseResponse({ result }, res); } catch (err) { next(err); diff --git a/models/community/service/index.js b/models/community/service/index.js index 585944a..ac0e562 100644 --- a/models/community/service/index.js +++ b/models/community/service/index.js @@ -4,46 +4,44 @@ const { deleteImageFromS3 } = require("../../../utils/s3/imageUploader"); const CustomException = require("../../../utils/handler/customException"); const { DATABASE_ERROR } = require("../../../utils/baseResponseStatus"); - -class CommunityService{ - async createPost(data){ - try{ - await dataSource.query( - ` +class CommunityService { + async createPost(data) { + try { + await dataSource.query( + ` INSERT INTO community( title, content, user_id ) VALUES (?, ?, ?) `, - [data.title, data.content, data.user_id] - ); - if(data.community_image_url !== 'null'){ - const community_id = await dataSource.query( - ` + [data.title, data.content, data.user_id] + ); + if (data.community_image_url !== "null") { + const community_id = await dataSource.query( + ` SELECT id FROM community WHERE title = ? AND content = ? AND user_id = ? `, - [data.title,data.content,data.user_id] - ); - await dataSource.query( - `INSERT INTO community_images( + [data.title, data.content, data.user_id] + ); + await dataSource.query( + `INSERT INTO community_images( community_id, user_id, community_image_url )VALUES(?,?,?)`, - [community_id[0].id,data.user_id,data.community_image_url] - ); - } - }catch(err){ - throw new CustomException(DATABASE_ERROR); - } - - }; + [community_id[0].id, data.user_id, data.community_image_url] + ); + } + } catch (err) { + throw new CustomException(DATABASE_ERROR); + } + } - async findPost(post_id){ - try{ - const result = await dataSource.query( - ` + async findPost(post_id) { + try { + const result = await dataSource.query( + ` SELECT c.id AS community_id, c.title AS community_title, @@ -58,21 +56,21 @@ class CommunityService{ community_images ci ON c.id = ci.community_id WHERE c.id = ? - `,[post_id] - ); - - return result; - }catch(err){ - throw new CustomException(DATABASE_ERROR); - }; - }; + `, + [post_id] + ); - async findPosts(page){ - try{ - console.log(1); - const offset = (page - 1) * 10; - const result = await dataSource.query( - ` + return result; + } catch (err) { + throw new CustomException(DATABASE_ERROR); + } + } + + async findPosts(page) { + try { + const offset = (page - 1) * 10; + const result = await dataSource.query( + ` SELECT c.id AS community_id, c.title AS community_title, @@ -87,69 +85,71 @@ class CommunityService{ community_images ci ON c.id = ci.community_id WHERE c.id BETWEEN ? AND ? - `,[offset+1,offset+10] - ); - return result; - }catch(err){ - throw new CustomException(DATABASE_ERROR); - }; - - }; - // 이걸 하나의 transaction으로 처리할 필요가 있음 - async deletePost(post_id){ - const queryRunner = await dataSource.createQueryRunner(); - await queryRunner.startTransaction(); - try{ - const s3Image = await queryRunner.manager.query( - `SELECT * FROM community_images WHERE community_id = ?`,[post_id] - ); - if(s3Image.length !== 0) { - await deleteImageFromS3(s3Image[0].community_image_url); - await queryRunner.manager.query( - ` + `, + [offset + 1, offset + 10] + ); + return result; + } catch (err) { + throw new CustomException(DATABASE_ERROR); + } + } + // 이걸 하나의 transaction으로 처리할 필요가 있음 + async deletePost(post_id) { + const queryRunner = await dataSource.createQueryRunner(); + await queryRunner.startTransaction(); + try { + const s3Image = await queryRunner.manager.query( + `SELECT * FROM community_images WHERE community_id = ?`, + [post_id] + ); + if (s3Image.length !== 0) { + await deleteImageFromS3(s3Image[0].community_image_url); + await queryRunner.manager.query( + ` DELETE ci FROM community_images ci WHERE ci.community_id = ? `, - [post_id] - ); - } - await queryRunner.manager.query( - ` + [post_id] + ); + } + await queryRunner.manager.query( + ` DELETE c FROM community c WHERE c.id = ? `, - [post_id] - ); - await queryRunner.commitTransaction(); - }catch(err){ - await queryRunner.rollbackTransaction(); - throw new CustomException(DATABASE_ERROR); - }; - }; + [post_id] + ); + await queryRunner.commitTransaction(); + } catch (err) { + await queryRunner.rollbackTransaction(); + throw new CustomException(DATABASE_ERROR); + } + } - async updatePost(post_id, data){ - try{ - const s3Image = await dataSource.query( - `SELECT * FROM community_images WHERE community_id = ?`,[post_id] - ); - if(s3Image.length !== 0) { - await deleteImageFromS3(s3Image[0].community_image_url); - } - await dataSource.query( - ` + async updatePost(post_id, data) { + try { + const s3Image = await dataSource.query( + `SELECT * FROM community_images WHERE community_id = ?`, + [post_id] + ); + if (s3Image.length !== 0) { + await deleteImageFromS3(s3Image[0].community_image_url); + } + await dataSource.query( + ` UPDATE community c LEFT JOIN community_images ci ON c.id = ci.community_id SET c.title = ?,c.content = ? , ci.community_image_url = ? WHERE c.id = ?; `, - [data.title,data.content,data.community_image_url,post_id] - ); - }catch(err){ - throw new CustomException(DATABASE_ERROR); - }; - }; -}; + [data.title, data.content, data.community_image_url, post_id] + ); + } catch (err) { + throw new CustomException(DATABASE_ERROR); + } + } +} -module.exports = CommunityService; \ No newline at end of file +module.exports = CommunityService; diff --git a/models/publicData/publicDataController.js b/models/publicData/publicDataController.js index 4ae3d2a..75b539a 100644 --- a/models/publicData/publicDataController.js +++ b/models/publicData/publicDataController.js @@ -30,7 +30,6 @@ const createPost = async (req, res) => { cost, 1 ); - return baseResponse({ postId: `${postId.insertId}` }, res); } catch (error) { console.log(error); @@ -58,7 +57,6 @@ const getAllposts = async (req, res) => { return baseResponse({ headInfo, rows }, res); } catch (error) { - console.log(error); return baseResponse(error, res); } }; @@ -86,7 +84,6 @@ const updatePost = async (req, res) => { url, cost ); - return baseResponse({ id: id, info: result.info }, res); } catch (error) { console.log(error); diff --git a/models/user/service/index.js b/models/user/service/index.js index 62b4ce0..95fdbbc 100644 --- a/models/user/service/index.js +++ b/models/user/service/index.js @@ -64,7 +64,6 @@ class UserService { const queryRunner = await dataSource.createQueryRunner(); await queryRunner.startTransaction(); try { - console.log(id); await queryRunner.manager.query( ` DELETE u @@ -73,7 +72,6 @@ class UserService { `, [id] ); - console.log(id); await queryRunner.commitTransaction(); //await queryRunner.release(); } catch (err) { diff --git a/utils/s3/imageUploader.js b/utils/s3/imageUploader.js index b3dc090..6a3412c 100644 --- a/utils/s3/imageUploader.js +++ b/utils/s3/imageUploader.js @@ -3,14 +3,15 @@ const { DeleteObjectCommand } = require("@aws-sdk/client-s3"); const { fromEnv } = require("@aws-sdk/credential-provider-env"); const multer = require("multer"); const path = require("path"); +const crypto = require("crypto"); const s3Client = new S3Client({ - region: process.env.AWS_S3_REGION, - credentials: fromEnv(), + region: process.env.S3_REGION, + // credentials: fromEnv(), }); const generateS3Url = (bucketName, key) => { - const region = process.env.AWS_S3_REGION; + const region = process.env.S3_REGION; return `https://${bucketName}.s3.${region}.amazonaws.com/${key}`; }; @@ -40,7 +41,7 @@ const uploadToS3 = async (req, res, next) => { for (let file of req.files) { const filename = `post/${Date.now()}-${crypto.randomUUID()}`; const params = { - Bucket: process.env.AWS_S3_BUCKET_NAME, + Bucket: process.env.BUCKET_NAME, Key: filename, Body: file.buffer, ContentType: file.mimetype, @@ -51,7 +52,7 @@ const uploadToS3 = async (req, res, next) => { await s3Client.send(new PutObjectCommand(params)); // 2. S3 URL 생성 - const fileUrl = generateS3Url(process.env.AWS_S3_BUCKET_NAME, filename); + const fileUrl = generateS3Url(process.env.BUCKET_NAME, filename); uploadedFileUrls.push(fileUrl); } catch (error) { console.log(error); @@ -64,11 +65,11 @@ const uploadToS3 = async (req, res, next) => { }; const deleteImageFromS3 = async (imageUrl) => { - const baseUrl = `https://${process.env.AWS_S3_BUCKET_NAME}.s3.${process.env.AWS_S3_REGION}.amazonaws.com/`; + const baseUrl = `https://${process.env.BUCKET_NAME}.s3.${process.env.S3_REGION}.amazonaws.com/`; const key = imageUrl.slice(baseUrl.length); // 키 추출 const params = { - Bucket: process.env.AWS_S3_BUCKET_NAME, + Bucket: process.env.BUCKET_NAME, Key: key, }; From e040f5bfe8315d6d7036cc497266f38112963818 Mon Sep 17 00:00:00 2001 From: tanonkim Date: Sat, 4 Nov 2023 19:50:49 +0900 Subject: [PATCH 5/5] Refactor : Fix .env --- .env.sample | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/.env.sample b/.env.sample index ba82134..92a3c82 100644 --- a/.env.sample +++ b/.env.sample @@ -1,21 +1,22 @@ -PORT=YOUR_POTR_NUMBER +# DB +DB_CONNECTION = DB_CONNECTION +DB_USERNAME = DB_USERNAME +DB_PASSWORD = DB_PASSWORD +DB_LOGGING = DB_LOGGING -DB_CONNECTION=CONNECTION -DB_HOST=HOST -DB_USERNAME=USERNAME -DB_PASSWORD=PASSWORD -DB_DATABASE=DATABASENAME -DB_PORT=PROT -DB_LOGGING=LOGGING +DB_HOST = DB_HOST +DB_DATABASE = DB_DATABASE +DB_PORT = DB_PORT +DATABASE_URL = DATABASE_URL -DATABASE_URL=URL - -SECRET_KEY=SECRET_KEY +PORT = PORT +SECRET_KEY = SECRET_KEY # AWS-S3 -AWS_ACCESS_KEY_ID=AWS_ACCESS_KEY_ID -AWS_SECRET_ACCESS_KEY=AWS_SECRET_ACCESS_KEY -AWS_S3_REGION=AWS_S3_REGION -AWS_S3_BUCKET_NAME=AWS_S3_BUCKET_NAME +AWS_ACCESS_KEY_ID = AWS_ACCESS_KEY_ID +AWS_SECRET_ACCESS_KEY = AWS_SECRET_ACCESS_KEY +S3_REGION = S3_REGION +BUCKET_NAME = BUCKET_NAME +API_ENDPOINT=API_ENDPOINT META_DATA_URL = META_DATA_URL \ No newline at end of file