Mac에서 켜 둔 웹페이지를 스마트폰으로 보고 싶다. 컴퓨터에서는 http://localhost:4173으로 잘 열리는데, 휴대폰에 같은 주소를 입력하면 아무것도 나오지 않는다. 집 Wi-Fi에서 열리던 주소가 밖에서는 먹히지 않기도 한다. 페이지는 그대로인데, 접속하는 기기와 장소가 바뀌면 무엇이 달라질까?
접속을 이해하려면 주소를 읽는 일과 서버가 연결을 받는 일을 함께 봐야 한다. IP 주소는 네트워크상의 목적지를, 포트는 그 목적지의 통신 창구를 가리킨다. 바인딩은 서버가 받을 주소와 포트를 정하는 일이고, 프로세스는 실제로 실행 중인 프로그램이다. 여기에 목적지까지 가는 경로와 접근 허용이 갖춰져야 페이지가 열린다.
이 글에서는 Mac의 Node 서버가 TCP 4173에서 웹페이지를 제공하고, 스마트폰으로 접속하는 상황을 따라간다. 4173은 이 예시 서버에서 사용하는 포트이며, 서버 설정에 따라 다른 번호를 쓸 수 있다.

서로 다른 출발 경로에서 같은 컴퓨터의 서버로 도착한다는 개념을 그린 이미지다. 실제 네트워크 구성이나 제품 화면을 보여주는 자료는 아니다.
IP와 포트는 어디까지 알려줄까
http://100.x.y.z:4173을 보면 http는 대화 방식, 100.x.y.z는 목적지 IP, 4173은 목적지 포트다. 여기서 x.y.z는 설명을 위한 자리 표시이며, 접속할 때는 Mac에 실제로 할당된 숫자를 사용한다.
| 개념 | 답하는 질문 | 이 글의 예 |
|---|---|---|
| IP 주소 | 네트워크의 어느 주소로 보낼까? | Mac의 LAN 주소 또는 Tailscale 주소 |
| 포트 | 그 주소의 어느 통신 창구로 보낼까? | TCP 4173 |
| 바인딩 | 서버가 어느 로컬 주소와 포트를 사용할까? | 127.0.0.1:4173 또는 0.0.0.0:4173 |
| 프로세스 | 실제로 어떤 프로그램이 요청을 처리할까? | 실행 중인 Node 프로그램 |
IP를 기기의 이름표로 생각하면 출발하기는 쉽다. 다만 컴퓨터 한 대에도 여러 주소가 붙는다. Mac의 Wi-Fi 주소, Tailscale 주소, 자기 자신을 가리키는 루프백 주소는 모두 다른 역할을 한다. 따라서 “Mac의 IP가 뭐야?” 다음에는 “어떤 경로로 접속할 건데?”가 따라온다.
포트는 운영체제가 통신을 구분할 때 사용하는 번호다. TCP와 UDP는 각각 포트 번호를 사용하며, 같은 숫자라도 서로 다른 통신 창구다. 번호 범위는 0–65535이고 0은 예약되어 있다. IANA 포트 등록부
하나의 서비스 포트를 여러 프로세스가 함께 쓰는 구성도 있다. 예를 들어 Node의 cluster는 여러 워커가 같은 서버 포트의 연결을 나눠 처리하게 한다. 포트 번호만 보고 요청을 처리하는 프로세스가 하나라고 단정하기는 어렵다. Node.js cluster 문서
방문자가 여럿이어도 같은 4173 포트로 접속할 수 있다. TCP는 양쪽의 IP와 포트 조합으로 연결을 구분한다. 스마트폰 쪽에도 출발 포트가 생기므로, 같은 서버 포트를 향한 여러 연결을 따로 관리할 수 있다. TCP 표준 RFC 9293
localhost가 휴대폰에서는 다른 곳을 가리킨다
localhost와 IPv4 루프백 주소 127.0.0.1은 “지금 이 요청을 보내는 기기 자신”을 가리킨다. Mac에서 입력하면 Mac, 스마트폰에서 입력하면 스마트폰이다. 루프백 주소는 일반적인 외부 목적지로 전달되지 않는다. IANA 특수 목적 IPv4 주소 등록부
그러니 휴대폰에서는 Mac의 실제 LAN 주소나 Tailscale 주소를 써야 한다. 주소를 제대로 골랐는데도 접속되지 않으면, 그다음은 서버가 어디에서 기다리는지 볼 차례다.
바인딩은 받을 주소를 정한다
서버가 127.0.0.1:4173에만 바인딩되어 있으면, Mac 자신의 루프백으로 들어오는 연결을 받는다. 휴대폰이 Mac의 다른 IP로 보낸 요청은 이 리스너의 대상이 아니다. 여기서 리스너는 새 연결을 기다리는 서버 측 소켓을 뜻한다.
0.0.0.0:4173은 하나의 IPv4 주소를 고르지 않고 모든 로컬 IPv4 주소에서 받겠다는 설정이다. 휴대폰 브라우저에 넣을 목적지는 여전히 Mac의 실제 주소다. 0.0.0.0을 “누구나 찾아오는 공개 주소”로 생각하면 안 된다.
Node에서 host를 생략하면 IPv6를 사용할 수 있을 때 ::, 그렇지 않으면 0.0.0.0에서 기다린다. IPv6 리스너가 IPv4도 받는지는 운영체제와 설정에 영향을 받는다. 접속 문제를 확인할 때는 서버 로그에 나온 주소와 실제 리스닝 상태를 함께 살펴보자. Node.js server.listen 문서
| 서버가 받도록 설정한 주소 | 의미 | 이것만으로 보장되지 않는 것 |
|---|---|---|
127.0.0.1:4173 |
Mac의 루프백 주소에서 대기 | 휴대폰에서 직접 접근 |
192.168.x.x:4173 |
해당 LAN 주소에서 대기 | 같은 Wi-Fi의 모든 기기에서 접근 |
100.x.y.z:4173 |
해당 Tailscale 주소에서 대기 | 모든 Tailnet 구성원의 접근 허용 |
0.0.0.0:4173 |
모든 로컬 IPv4 주소에서 대기 | 인터넷 공개, 방화벽 허용, 로그인 |
서버가 기다리는 주소를 확인했다면 경로·방화벽·접근 정책도 살펴봐야 한다. 바인딩이 올바르게 되어 있어도, 중간에서 연결을 막으면 요청은 서버까지 도착하지 못한다.
같은 Wi-Fi라면 인터넷을 돌아올 필요가 없다
스마트폰과 Mac이 서로 통신할 수 있는 같은 LAN에 있다면, 휴대폰은 Mac의 LAN 주소로 접속한다. Wi-Fi 액세스 포인트 등을 거쳐 Mac에 도착하고, 운영체제가 요청을 해당 서버 소켓으로 전달한다. 이 통신은 인터넷을 나갔다 돌아오는 과정이 필요 없다.
같은 Wi-Fi 이름이 보여도 게스트 네트워크나 기기 간 통신 차단 설정, Mac의 방화벽 때문에 접속이 막힐 수 있다. 이때는 바인딩에 더해 네트워크의 접근 제한을 확인해야 한다.
집 밖에서 192.168.x.x를 입력했을 때도 문제가 달라진다. 이런 사설 주소는 공개 인터넷에서 집의 Mac을 유일하게 가리키지 않는다. 다른 집에서도 같은 번호를 사용한다. 이동통신망에서 집 LAN으로 들어오는 별도의 경로가 필요하다. 사설 주소가 전역적으로 통용되지 않는다는 원칙은 RFC 1918에 정리되어 있다.
Tailscale은 밖에서 들어오는 경로를 만든다
Tailscale을 양쪽 기기에 연결하면, 물리적으로 다른 네트워크에 있는 스마트폰과 Mac을 하나의 사설 네트워크인 Tailnet으로 연결할 수 있다. Tailscale의 IPv4 주소는 보통 100.64.0.0/10, 즉 100.64.0.0–100.127.255.255 범위를 사용한다. 100으로 시작하는 주소 전체가 Tailscale 주소인 것은 아니다. Tailscale 주소 문서
IANA는 이 대역을 공유 주소 공간으로 분류하며, 공개 인터넷에서 전역적으로 도달할 수 있는 주소로 취급하지 않는다. IANA IPv4 등록부
두 기기는 처음에 DERP 중계를 이용해 연결 정보를 주고받으며 직접 경로를 시도한다. 직접 연결이 어려우면 사용 가능한 Peer Relay를 이용하거나 DERP 중계를 유지한다. 세 방식 모두 WireGuard로 종단 간 암호화되며, 직접 연결이 일반적으로 지연 시간과 처리량에 유리하다. Tailscale 연결 방식
이 구성에서는 웹 서버의 4173을 집 공유기에서 공개 포트포워딩할 필요가 없다. 다만 네트워크가 Tailscale 연결 자체를 막는다면 그 제한부터 확인해야 한다.
실제 요청의 흐름을 순서로 적으면 이렇다.
- 스마트폰 브라우저가 Mac의 Tailscale 주소와 TCP
4173으로 연결을 시도한다. - 양쪽 Tailscale이 직접 연결 또는 중계를 통해 트래픽을 전달한다.
- 접근 정책과 Mac의 방화벽이 허용하고, 해당 주소·포트에서 리스너가 기다리면 연결이 성립한다.
- Node 프로그램이 HTTP 요청을 처리하고, 브라우저가 응답을 받아 페이지를 보여준다.
같은 Tailnet 안에서도 Tailscale의 grants나 ACL 같은 정책은 어떤 사용자·기기가 어느 목적지와 포트에 접근할지 제한할 수 있다. 서버가 연결을 받고 있는지와 해당 사용자에게 접근 권한이 있는지를 따로 확인해야 한다. Tailscale grants 문서
페이지가 안 열릴 때는 한 단계씩 좁힌다
설정을 한꺼번에 바꾸면 무엇이 문제였는지 알기 어렵다. 아래 순서대로 확인 범위를 좁혀보자. 같은 증상에도 원인이 여럿일 수 있으므로, 각 항목은 진단을 시작할 지점으로 보면 된다.
| 관찰한 상황 | 먼저 확인할 것 |
|---|---|
| Mac에서도 페이지가 안 열린다 | 서버 프로세스가 실행 중인지, 포트가 정말 4173인지, 서버 로그에 오류가 있는지 |
| Mac에서는 열리고 휴대폰에서는 안 열린다 | 휴대폰 주소에 localhost를 쓰지 않았는지, 서버가 루프백에만 바인딩됐는지 |
| 같은 Wi-Fi인데 LAN 주소로 안 열린다 | Mac의 현재 LAN 주소, 방화벽, 게스트 네트워크·기기 간 통신 차단 |
| LAN으로는 되는데 Tailscale 주소로 안 된다 | 양쪽 Tailscale 연결, 목적지 주소, 접근 정책, 해당 주소의 리스너 |
| 연결은 되는데 오류 페이지가 나온다 | HTTP 상태와 서버 로그, 요청한 경로, 애플리케이션의 인증 조건 |
Tailscale도 연결 문제를 조사할 때 기기 상태, 정책, 방화벽과 서비스를 함께 확인하도록 안내한다. VPN 연결 표시 하나로 웹 서버의 정상 동작까지 확인할 수는 없다. Tailscale 연결 문제 해결
Mac의 launchd로 서버 실행을 관리한다면 작업 설정도 확인하자. 재시작 여부는 KeepAlive 같은 설정에 따라 달라진다. 소켓을 미리 열어 프로그램에 넘기는 구성도 가능하지만, 프로세스 관리가 외부 네트워크 경로나 애플리케이션 인증을 대신하지는 않는다. Apple launchd 안내
http://Mac의-실제-IP:4173에서 IP를 바꾸는 일, 서버의 바인딩을 바꾸는 일, Tailscale 정책을 바꾸는 일은 서로 다른 문제를 푼다. 다음에 페이지가 열리지 않으면 “서버가 안 된다”에서 멈추지 말고, 어느 주소로 보냈고, 어떤 경로를 지났으며, 도착한 곳에 무엇이 기다리고 있는지부터 확인하면 된다.