diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..0b93d25
Binary files /dev/null and b/.DS_Store differ
diff --git a/Unit6/unit6.md b/Unit6/unit6.md
new file mode 100644
index 0000000..904dccb
--- /dev/null
+++ b/Unit6/unit6.md
@@ -0,0 +1,42 @@
+### ⭐️ 6주차 과제 제출 ⭐️
+
+## ❗️ 강의 수강 여부
+수강한 강의에 체크표시 해주세요~
+
+- [ ] HTTP 통신
+- [ ] API
+- [ ] 데이터 포맷 - CSV, JSON, XML
+
+
+
+## ❗️ notion에 키워드 정리 완료 여부
+내가 notion에 키워드를 정리를 완료한 경우 체크표시 해주세요~
+
+- [ ] 키워드 정리 완료
+
+
+
+## ❗️ 6주차 과제
+1. 개발환경 구축하기 - nodejs 설치 및 사전에 올려둔 템플릿 적용하기
+ (완료된 내용 켬쳐본 올리기)
+
+
+
+2. 자신이 설계한 DB와 연동해서 API설계 (CRUD)
+ (완료된 내용 켬쳐본 올리기)
+
+
+
+3. Postman으로 API 테스트
+ (완료된 내용 켬쳐본 올리기)
+
+
+
+4. API Sheet 작성
+ (완료된 내용 켬쳐본 올리기)
+
+
+
+
+
+
diff --git a/Unit7/unit7.md b/Unit7/unit7.md
new file mode 100644
index 0000000..f701a84
--- /dev/null
+++ b/Unit7/unit7.md
@@ -0,0 +1,33 @@
+### ⭐️ 7주차 과제 제출 ⭐️
+
+## ❗️ 강의 수강 여부
+수강한 강의에 체크표시 해주세요~
+
+- [ ] Restful API
+- [ ] Path Variable, Query Parameter
+
+
+
+## ❗️ notion에 키워드 정리 완료 여부
+내가 notion에 키워드를 정리를 완료한 경우 체크표시 해주세요~
+
+- [ ] 키워드 정리 완료
+
+
+
+## ❗️ 7주차 과제
+1. GET 메소드 함수 작성 완료하기
+ (fork에 코드 올린 후 PR 날리기)
+
+
+
+2. test 진행하기(postman 이용하기)
+ (완료된 내용 켬쳐본 올리기)
+
+
+
+3. API Sheet 작성
+ (완료된 내용 켬쳐본 올리기)
+
+
+
diff --git a/server_nodejs_templete/.gitignore b/server_nodejs_templete/.gitignore
new file mode 100644
index 0000000..68d752c
--- /dev/null
+++ b/server_nodejs_templete/.gitignore
@@ -0,0 +1,5 @@
+.idea/*
+node_modules/*
+package-lock.json
+log/*
+.DS_Store
\ No newline at end of file
diff --git a/server_nodejs_templete/README.md b/server_nodejs_templete/README.md
new file mode 100644
index 0000000..22bc396
--- /dev/null
+++ b/server_nodejs_templete/README.md
@@ -0,0 +1 @@
+# Node.js Template
diff --git a/server_nodejs_templete/config/baseResponseStatus.js b/server_nodejs_templete/config/baseResponseStatus.js
new file mode 100644
index 0000000..77e5769
--- /dev/null
+++ b/server_nodejs_templete/config/baseResponseStatus.js
@@ -0,0 +1,49 @@
+module.exports = {
+
+ // Success
+ SUCCESS : { "isSuccess": true, "code": 1000, "message":"성공" },
+
+ // Common
+ TOKEN_EMPTY : { "isSuccess": false, "code": 2000, "message":"JWT 토큰을 입력해주세요." },
+ TOKEN_VERIFICATION_FAILURE : { "isSuccess": false, "code": 3000, "message":"JWT 토큰 검증 실패" },
+ TOKEN_VERIFICATION_SUCCESS : { "isSuccess": true, "code": 1001, "message":"JWT 토큰 검증 성공" }, // ?
+
+ //Request error
+ SIGNUP_EMAIL_EMPTY : { "isSuccess": false, "code": 2001, "message":"이메일을 입력해주세요" },
+ SIGNUP_EMAIL_LENGTH : { "isSuccess": false, "code": 2002, "message":"이메일은 30자리 미만으로 입력해주세요." },
+ SIGNUP_EMAIL_ERROR_TYPE : { "isSuccess": false, "code": 2003, "message":"이메일을 형식을 정확하게 입력해주세요." },
+ SIGNUP_PASSWORD_EMPTY : { "isSuccess": false, "code": 2004, "message": "비밀번호를 입력 해주세요." },
+ SIGNUP_PASSWORD_LENGTH : { "isSuccess": false, "code": 2005, "message":"비밀번호는 6~20자리를 입력해주세요." },
+ SIGNUP_NICKNAME_EMPTY : { "isSuccess": false, "code": 2006, "message":"닉네임을 입력 해주세요." },
+ SIGNUP_NICKNAME_LENGTH : { "isSuccess": false,"code": 2007,"message":"닉네임은 최대 20자리를 입력해주세요." },
+
+ SIGNIN_EMAIL_EMPTY : { "isSuccess": false, "code": 2008, "message":"이메일을 입력해주세요" },
+ SIGNIN_EMAIL_LENGTH : { "isSuccess": false, "code": 2009, "message":"이메일은 30자리 미만으로 입력해주세요." },
+ SIGNIN_EMAIL_ERROR_TYPE : { "isSuccess": false, "code": 2010, "message":"이메일을 형식을 정확하게 입력해주세요." },
+ SIGNIN_PASSWORD_EMPTY : { "isSuccess": false, "code": 2011, "message": "비밀번호를 입력 해주세요." },
+
+ USER_USERID_EMPTY : { "isSuccess": false, "code": 2012, "message": "userId를 입력해주세요." },
+ USER_USERID_NOT_EXIST : { "isSuccess": false, "code": 2013, "message": "해당 회원이 존재하지 않습니다." },
+
+ USER_USEREMAIL_EMPTY : { "isSuccess": false, "code": 2014, "message": "이메일을 입력해주세요." },
+ USER_USEREMAIL_NOT_EXIST : { "isSuccess": false, "code": 2015, "message": "해당 이메일을 가진 회원이 존재하지 않습니다." },
+ USER_ID_NOT_MATCH : { "isSuccess": false, "code": 2016, "message": "유저 아이디 값을 확인해주세요" },
+ USER_NICKNAME_EMPTY : { "isSuccess": false, "code": 2017, "message": "변경할 닉네임 값을 입력해주세요" },
+
+ USER_STATUS_EMPTY : { "isSuccess": false, "code": 2018, "message": "회원 상태값을 입력해주세요" },
+
+ // Response error
+ SIGNUP_REDUNDANT_EMAIL : { "isSuccess": false, "code": 3001, "message":"중복된 이메일입니다." },
+ SIGNUP_REDUNDANT_NICKNAME : { "isSuccess": false, "code": 3002, "message":"중복된 닉네임입니다." },
+
+ SIGNIN_EMAIL_WRONG : { "isSuccess": false, "code": 3003, "message": "아이디가 잘못 되었습니다." },
+ SIGNIN_PASSWORD_WRONG : { "isSuccess": false, "code": 3004, "message": "비밀번호가 잘못 되었습니다." },
+ SIGNIN_INACTIVE_ACCOUNT : { "isSuccess": false, "code": 3005, "message": "비활성화 된 계정입니다. 고객센터에 문의해주세요." },
+ SIGNIN_WITHDRAWAL_ACCOUNT : { "isSuccess": false, "code": 3006, "message": "탈퇴 된 계정입니다. 고객센터에 문의해주세요." },
+
+ //Connection, Transaction 등의 서버 오류
+ DB_ERROR : { "isSuccess": false, "code": 4000, "message": "데이터 베이스 에러"},
+ SERVER_ERROR : { "isSuccess": false, "code": 4001, "message": "서버 에러"},
+
+
+}
diff --git a/server_nodejs_templete/config/database.js b/server_nodejs_templete/config/database.js
new file mode 100644
index 0000000..03146d0
--- /dev/null
+++ b/server_nodejs_templete/config/database.js
@@ -0,0 +1,15 @@
+const mysql = require('mysql2/promise');
+const {logger} = require('./winston');
+
+// TODO: 본인의 DB 계정 입력
+const pool = mysql.createPool({
+ host: '',
+ user: '',
+ port: '3306',
+ password: '',
+ database: ''
+});
+
+module.exports = {
+ pool: pool
+};
\ No newline at end of file
diff --git a/server_nodejs_templete/config/express.js b/server_nodejs_templete/config/express.js
new file mode 100644
index 0000000..a7608c6
--- /dev/null
+++ b/server_nodejs_templete/config/express.js
@@ -0,0 +1,24 @@
+const express = require('express');
+const compression = require('compression');
+const methodOverride = require('method-override');
+var cors = require('cors');
+module.exports = function () {
+ const app = express();
+
+ app.use(compression());
+
+ app.use(express.json());
+
+ app.use(express.urlencoded({extended: true}));
+
+ app.use(methodOverride());
+
+ app.use(cors());
+ // app.use(express.static(process.cwd() + '/public'));
+
+ /* App (Android, iOS) */
+ // 도메인을 추가할 경우 이곳에 Route를 추가
+ require('../src/app/User/userRoute')(app);
+
+ return app;
+};
\ No newline at end of file
diff --git a/server_nodejs_templete/config/jwtMiddleware.js b/server_nodejs_templete/config/jwtMiddleware.js
new file mode 100644
index 0000000..92b2d14
--- /dev/null
+++ b/server_nodejs_templete/config/jwtMiddleware.js
@@ -0,0 +1,38 @@
+const jwt = require('jsonwebtoken');
+const secret_config = require('./secret');
+const { response } = require("./response")
+const { errResponse } = require("./response")
+const baseResponse = require("./baseResponseStatus");
+
+
+const jwtMiddleware = (req, res, next) => {
+ // read the token from header or url
+ const token = req.headers['x-access-token'] || req.query.token;
+ // token does not exist
+ if(!token) {
+ return res.send(errResponse(baseResponse.TOKEN_EMPTY))
+ }
+
+ // create a promise that decodes the token
+ const p = new Promise(
+ (resolve, reject) => {
+ jwt.verify(token, secret_config.jwtsecret , (err, verifiedToken) => {
+ if(err) reject(err);
+ resolve(verifiedToken)
+ })
+ }
+ );
+
+ // if it has failed to verify, it will return an error message
+ const onError = (error) => {
+ return res.send(errResponse(baseResponse.TOKEN_VERIFICATION_FAILURE))
+ };
+ // process the promise
+ p.then((verifiedToken)=>{
+ //비밀 번호 바뀌었을 때 검증 부분 추가 할 곳
+ req.verifiedToken = verifiedToken;
+ next();
+ }).catch(onError)
+};
+
+module.exports = jwtMiddleware;
\ No newline at end of file
diff --git a/server_nodejs_templete/config/response.js b/server_nodejs_templete/config/response.js
new file mode 100644
index 0000000..8992a22
--- /dev/null
+++ b/server_nodejs_templete/config/response.js
@@ -0,0 +1,18 @@
+const response = ({isSuccess, code, message}, result) => {
+ return {
+ isSuccess: isSuccess,
+ code: code,
+ message: message,
+ result: result
+ }
+ };
+
+ const errResponse = ({isSuccess, code, message}) => {
+ return {
+ isSuccess: isSuccess,
+ code: code,
+ message: message
+ }
+ };
+
+ module.exports = { response, errResponse };
\ No newline at end of file
diff --git a/server_nodejs_templete/config/secret.js b/server_nodejs_templete/config/secret.js
new file mode 100644
index 0000000..bef208e
--- /dev/null
+++ b/server_nodejs_templete/config/secret.js
@@ -0,0 +1,5 @@
+// 해당 KEY 값들을 꼭 바꿔서 사용하기!
+// 반드시 .gitignore에 추가하기!
+module.exports = {
+ 'jwtsecret' : '',
+};
\ No newline at end of file
diff --git a/server_nodejs_templete/config/winston.js b/server_nodejs_templete/config/winston.js
new file mode 100644
index 0000000..c01031e
--- /dev/null
+++ b/server_nodejs_templete/config/winston.js
@@ -0,0 +1,48 @@
+const { createLogger, format, transports } = require('winston');
+require('winston-daily-rotate-file');
+const fs = require('fs');
+
+const env = process.env.NODE_ENV || 'development';
+const logDir = 'log';
+
+// Javascript winston logger 이용하기
+// https://lovemewithoutall.github.io/it/winston-example/
+// Create the log directory if it does not exist
+if (!fs.existsSync(logDir)) {
+ fs.mkdirSync(logDir)
+}
+
+const dailyRotateFileTransport = new transports.DailyRotateFile({
+ level: 'debug',
+ filename: `${logDir}/%DATE%-smart-push.log`,
+ datePattern: 'YYYY-MM-DD',
+ zippedArchive: true,
+ maxSize: '20m',
+ maxFiles: '14d'
+});
+
+const logger = createLogger({
+ level: env === 'development' ? 'debug' : 'info',
+ format: format.combine(
+ format.timestamp({
+ format: 'YYYY-MM-DD HH:mm:ss'
+ }),
+ format.json()
+ ),
+ transports: [
+ new transports.Console({
+ level: 'info',
+ format: format.combine(
+ format.colorize(),
+ format.printf(
+ info => `${info.timestamp} ${info.level}: ${info.message}`
+ )
+ )
+ }),
+ dailyRotateFileTransport
+ ]
+});
+
+module.exports = {
+ logger: logger
+};
\ No newline at end of file
diff --git a/server_nodejs_templete/index.js b/server_nodejs_templete/index.js
new file mode 100644
index 0000000..3f8c580
--- /dev/null
+++ b/server_nodejs_templete/index.js
@@ -0,0 +1,6 @@
+const express = require('./config/express');
+const {logger} = require('./config/winston');
+
+const port = 3000;
+express().listen(port);
+logger.info(`${process.env.NODE_ENV} - API Server Start At Port ${port}`);
\ No newline at end of file
diff --git a/server_nodejs_templete/package.json b/server_nodejs_templete/package.json
new file mode 100644
index 0000000..584eaba
--- /dev/null
+++ b/server_nodejs_templete/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "api-server-node",
+ "version": "1.0.0",
+ "description": "Node.js API Server",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "dev": "NODE_ENV=development node index.js",
+ "prod": "NODE_ENV=production node index.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git@gitlab.com:softsquared/template/api-server-node.git"
+ },
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "compression": "^1.7.4",
+ "cors": "^2.8.5",
+ "crypto": "^1.0.1",
+ "express": "^4.17.1",
+ "jsonwebtoken": "^8.5.1",
+ "method-override": "^3.0.0",
+ "mysql2": "^2.0.0",
+ "nodemon": "^2.0.7",
+ "regex-email": "^1.0.2",
+ "winston": "^3.2.1",
+ "winston-daily-rotate-file": "^4.2.1"
+ }
+}
diff --git a/server_nodejs_templete/src/app/User/userController.js b/server_nodejs_templete/src/app/User/userController.js
new file mode 100644
index 0000000..7c92afc
--- /dev/null
+++ b/server_nodejs_templete/src/app/User/userController.js
@@ -0,0 +1,17 @@
+const jwtMiddleware = require("../../../config/jwtMiddleware");
+const userProvider = require("../../app/User/userProvider");
+const userService = require("../../app/User/userService");
+const baseResponse = require("../../../config/baseResponseStatus");
+const {response, errResponse} = require("../../../config/response");
+
+const regexEmail = require("regex-email");
+const {emit} = require("nodemon");
+
+/**
+ * API No. 0
+ * API Name : 테스트 API
+ * [GET] /app/test
+ */
+ exports.getTest = async function (req, res) {
+ return res.send(response(baseResponse.SUCCESS))
+ };
\ No newline at end of file
diff --git a/server_nodejs_templete/src/app/User/userDao.js b/server_nodejs_templete/src/app/User/userDao.js
new file mode 100644
index 0000000..e69de29
diff --git a/server_nodejs_templete/src/app/User/userProvider.js b/server_nodejs_templete/src/app/User/userProvider.js
new file mode 100644
index 0000000..d510e3b
--- /dev/null
+++ b/server_nodejs_templete/src/app/User/userProvider.js
@@ -0,0 +1,4 @@
+const { pool } = require("../../../config/database");
+const { logger } = require("../../../config/winston");
+
+const userDao = require("./userDao");
diff --git a/server_nodejs_templete/src/app/User/userRoute.js b/server_nodejs_templete/src/app/User/userRoute.js
new file mode 100644
index 0000000..38f8d89
--- /dev/null
+++ b/server_nodejs_templete/src/app/User/userRoute.js
@@ -0,0 +1,8 @@
+module.exports = function(app){
+ const user = require('./userController');
+ const jwtMiddleware = require('../../../config/jwtMiddleware');
+
+ // 0. 테스트 API
+ app.get('/app/test', user.getTest)
+
+};
diff --git a/server_nodejs_templete/src/app/User/userService.js b/server_nodejs_templete/src/app/User/userService.js
new file mode 100644
index 0000000..a2a83fb
--- /dev/null
+++ b/server_nodejs_templete/src/app/User/userService.js
@@ -0,0 +1,15 @@
+const {logger} = require("../../../config/winston");
+const {pool} = require("../../../config/database");
+const secret_config = require("../../../config/secret");
+const userProvider = require("./userProvider");
+const userDao = require("./userDao");
+const baseResponse = require("../../../config/baseResponseStatus");
+const {response} = require("../../../config/response");
+const {errResponse} = require("../../../config/response");
+
+const jwt = require("jsonwebtoken");
+const crypto = require("crypto");
+const {connect} = require("http2");
+
+// Service: Create, Update, Delete 비즈니스 로직 처리
+