서비스가 늘 때마다 포트를 하나씩 열고 있다면, 답은 각 서비스마다 포트를 여는 대신 리버스 프록시로 도메인 하나에 몰아주는 겁니다. 인증서 관리까지 자동으로 맡기고 싶으면 Caddy, 화면 보면서 클릭으로 설정하고 싶으면 Nginx Proxy Manager가 맞고, 관리자 페이지처럼 아예 밖에 안 보이게 하고 싶은 서비스는 Tailscale이나 Cloudflare Tunnel로 따로 빼는 게 낫습니다.

홈서버 시리즈, 이번엔 포트가 문제였습니다
NAS 물색하다 시놀로지 잠금 이슈를 겪고, 여름 정전에 UPS를 들이고, 와이파이7로 무선을 정리하고, 지난번엔 2.5기가 유선으로 마지막 병목까지 풀었습니다. 그렇게 네트워크는 정리가 됐는데, 정작 그 위에 얹은 서비스는 계속 늘어나고 있더라고요. 팀 Gitea를 3년째 도커로 돌리는 습관 그대로 집에도 개인용 Gitea를 하나 올렸고, NAS 관리자 페이지도 따로 있고, 사이드 프로젝트 테스트용으로 띄운 앱도 두어 개 더 생겼습니다.
문제는 이 서비스들을 밖에서 접속하려고 할 때마다 공유기에서 포트를 하나씩 열었다는 겁니다. Gitea는 3000번, NAS 관리자 페이지는 5000번, 다른 앱은 8080번 이런 식으로요. 처음 한두 개는 별생각 없었는데, 어느 순간 포트포워딩 목록이 다섯 줄을 넘어가는 걸 보고 나서야 "이거 이대로 가면 안 되겠다" 싶었습니다.
포트 하나 열 때마다 뭐가 늘어나는지는 회사에서 이미 봤습니다
회사에서 API 서버랑 사내 게이트웨이를 맡다 보니, 외부에 노출된 포트가 늘어나는 게 뭘 의미하는지는 감으로 압니다. 열린 포트마다 스캔 시도가 붙고, 로그인 폼이 있는 서비스는 무차별 대입 시도가 붙습니다. 지난달 Gitea 헤더 취약점이 공개됐을 때 팀 Gitea가 무사했던 건 순전히 프록시 인증 뒤에 있었기 때문이었는데, 그때 "집 서버도 이 구조로 가야겠다"는 생각을 처음 했어요.
집 공유기 방화벽 로그를 며칠 열어봤더니 포트별로 접속 시도 자체가 꽤 있더군요. 대부분은 자동화된 스캐너가 훑고 지나가는 수준이라 당장 뚫릴 위험은 아니지만, 포트가 늘어날수록 "혹시 이 서비스 하나만 패치를 놓쳤으면 어쩌지"라는 걱정도 같이 늘어납니다. 관리 포인트가 늘어나는 게 진짜 문제였던 거죠.
그래서 택한 답: 포트 대신 도메인 하나로
리버스 프록시는 외부에서 들어오는 요청을 전부 443(HTTPS) 포트 하나로 받은 다음, 요청한 도메인이나 경로를 보고 내부의 알맞은 서비스로 다시 넘겨주는 중간 서버입니다. 즉 gitea.내도메인.com으로 들어온 요청은 내부 3000번 포트로, nas.내도메인.com으로 들어온 요청은 내부 5000번 포트로 각각 돌려주는 식이라, 밖에서 볼 때는 포트가 하나뿐인 것처럼 보입니다. 공유기에는 443 하나만 열어두면 되니 포트포워딩 목록이 확 줄어드는 셈이고요.
도메인이 아직 없다면 서브도메인만 여러 개 파는 것도 방법입니다. 저는 이미 갖고 있던 개인 도메인에 서브도메인을 서비스 개수만큼 붙였어요.
이 구조를 실제로 구현하는 소프트웨어는 여러 개가 있는데, 홈랩 커뮤니티에서 가장 많이 언급되는 두 가지가 Caddy와 Nginx Proxy Manager(NPM)였습니다. 성격이 꽤 다르길래 둘 다 집 서버에 직접 올려보고 비교해봤어요.
선택 기준부터: Caddy와 NPM, 뭐가 다른가
비교할 때 기준을 셋으로 잡았습니다. 설정을 텍스트로 할 건지 화면으로 할 건지(설정 난이도), 웹 관리 화면이 있는지(GUI 유무), 그리고 HTTPS 인증서를 누가 어떻게 관리하는지(인증서 관리 방식)입니다. 둘 다 리버스 프록시라는 목적은 같지만 이 셋에서 완전히 다른 길을 가더라고요.
| 기준 | Caddy | Nginx Proxy Manager |
|---|---|---|
| 설정 방식 | Caddyfile 텍스트 몇 줄 | 웹 GUI에서 클릭 |
| nginx 문법 필요 여부 | 해당 없음(자체 문법) | 불필요(GUI가 대신 처리) |
| 인증서 관리 | 도메인만 지정하면 자동 발급·자동 갱신 | GUI 화면에서 발급 요청 |
| 설치 방식 | 단일 바이너리 또는 Docker | 공식 설치법: Docker Compose |
| 기본 사용 포트 | 80/443 | 80·443·81(관리자 UI) |
Caddy — 도메인만 적으면 끝나는 인증서
Caddy는 설정 파일(Caddyfile)에 도메인과 넘길 내부 주소만 적으면 나머지를 알아서 처리합니다. Let's Encrypt·ZeroSSL과 ACME 프로토콜로 통신해서 TLS 인증서를 자동 발급하고, 인증서 유효기간이 90일인데 만료 약 30일 전부터 자동으로 갱신을 시도하기 때문에 저는 인증서 만료를 신경 써본 적이 한 번도 없습니다. 예전에 다른 서버에서 certbot 크론잡을 따로 걸어두고 갱신 실패 알림을 확인하던 걸 생각하면 이 부분이 제일 편했어요.
실제로 넣은 설정은 이렇게 짧습니다.
서비스 하나당 이 정도 블록이면 됩니다. 도메인만 DNS에서 서버로 연결해두면 나머지는 Caddy가 알아서 인증서까지 처리해줍니다.
gitea.내도메인.com {
reverse_proxy localhost:3000
}
nas.내도메인.com {
reverse_proxy localhost:5000
}
다만 설정을 텍스트로 직접 건드려야 하다 보니, 서버 터미널이 낯선 사람에게는 진입장벽이 있을 수 있습니다. 저는 평소에 터미널 로그로 문제를 확인하는 걸 선호하는 편이라 오히려 이 방식이 더 손에 익더라고요.
Nginx Proxy Manager — 화면 보면서 설정하는 프록시
NPM은 nginx 설정 문법을 몰라도 되는 웹 GUI 기반 리버스 프록시입니다. 공식 설치법이 Docker Compose(docker compose up -d) 한 줄이고, 뜨고 나면 웹 브라우저로 관리 화면에 들어가서 "Proxy Host 추가" 버튼을 누르고 도메인이랑 내부 IP·포트만 입력하면 됩니다. 기본적으로 80(공개 HTTP)·443(공개 HTTPS)·81(관리자 웹 UI) 이렇게 3개 포트를 쓰는데, 81번은 관리 화면 전용이라 외부에는 열어두지 않는 게 맞고요.
화면으로 모든 프록시 규칙이 목록으로 보이니까, 지금 어떤 도메인이 어떤 내부 서비스로 연결돼 있는지 한눈에 파악하기는 이쪽이 확실히 낫습니다. 저처럼 서버가 하나뿐이면 크게 안 느껴지는데, 서비스가 열 개쯤 넘어가면 이 목록 화면의 가치가 커질 것 같아요. (여담이지만 NPM도 결국 내부적으로는 nginx 설정 파일을 자동 생성하는 구조라, "nginx를 안 쓴다"기보다는 "nginx를 손으로 안 만진다"에 더 가깝습니다.)
그래도 아예 밖에 안 보이게 하고 싶은 페이지가 있다면
여기서 하나 짚고 넘어가야 할 게 있습니다.
리버스 프록시는 포트를 하나로 줄여줄 뿐이지, 그 도메인 자체는 여전히 인터넷 전체에 공개돼 있다는 점입니다. NAS 관리자 페이지처럼 나 혼자만 접속하면 되는 서비스까지 굳이 도메인을 붙여 세상에 공개할 필요는 없거든요.
이런 경우에는 리버스 프록시 대신 사설 네트워크로 접속하는 방법이 낫습니다. Tailscale 무료 Personal 플랜은 사용자 최대 6명, 사용자 기기는 무제한(별도로 태그가 붙는 리소스는 50개까지)까지 지원하고 MagicDNS·서브넷 라우터·Exit Node 같은 핵심 기능이 다 포함돼 있어서, 공유기 포트를 하나도 열지 않고도 집 서버 관리자 페이지에 원격 접속할 수 있습니다. 제 노트북과 스마트폰에 Tailscale을 깔아두면 밖에서도 내부망에 있는 것처럼 접속되는 구조라, 관리자 페이지는 아예 이쪽으로 옮겨뒀거든요.
Cloudflare Tunnel도 방향은 비슷한데 방식이 다릅니다. 이건 사용량 제한 없이 완전히 무료인데, cloudflared라는 데몬이 집 서버에서 Cloudflare 네트워크 쪽으로 먼저 아웃바운드 연결을 개시하는 방식이라 공인 IP나 포트포워딩이 아예 없어도 외부 요청을 안전하게 받을 수 있습니다. Tailscale이 "나만 접속하는 사설망"에 가깝다면, Cloudflare Tunnel은 "포트는 안 열되 남들도 접속하게는 하고 싶은" 서비스에 더 맞는 느낌이었어요.
결국 어떤 상황에 뭐가 맞는지
세 가지 도구를 다 올려보고 나니 답은 하나가 아니라 상황별로 갈리더군요. 지금 저는 Gitea처럼 남들과 링크를 공유할 수도 있는 서비스는 Caddy로, NAS 관리자 페이지처럼 나만 보면 되는 건 Tailscale로 나눠서 쓰고 있습니다.
- 서버 터미널이 익숙하고 설정을 텍스트로 관리하고 싶다면 → Caddy
- 화면으로 프록시 규칙을 한눈에 보고 싶고 GUI가 편하다면 → Nginx Proxy Manager
- Gitea처럼 가끔 외부에 공유할 일이 있는 서비스라면 → 리버스 프록시(Caddy 또는 NPM)로 도메인 부여
- 나 혼자만 접속하면 되는 관리자 페이지라면 → 도메인 붙이지 말고 Tailscale
- 불특정 다수가 접속해야 하는데 공인 IP·포트포워딩을 아예 피하고 싶다면 → Cloudflare Tunnel
포트포워딩 목록을 다섯 줄까지 늘려놓고서야 이 문제를 진지하게 들여다봤는데, 막상 정리하고 보니 서비스 성격별로 나누는 게 정답이었습니다. 하나의 도구로 전부 해결하려던 게 오히려 욕심이었던 거죠. 회사 게이트웨이 운영하면서 배운 "노출 면적부터 줄인다"는 원칙이 집 서버에도 그대로 통하는 걸 보니, 이 시리즈도 결국 회사에서 몸으로 익힌 습관을 집으로 옮기는 과정이었구나 싶네요.
이 포스팅에는 쿠팡 파트너스 활동의 일환으로 일정 수수료를 제공받을 수 있습니다.
'Tech > Dev Notes' 카테고리의 다른 글
| 무료 공공 API로 만든 앱, 출시에서 막히는 4개 지점 — 기상청 1만 vs 고캠핑 1천, 테스터 12명·14일 (0) | 2026.08.06 |
|---|---|
| 인증서 자동 갱신은 돌고 있는데 왜 사이트는 만료라고 뜰까요? 200일 시대 점검 지점 3곳 (0) | 2026.08.05 |
| Claude가 CTF 평가 중 진짜 서버를 뚫었다고요? — Anthropic이 밝힌 사이버보안 사고 3건 (0) | 2026.07.31 |
| 면접 과제 레포에 npm install, 그냥 해도 될까? npm 12 스크립트 차단과 격리 셋업 (1) | 2026.07.24 |
| tmux 완벽 가이드 - 설치부터 .tmux.conf 설정, 세션 관리, 단축키까지 (1) | 2026.07.17 |