← posts/b.log()

blog92@web:~$ cat posts/network-03-ip-and-routing.md

NETWORK4 min read

풀스택 개발자를 위한 네트워크 3장 — 네트워크 계층: IP, 서브넷, NAT, 라우팅

CIDR 계산법과 사설 대역, NAT가 Rate Limit·WebRTC에 미치는 영향, 라우팅 테이블과 Docker 대역 충돌, MTU·PMTU 블랙홀, IPv6 환경의 ECONNREFUSED까지 네트워크 계층을 정리한다.

2장의 MAC 주소는 같은 링크 안에서만 통하는 주소였습니다. 이번 장은 링크를 넘어 최종 목적지까지 찾아가는 계층입니다.

3.1 IPv4 주소

  • 32비트, 점으로 구분한 4개의 옥텟: 192.168.10.25
  • 약 43억 개 → 이미 고갈 → 사설 IP와 NAT, 그리고 IPv6 등장

3.2 서브넷과 CIDR

IP 주소는 네트워크 부분과 호스트 부분으로 나뉩니다. 그 경계를 표시하는 것이 서브넷 마스크, 이를 줄여 쓰는 것이 CIDR 표기법입니다.

text
192.168.10.25/24
  → 앞 24비트가 네트워크: 192.168.10.0
  → 뒤 8비트가 호스트: 0 ~ 255
  → 서브넷 마스크: 255.255.255.0
CIDR서브넷 마스크전체 주소 수사용 가능 호스트
/32255.255.255.2551단일 호스트 지정
/30255.255.255.25242
/28255.255.255.2401614
/24255.255.255.0256254
/16255.255.0.065,53665,534
/8255.0.0.016,777,21616,777,214

사용 가능 호스트가 2개 적은 이유는 네트워크 주소(맨 앞) 와 브로드캐스트 주소(맨 뒤) 를 제외하기 때문입니다. (클라우드 VPC는 추가로 몇 개를 예약합니다. AWS는 서브넷마다 5개.)

계산 예시: 10.0.4.130/26은 어떤 네트워크에 속할까?

text
/26 → 블록 크기 = 2^(32-26) = 64
4번째 옥텟: 0, 64, 128, 192 단위로 나뉨
130은 128~191 구간 → 네트워크 10.0.4.128, 브로드캐스트 10.0.4.191
사용 가능: 10.0.4.129 ~ 10.0.4.190

개발자에게 중요한 이유: 방화벽 허용 규칙(10.10.0.0/16 허용), 클라우드 보안 그룹, Docker 네트워크 대역, Kubernetes Pod CIDR, Nginx allow/deny, DB의 pg_hba.conf가 모두 CIDR로 작성됩니다.

3.3 공인 IP와 사설 IP

RFC 1918에 정의된 사설 대역은 인터넷에서 라우팅되지 않습니다.

대역CIDR
10.0.0.0 ~ 10.255.255.25510.0.0.0/8
172.16.0.0 ~ 172.31.255.255172.16.0.0/12
192.168.0.0 ~ 192.168.255.255192.168.0.0/16

그 외 알아둘 특수 주소:

  • 127.0.0.0/8 — 루프백. 127.0.0.1 = 자기 자신
  • 0.0.0.0 — 서버 바인딩 시 "모든 인터페이스"
  • 169.254.0.0/16 — 링크 로컬. DHCP 실패 시 자동 할당, 클라우드 메타데이터 서버(169.254.169.254)
  • 100.64.0.0/10 — 통신사 NAT(CGNAT) 용도

자주 겪는 함정 — 127.0.0.1 vs 0.0.0.0 바인딩 개발 서버를 127.0.0.1에 바인딩하면 같은 머신에서만 접근됩니다. 컨테이너 안에서 서버를 127.0.0.1로 띄우면 포트를 publish해도 외부에서 접근할 수 없습니다. 컨테이너 안의 서버는 0.0.0.0으로 바인딩해야 합니다. (Vite의 --host, Next.js의 -H 0.0.0.0이 필요한 이유)

3.4 NAT (Network Address Translation)

사설 IP를 가진 장비가 인터넷에 나갈 때, 라우터가 출발지 주소를 공인 IP로 바꿔줍니다.

text
[내 PC 192.168.0.10:52000] → [공유기 NAT] → [공인 IP 203.0.113.5:40001] → 서버
  • SNAT(Source NAT): 출발지 변환. 내부 → 외부 통신 시.
  • DNAT(Destination NAT): 목적지 변환. 포트 포워딩. 외부 → 내부 서비스 노출 시.
  • PAT/NAPT: 포트까지 변환해 공인 IP 하나를 여럿이 공유.

개발자에게 미치는 영향:

  • 서버는 클라이언트의 진짜 IP를 모른다. 같은 회사 직원 수백 명이 서버 입장에선 하나의 IP로 보입니다. IP 기반 Rate Limit을 걸 때 주의해야 합니다.
  • 외부에서 먼저 내부로 연결할 수 없다. 이것이 WebRTC에 STUN/TURN이 필요한 이유입니다(9장).
  • Docker의 포트 매핑(-p 8080:80)도 내부적으로 iptables DNAT입니다.

3.5 라우팅

라우터는 라우팅 테이블을 보고 "이 목적지로 가려면 다음에 어디로 보내야 하는가"를 결정합니다. 가장 구체적인(prefix가 긴) 규칙이 우선합니다(Longest Prefix Match).

bash
ip route
# default via 192.168.0.1 dev eth0          ← 나머지는 전부 게이트웨이로
# 192.168.0.0/24 dev eth0 scope link         ← 같은 대역은 직접 전달
# 172.17.0.0/16 dev docker0                  ← Docker 브리지 대역

실무 사례 — Docker 대역 충돌: Docker 기본 브리지는 172.17.0.0/16을 사용합니다. 사내망에 172.17.x.x 대역 서버가 있으면, 서버의 라우팅 테이블이 해당 트래픽을 docker0으로 보내버려 특정 사내 서버에만 접속이 안 되는 기이한 현상이 생깁니다. 폐쇄망/사내 서버에 Docker를 설치할 때는 /etc/docker/daemon.json의 bip, default-address-pools로 대역을 미리 지정하는 것이 안전합니다.

json
{
  "bip": "10.200.0.1/24",
  "default-address-pools": [
    { "base": "10.201.0.0/16", "size": 24 }
  ]
}

3.6 ICMP, TTL, traceroute

  • ICMP: IP 계층의 제어/오류 메시지 프로토콜. ping이 사용.
  • TTL(Time To Live): 패킷이 거칠 수 있는 최대 라우터 수. 라우터를 지날 때마다 1씩 감소, 0이 되면 폐기하고 ICMP Time Exceeded를 돌려보냄.
  • traceroute: TTL을 1, 2, 3...으로 늘려가며 경로상의 라우터를 찾아냄.

주의: 많은 기업망/클라우드는 ICMP를 차단합니다. ping이 안 된다고 서버가 죽은 것이 아닙니다. 포트 단위로 확인해야 합니다(14장).

3.7 MTU와 단편화

  • MTU: 링크 계층이 한 번에 보낼 수 있는 최대 크기. 이더넷 기본 1500바이트.
  • MSS: TCP 페이로드 최대 크기. 보통 1500 − IP 헤더 20 − TCP 헤더 20 = 1460.
  • VPN, 터널(VXLAN, IPsec), PPPoE를 거치면 헤더가 추가되어 실제 MTU가 줄어듭니다.

증상: "작은 요청은 잘 되는데 큰 응답(또는 TLS 핸드셰이크의 긴 인증서)에서 멈춘다", "VPN 붙이면 특정 사이트만 안 열린다" → MTU 문제(PMTU 블랙홀) 를 의심하세요. ICMP 차단 때문에 "패킷이 너무 크다"는 신호가 발신자에게 돌아오지 못해 생깁니다.

3.8 IPv6 간단 정리

  • 128비트: 2001:0db8:0000:0000:0000:ff00:0042:8329 → 2001:db8::ff00:42:8329
  • NAT 없이 모든 장비에 공인 주소 부여 가능
  • 루프백은 ::1, 모든 인터페이스는 ::
  • 개발 시 주의: Node.js 17+부터 localhost 해석 시 OS 설정 순서를 따르면서 ::1이 먼저 나올 수 있습니다. 서버는 127.0.0.1(IPv4)에만 떠 있는데 클라이언트가 ::1로 붙어 ECONNREFUSED가 나는 사례가 흔합니다. 이럴 땐 127.0.0.1을 명시하세요.
COMMENTS (…)

댓글을 불러오는 중이에요.

NEW COMMENT0 / 1000
⌘↵ 전송

blog92@web:~$ cd ..