192.168.1.0/24를 4개로 쪼개면 시작 주소가 .0, .64, .128, .192에 떨어진다. 50번지에서 시작할 수는 없다. 서브네팅을 표로 외우면 /26은 64, /27은 32 같은 숫자가 손에 익지만, 비표준 경계나 VLSM 같은 변형이 나오면 무너진다.
CIDR 접두사는 네트워크 비트가 어디까지인지 가리키는 자리표시이고, 모든 경계 계산은 그 자리에서의 비트 연산으로 환원된다. 아래에서 그 비트 연산을 짚고, 파이썬 ipaddress로 실제 출력을 뽑아 검산한다.
/24 뒤의 숫자가 뜻하는 것
CIDR은 IP 주소 뒤에 슬래시와 네트워크 비트 수를 붙인다. 192.168.1.0/24는 앞 24비트가 네트워크, 나머지 8비트(32 - 24)가 호스트라는 뜻이다. IPv4 주소가 32비트이므로 접두사는 /0부터 /32까지 가능하며, /0(0.0.0.0/0)은 전체 인터넷을 가리키는 디폴트 라우트, /32는 단일 호스트다.
이진수로 펼치면 경계가 드러난다. 192.168.1.64/26은 다음과 같다.
주소 192.168.1.64 = 11000000.10101000.00000001.01000000
└──────── 26비트 네트워크 ──────┘└6 호스트┘
마스크 /26 = 11111111.11111111.11111111.11000000 (255.255.255.192)
마스크는 네트워크 비트가 전부 1, 호스트 비트가 전부 0인 32비트 값이다. /26이면 앞 26비트가 1이고 마지막 옥텟은 11000000 = 192가 되어, 마스크가 255.255.255.192다. 1을 몇 개 세웠는지만 보면 외울 필요가 없다.
자주 쓰는 대응 관계는 호스트 비트 n개에 주소 2ⁿ개라는 규칙의 반복이다.
| 접두사 | 마스크 | 호스트 비트 | 전체 주소 | 사용 가능 호스트 |
|---|---|---|---|---|
| /24 | 255.255.255.0 | 8 | 256 | 254 |
| /25 | 255.255.255.128 | 7 | 128 | 126 |
| /26 | 255.255.255.192 | 6 | 64 | 62 |
| /27 | 255.255.255.224 | 5 | 32 | 30 |
| /28 | 255.255.255.240 | 4 | 16 | 14 |
| /30 | 255.255.255.252 | 2 | 4 | 2 |
각 블록의 첫 주소는 네트워크 주소, 마지막 주소는 브로드캐스트 주소라 호스트에 줄 수 없다. 그래서 사용 가능 호스트는 항상 2ⁿ - 2다. 예외로 /31은 RFC 3021에 따라 라우터 간 점대점 링크에서 브로드캐스트 없이 주소 2개를 모두 호스트로 쓴다. /32는 호스트 하나이므로 호스트 라우트나 루프백에 쓴다.
서브넷 경계가 거기 떨어지는 이유
서브네팅은 접두사를 늘려 네트워크 부분을 키우고 호스트 부분을 줄이는 것이다. 192.168.1.0/24를 /26으로 쪼개면 64개씩 4개의 서브넷이 나온다. 파이썬으로 정확한 답부터 뽑는다.
import ipaddress
net = ipaddress.ip_network('192.168.1.0/24')
for s in net.subnets(new_prefix=26):
h = list(s.hosts())
print(f'{s} net={s.network_address} bcast={s.broadcast_address} '
f'usable={h[0]}-{h[-1]} ({len(h)} hosts)')
실제 출력:
192.168.1.0/26 net=192.168.1.0 bcast=192.168.1.63 usable=192.168.1.1-192.168.1.62 (62 hosts)
192.168.1.64/26 net=192.168.1.64 bcast=192.168.1.127 usable=192.168.1.65-192.168.1.126 (62 hosts)
192.168.1.128/26 net=192.168.1.128 bcast=192.168.1.191 usable=192.168.1.129-192.168.1.190 (62 hosts)
192.168.1.192/26 net=192.168.1.192 bcast=192.168.1.255 usable=192.168.1.193-192.168.1.254 (62 hosts)
시작 주소는 0, 64, 128, 192다. /26의 호스트 비트는 6개이고, 이 6비트가 한 서브넷 안에서 변하는 범위(0~63, 즉 64개)다. 따라서 네트워크의 시작 주소는 64의 배수여야 한다. 50에서 시작할 수 없는 까닭도 같다. 50의 마지막 옥텟은 00110010이라 호스트 비트(하위 6비트)가 0이 아니다. 시작 주소가 되려면 호스트 비트가 모두 0이어야 한다. 유효한 서브넷 경계는 호스트 비트가 전부 0인 주소다.
블록 소속 판정
한 주소가 특정 블록에 속하는지는 주소와 마스크를 AND 해서 나온 네트워크 주소가 블록의 네트워크 주소와 같은지로 판단한다.
192.168.1.75가 192.168.1.64/26에 속하는지 확인한다.
주소 192.168.1.75 = 11000000.10101000.00000001.01001011
마스크 /26 = 11111111.11111111.11111111.11000000
AND 결과 = 11000000.10101000.00000001.01000000 = 192.168.1.64 ✓
결과가 192.168.1.64라 블록의 네트워크 주소와 일치 → 속한다. 반면 192.168.1.200은 같은 마스크로 AND하면 192.168.1.192가 나와 일치하지 않는다. 파이썬으로 검산하면 다음과 같다.
import ipaddress
for ip in ['192.168.1.75', '192.168.1.200']:
a = ipaddress.ip_address(ip)
for s in ipaddress.ip_network('192.168.1.0/24').subnets(new_prefix=26):
if a in s:
print(f'{ip} -> {s}')
break
192.168.1.75 -> 192.168.1.64/26
192.168.1.200 -> 192.168.1.192/26
호스트 수에서 접두사 구하기
실무에서는 보통 반대 방향이다. “호스트 50개가 필요한데 어떤 블록을 줄까?” 절차는 세 단계다.
- 필요한 호스트 수에 2를 더한다 (네트워크 + 브로드캐스트 몫).
- 그 값 이상이 되는 가장 작은 2의 거듭제곱을 찾는다 → 호스트 비트 수.
32 - 호스트 비트= 접두사.
호스트 50개라면 50 + 2 = 52, 이를 담는 가장 작은 거듭제곱은 2⁶ = 64, 호스트 비트 6개 → /26이다. 같은 방식으로:
- 10개 →
12→2⁴ = 16→/28(14개 사용 가능) - 100개 →
102→2⁷ = 128→/25(126개) - 500개 →
502→2⁹ = 512→/23(510개)
라우터 간 점대점 링크는 호스트 2개면 되니 /30 또는 /31을 쓴다.
VLSM
고정 길이 마스크는 모든 서브넷을 같은 크기로 만든다. 100개짜리 부서와 2개짜리 라우터 링크를 같은 크기로 자르면 한쪽이 크게 낭비된다. VLSM은 서브넷마다 필요한 크기를 따로 정해 이 낭비를 없앤다.
할당은 큰 것부터 한다. 작은 것부터 배치하면 정렬 경계가 어긋나 단편화가 생긴다. 192.168.1.0/24 하나를 필요 크기에 맞춰 나누는 과정을 파이썬으로 검산했다.
import ipaddress
reqs = [('서버팜', 100), ('사무실', 50), ('DMZ', 10),
('P2P A', 2), ('P2P B', 2), ('P2P C', 2)]
cursor = int(ipaddress.ip_network('192.168.1.0/24').network_address)
for name, need in reqs:
bits = 0
while (2**bits) - 2 < need:
bits += 1
net = ipaddress.ip_network((cursor, 32 - bits))
print(f'{name:6s} 필요 {need:3d} -> {str(net):18s} ({net.num_addresses - 2} 사용 가능)')
cursor += net.num_addresses
서버팜 필요 100 -> 192.168.1.0/25 (126 사용 가능)
사무실 필요 50 -> 192.168.1.128/26 (62 사용 가능)
DMZ 필요 10 -> 192.168.1.192/28 (14 사용 가능)
P2P A 필요 2 -> 192.168.1.208/30 (2 사용 가능)
P2P B 필요 2 -> 192.168.1.212/30 (2 사용 가능)
P2P C 필요 2 -> 192.168.1.216/30 (2 사용 가능)
DMZ는 호스트 10개라 /27(30개)이 아니라 /28(14개)로 떨어진다. 필요한 만큼만 잘라야 뒤쪽에 192.168.1.224/27 한 블록이 통째로 남아 확장에 쓸 수 있다. 손으로 계산하면 이런 경계를 놓치기 쉽지만, 위 스크립트는 매번 호스트 비트를 정확히 계산해 커서를 옮긴다. 이 설계는 VLSM을 지원하는 라우팅 프로토콜(RIPv2, OSPF, EIGRP, IS-IS, BGP)에서만 동작한다. RIPv1과 IGRP는 지원하지 않는다.
슈퍼넷팅
슈퍼넷팅은 반대로 접두사를 줄여 여러 작은 네트워크를 하나로 합친다. 라우팅 테이블 항목을 줄여 라우터 메모리와 경로 탐색 시간을 아끼는 라우트 집약(route aggregation)의 핵심이다.
연속된 네 개의 /24를 묶는 과정도 파이썬으로 확인했다.
import ipaddress
nets = [ipaddress.ip_network(f'192.168.{i}.0/24') for i in range(4)]
print(list(ipaddress.collapse_addresses(nets))[0])
192.168.0.0/22
/22로 묶이는 이유는 이진수에서 드러난다. 192.168.0.0부터 192.168.3.255까지 앞 22비트가 공통이고 세 번째 옥텟의 하위 2비트(0~3)만 달라진다.
192.168.0.0 = 11000000.10101000.000000 00.00000000
192.168.3.255 = 11000000.10101000.000000 11.11111111
└──────── 공통 22비트 ───┘
이 22비트 공통 접두사가 곧 192.168.0.0/22다. ISP와 BGP 라우팅은 이 집약 덕분에 전 세계 라우팅 테이블을 관리 가능한 크기로 유지한다.