터미널에서 포트 포워딩
대화의 터미널에서 시작한 서버는 해당 스페이스에만 게시됩니다. 포트 패널은
이 앱이 거기서 시작한 리스너를 감지해 매핑하고, 접근하고 싶을 만한 모든
위치에 대한 주소를 제공합니다. 두 스페이스가 모두 5173에서 리슨할 수
있지만, 두 스페이스의 맵은 결코 섞이지 않습니다.
이 과정에서 머신이 열리는 일은 없습니다. 모든 경로는 요청이 있을 때 서버가 만들고, 터미널이나 리그와 함께 사라집니다.
수신 중인 포트 확인
섹션 제목: “수신 중인 포트 확인”- 대화의 터미널 (VM) 또는 호스트 셸(스페이스나 PR 페이지에서)을 엽니다.
- 서버를 시작합니다 —
pnpm dev,python -m http.server 8000, 무엇이든 좋습니다. - 몇 초 안에 터미널 오른쪽 위 모서리의 플러그 아이콘에 점이 생깁니다. 클릭합니다.
패널은 수신 중인 모든 포트를 이를 소유한 프로세스와 함께 3000 → 3000
형식으로 나열합니다. 왼쪽은 프로세스가 바인딩한 포트, 오른쪽은 로컬에서
응답하는 포트입니다(여러분의 머신에서 비어 있었다면 같은 번호). 각 행은
데스크톱 localhost, 브라우저 (VM), Android에서 접근할 수 있는지도 알려
줍니다.
탐색 범위는 격리되어 있습니다. 터미널 (VM)은 해당 게스트 내부에서 폴링되고, 호스트 셸은 그 세션의 PTY 프로세스 트리에서 폴링됩니다. 다른 스페이스와 여러분의 Mac에 있는 다른 프로세스는 나열되지 않습니다.
이 터미널의 새 포트는 자동으로 전달됩니다. 직접 추가한 포트만 원한다면 같은 패널에서 포트 자동 전달을 끄십시오.
이 컴퓨터에서 접근
섹션 제목: “이 컴퓨터에서 접근”행에서 로컬 URL 복사를 사용합니다 — http://localhost:3000. 전달은
루프백에서만 리슨하므로, 네트워크의 다른 어떤 것도 이를 볼 수 없습니다.
두 스페이스가 모두 게스트 5173을 노출하고 여러분의 머신이 이미
127.0.0.1:5173을 점유하고 있다면, 두 번째 스페이스는 게스트 5173을
유지하고 임시 로컬 포트를 받습니다. URL 복사는 오른쪽 번호를 사용합니다.
호스트 셸에서는 프로세스가 이미 여러분의 머신에 있습니다. 같은 로컬 포트를 매핑하는 것은 아무 효과가 없고, 다른 로컬 포트를 고르면 선택한 포트에 루프백 프록시가 바인딩됩니다.
--host(또는 0.0.0.0 바인딩)를 써도 인클로저 안의 브라우저 (VM)가 Mac의
서버에 접근할 수 있게 되지는 않습니다. 게스트에는 자체 루프백이 있습니다.
브라우저 탭이 같은 스페이스에 있을 때 서버가 그 게스트 안으로 터널을
심습니다.
브라우저 (VM)에서 접근
섹션 제목: “브라우저 (VM)에서 접근”같은 대화에서 인클로저 브라우저를 엽니다. localhost:<left-hand port>를
입력합니다 — 프로세스가 바인딩한 번호입니다. 리매핑(5173 → 3000)된
경우에도 그 브라우저에서는 오른쪽 번호로 응답하므로, 로컬 URL 복사도 거기서
작동합니다. 에이전트의 browser_use는 둘 중 어느 쪽으로든 이동할 수
있습니다. 스페이스 A의 서버는 스페이스 B의 브라우저에 localhost:5173으로
나타나지 않습니다.
LAN IP가 아니라 localhost를 사용하고, --host도 사용하지 않습니다.
게스트에는 자체 루프백이 있으며, 터널은 그곳에서 IPv4와 IPv6 모두로
리슨합니다.
한꺼번에 많은 연결을 여는 페이지(수십 개의 애셋, 라이브 리로드 소켓)는 그 같은 터널을 공유합니다. 브라우저 (VM)는 이들을 하나의 영속 exec로 멀티플렉싱하므로, 몰려든 페치가 연결마다 프로세스를 하나씩 생성하는 일도, 흰 페이지로 타임아웃되는 일도 없습니다.
한 스페이스 안에서 같은 번호라면 터미널 (VM) 전달이 호스트 셸보다 우선합니다. 스페이스 사이에는 우선순위가 없습니다 — 서로 별개의 맵입니다.
Android에서 접근
섹션 제목: “Android에서 접근”해당 스페이스의 Android 탭을 엽니다. 그러면 에뮬레이터의
localhost:<port>가 이 스페이스의 게시된 포트로 리버스됩니다
(adb reverse). 에뮬레이터는 기기 전역에 하나뿐입니다. 스페이스 B를
연결하면 :5173이 B로 재지정되고 A의 것은 제거됩니다. 탭을 닫으면 이 리그가
심어 둔 리버스가 제거됩니다.
iOS 시뮬레이터는 이미 Mac 자체이므로 리버스가 필요 없습니다. 실제 iPhone은 여전히 LAN 공유가 필요합니다.
네트워크에서 공유
섹션 제목: “네트워크에서 공유”⋯ → 로컬 네트워크에서 공유를 선택하면 포트가
<server-ip>:<random port>로 게시됩니다 — 휴대폰에서 페이지를 열거나,
서버가 다른 머신에서 실행될 때 유용합니다.
- LAN 포트는 항상 OS가 할당하며 게스트의 번호가 결코 아니므로, 노출되는 주소는 추측 가능한 주소가 아니라 의도적이고 눈에 보이는 주소입니다.
- 이 기능을 켜기 전까지는 비공개(루프백 전용)로 유지되며, ⋯ → 로컬 전용을 선택하면 다시 네트워크에서 내려갑니다.
이름 붙이기 — HTTPS와 함께
섹션 제목: “이름 붙이기 — HTTPS와 함께”**⋯ → 브라우저 도메인 설정 (.test)**은 포트에 myapp.test 같은 개발
도메인을 할당합니다. 그러면 브라우저 (VM) 안에서 https://myapp.test가
유효한 자물쇠와 함께 여러분의 서버를 로드합니다 — 이름이 있는 오리진이나
보안 컨텍스트에서 다르게 동작하는 모든 것(쿠키, 서비스 워커, OAuth 콜백)에
유용합니다.
- 도메인은
.test또는.localhost로 끝나야 합니다 — 개발용으로 예약된 두 TLD이므로, 개발용 이름이 실제 사이트를 가릴 수 없습니다. - 도메인 이름은 서버에서 고유하지만, 포트 번호는 그렇지 않습니다. 두
스페이스가 모두
5173을 사용할 수 있지만, 둘 다myapp.test를 차지할 수는 없습니다. - 인증서는 처음 필요할 때 여러분의 서버에서 생성된 로컬 인증 기관에서 발급됩니다. 그 키는 서버의 데이터 디렉터리 아래에 있으며 어떤 게스트에도 들어가지 않습니다. 인클로저 브라우저는 정확히 그 키 하나만 신뢰하므로, 실제 인터넷으로 향하는 TLS는 여전히 정상적으로 검증됩니다.
- 도메인은 브라우저 (VM) 내부에서만 확인됩니다. 호스트에 있는 여러분의
브라우저는 대신
localhost:<port>를 사용합니다. - 평문
http://myapp.test도 작동합니다.
수동으로 포트 전달
섹션 제목: “수동으로 포트 전달”패널 하단의 포트 추가는 수신 중인 것이 있기 전에(또는 있든 없든) 포트를 매핑합니다. 수동 전달은 서버가 재시작하는 동안에도 주소를 유지하며 — 서버가 돌아올 때까지 행에 수신 중 아님이 표시됩니다 — 자동 전달은 해당 포트가 사라지면 함께 사라집니다. 호스트 셸에서는 다른 로컬 포트를 설정할 수도 있습니다.
어떻게 격리되는가
섹션 제목: “어떻게 격리되는가”포트는 워크스페이스와 스페이스로 키가 지정됩니다. 하이퍼바이저 자체의 포트 맵은 머신이 부팅할 때 고정되므로, 터미널 (VM)은 서버가 통제하는 두 개의 좁은 채널을 탑니다. 하나는 게스트로 들어가는 미리 만들어진 인바운드 레인으로, 게스트가 실제로 리슨하지 않는 포트에는 접속을 거부합니다. 다른 하나는 서버가 브라우저 (VM)와 Android를 위해 열어 두는 리버스 터널입니다. 호스트 셸은 머신 전체를 스캔하지 않습니다. 서버가 넣지 않은 리스너는 게스트 안에 결코 만들어지지 않으며, 모든 것은 터미널이나 리그와 함께 정리됩니다. 설계는 리그와 인클로저에서 설명하며, 정확한 예약 포트와 도메인 규칙은 리그 레퍼런스에 있습니다.
관련 항목
섹션 제목: “관련 항목”- 에이전트에 테스트용 머신 제공 — 리그를 열고, 지켜보고, 넘겨받기
- 리그 레퍼런스 — 예약 포트, 개발용 TLD, 기본값