Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 168 additions & 0 deletions config/create.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
CREATE TABLE `user` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`profile_img_id` bigint,
`email` varchar(30),
`name` varchar(20),
`phone_number` varchar(15),
`gender` varchar(10),
`birth` date,
`address` varchar(40),
`position` point,
`is_deleted` boolean,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` TIMESTAMP
);

CREATE TABLE `restaurant` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`category_id` bigint NOT NULL,
`region_id` bigint NOT NULL,
`name` varchar(30),
`address` varchar(40),
`position` point,
`status` varchar(10),
`rate` double,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE `category` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`name` varchar(30),
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE `user_mission` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`user_id` bigint NOT NULL,
`mission_id` bigint NOT NULL,
`is_finished` boolean,
`verification` bigint,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE `notification` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`member_id` bigint NOT NULL,
`message` varchar(100),
`is_read` boolean,
`type` varchar(20),
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE `mission` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`restaurant_id` bigint NOT NULL,
`title` varchar(15),
`reward` int,
`end_date` datetime,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE `review` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`restaurant_id` bigint NOT NULL,
`user_id` bigint NOT NULL,
`rate` double,
`contents` varchar(255),
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE `favor_food` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`category_id` bigint NOT NULL,
`user_id` bigint NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE `point` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`user_id` bigint NOT NULL,
`mission_id` bigint NOT NULL,
`reward` int,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE `invoice` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`member_id` bigint NOT NULL,
`message` varchar(15),
`is_read` varchar(30),
`type` text,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE `image` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`message` text,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE `review_image` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`review_id` bigint NOT NULL,
`image_id` bigint NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE `invoice_image` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`invoice_id` bigint NOT NULL,
`image_id` bigint NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE `region` (
`id` bigint AUTO_INCREMENT PRIMARY KEY NOT NULL,
`name` varchar(30),
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

ALTER TABLE `user` ADD CONSTRAINT `FK_image_TO_user_1` FOREIGN KEY (`profile_img_id`) REFERENCES `image` (`id`);

ALTER TABLE `restaurant` ADD CONSTRAINT `FK_category_TO_restaurant_1` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`);

ALTER TABLE `restaurant` ADD CONSTRAINT `FK_region_TO_restaurant_1` FOREIGN KEY (`region_id`) REFERENCES `region` (`id`);

ALTER TABLE `user_mission` ADD CONSTRAINT `FK_user_TO_user_mission_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`);

ALTER TABLE `user_mission` ADD CONSTRAINT `FK_mission_TO_user_mission_1` FOREIGN KEY (`mission_id`) REFERENCES `mission` (`id`);

ALTER TABLE `notification` ADD CONSTRAINT `FK_user_TO_notification_1` FOREIGN KEY (`member_id`) REFERENCES `user` (`id`);

ALTER TABLE `mission` ADD CONSTRAINT `FK_restaurant_TO_mission_1` FOREIGN KEY (`restaurant_id`) REFERENCES `restaurant` (`id`);

ALTER TABLE `review` ADD CONSTRAINT `FK_restaurant_TO_review_1` FOREIGN KEY (`restaurant_id`) REFERENCES `restaurant` (`id`);

ALTER TABLE `review` ADD CONSTRAINT `FK_user_TO_review_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`);

ALTER TABLE `favor_food` ADD CONSTRAINT `FK_category_TO_favor_food_1` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`);

ALTER TABLE `favor_food` ADD CONSTRAINT `FK_user_TO_favor_food_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`);

ALTER TABLE `point` ADD CONSTRAINT `FK_user_TO_point_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`);

ALTER TABLE `point` ADD CONSTRAINT `FK_user_mission_TO_point_1` FOREIGN KEY (`mission_id`) REFERENCES `user_mission` (`id`);

ALTER TABLE `invoice` ADD CONSTRAINT `FK_user_TO_invoice_1` FOREIGN KEY (`member_id`) REFERENCES `user` (`id`);

ALTER TABLE `review_image` ADD CONSTRAINT `FK_review_TO_review_image_1` FOREIGN KEY (`review_id`) REFERENCES `review` (`id`);

ALTER TABLE `review_image` ADD CONSTRAINT `FK_image_TO_review_image_1` FOREIGN KEY (`image_id`) REFERENCES `image` (`id`);

ALTER TABLE `invoice_image` ADD CONSTRAINT `FK_invoice_TO_invoice_image_1` FOREIGN KEY (`invoice_id`) REFERENCES `invoice` (`id`);

ALTER TABLE `invoice_image` ADD CONSTRAINT `FK_image_TO_invoice_image_1` FOREIGN KEY (`image_id`) REFERENCES `image` (`id`);
17 changes: 17 additions & 0 deletions config/db.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import mysql from 'mysql2/promise';
import dotenv from 'dotenv';

dotenv.config();

export const pool = mysql.createPool({
host: process.env.DB_HOST || 'localhost', // mysql의 hostname
user: process.env.DB_USER || 'root', // user 이름
port: process.env.DB_PORT || 3306, // 포트 번호
database: process.env.DB_TABLE || 'umc_study', // 데이터베이스 이름
password: process.env.DB_PASSWORD || 'password', // 비밀번호
waitForConnections: true,
// Pool에 획득할 수 있는 connection이 없을 때,
// true면 요청을 queue에 넣고 connection을 사용할 수 있게 되면 요청을 실행하며, false면 즉시 오류를 내보내고 다시 요청
connectionLimit: 10, // 몇 개의 커넥션을 가지게끔 할 것인지
queueLimit: 0, // getConnection에서 오류가 발생하기 전에 Pool에 대기할 요청의 개수 한도
});
6 changes: 6 additions & 0 deletions config/error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export class BaseError extends Error {
constructor(data) {
super(data.message);
this.data = data;
}
}
8 changes: 8 additions & 0 deletions config/response.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const response = ({isSuccess, code, message}, result) => {
return {
isSuccess: isSuccess,
code: code,
message: message,
result: result
}
};
25 changes: 25 additions & 0 deletions config/response.status.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { StatusCodes } from "http-status-codes";

export const status = {
// success
SUCCESS: {status: StatusCodes.OK, "isSuccess": true, "code": 2000, "message": "success!"},

// error
// common err
INTERNAL_SERVER_ERROR: {status: StatusCodes.INTERNAL_SERVER_ERROR, "isSuccess": false, "code": "COMMON000", "message": "서버 에러, 관리자에게 문의 바랍니다."},
BAD_REQUEST: {status: StatusCodes.BAD_REQUEST, "isSuccess": false, "code": "COMMON001", "message": "잘못된 요청입니다."},
UNAUTHORIZED: {status: StatusCodes.UNAUTHORIZED, "isSuccess": false, "code": "COMMON002", "message": "권한이 잘못되었습니다."},
METHOD_NOT_ALLOWED: {status: StatusCodes.METHOD_NOT_ALLOWED, "isSuccess": false, "code": "COMMON003", "message": "지원하지 않는 Http Method 입니다."},
FORBIDDEN: {status: StatusCodes.FORBIDDEN, "isSuccess": false, "code": "COMMON004", "message": "금지된 요청입니다."},
NOT_FOUND: {status: StatusCodes.NOT_FOUND, "isSuccess": false, "code": "COMMON005", "message": "요청한 페이지를 찾을 수 없습니다. 관리자에게 문의 바랍니다."},

// member err
MEMBER_NOT_FOUND: {status: StatusCodes.BAD_REQUEST, "isSuccess": false, "code": "MEMBER4001", "message": "사용자가 없습니다."},
NICKNAME_NOT_EXIST: {status: StatusCodes.BAD_REQUEST, "isSuccess": false, "code": "MEMBER4002", "message": "닉네임은 필수입니다."},

// article err
ARTICLE_NOT_FOUND: {status: StatusCodes.NOT_FOUND, "isSuccess": false, "code": "ARTICLE4001", "message": "게시글이 없습니다."},


PARAMETER_IS_WRONG: {status: StatusCodes.BAD_REQUEST, "isSuccess": false, "code": "VALID4001", "message": "전달한 파라미터 정보가 잘못되었습니다."},
}
16 changes: 16 additions & 0 deletions config/swagger.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import SwaggerJsdoc from "swagger-jsdoc";

const options = {
definition: {
info: {
title: 'UMC Study API',
version: '1.0.0',
description: 'UMC Study API with express, API 설명'
},
host: 'localhost:3000',
basepath: '../'
},
apis: ['./src/routes/*.js', './swagger/*']
};

export const specs = SwaggerJsdoc(options);
46 changes: 46 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import express from 'express';
import { userRouter } from './src/routes/user.route.js';
import { response } from './config/response.js';
import { BaseError } from './config/error.js';
import { status } from './config/response.status.js';
import dotenv from 'dotenv';
import cors from 'cors';

import { specs } from './config/swagger.config.js';
import SwaggerUi from 'swagger-ui-express';

dotenv.config();

const app = express();

// server setting - view, static, body-parser etc..
app.set('port', process.env.PORT || 3000); // 서버 포트 지정
app.use(cors()); // cors 방식 허용
app.use(express.static('public')); // 정적 파일 접근
app.use(express.json()); // request의 본문을 json으로 해석할 수 있도록 함 (JSON 형태의 요청 body를 파싱하기 위함)
app.use(express.urlencoded({extended: false})); // 단순 객체 문자열 형태로 본문 데이터 해석

// swagger
app.use('/api-docs', SwaggerUi.serve, SwaggerUi.setup(specs));

// router setting
app.use('/user', userRouter);

// index.js
app.use((req, res, next) => {
const err = new BaseError(status.NOT_FOUND);
next(err);
});

// error handling
app.use((err, req, res, next) => {
// 템플릿 엔진 변수 설정
res.locals.message = err.message;
// 개발환경이면 에러를 출력하고 아니면 출력하지 않기
res.locals.error = process.env.NODE_ENV !== 'production' ? err : {};
res.status(err.data.status || status.INTERNAL_SERVER_ERROR).send(response(err.data));
});

app.listen(app.get('port'), () => {
console.log(`Example app listening on port ${app.get('port')}`);
})
Loading