본문 바로가기
카테고리 없음

리버스 프록시로 도메인 하나에 여러 서비스 연결 (포트 없이 이름으로 접속) — 홈랩 입문 7편

by DDlabx 2026. 7. 8.

리버스 프록시는 하나의 주소로 들어온 요청을 뒤에서 돌아가는 여러 서비스로 알아서 나눠주는 교통정리 역할을 합니다. 이걸 쓰면 IP:9443 같은 포트 번호를 외우지 않고 portainer.내주소처럼 깔끔한 이름만으로 각 서비스에 접속할 수 있습니다. 이 글에서는 웹 화면으로 리버스 프록시를 다루는 Nginx Proxy Manager(NPM)를 설치하고, 실제로 Portainer를 도메인에 연결해 외부에서 접속되는 것까지 직접 확인한 과정을 정리합니다.

이 글은 6편(DDNS 설정)6-2편(포트포워딩)에서 이어집니다. 외부 접속용 주소와 포트가 준비돼 있어야 이번 편이 의미가 있습니다.

리버스 프록시가 왜 필요한가

리버스 프록시가 필요한 이유는 '주소가 지저분해지는 문제'를 해결하기 위해서입니다. 홈랩에 앱을 여러 개 올리면 각 앱이 서로 다른 포트를 씁니다. Portainer는 9443, 사진 서버는 2283, 광고 차단기는 3000처럼요. 이걸 그대로 쓰면 접속할 때마다 IP:포트를 외워야 하고, 외부 공유도 번거롭습니다.

리버스 프록시는 이 모든 요청을 한 곳(80·443 포트)에서 받은 뒤, 주소를 보고 알맞은 서비스로 연결해줍니다. 예를 들어 photo.내주소로 들어오면 사진 서버(2283)로, portainer.내주소로 들어오면 Portainer(9443)로 자동 전달하는 식이죠. 사용자는 포트를 전혀 몰라도 이름만으로 접속할 수 있습니다. 게다가 다음 편에서 다룰 SSL 인증서(https 자물쇠)도 이 리버스 프록시에서 한 번에 관리할 수 있어, 홈랩의 '관문' 역할을 합니다. 그래서 이 편에서 만든 NPM은 앞으로 앱을 올릴 때마다 계속 되돌아와 참조하게 됩니다.

Nginx Proxy Manager 설치하기

NPM은 Docker Compose로 설치하는 것이 가장 표준적입니다. 이름에 Nginx가 들어가지만 서버의 Nginx와는 무관하며, 리버스 프록시와 SSL 인증서 관리를 웹 화면(GUI)으로 쉽게 해주는 독립 도구입니다.

먼저 서버에 작업 폴더를 만들고 그 안에 docker-compose.yml 파일을 작성합니다.

1. 작업 폴더 만들고 이동

mkdir ~/npm && cd ~/npm

2. docker-compose.yml 파일 생성

nano docker-compose.yml

나노(nano) 편집기가 열리면 아래 내용 붙여 넣기

*nano 저장 방법: 붙여넣은 뒤 Ctrl + O(저장) → Enter(파일명 확인) → Ctrl + X(나가기).

services:
  npm:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80'
      - '81:81'
      - '443:443'
    environment:
      TZ: "Asia/Seoul"
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt

80은 http, 443은 https 서비스용이고, 81번이 관리자 화면 포트입니다. 파일을 저장할 때 나노(nano) 편집기에서는 붙여넣기 과정에서 들여쓰기가 깨지기 쉬우니, 저장 후 cat docker-compose.yml로 위 형태(2칸 들여쓰기)가 유지됐는지 확인하는 것이 안전합니다. 이어서 같은 폴더에서 docker compose up -d를 실행하면 컨테이너가 뜹니다. 이제 브라우저에서 http://내서버IP:81(제 경우 http://172.30.1.51:81)로 접속하면 로그인 화면이 나오는데, *최초 기본 계정은 이메일 admin@example.com, 비밀번호 changeme*입니다. 로그인하면 곧바로 이메일과 비밀번호를 바꾸라고 나오는데, 이건 반드시 즉시 변경해야 합니다. 기본값 그대로 두면 외부에서 누구나 관리자 화면에 접근할 수 있어 심각한 보안 구멍이 되기 때문입니다.

프록시 호스트 등록하고 실제 도메인으로 접속하기

이제 실제로 서비스를 도메인에 연결해봅니다. 대상은 이미 돌아가고 있는 Portainer로 잡았습니다. NPM 대시보드에서 'Hosts → Proxy Hosts → Add Proxy Host'를 누르고 Details 탭에 값을 입력합니다. Domain Names에 portainer.ddlabx-home.duckdns.org, Scheme에 https, Forward Hostname/IP에 172.30.1.51, Forward Port에 9443을 넣습니다. Portainer는 실시간 통신을 쓰므로 'Websockets Support'도 켜줍니다. SSL 탭은 다음 편에서 다룰 것이므로 지금은 건드리지 않습니다.

여기서 한 가지 반가운 사실이 있습니다. DuckDNS는 하위 서브도메인을 자동으로 지원해서, portainer.ddlabx-home.duckdns.org처럼 앞에 무엇을 붙여도 모두 같은 집 IP로 연결됩니다. 별도의 DNS 레코드를 추가할 필요 없이 서비스별로 이름을 나눌 수 있다는 뜻입니다. 설정을 저장한 뒤 휴대폰 데이터(5G)로 portainer.ddlabx-home.duckdns.org에 접속하니, IP:9443이 아니라 이름만으로 Portainer 로그인 페이지가 정상적으로 떴습니다. 비교로 ddlabx-home.duckdns.org(앞에 portainer 없이)에 접속하면 여전히 NPM 기본 페이지가 나옵니다. 같은 집 IP인데 주소 앞부분에 따라 다른 서비스로 연결되는 것, 이것이 리버스 프록시의 핵심입니다.

다만 이 시점에는 아직 SSL이 없어 http 접속이므로, 로그인 페이지가 떠도 실제 로그인은 하지 마세요. 비밀번호가 암호화 없이 오갑니다. 실제 로그인은 다음 편에서 https 자물쇠를 단 뒤에 하는 것이 안전합니다. 참고로 집 와이파이(내부망)에서는 이 도메인이 안 열릴 수 있는데, 일부 공유기가 내부에서 자기 공인주소로 되돌아 들어오는 방식(NAT 루프백)을 지원하지 않기 때문입니다. 그래서 외부망인 휴대폰 5G 테스트가 가장 확실합니다.

자주 나는 오류 — "Client sent an HTTP request to an HTTPS server"

프록시 호스트를 연결할 때 가장 흔히 만나는 오류가 Client sent an HTTP request to an HTTPS server입니다. 저도 이 메시지를 만났는데, 원인은 명확합니다. Add Proxy Host의 Scheme을 http로 둔 채, https만 받는 Portainer(9443)에 연결했기 때문입니다. NPM은 설정대로 http로 백엔드에 요청을 보냈지만, Portainer는 https만 받으므로 거부한 것이죠.

해결은 간단합니다. 해당 프록시 호스트를 편집해 Scheme을 https로 바꾸고 저장한 뒤 다시 접속하면 됩니다. 핵심 원칙은 '연결하려는 서비스가 http를 쓰면 Scheme도 http, https를 쓰면 Scheme도 https'로 맞추는 것입니다. Portainer(9443)나 일부 관리도구는 https 전용이므로 반드시 https로 지정해야 합니다. 흥미로운 점은 이 오류가 났다는 것 자체가 '리버스 프록시가 백엔드까지 정상적으로 연결을 시도했다'는 증거라는 것입니다. 즉 라우팅은 성공했고 프로토콜만 안 맞았던 것이라, Scheme만 고치면 바로 해결됩니다.

이제 포트 없이 이름으로 서비스에 접속하는 리버스 프록시가 완성됐습니다. 남은 것은 브라우저의 '주의 요함' 경고를 없애는 https 자물쇠뿐입니다. 다음 편에서 Let's Encrypt 무료 인증서로 SSL을 적용해, https://portainer.ddlabx-home.duckdns.org가 초록 자물쇠로 열리게 만듭니다. → 8편. Let's Encrypt로 SSL 인증서 자동 발급


소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 블로그 이름