기타

기타 팁> 라우터를 구분해서 사용하면 용이하다

연습노트 2024. 7. 26. 22:10

코드의 구조를 간단하게 하기 위해 공통 기능을 미들웨어로 추출하고, 각 기능을 모듈화할 수 있습니다. 아래는 개선된 버전으로, 공통 기능을 미들웨어로 분리하고 라우트 핸들러를 별도의 파일로 분리한 예입니다.

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