코드의 구조를 간단하게 하기 위해 공통 기능을 미들웨어로 추출하고, 각 기능을 모듈화할 수 있습니다. 아래는 개선된 버전으로, 공통 기능을 미들웨어로 분리하고 라우트 핸들러를 별도의 파일로 분리한 예입니다.
1. 환경 변수 설정 파일 (.env)
DB_URL=mongodb+srv://hjw1191:zxc123@hjw1191.zaqklsn.mongodb.net/?retryWrites=true&w=majority&appName=hjw1191
PORT=8080
SESSION_SECRET=세션 암호화 비번~~
2. 서버 설정 파일 (server.js)
// server.js
const express = require('express');
const app = express();
const session = require('express-session');
const passport = require('passport');
const MongoStore = require('connect-mongo');
const methodOverride = require('method-override');
const path = require('path');
require('dotenv').config();
require('./config/passport'); // 패스포트 설정 파일 불러오기
const dbClient = require('./config/db'); // DB 설정 파일 불러오기
app.use(express.static(path.join(__dirname, 'public')));
app.set('view engine', 'ejs');
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride('_method'));
app.use(session({
resave: false,
saveUninitialized: false,
secret: process.env.SESSION_SECRET,
cookie: { maxAge: 1000 * 60 },
store: MongoStore.create({
mongoUrl: process.env.DB_URL,
dbName: 'forum',
})
}));
app.use(passport.initialize());
app.use(passport.session());
// 라우터 설정
const indexRouter = require('./routes/index');
const userRouter = require('./routes/user');
const postRouter = require('./routes/post');
app.use('/', indexRouter);
app.use('/user', userRouter);
app.use('/post', postRouter);
// 서버 실행
dbClient.connect().then(() => {
app.listen(process.env.PORT, () => {
console.log(`http://localhost:${process.env.PORT} 에서 서버 실행중`);
});
}).catch((err) => {
console.log(err);
});
3. 데이터베이스 설정 파일 (config/db.js)
const { MongoClient } = require('mongodb');
const url = process.env.DB_URL;
let db;
const client = new MongoClient(url, { useNewUrlParser: true, useUnifiedTopology: true });
module.exports = {
connect: async () => {
await client.connect();
db = client.db('forum');
console.log('DB연결성공');
},
getDb: () => db
};
4. 패스포트 설정 파일 (config/passport.js)
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');
const dbClient = require('./db');
passport.use(new LocalStrategy(async (username, password, done) => {
const db = dbClient.getDb();
const user = await db.collection('user').findOne({ username: username });
if (!user) {
return done(null, false, { message: '아이디 DB에 없음' });
}
const isMatch = await bcrypt.compare(password, user.password);
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: '비번불일치' });
}
}));
passport.serializeUser((user, done) => {
done(null, { id: user._id, username: user.username });
});
passport.deserializeUser(async (user, done) => {
const db = dbClient.getDb();
const result = await db.collection('user').findOne({ _id: new ObjectId(user.id) });
if (result) {
delete result.password;
return done(null, result);
} else {
return done(null, false);
}
});
5. 라우터 파일 (routes/index.js)
// routes/index.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '../public/index.html'));
});
module.exports = router;
6. 사용자 관련 라우터 파일 (routes/user.js)
// routes/user.js
const express = require('express');
const router = express.Router();
const bcrypt = require('bcrypt');
const passport = require('passport');
const dbClient = require('../config/db');
router.get('/login', (req, res) => {
res.render('login.ejs');
});
router.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/user/login'
}));
router.get('/signup', (req, res) => {
res.render('signup.ejs');
});
router.post('/signup', async (req, res) => {
const db = dbClient.getDb();
const hashedPassword = await bcrypt.hash(req.body.password, 10);
await db.collection('user').insertOne({
username: req.body.username,
password: hashedPassword
});
res.redirect('/');
});
module.exports = router;
7. 게시글 관련 라우터 파일 (routes/post.js)
// routes/post.js
const express = require('express');
const router = express.Router();
const { ObjectId } = require('mongodb');
const dbClient = require('../config/db');
router.get('/list', (req, res) => {
res.redirect('/post/list/1');
});
router.get('/list/:id', async (req, res) => {
const db = dbClient.getDb();
const result = await db.collection('post').find()
.skip((req.params.id - 1) * 5).limit(5).toArray();
const currentId = parseInt(req.params.id, 10);
res.render('list.ejs', { 글목록: result, currentId: currentId });
});
router.get('/write', (req, res) => {
res.render('write.ejs');
});
router.post('/add', async (req, res) => {
const db = dbClient.getDb();
const title = req.body.title ? req.body.title.trim() : '';
if (title === '') {
res.send('제목을 입력하지 않았습니다.');
} else {
await db.collection('post').insertOne({ title: title, content: req.body.content });
res.redirect('/post/list');
}
});
router.get('/detail/:id', async (req, res) => {
const db = dbClient.getDb();
const result = await db.collection('post').findOne({ _id: new ObjectId(req.params.id) });
res.render('detail.ejs', { result: result });
});
router.get('/edit/:id', async (req, res) => {
const db = dbClient.getDb();
const result = await db.collection('post').findOne({ _id: new ObjectId(req.params.id) });
res.render('edit.ejs', { result: result });
});
router.put('/edit', async (req, res) => {
const db = dbClient.getDb();
await db.collection('post').updateOne({ _id: new ObjectId(req.body.id) },
{ $set: { title: req.body.title, content: req.body.content } }
);
res.redirect('/post/list');
});
router.delete('/delete', async (req, res) => {
const db = dbClient.getDb();
await db.collection('post').deleteOne({ _id: new ObjectId(req.query.docid) });
res.send('삭제완료');
});
module.exports = router;
'기타' 카테고리의 다른 글
docker (0) | 2024.08.13 |
---|---|
배포하기>https://console.firebase.google.com (0) | 2024.08.13 |
팁>h1 한줄에 띄어쓰기 , 탭 (0) | 2024.08.07 |
로그인 연동 - 구글 (0) | 2024.08.07 |
만든 사이트 발행하기 (0) | 2024.07.10 |