- express ํ๋ก์ ํธ ํด๋ ์์ฑ
- ejs ์ ์ฉ
$ express --ejs ํ๋ก์ ํธ์ด๋ฆ
- ์ค์ ํ๋ก์ ํธ ์งํ ์์๋, .gitignore์
#### ์ง์ ์ค์ ํ Gitignore ####
๋ก ์ฃผ์ ์ฒ๋ฆฌ ๋์ด ์๋ ๋ฐ ๋ถ๋ถ์ ์ฝ๋์ ๋ํด ์ฃผ์์ฒ๋ฆฌ ํด์ ํ๊ธฐ - .env ์ฃผ์ ์ฒ๋ฆฌ ๋์ด ์๋ ๋ถ๋ถ ํด์ ํ๊ธฐ
- index.js๋ฅผ ํ์ฉํ ๋ผ์ฐํ ํด๋ ๋๋๊ธฐ
- app.js ํ์ผ
- routes ํด๋
- ํน์ ํค๋ฅผ ํ๋์ฝ๋ฉํ๋ฉด ์์ค ์ฝ๋๊ฐ ์ ์ถ๋์์ ๋ ํค๋ ๊ฐ์ด ์ ์ถ๋๋ฏ๋ก ๋ณ๋๋ก ๊ด๋ฆฌํด์ผ ํ๋ค. ์ด๋ฅผ ์ํ ํจํค์ง๊ฐ dotenv์ด๋ค. ๋น๋ฐํค๋ .env๋ผ๋ ํ์ผ์ ๋ชจ์๋๊ณ , dotenv๊ฐ .env ํ์ผ์ ์ฝ์ด process.env(ํ๊ฒฝ๋ณ์) ๊ฐ์ฒด์ ๋ฃ๋๋ค.
$ npm i dotenv
- app.js ํ์ผ
- .env ํ์ผ
$ npm i helmet hpp
- app.js ํ์ผ
- log/server/combined ํด๋์ 1์๊ฐ ๋จ์๋ก ๋ก๊ทธ ํ์ผ์ด ๋จ์ ๊ฒ์ด๋ค.
- log/server/error ํด๋์ ํ๋ฃจ ๋จ์๋ก ๋ก๊ทธ ํ์ผ์ด ๋จ์ ๊ฒ์ด๋ค.
$ npm run production
์ผ๋ก ์คํ์ํฌ ๋, ๋ก๊ทธ๊ฐ ๊ธฐ๋ก๋๋ค.- log/server/combined ํด๋์ log/server/error ํด๋์ ๋ก๊ทธ ํ์ผ๋ค์ด ์ ์ฅ๋๋ค.
a) ์ผ๋ฐ ๋ผ์ฐํ ํต์ ์ ์ ์ฅ๋๋ ๋ก๊ทธ์ ํํ
- ํํ : ${๋ ์ง ๋ฐ ์๊ฐ} [${๋ก๊ทธ ์ข ๋ฅ}] ์์ฒญ์ ip = ${์์ฒญ์ ip} || ${HTTP Method ์ข ๋ฅ} ${HTTP ํต์ ์ฃผ์} ${์๋ต ์ฝ๋} ${์๋ต ์๊ฐ} || ์ด์ url = ${์ด์ url}
2020-03-02 11:04:47 [INFO] ์์ฒญ์ ip = 211.111.111.11:34974 || GET /webview/kakao_map 304 140.744 ms || ์ด์ url = -
b) ์๋ฌ ๋ฐ์ ์ ์ ์ฅ๋๋ ๋ก๊ทธ์ ํํ
2020-02-28 08:38:21 [ERROR] Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
$ npm i winston winston-daily-rotate-file
- app.js ํ์ผ
- module/winston.js ํ์ผ
- ๋ฐ์ํ ์๋ฌ์ ๋ํด์ winston์ ํ์ฉํด ๋ก๊ทธ ํ์ผ๋ก ๊ธฐ๋ก
- ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ ์๋ฌ ์ฒ๋ฆฌ ๊ฐ๋ฅ
- sequelize transaction ์๋ฌ ์ฒ๋ฆฌ ๊ฐ๋ฅ
- axios๋ก ์ธํ ์๋ฌ ์ฒ๋ฆฌ ๊ฐ๋ฅ
- token์ ๋ฐ๋ฅธ ์๋ฌ ์ฒ๋ฆฌ ๊ฐ๋ฅ
- GraphQL ํต์ ์๋ฌ ์ฒ๋ฆฌ ๊ฐ๋ฅ
// ํ์ผ๋ช
: routes/daly/v2/region/region.js
var express = require('express');
var router = express.Router();
const error_handling = require('../../../../module/error_handling');
router.get('/', async (req, res) => {
try {
...
} catch (err) {
error_handling.normal(err, res, transaction);
}
});
module.exports = router;
- module/error_handling.js
- ํด๋ผ์ด์ธํธํํ ์ผ๊ด๋ ํํ๋ก ์๋ต ์ฝ๋์ ์๋ต ๋ฉ์์ง๋ฅผ ๋ณด๋ด๊ธฐ ์ํ ๋ชจ๋
var express = require('express');
var router = express.Router();
const error_handling = require('../../../../module/error_handling');
router.get('/', async (req, res) => {
try {
...
res.status(200).json(response(resMessage.EXPIRED_TOKEN));
} catch (err) {
...
}
});
module.exports = router;
- module/response/index.js
- module/response/message.js
$ npm i sequelize
- config/sequelize/dbConfig.json ํ์ผ์์ ์ฐ๊ฒฐ์ํฌ DB ๊ด๋ จ ์ ๋ณด๋ฅผ ์ ๋ ฅํด์ผ ํ๋ค.
- models ํด๋์์ ์ ์ํ DB ํ ์ด๋ธ์ ๋ํด์ ์ ์ธํด์ฃผ์ด์ผ ํ๋ค.
var express = require('express');
var router = express.Router();
const { Sequelize, Sequelize: { Op }, sequelize, User, Store, Store_img,
Product, Product_img, Banner, Payment_history, Category, Category_product, Hashtag,
Hashtag_product, Precaution, Banner_btn, Banner_sub_img } = require('../../../../models');
router.delete('/', async(req, res) => {
try {
...
const result = await Store.destroy({
where: {
id
},
transaction
})
...
} catch(err) {
...
}
});
module.exports = router;
- app.js ํ์ผ
- models ํด๋
- config/sequelize/dbConfig.json ํ์ผ
- config/awsconfig.json์ AWS IAM์ access key์ access key secret์ ์ ๋ ฅํด์ผ ํ๋ค.
- config/multer.js์ S3 bucket ์ด๋ฆ์ ์ ๋ ฅํด์ผ ํ๋ค.
- ๋ผ์ฐํ ์์ multer์ ๋ํ ์์ธํ ์ฌ์ฉ๋ฒ์ multer Docs์ ์ฐธ๊ณ ํด๋ผ.
var express = require('express');
var router = express.Router();
const response = require('../../../module/response');
const resMessage = require('../../../module/response/message');
const upload = require('../../../config/multer');
const logger = require('../../../config/winstonConfig');
// ์ํ ๋ฑ๋ก
router.post('/', jwt.isLoggedIn, (req, res, next) => {
upload.array('images', 10)(req, res, function (err) {
if (err) {
if (err.code === 'LIMIT_FILE_SIZE') {
// ํ์ผ ์ ํ ์ฉ๋์ ๋์ ๊ฒฝ์ฐ
logger.log('error', err.stack);
res.status(200).json(response(resMessage.LIMIT_FILE_SIZE));
} else {
// console.log('multer์ ์์์น ๋ชปํ ์๋ฌ');
logger.log('error', err.stack);
res.status(200).json(response(resMessage.INTERNAL_SERVER_ERROR));
}
} else {
next()
}
})}, async(req, res) => {
try {
...
} catch(err) {
...
}
});
module.exports = router;
- config/awsconfig.json
- config/multer.js
- module/auth/jwt.js ํ์ผ์์ process.env.JWT_SECRET, process.env.JWT_REFRESH_TOKEN_SECRET์ ์ธ์ํ ์ ์๋๋ก .env ํ์ผ์ ๋ณ์๋ฅผ ์ ์ธํด์ค์ผ ํ๋ค.
var express = require('express');
var router = express.Router();
const jwt = require('../../../module/auth/jwt');
router.get('/', jwt.isLoggedIn, async(req, res) => {
try {
...
} catch(err) {
...
}
});
module.exports = router;
- module/auth/jwt.js
- ์ํธํ ์ํค๋ ๋ฐ ์ฌ์ฉ (์ฃผ๋ก ๋น๋ฐ๋ฒํธ๋ฅผ ์ํธํ ์ํค๋ ๋ฐ ์ฌ์ฉ)
var express = require('express');
var router = express.Router();
const response = require('../../../module/response');
const resMessage = require('../../../module/response/message');
const cryptoPassword = require('../../../module/auth/cryptoPassword');
const jwt = require('../../../module/auth/jwt');
const { sequelize, User, Marketing } = require('../../../models');
const logger = require('../../../config/winstonConfig');
const error_handling = require('../../../module/error_handling');
// ๋ก๊ทธ์ธ
router.post('/', async(req, res) => {
try {
// ํธ๋์ญ์
์ฒ๋ฆฌ
var transaction = await sequelize.transaction();
let { email, password } = req.body;
// Params๋ Body๊ฐ์ ํ์์ ์ผ๋ก ๋ค์ด์์ผ ํ๋ ๊ฐ์ด ๋ค์ด์ค์ง ์์ ๊ฒฝ์ฐ
if (!email || !password) {
res.status(200).json(response.failure(resMessage.NULL_VALUE));
} else {
// users์ user_id, email, name ์ ๋ณด ๋ถ๋ฌ์ค๊ธฐ
const result = await User.findOne({
where: {
email,
provider: 'local'
},
attributes: ['id', 'name', 'email', 'birth', 'gender', 'createdAt', 'updatedAt', 'deletedAt', 'salt', 'password', 'role'],
include: [{
model: Marketing,
attributes: ['is_third_party_agreement', 'is_event_alarm']
}],
transaction
});
// console.log('ํ
์คํธ : ', result);
// ์กด์ฌํ์ง ์๋ ์์ด๋์ ๊ฒฝ์ฐ
if (result === null) {
res.status(200).json(response.success(resMessage.NULL_USER));
// ์กด์ฌํ๋ ์์ด๋์ธ ๊ฒฝ์ฐ
} else {
const salt = result.dataValues.salt;
const db_hashed_password = result.dataValues.password;
const hashed_password = await cryptoPassword.hashedPassword(password, salt);
// ํจ์ค์๋๊ฐ ์ผ์นํ์ง ์๋ ๊ฒฝ์ฐ
if (db_hashed_password !== hashed_password) {
res.status(200).json(response.success(resMessage.INVALID_PASSWORD));
// ํจ์ค์๋๊ฐ ์ผ์นํ๋ ๊ฒฝ์ฐ -> ๋ก๊ทธ์ธ ์ฑ๊ณต
} else {
const token = jwt.sign(result.dataValues);
const refresh_token = jwt.refresh_token_sign(result.dataValues);
// ๋ฆฌํ๋ ์ ํ ํฐ ์ ์ฅ
const response_ = await User.update({
refresh_token
}, {
where: { id: result.dataValues.id },
transaction
});
// console.log('๋ฆฌํ๋ ์ ํ ํฐ ์ ์ฅ ์ฌ๋ถ : ', response_);
// ํด๋ผ์ด์ธํธํํ
ํ ํฐ๊ณผ ๋ฆฌํ๋ ์ ํ ํฐ ์ ์ก
let data = {
token,
refresh_token
};
res.status(200).json(response.success(resMessage.LOGIN_SUCCESS, data));
}
}
}
await transaction.commit();
} catch(err) {
error_handling.normal(err, res, transaction);
}
});
module.exports = router;
- module/auth/cryptoPassword.js