본문 바로가기
Node.js

익스프레스 웹 서버 만들기 - 라우터 분리하기

by Programmer.Junny 2025. 1. 15.

1. 라우터 분리란?

 

  • 기능, 도메인(업무 영역), 리소스 기준 등으로 라우트를 분리해 놓는 방식이다.
  • 예: user 관련 엔드포인트는 routes/user.js, posts 관련 엔드포인트는 routes/post.js 등에 배치.
  • 장점
    • 코드 구조가 깔끔해진다.
    • 여러 파일로 나누어 작성하므로 팀 협업 시 충돌을 줄일 수 있다.
    • 유지보수가 쉬워진다. (수정, 추가가 용이)

 

2. 라우터 분리 예시

📁 my-project
 ┣ 📁 routes
 ┃ ┣ 📜 user.js
 ┃ ┗ 📜 index.js
 ┣ 📜 app.js
 ┗ ...

위와 같은 구조로 app.js에서 user와 index 파일로 분리 후 라우터를 분리해보자.

const express = require('express');

const router = express.Router();

//Get / 라우터
router.get('/', (req, res) => {
    res.send('Hello, Express');
});

module.exports = router;

index.js 파일 내부에 위와 같이 작성하였다.

여기서 핵심은 express.Router()와 이렇게 받아온 router 객체를 다시 module.exports 로 넘겨준 것이다.

const express = require('express');

const router = express.Router();

//Get / 라우터
router.get('/', (req, res) => {
    res.send('Hello, User');
});

module.exports = router;

마찬가지로 user.js 파일

const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const dotenv = require('dotenv');
const path = require('path');

dotenv.config();
const indexRouter = require('./routes/index');
const userRouter = require('./routes/user');

const app = express();
app.set('port', process.env.PORT || 3000);

app.use(morgan('dev'));
// app.use('/', express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
  resave: false,
  saveUninitialized: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false,
  },
  name: 'session-cookie',
}));

const multer = require('multer');
const fs = require('fs');

try {
  fs.readdirSync('uploads');
} catch (error) {
  console.error('uploads 폴더가 없어 uploads 폴더를 생성합니다.');
  fs.mkdirSync('uploads');
}
const upload = multer({
  storage: multer.diskStorage({
    destination(req, file, done) {
      done(null, 'uploads/');
    },
    filename(req, file, done) {
      const ext = path.extname(file.originalname);
      done(null, path.basename(file.originalname, ext) + Date.now() + ext);
    },
  }),
  fileFilter: (req, file, done) => {
    // 이미지 파일만 허용
    if (/^image\/(jpeg|png|gif)$/.test(file.mimetype)) {
        done(null, true);
    } else {
        done(new Error('이미지 파일만 업로드 가능합니다.'), false);
    }
  },
  limits: { fileSize: 5 * 1024 * 1024 },
});

app.get('/upload', (req, res) => {
  res.sendFile(path.join(__dirname, 'multipart.html'));
});

// app.post('/upload', upload.array('image'), (req, res) => {
// //   console.log(req.file);
//     console.dir(req.files);
//   res.send('ok');
// });

app.post('/upload', (req, res) => {
    upload.array('image')(req, res, (err) => {
        if(err) {
            // 에러 발생 시 -> error.html 응답
            return res.sendFile(path.join(__dirname, 'public', 'error.html'));
        }

        if(!req.files || req.files.length == 0) {
            return res.sendFile(path.join(__dirname, 'public', 'emptyFiles.html'));
        }

        // 성공 시
        res.sendFile(path.join(__dirname, 'public', 'success.html'));
    });
});

app.use('/', indexRouter);
app.use('/user', userRouter);

app.get('/', (req, res, next) => {
  console.log('GET / 요청에서만 실행됩니다.');
  next();
}, (req, res) => {
  throw new Error('에러는 에러 처리 미들웨어로 갑니다.')
});

app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).send(err.message);
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '번 포트에서 대기 중');
});
const indexRouter = require('./routes/index');
const userRouter = require('./routes/user');
app.use('/', indexRouter);
app.use('/user', userRouter);

지난 Node.js 기본 모듈 (CommonJS, ES모듈) 포스팅에서 알 수 있듯이 CommonJS 모듈을 통해 index.js와 user.js 를 가져온다.

그렇게 설정된 객체들은 app.use() 로 경로 설정 후, 해당 객체를 아규먼트로 구성한다.

3. 주의 사항

3.1. 각 분리된 파일의 라우터 경로를 '/'로 설정해야 한다.

//Get / 라우터
router.get('/', (req, res) => {
    res.send('Hello, Express');
});

각 파일들(index.js, user.js) 에는 위와 같이 라우터가 구성되어 있는데, 실제 경로는 app.js의 use()에서 입력하므로 각 파일에서는 라우터 경로를 '/'로 설정하여야 한다.

만약 다른 경로를 입력 시 404에러가 발생한다.

3.2. 미들웨어간 순서를 조심하여야 한다.

미들웨어는 위에서 아래로 실행되며 next() 호출 시 다음 미들웨어로 넘어간다.

app.get('/', (req, res, next) => {
    console.log('GET / 요청에서만 실행됩니다.');
    next();
  }, (req, res) => {
    throw new Error('에러는 에러 처리 미들웨어로 갑니다.')
  });

app.use('/', indexRouter);
app.use('/user', userRouter);

만약 위와 같이 코드가 되어있다면 우리가 실행하고자 하는 use가 아닌 app.get('/' , ~~) 가 실행된다.

app.use('/', express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/user', userRouter);

위와 같이 코드가 설정되있다면 static 모듈만이 실행된다.

최근댓글

최근글

skin by © 2024 ttuttak