서브 도메인을 이용하려고 검색을 하다가 호스팅 서버 뿐만 아니라 서버쪽에서 해줘야 한다는 것을 깨달았다.
먼저 호스팅 서비스에서는 A나 CNAME 레코드를 등록한다.
그리고 해당 요청이 컴퓨터로 들어오면 헤더의 host를 기반으로 리벅스 프록시 설정에 따라 포트를 전달한다.
먼저 프록시가 뭔지, 리버스 프록시가 뭔지 배운 것부터 적어본다.
프록시(proxy)는 '대리인' 혹은 '대리'라는 뜻이다.
프록시는 사용자 입장에서 중계를 해주는 서버이다.
사용자가 프록시에 요청을 보내면, 프록시는 사용자가 원하는 실제 목적지에 해당 내용을 받아 전달한 뒤, 그 요청을 받아 사용자에게 전달해준다.
비유 하자면 편의점 택배과 같다.
우리가 택배를 전달하고 싶은 곳은 편의점이 아니라 배송업체이다.
편의점에 우편물을 맡기면, 이를 편의점에서 대신 배송업체에 전달하고 응답을 돌려준다.
프록시는 클라이언트에서 외부 서버로 가는 요청을 대신해 전해주는 거라면, 리버스 프록시는 내부 서버에서의 분배 과정이다.
위에서 설명한 우편물이 배송업체로 가는 과정이 프록시라면, 배송물을 각 가정으로 나누어주는 과정이다.
흐름이 정 반대이기에 리버스(reverse)를 붙이게 된 것.
내가 하고싶은건 서브 도메인을 만들고, 요청 헤드에 포함된 host명에 따라 내부 서벙의 포트를 분배하는 과정이므로 리버스 프록시이다.
과정은 생각보다 간단했다.
nginx 설치 -> server.js 제거 및 nextjs의 package.json 원상복귀
-> nginx.conf 변경 -> nextjs, nginx 시작
chatgpt에게 모르는건 질문해가면서 하니 대락 15~20분 정도 걸린 듯 하다.
역시 코딩은 몰라도 일단 해보고 시작해야 하는 듯 하다.
항상 생각하지만 이 맛에 맥북 쓴다.
homebrew만 깔려 있다면 잡다한 설정 없이 설치는 한방이다.
그리고 바로 서비스를 등록해준다.
brew install nginx
brew services start nginx
원래 사용하던 서버의 함수는 아래와 같다.
이건 그냥 지워줘도 되지만 혹시나 몰라 백업해 두었다.
const https = require("https");
const http = require("http");
const { parse } = require("url");
const next = require("next");
const fs = require("fs");
const dev = process.env.NODE_ENV !== "production";
const PORT_HTTPS = 8000;
const PORT_HTTP = 3000;
const hostname = "localhost"; // or 커스텀 도매인
const app = next({ dev, hostname, PORT: PORT_HTTPS });
const handle = app.getRequestHandler();
const httpsOptions = {
key: fs.readFileSync(
"privkey 경로",
"utf8"
), // 발급한 ssl인증키를 "readFileSync"로 읽기
cert: fs.readFileSync(
"fullchain 경로",
"utf8"
),
};
async function startServer() {
try {
await app.prepare();
const httpsServer = https.createServer(httpsOptions, (req, res) => {
const parsedUrl = parse(req.url, true);
handle(req, res, parsedUrl);
});
httpsServer.listen(PORT_HTTPS, () => {
console.log(`> Ready on https://${hostname}:${PORT_HTTPS}`);
});
const httpServer = http.createServer((req, res) => {
res.writeHead(301, { Location: `https://${req.headers.host}${req.url}` });
res.end();
})
httpServer.listen(PORT_HTTP, () => {
console.log(`> Ready on http://${hostname}:${PORT_HTTP}`);
})
} catch (err) {
console.error("Error starting the server:", err);
}
}
startServer();
그리고 package.json에서 script 부분을 아래와 같이 변경했다.
"scripts": {
"dev": "nodemon server.js",
"build": "next build",
"start": "NODE_ENV=production nodemon server.js",
"lint": "next lint",
},
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
},
이렇게 한 뒤 sudo yarn dev를 하면 http://localhost:3000 에서 자동으로 서버가 실행된다.
이제 기본적인 준비는 끝났으니 nginx를 건드려보자.
chatgpt는 conf 파일을 아래처럼 나노로 편집하랬는데 답답해서 참을 수 없었다.
nano /opt/homebrew/etc/nginx/nginx.conf
해당 경로로 쳐들아거 vscode로 파일을 열었다.
그리고 내부에 있는 내용은 모두 지워버리고 지피티 형님이 주신 내용을 복붙했다.
자세한 내용은 주석을 참고해주길 바란다.
# 프로세서 수는 자동. 저부하라면 1도 괜찮음.
# events에서 connections의 수는 처리할 연결 수.
# 프로세서 수 * 커넥션 수 = 동시 처리가능한 연결 수.
worker_processes auto;
events {
worker_connections 1024;
}
# http요청에 대한 처리를 함. mail{}, stream{} 등 다양한 유형을 처리 가능.
http {
# 컨텐츠 확장자에 따라 MIME 타입을 지동으로 지정해 줌.
include mime.types;
# server 설정을 지정할 가상 호스트 설정
include /opt/homebrew/etc/nginx/sites-enabled/*;
# MIME 설정을 모를 때 기본으로 쓸 MIME 타입
default_type application/octet-stream;
# os의 커널 기능으로 파일 전송기능 향상. 정적 파일을 서비스할 때 사용.
sendfile on;
# 클라이언트와 연결을 유지하는 시간. 불필요한 TCP 연결을 줄여 서버 성능 향상.
keepalive_timeout 65;
# 이 안에 server 블럭을 넣어주면 됨.
# 첫번째는 http 요청을 https로 리다이렉션
server {
listen 80;
server_name www.earthscience.kr earthscience.kr;
return 301 https://$host$request_uri;
}
# 두번째는 https 요청과 ssl 인증서, 키 위치 등을 포함.
server {
listen 443 ssl;
server_name www.earthscience.kr earthscience.kr;
ssl_certificate /etc/letsencrypt/live/www.earthscience.kr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.earthscience.kr/privkey.pem;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
}
이제 nextjs에서 파일 빌드 -> 서버 시작 후 nginx를 실행하면 된다.
sudo yarn build
sudo yarn start
sudo nginx # nginx를 아직 시작 안했다면
처음 nginx에 대해 들었을 때는 또 새로운 언어를 입문해야 할지도 모른다는 중압감에 넘어가지 않았다.
막상 해보니 server.js를 설정하는 것보다 훨씬 쉽다.
역시 프로그래밍은 일단 시작하고 보는게 맞는 것 같다.
그런데...
밈을 찾다가 nginx보다 좋다는 caddy를 찾아버렸네?
또 다시 여행이 시작될 것 같다.