1. localhost는 여러분만을 위한 주소이며, ChatGPT에서는 통하지 않습니다
이 모듈에서 가장 큰 인지 부조화부터 시작해 봅시다. 여러분은 브라우저에서 http://localhost:3000을 열고, 모든 것이 잘 동작하고, Next.js가 미소 짓고, 위젯이 렌더링되는 것을 봅니다. 논리적으로 보일 수 있습니다: “URL이 있으니 ChatGPT에 그냥 주면 되겠지.”
문제는 localhost가 “인터넷에서 내 컴퓨터의 마법 도메인”이 아니라는 점입니다. 이 이름은 항상 브라우저나 클라이언트가 실행 중인 바로 그 머신을 가리킵니다. 여러분의 노트북은 자기 자신에게 연결합니다. ChatGPT가 돌아가는 OpenAI 서버들도 localhost에 접속할 수 있지만… 자기들의 데이터센터 내부에 있는 localhost입니다. 여러분의 Next.js는 가정용 라우터, NAT, 그리고 경우에 따라 기업 VPN 뒤에 행복하게 숨어 있습니다.
이 강의에서 우리는 다음을 수행합니다:
- 왜 localhost가 ChatGPT에서 접근 불가능한지 이해합니다.
- localhost:3000에서 퍼블릭 URL로 이어지는 cloudflared 기반 HTTPS 터널을 설정합니다.
- 이 URL을 ChatGPT Dev Mode에 연결합니다.
- 간단한 위젯 변경으로 “코드 → 터널 → ChatGPT” 체인을 검증하고, 흔한 함정을 살펴봅니다.
여기서 두 가지 간단한 사실을 얻을 수 있습니다:
- ChatGPT는 여러분의 노트북이 어디 있는지 모릅니다.
- 설령 알더라도, 직접 연결할 수 없습니다 — 인바운드 연결은 차단되어 있습니다.
또한 ChatGPT는 원칙적으로 퍼블릭 HTTPS 엔드포인트(진입점)만 사용합니다: 정상적인 도메인과 TLS 인증서가 필요합니다. 보안상의 이유로 OpenAI 서버는 암호화되지 않은 임의의 HTTP 주소로 접근하지 않으므로, 유효한 인증서가 있는 HTTPS 도메인이 반드시 필요합니다. 단순히 http://내-외부-IP:3000을 외부로 노출하는 것은 더 이상 선택지가 아닙니다.
따라서 다음을 해주는 중개자가 필요합니다 — 즉, 다음을 수행하는 서비스입니다:
- 정상적인 HTTPS 도메인으로 인터넷에 존재합니다.
- 이 도메인으로 온 요청을 안전하게 여러분의 localhost:3000으로 프록시할 수 있습니다.
이것이 바로 HTTPS 터널입니다.
2. HTTPS 터널이란 무엇인가: 직관적 모델
어려운 말을 잠시 잊고 보면, 터널은 여러분에게 임시(또는 영구) 퍼블릭 URL을 제공하고, 그곳으로 들어온 모든 요청을 여러분의 로컬 포트로 전달하는 서비스입니다. 네트워크 용어로 보면, 클라우드로 나가는 연결을 유지하는 리버스 프록시 서버에 가깝습니다.
직관적인 비유를 들어 보겠습니다: 여러분은 닫힌 문(가정용 라우터) 뒤에 있고, 터널은 바깥에서 “모든 편지는 여기로”라는 팻말을 들고 있는 배달원입니다. 그 배달원이 때때로 비밀 통로로 집 안에 들어와 여러분에게 편지를 직접 건네줍니다.
요청의 흐름은 대략 다음과 같습니다:
sequenceDiagram
participant ChatGPT as ChatGPT (클라우드)
participant Tunnel as HTTPS 터널
(Cloudflare / ngrok)
participant Dev as 여러분의 dev 서버
(localhost:3000)
ChatGPT->>Tunnel: https://xyz.trycloudflare.com 로 HTTPS 요청
Tunnel->>Dev: http://localhost:3000 로 HTTP 요청
Dev-->>Tunnel: Next.js 응답
Tunnel-->>ChatGPT: HTTPS 응답
여기서 핵심 포인트는 다음과 같습니다.
첫째, 터널 서비스와의 연결을 시작하는 주체는 여러분입니다. 유틸리티(cloudflared, ngrok 등)가 스스로 클라우드로 나가는 연결을 수립합니다. 이는 NAT/방화벽 뒤에서도 거의 항상 허용됩니다.
둘째, 터널 서비스는 유효한 인증서가 있는 HTTPS 도메인을 제공합니다. 따라서 자체 서명된 TLS를 수동으로 구성할 필요가 없습니다.
셋째, ChatGPT 입장에서 여러분의 앱은 HTTPS 도메인이 붙은 평범한 웹 서비스로 보입니다. 그 뒤에서 트래픽이 누군가의 노트북으로 향한다는 사실은 알 수 없습니다.
3. 어떤 터널들이 있고, 본 강의에서는 무엇을 사용할까
웹 개발 생태계에는 이 문제를 해결하는 여러 인기 있는 솔루션이 있습니다:
- ngrok — 현역의 고전으로, “로컬을 외부에 보여주기”의 사실상 표준이었던 도구.
- Cloudflare Tunnel (cloudflared) — Cloudflare의 현대적인 무료 솔루션으로, 회원가입 없이도 *.trycloudflare.com 도메인을 제공합니다. 원한다면 자신의 도메인을 연결할 수도 있습니다.
- LocalTunnel — 마법을 최소화한 npm 패키지로, https://something.loca.lt 같은 임시 HTTPS URL을 발급합니다.
이들 모두는 동일한 문제를 해결합니다: 로컬 서버에 ChatGPT가 사용할 수 있는 퍼블릭 HTTPS 도메인을 제공하는 것입니다.
강의에서는 집중을 위해 주요 도구로 Cloudflare Tunnel과 cloudflared 유틸리티를 사용합니다. 이유는 간단합니다: 빠른 터널은 회원가입이 필요 없고, 정상적인 HTTPS를 제공하며, 한 줄 명령으로 쉽게 실행됩니다.
물론 이미 ngrok을 선호하셔도 괜찮습니다. 명령어만 조금 다를 뿐 개념은 동일합니다: ngrok http 3000 대신 cloudflared tunnel --url http://localhost:3000을 사용하면 됩니다.
비교를 쉽게 하기 위해 간단한 표로 정리해 봅시다.
| 도구 | 회원가입 필요? | URL 형식 | 주요 장점 | 주요 단점 |
|---|---|---|---|---|
| Cloudflare Tunnel | 아니요 | |
빠른 시작, 유효한 HTTPS | 실행할 때마다 URL이 바뀜 |
| ngrok | 예 | |
방대한 문서와 에코시스템 | 무료 URL도 변경됨 |
| LocalTunnel | 아니요 | |
npm 설치, 최소한의 마법 | 도메인이 불안정, 기능 적음 |
이 강의에서는 Cloudflare Tunnel의 “빠른 일회성 터널”에 집중합니다. 이것만으로도 Dev Mode에서 여러분의 Next.js를 ChatGPT와 “연결”하기에 충분합니다.
4. 로컬 Next.js가 살아 있는지 확인
터널로 무언가를 외부에 노출하기 전에, 로컬 서버가 실제로 동작하는지 확인해야 합니다. 그렇지 않으면 문제는 Next.js가 실행되지 않았는데, 여러분은 터널만 디버깅하게 됩니다.
표준적인 순서는 다음과 같습니다:
# Apps SDK 템플릿이 있는 프로젝트 루트에서
npm install # 아직 하지 않았다면
npm run dev # Next.js dev 서버 실행
기본적으로 Next.js 16은 http://localhost:3000에서 뜹니다(포트가 비어있는 경우). 터미널에는 다음과 비슷한 로그가 보일 것입니다:
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
브라우저에서 http://localhost:3000을 열어 템플릿 페이지가 표시되는지 확인하세요. 이곳이 여러분의 “로컬 실험실”입니다. 여기서 문제가 있다면(빌드 에러, TypeScript 오류, 포트 충돌 등) — 먼저 이것들을 해결한 뒤 터널로 넘어가세요.
5. Cloudflare Tunnel 실행: localhost에서 퍼블릭 HTTPS로
이제 본격적으로 진행해 봅시다 — 인터넷의 누구든지(물론 ChatGPT 포함) 여러분의 Next.js를 HTTPS URL로 열 수 있도록 만들어 보겠습니다.
cloudflared 설치
설치 방법은 OS에 따라 다릅니다. macOS에서는 Homebrew가 가장 간단합니다:
brew install cloudflare/cloudflare/cloudflared
Windows와 Linux에서는 문서에서 권장하는 방식대로 패키지 매니저를 사용하거나, 준비된 바이너리를 다운로드할 수 있습니다 (링크는 모듈의 추가 자료에 있습니다).
설치 확인은 다음 명령으로 할 수 있습니다:
cloudflared --version
유틸리티를 찾지 못한다면 PATH를 확인하거나 터미널을 재시작하세요.
빠른 일회성 터널
우리의 목표는 지금 최소한의 작동 예시입니다. 계정, 도메인, 복잡한 설정 없이요. 이를 위해 cloudflared에는 quick tunnel 모드가 있으며, trycloudflare.com 도메인의 URL을 제공합니다.
npm run dev가 실행 중일 때, 다른 터미널에서 다음을 실행하세요:
cloudflared tunnel --url http://localhost:3000
다음 규칙을 기억하세요: 바깥쪽은 HTTPS, 안쪽은 HTTP. cloudflared가 바깥쪽에는 HTTPS 도메인을 제공하지만, 여러분의 localhost:3000에는 일반 HTTP로 접속합니다.
잠시 로그가 출력된 후 다음과 같은 줄을 보게 됩니다:
INF +-------------------------------------------------------------+
INF | Your quick Tunnel has been created! |
INF | https://giftgenius-1234.trycloudflare.com |
INF +-------------------------------------------------------------+
이 https://giftgenius-1234.trycloudflare.com이 바로 여러분 로컬 애플리케이션의 새 퍼블릭 주소입니다. 터널은 이 도메인으로 들어온 HTTPS 요청을 http://localhost:3000으로 전달합니다.
중요한 포인트 두 가지.
첫째, cloudflared가 실행 중인 터미널은 터널이 필요한 동안 계속 열려 있어야 합니다. 해당 터미널을 닫거나 Ctrl+C를 누르면 터널이 종료되고, URL은 더 이상 동작하지 않습니다.
둘째, quick tunnel 모드에서는 매 실행마다 URL이 바뀔 수 있습니다. 학습 개발에는 충분히 괜찮습니다: 현재 모듈의 목표는 여러분의 로컬 Next.js에 ChatGPT가 접근할 수 있도록 “어떤 작동하는 HTTPS 주소든” 제공하는 것입니다. 다만 그만큼 ChatGPT Dev Mode에서 URL을 가끔 갱신해야 한다는 뜻입니다. 모듈 7에서 터널 주제를 다시 다루며, 주소가 바뀌지 않는 안정적인 개발용 도메인을 설정해 보겠습니다.
일반 웹사이트처럼 터널 확인
ChatGPT에 연결하기 전에, 정말 인터넷에서 터널이 열려 있는지 먼저 확인해 봅시다.
- 발급받은 https://...trycloudflare.com을 브라우저에서 엽니다.
- http://localhost:3000에서 보던 동일한 UI가 보여야 합니다.
- npm run dev가 실행 중인 콘솔에 새 요청 로그가 보일 것입니다 — 즉, Next.js가 외부 요청을 실제로 처리하고 있다는 뜻입니다.
페이지가 열리지 않거나 오류가 있다면 먼저 다음을 확인하세요:
- npm run dev가 실행 중인지.
- 터널 실행 시 로컬 URL을 잘못 입력하지 않았는지(http://localhost:3000이어야 하며, https://가 아니고 포트 3001도 아님).
- (드물지만) 엄격한 기업 네트워크에서 아웃바운드 연결이 차단되지 않았는지.
6. 이 URL을 ChatGPT Dev Mode에 연결하기
이제 다음 체인을 연결할 모든 준비가 되었습니다:
ChatGPT(클라우드) → 여러분의 HTTPS 터널 → 로컬 Next.js.
Dev Mode 인터페이스 부분은 이전 강의에서 이미 보았습니다. 이제 이 과정을 실제 HTTPS URL로 반복해 보겠습니다.
ChatGPT에서의 일반적인 순서는 다음과 같습니다.
브라우저에서 ChatGPT를 열고 개발자 섹션으로 이동합니다(보통 “Developer”, “Apps”, “My apps” 등 — UI가 업데이트되며 이름이 바뀔 수 있습니다).
새 애플리케이션을 만들거나, 이미 만들었던 개발용 앱을 수정하세요.
앱의 URL을 입력하는 필드에 터널의 루트 주소를 입력합니다. 예를 들어:
https://giftgenius-1234.trycloudflare.com/mcp
진입점은 우리의 /route/mcp.ts입니다. ChatGPT는 여기에 먼저 접속하고 필요한 정보를 모두 가져갑니다. 템플릿의 README에 다른 경로가 필요하다고 명시될 수 있고, 앱이 여러 개일 수도 있지만, 지금은 터널의 루트 URL + /mcp가 여러분에게 필요한 경로라고 가정하겠습니다.
앱 설정을 저장하세요. 이 시점에 ChatGPT는 터널을 통해 여러분의 애플리케이션에 몇 가지 요청을 보냅니다:
- 앱 매니페스트(메타데이터, 도구 등)를 읽습니다.
- MCP 엔드포인트의 접근성을 확인합니다.
- 모든 tools와 리소스 목록을 가져옵니다.
- 모든 위젯의 HTML 코드를 캐시합니다(!)
모든 것이 정상이라면, Dev‑Apps 목록에 여러분의 앱이 보일 것입니다. 무언가 문제가 있다면(매니페스트가 유효하지 않거나, 서버가 응답하지 않거나, 터널이 내려갔거나), ChatGPT는 “App unavailable”과 같은 오류를 표시합니다.
중요: ChatGPT는 이 동일한 HTTPS 터널 URL을 도구 호출(MCP)에도 사용하고, 위젯과 정적 파일을 로드할 때도 사용합니다. 다음 섹션에서 이 두 가지 역할을 별도로 살펴봅니다.
7. 이제 요청은 어떻게 흐르는가: 터널의 두 가지 역할
ChatGPT가 이 URL로 정확히 무엇을 하는지를 명확히 이해하는 것이 중요합니다. Apps SDK 아키텍처에는 MCP 엔드포인트와 UI 위젯이라는 두 가지 주요 진입점이 있습니다.
단순화한 체인은 다음과 같습니다:
flowchart LR
ChatGPT["ChatGPT (모델)"]
subgraph Internet
Tunnel[HTTPS 터널
giftgenius-1234.trycloudflare.com]
end
Local["Next.js 개발 서버 http://localhost:3000"]
ChatGPT -- HTTP(S) 요청 /mcp --> Tunnel
ChatGPT -- iframe 로드 /widget --> Tunnel
Tunnel --> Local
터널에는 사실상 두 가지 주요 역할이 있습니다:
- 역할 1: MCP 엔드포인트(도구). 모델이 도구(tool)를 호출하기로 결정하면, 동일한 터널 도메인에서 MCP 엔드포인트로 HTTP POST를 보냅니다 (템플릿에서는 Next.js의 app/mcp/route.ts 라우트).
- 역할 2: UI 위젯과 정적 파일. 모델이 위젯을 표시하기로 하면, 여러분의 URL(보통 /widget 또는 매니페스트에 지정된 값)로 iframe을 삽입하며, 로드 역시 터널을 통해 진행됩니다.
이런 의미에서 터널은 “무언가 하나만 위한” 것이 아니라, 여러분의 로컬 앱으로 들어오는 하나의 통합 문입니다: UI, MCP, 정적 파일 — 모두 동일한 퍼블릭 HTTPS 도메인을 통해 오갑니다.
8. 실습: “코드 → 터널 → ChatGPT” 체인 점검
그림만 예쁘게 그려진 게 아니라 실제로 동작한다는 것을 확인하기 위해, 최소한의 실습 시나리오를 수행해 봅시다.
첫째, npm run dev를 실행하고 http://localhost:3000이 브라우저에서 열리는지 확인하세요.
둘째, cloudflared tunnel --url http://localhost:3000을 실행해 퍼블릭 HTTPS URL을 받으세요. 다른 브라우저나 심지어 다른 기기(예: 모바일 데이터가 켜진 휴대폰)로도 확인해 보세요 — 이렇게 하면 요청이 실제 인터넷을 통해 전달되는지, 아니면 여러분의 머신에서만 맴도는지 확실히 알 수 있습니다.
셋째, ChatGPT를 열고 Dev Mode로 이동한 다음, 여러분의 앱이 이 URL에 연결되어 있는지 확인하세요. ChatGPT의 Composer에서 여러분의 앱을 선택하고 대화를 시작해, ChatGPT가 위젯을 삽입하고 여러분의 UI를 로드하는지 살펴보세요.
정말로 여러분의 코드가 반영되는지 눈으로 확인하려면, 위젯에서 아주 간단한 것을 바꾸면 됩니다. 예를 들어 제목을 바꿔 보세요:
// app/widget/page.tsx (예시)
'use client';
export default function GiftGeniusWidget() {
return <h1>GiftGenius 터널을 통해 🚇</h1>;
}
파일을 저장한 뒤:
- Next.js가 fast refresh를 완료할 때까지 기다립니다.
- 여러분이 앱을 추가했던 ChatGPT의 해당 섹션으로 가서 새로고침(refresh)하세요.
- ChatGPT에서 앱 세션을 열거나 새로고침하세요.
- ChatGPT에 위젯을 표시해 달라는 새 요청을 입력하세요.
- 변경된 제목 텍스트가 ChatGPT 내부에 표시되는지 확인하세요.
바로 이 순간이 작은 진실의 순간입니다: 방금 여러분의 머신에서 코드를 변경했고, 그 변경 사항이 터널을 통해 ChatGPT의 클라우드 인터페이스에 반영되었습니다.
9. 보안에 대하여: “무엇을 외부에 노출했는가”
어떤 터널이든 장난감이 아닌, 여러분의 머신으로 들어오는 실제 퍼블릭 진입점입니다. 우리의 학습 시나리오에서는 localhost:3000 — 즉 Next.js 애플리케이션만을 노출합니다. 다음과 같은 경우 비교적 안전합니다:
- 이 포트가 다른 용도로 사용되지 않는 경우;
- 불필요하게 DB 관리자, phpMyAdmin, 여러 데모 서비스 같은 “괴물 앱”을 같은 포트에 얹어두지 않은 경우.
실무에서 중요한 몇 가지 규칙.
터널은 개발용 도구이지, 운영(production) 환경이 아닙니다. 우리는 의도적으로 Dev Mode에서 사용하며, 실제 사용자용이나 결제 처리용으로 사용하지 않습니다.
같은 포트(3000)에 관리자 패널, 암호 없는 DB, 그 밖의 민감한 것들을 올려두지 마세요. 터널이 살아 있는 동안, 이 포트에서 응답하는 모든 것은 인터넷에 보이게 됩니다.
trycloudflare.com URL을 아무 데나 공유하지 마세요. 학습 프로젝트를 진행하는 동안 누군가가 적극적으로 스캔할 가능성은 높지 않겠지만, “개발 서버 링크를 아무 데나 뿌린다”는 습관은 운영에서 큰 문제가 될 수 있습니다.
이후 Vercel과 프로덕션 환경을 다룰 때는 안정적인 도메인을 갖춘 정상적인 호스팅과 프로덕션 보안을 사용할 것이며, 터널은 철저히 개발용 도구로 남겨둘 것입니다.
10. 로컬 실행과 터널에서 흔히 발생하는 오류
이제 로컬 Next.js, 작동하는 HTTPS 터널, ChatGPT의 Dev Mode 연결이 모두 준비되었습니다. 마지막으로, 초기 단계에서 거의 누구나 한 번쯤 겪는 전형적인 오류와 빠르게 진단하는 방법을 정리합니다.
오류 1: http://localhost:3000을 ChatGPT에 그대로 사용하려는 시도.
초보 개발자들이 이 URL을 Dev Mode 설정에 그대로 붙여넣고, ChatGPT가 앱에 연결할 수 없다며 놀라는 경우가 있습니다. 다시 상기합시다: localhost는 요청을 보내는 그 주체 자신을 의미합니다. ChatGPT에겐 OpenAI 서버이지, 여러분의 노트북이 아닙니다. 이 경우 여러분의 머신에 요청이 도달하지 않기 때문에, 로컬 로그에서도 아무것도 보이지 않을 것입니다.
오류 2: 존재하지 않거나 잘못된 포트로 터널을 연결.
자주 있는 시나리오: 예전에 npm run dev를 3000번 포트에서 돌렸고, 서버는 이미 내려갔는데, 습관적으로 다른 터미널에서 cloudflared tunnel --url http://localhost:3000을 실행합니다. Cloudflare는 그럴듯한 HTTPS 도메인을 주지만, 열어보면 오류가 납니다. 진단은 간단합니다: 로컬 서버가 살아있지 않습니다. 항상 먼저 브라우저에서 http://localhost:3000을 확인한 뒤, 그 다음에 터널을 켜세요.
오류 3: 터널 실행 시 http://와 https://를 혼동.
터널은 바깥쪽 HTTPS를 제공하지만, 로컬 서버에는 HTTP로 접속해야 합니다. 예: http://localhost:3000. https://localhost:3000을 지정하면 내부 TLS 관련 이상한 오류가 나거나 단순히 연결이 안될 수 있습니다. 기억하세요: 바깥쪽은 HTTPS, 안쪽은 HTTP.
오류 4: ChatGPT에서 테스트 중 터널이 실행 중인 터미널을 닫음.
또 하나의 고전적 사례입니다: 모든 설정을 마치고 앱이 ChatGPT에서 잘 동작하다가, cloudflared가 열려 있던 터미널 창을 실수로 닫습니다. 10분 뒤 ChatGPT로 돌아오면 “App unavailable”이 보입니다. 이유는 간단합니다: 앱 설정에는 URL이 남아 있지만, 터널 자체가 내려갔기 때문입니다. 기억하세요: Dev Mode에서 앱을 테스트하는 동안에는, 터널이 실행 중인 터미널이 항상 옆에 살아 있어야 합니다.
오류 5: 터널 재시작 후 새 URL을 의식하지 못하고 사용.
quick tunnel 모드에서는 Cloudflare가 실행할 때마다 새로운 *.trycloudflare.com을 줍니다. cloudflared를 중지했다가 다시 실행했는데, ChatGPT 설정에는 여전히 예전 URL이 있다면, ChatGPT는 그곳으로 가서 타임아웃을 받거나 엉뚱한 서비스를 보게 됩니다. 터널 URL이 바뀌면 Dev Mode 설정에서도 반드시 갱신하세요. 이후 우리는 URL을 쫓아다니지 않도록 안정적인 개발용 도메인을 만드는 방법을 다룰 것입니다.
오류 6: 같은 포트로 불필요하거나 위험한 서비스까지 노출.
가끔 편의상 3000번 포트에 Next.js만이 아니라 각종 “관리용”을 함께 올려두는 경우가 있습니다: 디버그 패널, 인증 없는 실험적 API 등. 이 포트를 터널로 노출하는 순간, 이런 것들이 전부 외부에 공개됩니다. 학습 프로젝트라 큰일이 없을 수도 있지만, 실전 프로젝트에서는 유출과 침해 위험을 크게 높이는 습관입니다. 항상 명심하세요: 터널에 지정한 포트에서 응답하는 모든 것은 인터넷을 향하고 있습니다.
GO TO FULL VERSION