개발자
류준열
Nginx로 Reverse Proxy 하여 백엔드 띄우기
바이브코딩으로 만든 서비스가 있는데, 어느날 서버가 터졌다. 2주간 차일피일 미루다 살펴보니 인증서가 만료된 것이었다.
서버 url도 사용되지 않는 도메인에 연결되어 있었는데, 제대로 된 도메인 api.calendiary.xyz에 연결하며 인증서를 갱신했다.
두번째 회사에서 폐쇄망 내에서 어플리케이션을 띄웠었는데 그 때 경험이 많이 도움이 되었다. 그때의 경험덕분에 수월하게 처리할 수 있었다.
localhost를 인스턴스 내부 nginx를 이용해 public ip에 포워딩하여 도메인에 연결하기까지의 과정을 기록한다.
인증서를 갱신하며 겪은 과정이지만 인증서 갱신보다는 작업하며 이해한 Reverse Proxy의 원리에 대해 설명한다.
EC2 인스턴스, public ip 세팅, 가비아등 기본적인 사용법을 따로 설명하진 않는다.
백엔드 서버(express)는 localhost
백엔드 서버는 기본적으로 http://localhost:4000 같은 내부 포트에서 동작하며 외부에서 접근가능하도록 노출하지 않는다. 그리고 백엔드 서버는 비즈니스 로직만 수행한다.
이 비즈니스 로직을 띄우기 위해 인스턴스 내 Nginx를 이용하여 localhost를 public ip로 포워딩했다.
백엔드 서버
express 서버는 다음과 같이 localhost:4000에 띄워져있다.
그리고 이 localhost:4000은 외부에서 접근 할 수 없는 내부 포트이다.
const app = express();
const PORT = process.env.PORT || 4000;
const startServer = async () => {
try {
// 서버 시작
app.listen(PORT, () => {
console.log(`🚀 Server is running on port ${PORT}`);
console.log(`🌍 Environment: ${process.env.NODE_ENV}`);
});
} catch (error) {
console.error("❌ Failed to start server:", error);
process.exit(1);
}
};
startServer();
Nginx
Nginx는 인터넷과 백엔드 서버 사이의 Gateway 역할을 한다.
-
HTTP, HTTPS 요청을 받는 역할
- Nginx는 80(HTTP), 443(HTTPS) 포트를 열어두고 외부 트래픽을 받아낸다.
-
내부 서버로 요청을 전달하는 Reverse Proxy
- Nginx는 받은 요청을 내부에서만 접근 가능한 백엔드 서버로 전달한다.
EC2내에서 Nginx의 proxy_pass를 살펴보면 http://localhost:4000에 연결시켜놓은것을 확인 할 수 있다.
> grep -R "proxy_pass" /etc/nginx > /etc/nginx/conf.d/app.conf: proxy_pass http://127.0.0.1:4000;
즉, 외부 요청 Nginx 로 도착하고, Nginx가 해당 요청을 내부 localhost:4000 으로 전달한다.
proxy_pass는 외부 요청을 내부 서버로 전달하는 역할을 한다.
전체 흐름
전체 흐름을 설명하면 다음과 같다.

-
사용자가 https://api.calendiary.xyz/.. 로 요청
-
브라우저가 dns를 조회에 EC2 퍼블릭 ip를 얻고 HTTPS 요청을 EC2로 보낸다.
-
EC2에서 Nginx가 443 포트에서 요청을 받는다.
- 이 과정에서 TLS연결을 만들고 암호화 된 요청을 해독해 내부 처리로 넘긴다.
-
Nginx의 proxy_pass 설정에 따라 내부 백엔드 서버로 다시 요청을 보낸다.
proxy_pass http://127.0.0.1:4000; -
내부 백엔드에서 응답을 Nginx로 보낸다.
- 내부 백엔드는 비즈니스 로직, DB접근, 응답데이터 반환 같은 어플리케이션 레벨 업무만 수행한다.
-
Nginx가 응답을 다시 브라우저에게 전달한다.
HTTPS 적용
https 는 http와 연결할 수 없고 네트워크에서 훔쳐보는 것을 방지하려면 TLS 통신을 하는 https와 연결을 해야 한다.
즉, 백엔드 서버를 https로 띄워야 한다.
Certbot으로 인증서 발급
Let's Encrypt라는 비영리 단체에서 무료 SSL 인증서를 발급해주는데 이를 위해 Certbot을 사용했다.
Certbot은 Nginx 설정 파일을 자동으로 수정하고 pem을 추가하여 HTTPS 통신을 처리한다.
pem은 비대칭키 암호화 알고리즘에 사용되는 비밀키 파일 포멧이다.
이 작업을 통해 알게된건 Let's Encrypt 인증서는 90일짜리 단기 인증서라는 것이다. 그래서 인증서가 만료되었던 것이고 cron 작업이 필요할 것 같다.
HTTPS 에서 Nginx 역할
HTTPS가 켜지면 아래 구조에서 Nginx는 다음 역할을 한다.
- TLS
- 암호화된 요청 복호화
- Express에 평문 HTTP 요청 전달
즉, 실제 HTTPS는 Express가 아니라 Nginx가 처리하고 Express는 서두에 말했듯 비즈니스 로직만 처리한다.

마무리
Nginx로 Reverse Proxy를 구성해 내부 localhost를 public ip와 연결하고 Certbot으로 https를 적용해보았다.
인증서를 갱신하는 작업을 통해 어플리케이션이 동작하는 계층의 원리를 이해할 수 있었다. (도메인 → DNS → IP → Nginx → Express → DB)
- Express 는 비즈니스 로직만 담당
- Nginx는 외부 요청을 받아 TLS 처리하고 내부 백엔드 서버(localhost)로 전달
- DNS는 Nginx의 입구 역할
위 원리를 이해하고나니 꽤 단순하다.
- 가비아에서 도메인을 public ip에 연결
- Nginx로 public ip와 localhost 연결
- Certbot으로 https 적용