커스텀 도메인 연결하기
Cloudflare를 리버스 프록시로 사용해 Daki에서 호스팅하는 웹 앱에 내 도메인을 연결하세요 — 무료 HTTPS와 사용자 지정 포트 전달 포함. 고급 Cloudflare Tunnel(cloudflared) 대안도 설명합니다.
웹 앱을 hostname:port 주소 대신 yourdomain.com에서 접근할 수 있게 하고 싶으신가요? 이 가이드에서는 무료 리버스 프록시인 Cloudflare를 사용해 내 도메인을 Daki 서버에 연결하는 방법을 알려 드려요. Cloudflare가 HTTPS를 처리하고, 방문자의 요청을 앱이 수신하는 사용자 지정 포트로 전달해 줘요.
커스텀 도메인은 유료 플랜에서만 사용할 수 있어요. 공개적으로 접근 가능한 포트가 필요한데, 공개 포트는 유료 플랜(Bronze, Silver, Gold 및 게임 서버 플랜)에만 포함돼요. Free Tier 서버는 외부 연결을 받을 수 없으므로 거기서는 커스텀 도메인이 작동하지 않아요. 앱 & 봇 호스팅 플랜과 네트워크 & 할당을 참고하세요.
배울 내용
- Daki에서 커스텀 도메인에 Cloudflare 같은 리버스 프록시가 필요한 이유
- 프록시가 적용된 DNS 레코드로 도메인을 서버에 연결하는 방법
- 도메인에 무료 HTTPS를 활성화하는 방법
- Origin Rule로 앱 포트에 트래픽을 전달하는 방법
- Cloudflare Tunnel(
cloudflared)을 사용하는 고급 대안
준비물
- 공개 포트 할당이 있는 유료 플랜 서버 — 앱 & 봇 호스팅 플랜을 참고하세요
- 내가 소유한 도메인 이름(어떤 등록기관에서든 등록 가능, 예: Namecheap, GoDaddy, IONOS, Cloudflare Registrar)
- 무료 Cloudflare 계정
- 서버의 할당 포트에서 실행 중이며 수신 대기 중인 웹 앱(HTTP/HTTPS)
앱은 할당 포트에서 0.0.0.0(모든 인터페이스)에 바인딩해야 해요 — 127.0.0.1 / localhost가 아니에요. localhost에만 바인딩된 앱은 컨테이너 외부에서 접근할 수 없어서, 프록시가 연결에 실패해요. 대부분의 프레임워크는 호스트 인수를 받아요(예: Flask에서는 app.run(host="0.0.0.0", port=...), 많은 Node.js 앱에서는 HOST=0.0.0.0).
Cloudflare가 필요한 이유
Daki는 노드 전체에서 공유 IP 주소를 사용하고, 앱은 표준이 아닌 포트(서버에 할당된 포트)에서 수신해요. 그래서 다음 두 가지 문제가 생겨요:
- 방문자는
yourdomain.com:4129가 아니라 표준 HTTPS 포트(443)에서https://yourdomain.com에 접속하길 기대해요. - 직접 관리하지 않고도 유효한 HTTPS 인증서를 쓰고 싶으시죠.
서버 앞에 Cloudflare를 두면 두 문제가 모두 해결돼요. Cloudflare는 리버스 프록시 역할을 해요. 브라우저는 443 포트의 HTTPS로 Cloudflare에 연결하고, Cloudflare가 요청을 사용자 지정 포트의 서버로 전달해요. 무료 SSL과 깔끔한 URL을 얻을 수 있고, 서버의 실제 IP는 숨겨진 상태로 유지돼요.
이 방법은 HTTP/HTTPS 웹 앱(웹사이트, API, 대시보드, 웹훅)에 적합해요. 대부분의 게임 서버처럼 순수 TCP/UDP 서비스에는 작동하지 않아요 — Cloudflare의 기본 프록시는 HTTP(S)만 처리해요. HTTP가 아닌 서비스라면 아래의 Cloudflare Tunnel 방법을 사용하거나 지원팀에 문의하세요.
서버 IP와 포트 찾기
Portal의 Network 탭에서 두 가지 값을 확인해야 해요:
| 값 | 확인 위치 | 예시 |
|---|---|---|
| 서버 IP | 서버 호스트 이름이 변환되는 IP 주소(Network 탭에 표시돼요). 호스트 이름만 표시된다면 ping eu-node1.daki.cc 같은 명령으로 확인하거나 지원팀에 문의하세요. | 203.0.113.10 |
| 할당 포트 | Network 탭에서 호스트 이름 옆에 표시되는 포트. 앱이 이 포트에서 수신해야 해요. | 4129 |
이 가이드 전체에서 예시 값을 사용해요. 등장하는 곳마다 본인의 값으로 바꾸세요. 할당에 대한 자세한 내용은 네트워크 & 할당을 참고하세요.
1부: Cloudflare 설정
Cloudflare에 도메인 추가하기
- dash.cloudflare.com에서 무료 계정을 만드세요(또는 로그인하세요).
- Add a site를 클릭하고 도메인(예:
yourdomain.com)을 입력하세요. - 안내가 나오면 Free 플랜을 선택하세요.
- Cloudflare가 네임서버 두 개(예:
xxx.ns.cloudflare.com)를 알려 줘요. - 도메인 등록기관 사이트에 로그인하고 도메인의 네임서버 / DNS 설정을 찾은 다음, 기존 네임서버를 Cloudflare가 준 두 개로 바꾸세요.
네임서버 변경이 반영되는 데는 몇 분에서 최대 24시간까지 걸릴 수 있어요. 도메인이 활성화되면 Cloudflare가 이메일로 알려 줘요. 그동안 다음 단계를 계속 진행해도 돼요.
DNS 레코드 만들기
도메인의 Cloudflare 대시보드에서 DNS → Records로 이동한 뒤 Add record를 클릭하세요:
필드 값 Type AName @(루트 도메인yourdomain.com을 의미해요)IPv4 address 서버 IP (예: 203.0.113.10)Proxy status Proxied (주황색 구름 ☁️) Save를 클릭하세요.
주황색 구름(Proxied) 상태가 필수예요 — 트래픽이 Cloudflare를 거쳐야 SSL과 2부의 포트 변경이 작동해요. 회색 구름(DNS only)으로 두면 Cloudflare를 완전히 우회하게 되어 서버 IP가 노출돼요.
www.yourdomain.com도 제공하려면 이름을www로 한 프록시 레코드를 하나 더 추가하세요.SSL/TLS 설정하기
- SSL/TLS → Overview로 이동하세요.
- 암호화 모드를 Flexible로 설정하세요.
Flexible은 방문자와 Cloudflare 사이의 트래픽은 암호화(HTTPS)되지만, Cloudflare가 사용자 지정 포트의 앱에 일반 HTTP로 연결한다는 뜻이에요. 사용자 지정 포트에서 일반 HTTP를 제공하는 대부분의 앱에 알맞은 선택이에요.
앱이 자체 TLS를 처리한다면(즉, 포트에서 HTTPS를 직접 제공한다면) 대신 Full을 선택하세요. Flexible은 Cloudflare와 서버 사이의 연결을 암호화하지 않으니, 민감한 트래픽에는 앱에서 HTTPS를 사용하는 Full을 권장해요.
2부: 앱 포트로 트래픽 전달하기
앱은 표준 80/443이 아닌 사용자 지정 포트(예: 4129)에서 실행되므로, Cloudflare가 서버에 연결할 때 어떤 포트를 사용할지 알려 줘야 해요. Origin Rule이 바로 그 역할을 해요 — 들어오는 요청의 대상 포트를 바꿔 줘요.
Origin Rule 만들기
- Cloudflare 대시보드에서 Rules → Origin Rules로 이동하세요.
- Create Origin Rule을 클릭하세요.
- 규칙을 설정하세요:
설정 값 When incoming requests match 호스트 이름이 yourdomain.com과 equals일 때Then... Rewrite to Destination Port → 4129(할당 포트)- Save(또는 Deploy)를 클릭하세요.
DNS가 전파되면 앱은 이제 https://yourdomain.com에서 접근할 수 있어요 — Cloudflare가 HTTPS로 제공하고, 트래픽을 포트 4129의 서버로 전달해요.
작동 확인하기
- 서버가 실행 중이고 앱이 할당 포트에서 수신하고 있는지 확인하세요(Console 탭에서 확인할 수 있어요).
- 브라우저에서
https://yourdomain.com을 여세요. - 앱이 유효한 자물쇠 아이콘과 함께 HTTPS로 로드되어야 해요.
바로 로드되지 않으면 DNS가 전파될 시간을 조금 더 주고, 아래의 자주 발생하는 문제를 확인하세요.
고급 대안: Cloudflare Tunnel (cloudflared)
공개 포트를 열고 서버를 가리키는 A 레코드를 만드는 대신, Cloudflare의 터널 클라이언트인 cloudflared를 앱과 함께 실행할 수 있어요. 이 방식은 Cloudflare로 아웃바운드 연결을 열고 트래픽을 로컬의 앱으로 전달하므로, 서버의 IP와 포트가 숨겨진 상태로 유지되고 DNS A 레코드도 Origin Rule도 필요 없어요.
Daki 환경이 이 방식에 주는 영향. Startup 탭에는 두 가지 명령이 있어요 — 설치 명령(설정/재설치 시 한 번 실행)과 시작 명령(부팅할 때마다 실행). 시작 명령을 bash로 임시 설정하면 셸을 열 수도 있어요. 하지만 서버는 전체 Linux VM이 아니라 컨테이너예요: apt가 없고, 시스템 서비스를 등록할 수 없으며, 콘솔에서 직접 시작한 터널은 서버가 재시작되면 사라져요. 그래서 가장 안정적인 방법은 터널을 앱 자체의 시작 과정에 포함하는 거예요 — 런타임에 cloudflared 바이너리를 내려받고, 환경 변수로 제어되는 자식 프로세스로 앱 옆에서 실행하는 거죠.
터널 만들기
- Cloudflare Zero Trust 대시보드에서 Networks → Tunnels로 이동하고 Create a tunnel을 클릭한 다음 Cloudflared를 선택하세요.
- 이름을 정하고, Cloudflare가 표시하는 터널 토큰을 복사하세요(설치 명령의
--token뒤에 있는 긴 문자열이에요). - 터널에 Public Hostname을 추가하세요:
- Domain:
yourdomain.com - Service:
http://localhost:4129(앱의 로컬 포트)
- Domain:
.env에 토큰 저장하기
토큰을 서버의
.env파일에 추가하세요(환경 변수 참고). 그래야 소스 코드에 노출되지 않아요:.envCLOUDFLARE_TUNNEL_TOKEN=your_tunnel_token_here코드에서 터널 시작하기
처음 실행할 때
cloudflared를 내려받고 앱 옆에서 시작하는 작은 런처를 추가한 다음, 그 런처를 시작 명령으로 설정하세요.CLOUDFLARE_TUNNEL_TOKEN이 설정되어 있을 때만 터널을 시작하므로, 같은 코드를 토큰 없이 로컬에서 실행해도 문제없어요.start.js로 저장한 다음, 시작 명령을node start.js로 설정하세요:JavaScript// start.js — starts your app and, if a token is set, a Cloudflare tunnel. require("dotenv").config(); const fs = require("fs"); const path = require("path"); const { spawn, spawnSync } = require("child_process"); const CLOUDFLARED_URL = "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64"; const binaryPath = path.join(__dirname, "cloudflared"); const children = []; // The container has no apt — download the binary on first run, reuse it after. function ensureCloudflared() { if (fs.existsSync(binaryPath)) return binaryPath; console.log("[tunnel] downloading cloudflared..."); const dl = spawnSync("curl", ["-fsSL", "-o", binaryPath, CLOUDFLARED_URL], { stdio: "inherit", }); if (dl.status !== 0) return null; fs.chmodSync(binaryPath, 0o755); return binaryPath; } // Spawn a child process; if any child exits, stop the rest and quit. function start(name, command, args) { const child = spawn(command, args, { stdio: "inherit", env: process.env }); child.on("exit", (code) => { console.error(`[${name}] exited (${code}); shutting down`); for (const c of children) if (!c.killed) c.kill("SIGTERM"); process.exit(code ?? 1); }); children.push(child); } const token = process.env.CLOUDFLARE_TUNNEL_TOKEN?.trim(); if (token) { const binary = ensureCloudflared(); if (binary) start("tunnel", binary, ["tunnel", "run", "--token", token]); } else { console.log("[tunnel] CLOUDFLARE_TUNNEL_TOKEN not set; skipping tunnel"); } // Start your app — change this to your real entry point. start("app", "node", ["index.js"]);start.sh로 저장한 다음, 시작 명령을bash start.sh로 설정하세요:Shell#!/usr/bin/env bash # Load variables from .env into the environment. set -a; [ -f .env ] && . ./.env; set +a # The container has no apt — download cloudflared on first run, reuse it after. if [ ! -x ./cloudflared ]; then curl -fsSL -o ./cloudflared \ https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 chmod +x ./cloudflared fi # Start the tunnel in the background only if a token is set. if [ -n "$CLOUDFLARE_TUNNEL_TOKEN" ]; then ./cloudflared tunnel run --token "$CLOUDFLARE_TUNNEL_TOKEN" & fi # Start your app in the foreground — change this to your real command. exec python main.py매번 다시 다운로드하지 않으려면 다운로드 과정을 설치 명령으로 옮기고, 시작 명령에는 실행 로직만 남겨 둘 수 있어요. 위 예시는 바이너리가 이미 있으면 다운로드를 건너뛰므로, 매 부팅마다 실행해도 안전해요.
장단점:
| Cloudflare 프록시 (1–2부) | Cloudflare Tunnel (cloudflared) | |
|---|---|---|
| 설정 난이도 | 더 쉬움 (대시보드만 사용) | 더 고급 (앱의 시작 과정에 포함) |
| 서버 IP/포트 노출 | 프록시 뒤에 숨겨짐 | 완전히 숨겨짐 (아웃바운드 전용) |
| 공개 포트 / Origin Rule 필요 여부 | 필요 | 필요 없음 |
| 서버 리소스 사용 | 서버에서는 사용 안 함 | 추가 프로세스 실행 |
자주 발생하는 문제
사이트가 전혀 열리지 않아요
DNS가 아직 전파되는 중일 수 있어요. 네임서버 변경은 최대 24시간이 걸릴 수 있어요(보통은 훨씬 빨라요). Cloudflare에서 도메인 상태가 Active인지, A 레코드가 있고 Proxied(주황색 구름)인지 확인하세요. 전파 상태는 dnschecker.org 같은 도구로 확인할 수 있어요.
Error 522 / 523 — 연결 시간 초과 / 원본에 도달할 수 없음
Cloudflare가 앱에 연결할 수 없어요. 다음 순서로 확인하세요:
- 서버가 실행 중이고 앱이 완전히 시작되었는지 확인하세요(Console 탭에서 확인할 수 있어요).
- Origin Rule이 포트를 정확한 할당 포트로 바꾸고 있는지 확인하세요.
- A 레코드의 IP가 서버 IP와 일치하는지 확인하세요.
- 앱이
127.0.0.1/localhost가 아니라0.0.0.0에 바인딩되어 있는지 확인하세요.
리다이렉트가 너무 많아요 / ERR_TOO_MANY_REDIRECTS
보통 SSL 모드가 맞지 않아서 생기는 문제예요. 앱이 HTTPS를 강제하는데 Cloudflare가 HTTP로 연결하면 리다이렉트 루프가 생겨요. 앱이 일반 HTTP를 제공하도록 바꾸고 Flexible을 사용하거나, 앱이 HTTPS를 제공하도록 하고 SSL/TLS → Overview에서 Cloudflare를 Full로 바꾸세요.
http://에서는 되는데 https://에서는 안 돼요
DNS 레코드가 Proxied(주황색 구름)인지, 그리고 SSL/TLS 모드(Flexible 또는 Full)가 설정되어 있는지 확인하세요. 회색 구름(DNS only)이면 Cloudflare의 SSL이 우회돼요.
게임 서버 / 비HTTP 서비스가 작동하지 않아요
Cloudflare를 꼭 써야 하나요?
아니요 — Cloudflare가 가장 간단한 무료 옵션이지만, 사용자 지정 포트로 전달할 수 있는 리버스 프록시라면 무엇이든 작동해요(예: cloudflared 터널, 또는 앱 앞단에 둔 직접 설치한 Nginx/Caddy). Cloudflare를 권장하는 이유는 무료 SSL을 제공하고, 서버 IP를 숨기며, 프록시 방식에서는 서버에 추가 소프트웨어가 필요 없기 때문이에요.
다음 단계
- 네트워크 & 할당 — 호스트 이름과 포트를 확인하고, 할당을 추가하세요.
- 앱 & 봇 호스팅 플랜 — 공개 포트를 얻으려면 유료 플랜으로 업그레이드하세요.
- 환경 변수 — 코드에서 환경 변수로 포트를 읽어 보세요.
- 도움 받기 — 막히면 지원팀에 문의하세요.