NextJS를 사용하여 프로젝트를 진행하던 도중 도메인이 결정되었고 서브도메인을 사용하게 되었습니다.
생각지도 못하게 서브 도메인이 붙어서 NextJS를 이제 막 사용해보기 시작한 저로서는 매우 당황스러웠습니다.
서브도메인이란 DNS 계층에서 주 도메인을 보조하는 도메인입니다. 우리가 흔히 사용하는 네이버를 예로 들어보면
에서 굵게 표시된 부분으로 서브도메인을 통해 다른 서비스에 사용자가 접근할 수 있죠.
NextJS에서는 pages
디렉토리 내 폴더 및 파일 이름대로 라우팅됩니다.
즉 디렉토리 구조가 아래와 같이 구성되어 있고 사용하는 도메인이 hyeonqyu.com
이라고 한다면
📂pages
📂members
🗒️index.tsx
🗒️login.tsx
📂accounts
🗒️index.tsx
🗒️user.tsx
hyeonqyu.com/members
hyeonqyu.com/members/login
hyeonqyu.com/accounts
hyeonqyu.com/accounts/user
와 같은 URL로 페이지에 접근할 수 있을 거에요.
그러나 해야 하는 것은
hyeonqyu.com/members
hyeonqyu.com/members/login
hyeonqyu.com/accounts
hyeonqyu.com/accounts/user
이 URL이 아니라
members.hyeonqyu.com
members.hyeonqyu.com/login
accounts.hyeonqyu.com
accounts.hyeonqyu.com/user
이 URL이었습니다.
그러나 NextJS의 pages 폴더만으로는 이처럼 구현할 수 없었죠.
그래서 서브도메인마다 각각 다른 NextJS 앱을 구동시켜야 하는건가 하는 생각이 들었지만 서브도메인 하나하나가 그렇게 덩치가 크지 않음에도 불구하고 여러 서버를 띄우면 그만큼 서버 비용도 늘어나고.. 관리해야 할 프로젝트도 늘어나기에..
하나의 앱으로 여러 서브도메인에 라우팅할 수 있도록 만드는 것이 베스트였습니다.
열심히 구글링한 결과 https://github.com/dcangulo/nextjs-subdomain-example 이 레포지토리를 찾을 수 있었습니다.
먼저 package.json
의 script 부분을 보면 아래와 같이 되어있는 것을 볼 수 있습니다.
"dev": "node server.js",
"build": "next build",
"start": "NODE_ENV=production node server.js"
일반적으로 create next app으로 프로젝트를 생성하면 dev
는 next dev, start
는 next start로 작성되어 있지만 여기서는 node server.js로 작성되어 있습니다.
루트에 커스텀 서버 스크립트인 server.js
가 있는데 여기를 수정하면 원하는대로 서브도메인을 사용할 수 있었습니다.
const express = require('express');
const next = require('next');
const port = process.env.PORT || 3000;
const app = next({ dev: process.env.NODE_ENV !== 'production' });
이 server.js에서 next를 실행시키는 것으로 보이는군요.
app.prepare().then(() => {
const mainServer = express();
const membersServer = express();
const accountsServer = express();
...
});
다음으로
members.hyeonqyu.com
accounts.hyeonqyu.com
이렇게 두개의 서브도메인을 사용하기 위해서 express 서버를 3개 만듭니다.
membersServer
는 members
서브도메인, accountsServer
는 accounts
서브 도메인을 위해 생성했어요.
app.prepare().then(() => {
...
membersServer.get('/', (req, res) => {
return app.render(req, res, '/members', req.query);
});
membersServer.get('/*', (req, res) => {
return app.render(req, res, `/members${req.path}`, req.query);
});
membersServer.all('*', (req, res) => {
return handle(req, res);
});
accountsServer.get('/', (req, res) => {
return app.render(req, res, '/accounts', req.query);
});
accountsServer.get('/*', (req, res) => {
return app.render(req, res, `/accounts${req.path}`, req.query);
});
accountsServer.all('*', (req, res) => {
return handle(req, res);
});
});
membersServer에 들어오는 요청은 /members 하위 페이지를 렌더링하고 accountsServer에 들어오는 요청은 /accounts 하위 페이지를 렌더링하도록 합니다.
app.prepare().then(() => {
...
mainServer.use(vhost('members.midasuser.com', membersServer));
mainServer.use(vhost('accounts.midasuser.com', accountsServer));
mainServer.listen(port, (err) => {
if (err) {
throw err;
}
});
});
가상호스트 라이브러리인 vhost를 사용해 서브도메인을 등록해주면 됩니다.
서브도메인이 잘 적용되었는지 로컬에서 확인해보려면 hosts
파일을 수정해야해요.
hosts
파일은 C:\Windows\System32\drivers\etc
에 있으며 파일을 열어 다음 내용을 추가합니다.
127.0.0.1 members.hyeonqyu.com
127.0.0.1 accounts.hyeonqyu.com
npm run dev
로 앱을 실행하여 members.hyeonqyu.com:3000
에 접속합니다.
/members/index.tsx(jsx) 파일에 작성한 내용이 렌더링된다면 성공적으로 적용된 것입니다.