Next.js를 Express 서버와 함께 실행시키는 방법입니다.
npx create-next-app@latest
# √ What is your project named? ... client
# √ Would you like to use TypeScript with this project? ... No
# √ Would you like to use ESLint with this project? ... Yes
기존 폴더 구조 | src 사용 |
---|---|
npm install --save express dotenv
# 서버 자동 재시작을 위한 패키지
npm install --save-dev nodemon
Express 서버파일을 작성합니다.
|
// server.js
const express = require('express');
const dotenv = require('dotenv');
dotenv.config({ path: '.env' }); // 환경변수 사용
const app = express();
const port = process.env.PORT; //.env 파일에서 설정해준다
app.set('port', port);
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use('/', (req, res, next) => {
res.send('hello!');
});
app.listen(app.get('port'), () => {
console.log(`Express server listen port:${port}`);
console.log(`http://localhost:${port}`);
});
server/server.js 파일에 next.js 서버 설정을 추가합니다.
# .env
SERVER_PORT=[YOUR_PORT]
// server.js
const express = require('express');
const dotenv = require('dotenv');
dotenv.config({ path: '.env' }); // 환경변수 사용
const path = require('path');
/** Create Express */
const app = express();
/** Next.js 모듈 가져오기 */
const next = require('next');
const { parse } = require('url');
/** Next.js 설정 */
const port = process.env.SERVER_PORT;
/**
* 개발환경이아니라면 dev 옵션을 false 로 설정하고
* 서버 시작전에 next build 를 실행해준다.
*/
const nextApp = next({ dev: true, port });
const handle = nextApp.getRequestHandler();
nextApp
.prepare()
.then(() => {
/** Express Settings */
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
/** static 경로 설정 */
app.use(express.static(path.join(__dirname, '../', 'public')));
/** Express Router Settings */
app.use('/api', (req, res, next) => {
res.send('hello!');
});
/** Next.js Routing */
app.get('/', (req, res) => {
const parsedUrl = parse(req.url, true);
const { pathname, query } = parsedUrl;
nextApp.render(req, res, pathname, query);
});
app.get('*', (req, res) => {
return handle(req, res);
});
app.listen(port, () => {
console.log(`Express server listen port:${port}`);
console.log(`http://localhost:${port}`);
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
module.exports = app;
package.json 파일의 시작명령어 script를 Express를 사용하도록 수정합니다.
// package.json
...,
"scripts": {
"dev": "node server/server.js",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
...
// package.json
...,
"scripts": {
"dev": "nodemon server/server.js",
},
...
// nodemon.json
{
"watch": ["server/server.js", "server/src"],
"exec": "node server/server.js",
"ext": "js json"
}
// package.json
...,
"scripts": {
"dev": "nodemon",
},
...
모든 설정이 완료되었습니다!
이제 시작명령어를 입력하고 Express를 Custom 서버로 사용하는 Next.js를 시작해보세요.
npm run dev
좋은 글 잘 읽었습니다.
다만 Express.js 5.x이 출시되면서 일부 변경사항이 있어 말씀드립니다.
Express.js 5.x부터 경로에 와일드카드(*) 사용이 제한되었기 때문에, 위 코드가 Express.js 5.x 환경에서 실행될 경우 TypeError가 발생할 수 있습니다.
해결 방법은 "app.get('*', (req, res) => {" 부분을 "app.use((req, res) => {" 로 수정해 미들웨어로 바꾸면 정상적으로 동작합니다.
이 문제의 원인은 Express.js의 버전 업그레이드와 함께 사용되는 패키지들의 변화 때문입니다.
특히, router 2.0.0 패키지가 도입되면서 path-to-regexp 8.0.0이 적용되었는데, 이로 인해 와일드카드(*)의 의미가 변경되었습니다.
Express.js 4.x까지는 path-to-regexp 0.1.12 버전을 사용해 단독 와일드카드가 허용되었으나, Express.js 5.x에서는 더 이상 사용할 수 없습니다.
제가 위 코드를 직접 실행해보진 않았지만, 참고 자료로 활용했으며 이 글이 Next.js custom-server와 Express.js를 검색하면 가장 먼저 보이는 글이라 정보를 공유합니다.
참고