본문 바로가기
TYLER SONGBlog
← Blog index
CS10 min read

Network: IP 주소와 라우팅으로 서로 다른 네트워크를 연결하는 계층

네트워크 계층(Network Layer)은 인터넷 프로토콜(IP) 주소를 사용해 서로 다른 네트워크 사이로 패킷(Packet)을 전달한다. 라우터(Router)는 목적지 주소와 라우팅 테이블(Routing Table)을 비교하고, 최장 접두사 일치(Longest Prefix Match)로 다음 홉(Next Hop)을 선택한다. IP는 패킷 도착, 순서, 중

By 송민성

1. 개념

네트워크 계층(Network Layer)은 개방형 시스템 상호 연결 모형(OSI Model)의 3계층이다. 서로 다른 네트워크에 있는 호스트 사이에서 패킷(Packet)이 이동할 경로를 결정한다.

인터넷에서는 인터넷 프로토콜(Internet Protocol, IP)이 네트워크 계층의 중심 역할을 한다.

주요 기능은 다음과 같다.

  • 논리 주소 지정(Logical Addressing): IP 주소로 호스트와 네트워크 식별
  • 라우팅(Routing): 목적지까지 도달할 경로 계산
  • 포워딩(Forwarding): 라우팅 테이블에 따라 패킷을 다음 인터페이스로 전달
  • 단편화(Fragmentation): 일부 환경에서 전송 가능한 크기에 맞게 패킷 분할
  • 오류 보고(Error Reporting): 인터넷 제어 메시지 프로토콜(ICMP)로 전달 실패나 진단 정보 전송

IP는 비연결형(Connectionless), 최선형 전달(Best-Effort Delivery) 프로토콜이다. 패킷을 보내기 전에 연결을 만들지 않으며 다음 항목을 보장하지 않는다.

  • 목적지 도착
  • 도착 순서
  • 중복 방지
  • 손상된 패킷 복구

전송 제어 프로토콜(Transmission Control Protocol, TCP)은 이런 한계를 전송 계층에서 보완한다.

2. 왜 사용하는가

매체 접근 제어 주소(Media Access Control Address, MAC Address)는 같은 링크 안에서 프레임(Frame)을 전달할 때 사용한다. 라우터를 넘어 다른 네트워크로 이동하려면 계층적인 IP 주소와 라우팅이 필요하다.

text
호스트 A
192.168.1.10
    │
    │ 이더넷 프레임
    ▼
라우터 1 ───── 라우터 2 ───── 호스트 B
192.168.1.1                    10.0.0.20
         IP 패킷 전달

호스트 A가 호스트 B로 데이터를 보낼 때 목적지 IP 주소는 10.0.0.20으로 유지된다. 각 링크에서 사용하는 출발지와 목적지 MAC 주소는 라우터를 지날 때마다 바뀐다.

계층적인 IP 주소는 개별 호스트가 아니라 네트워크 범위를 하나의 경로로 묶을 수 있게 한다.

text
10.0.0.0/8      → 10으로 시작하는 약 1,677만 개 주소
10.20.0.0/16    → 10.20으로 시작하는 65,536개 주소
10.20.30.0/24   → 10.20.30으로 시작하는 256개 주소

라우터는 모든 호스트의 주소를 따로 저장하지 않고 이런 네트워크 접두사(Network Prefix)를 라우팅 테이블에 저장한다.

3. 동작 원리

IP 주소와 서브넷

인터넷 프로토콜 버전 4(IPv4) 주소는 32비트다. 사람이 읽기 쉽도록 8비트씩 나누어 십진수로 표현한다.

text
192.168.10.34

클래스 없는 도메인 간 라우팅(Classless Inter-Domain Routing, CIDR) 표기법은 주소 뒤에 네트워크 접두사 길이를 붙인다.

text
192.168.10.34/24

/24는 앞의 24비트가 네트워크 부분이라는 뜻이다.

text
IP 주소:       192.168.10.34
서브넷 마스크: 255.255.255.0
네트워크 주소: 192.168.10.0
브로드캐스트:  192.168.10.255
호스트 범위:   192.168.10.1 ~ 192.168.10.254

일반적인 IPv4 서브넷에서 전체 주소 수는 다음과 같다.

text
전체 주소 수 = 2^(32 - 접두사 길이)

/24에는 2^8 = 256개의 주소가 있다. 전통적인 브로드캐스트 서브넷에서는 네트워크 주소와 브로드캐스트 주소를 제외한 254개를 호스트에 할당할 수 있다. /31은 지점 간 링크(Point-to-Point Link)에서 두 주소를 모두 사용할 수 있으며, /32는 단일 호스트 경로를 나타낸다.

같은 네트워크인지 판단하기

호스트는 자신의 서브넷 마스크를 사용해 목적지가 같은 네트워크에 있는지 판단한다.

text
자신의 네트워크 주소 = 자신의 IP 주소 AND 서브넷 마스크
목적지 네트워크 주소 = 목적지 IP 주소 AND 서브넷 마스크

두 결과가 같으면 목적지로 직접 전송한다. 다르면 기본 게이트웨이(Default Gateway)로 전송한다.

text
출발지: 192.168.10.34/24

목적지 192.168.10.80
→ 같은 192.168.10.0/24
→ 목적지의 MAC 주소를 확인해 직접 전송

목적지 10.0.0.20
→ 다른 네트워크
→ 기본 게이트웨이의 MAC 주소를 확인해 전송

IPv4에서는 주소 결정 프로토콜(Address Resolution Protocol, ARP)로 다음 전달 대상의 IPv4 주소에 대응하는 MAC 주소를 확인한다.

라우팅과 포워딩

라우팅은 경로 정보를 만들고 갱신하는 과정이다. 포워딩은 실제 패킷마다 라우팅 테이블을 조회해 출력 인터페이스와 다음 홉을 선택하는 과정이다.

라우팅 테이블은 대략 다음 정보를 가진다.

목적지 네트워크다음 홉출력 인터페이스
192.168.10.0/24직접 연결eth0
10.20.0.0/16172.16.0.2eth1
10.0.0.0/8172.16.0.6eth2
0.0.0.0/0203.0.113.1eth3

목적지 10.20.30.40은 10.20.0.0/16, 10.0.0.0/8, 0.0.0.0/0에 모두 포함된다. 라우터는 가장 구체적인 /16 경로를 선택한다. 이를 최장 접두사 일치(Longest Prefix Match)라고 한다.

일치하는 경로가 없으면 기본 경로(Default Route)인 0.0.0.0/0을 사용한다. 기본 경로도 없으면 패킷을 폐기한다.

라우터를 통과할 때

IPv4 패킷이 라우터를 하나 통과하는 과정은 다음과 같다.

  1. 입력 인터페이스에서 프레임을 수신한다.
  2. 프레임에서 IP 패킷을 꺼낸다.
  3. 헤더 검사합(Header Checksum)과 목적지 IP 주소를 확인한다.
  4. 생존 시간(Time To Live, TTL)을 1 줄인다.
  5. TTL이 0이면 패킷을 폐기하고 ICMP 시간 초과 메시지를 보낸다.
  6. 라우팅 테이블에서 최장 접두사 일치 경로를 찾는다.
  7. 다음 링크에 맞는 새 프레임으로 감싸 출력 인터페이스로 보낸다.

TTL은 라우팅 오류로 패킷이 무한히 순환하는 상황을 막는다. IPv6에서는 같은 필드를 홉 제한(Hop Limit)이라고 부른다.

4. 코드 예제

파이썬 표준 라이브러리의 ipaddress를 사용해 서브넷 계산과 최장 접두사 일치를 구현할 수 있다.

python
from dataclasses import dataclass from ipaddress import IPv4Address, IPv4Network @dataclass(frozen=True) class Route: network: IPv4Network next_hop: IPv4Address interface: str ROUTES = [ Route( network=IPv4Network("192.168.10.0/24"), next_hop=IPv4Address("192.168.10.1"), interface="eth0", ), Route( network=IPv4Network("10.20.0.0/16"), next_hop=IPv4Address("172.16.0.2"), interface="eth1", ), Route( network=IPv4Network("10.0.0.0/8"), next_hop=IPv4Address("172.16.0.6"), interface="eth2", ), Route( network=IPv4Network("0.0.0.0/0"), next_hop=IPv4Address("203.0.113.1"), interface="eth3", ), ] def find_route(destination: str, routes: list[Route]) -> Route | None: destination_ip = IPv4Address(destination) matches = [ route for route in routes if destination_ip in route.network ] if not matches: return None return max(matches, key=lambda route: route.network.prefixlen) def show_subnet(cidr: str) -> None: network = IPv4Network(cidr, strict=False) print(f"네트워크 주소: {network.network_address}") print(f"브로드캐스트 주소: {network.broadcast_address}") print(f"전체 주소 수: {network.num_addresses}") if network.prefixlen <= 30: print(f"첫 번째 호스트: {network.network_address + 1}") print(f"마지막 호스트: {network.broadcast_address - 1}") def main() -> None: show_subnet("192.168.10.34/24") destinations = [ "10.20.30.40", "10.99.1.5", "8.8.8.8", ] for destination in destinations: route = find_route(destination, ROUTES) if route is None: print(f"{destination}: 경로 없음") continue print( f"{destination}: " f"{route.network} 경로 선택, " f"다음 홉 {route.next_hop}, " f"인터페이스 {route.interface}" ) assert find_route("10.20.30.40", ROUTES) == ROUTES[1] assert find_route("10.99.1.5", ROUTES) == ROUTES[2] assert find_route("8.8.8.8", ROUTES) == ROUTES[3] if __name__ == "__main__": main()

실행 결과에서 10.20.30.40은 /8보다 접두사가 긴 /16 경로를 선택한다.

운영체제의 실제 라우팅 테이블은 다음 명령으로 확인할 수 있다.

shell
ip route

목적지까지 패킷이 거치는 라우터는 다음 명령으로 확인한다.

shell
traceroute example.com

traceroute는 TTL을 점차 증가시킨 패킷을 보내고 각 라우터가 반환하는 ICMP 시간 초과 메시지를 이용한다. 방화벽이나 라우터 정책이 ICMP 응답을 차단하면 일부 홉이 표시되지 않을 수 있다.

5. 시간 복잡도 또는 성능 특성

예제의 find_route는 라우팅 항목을 모두 검사하므로 라우팅 항목 수가 R일 때 시간복잡도가 O(R)이다. 추가로 만든 일치 목록은 최악의 경우 O(R) 공간을 사용한다.

실제 라우터는 선형 탐색 대신 트라이(Trie), 압축 트라이(Compressed Trie), 테너리 콘텐츠 주소화 메모리(Ternary Content-Addressable Memory, TCAM) 같은 구조를 사용한다. 구현과 하드웨어에 따라 조회 성능과 메모리 비용이 달라진다.

IP 패킷 크기는 링크의 최대 전송 단위(Maximum Transmission Unit, MTU)에 영향을 받는다. 일반적인 이더넷 MTU는 1,500바이트다.

IPv4에서 패킷이 MTU보다 크면 라우터가 단편화할 수 있다. 단편 금지(Don't Fragment, DF) 비트가 설정되어 있으면 라우터는 패킷을 폐기하고 ICMP 메시지를 보낸다. IPv6 라우터는 패킷을 단편화하지 않는다. 송신 호스트가 경로 MTU 탐색(Path MTU Discovery) 결과에 맞춰 크기를 조절한다.

단편 하나가 손실되면 상위 계층 데이터 전체의 재조립이 실패할 수 있으므로 단편화는 성능과 안정성에 불리하다.

6. 실무 사용 사례

웹 서버의 기본 게이트웨이

웹 서버가 다른 서브넷의 데이터베이스나 외부 API에 접근할 때 기본 게이트웨이로 패킷을 보낸다. 기본 경로가 없거나 잘못 설정되면 같은 서브넷 통신은 되지만 외부 통신은 실패한다.

클라우드 가상 네트워크

가상 사설 클라우드(Virtual Private Cloud, VPC)는 CIDR 범위로 네트워크를 정의한다. 서브넷, 라우팅 테이블, 인터넷 게이트웨이, 네트워크 주소 변환(Network Address Translation, NAT) 게이트웨이가 IP 경로를 제어한다.

CIDR 범위가 겹치면 VPC 피어링이나 가상 사설망(Virtual Private Network, VPN) 연결에서 목적지 경로를 구분하기 어렵다.

컨테이너와 쿠버네티스

컨테이너(Container)와 파드(Pod)는 각각 가상 IP 주소를 받을 수 있다. 컨테이너 네트워크 인터페이스(Container Network Interface, CNI) 구현은 라우팅, 터널링(Tunneling), 네트워크 주소 변환 등을 사용해 노드 간 통신을 구성한다.

장애 분석

다음 순서로 범위를 좁힐 수 있다.

  1. 인터페이스에 올바른 IP 주소와 접두사가 있는지 확인한다.
  2. 목적지가 같은 서브넷인지 계산한다.
  3. 기본 게이트웨이와 목적지 경로가 있는지 확인한다.
  4. traceroute로 패킷이 멈추는 구간을 찾는다.
  5. 방화벽, 보안 그룹, NAT 설정을 확인한다.

7. 주의할 점

IP 주소와 MAC 주소를 같은 식별자로 보면 안 된다

IP 주소는 네트워크 간 라우팅에 사용된다. MAC 주소는 현재 링크의 다음 전달 대상에 프레임을 보내는 데 사용된다. 라우터를 통과하면 프레임의 MAC 주소는 바뀌지만 일반적인 전달 과정에서 IP 패킷의 목적지 주소는 유지된다.

서브넷 범위를 문자열 앞부분으로 판단하면 안 된다

192.168.1.20과 192.168.10.20은 문자열이 비슷해도 같은 네트워크라는 뜻이 아니다. IP 주소와 서브넷 마스크의 비트 연산으로 판단해야 한다.

NAT를 라우팅과 혼동하면 안 된다

라우팅은 목적지에 맞는 경로를 선택한다. NAT는 패킷의 출발지 또는 목적지 IP 주소와 포트를 변환한다. 두 기능은 함께 사용될 수 있지만 같은 작업이 아니다.

ping 실패만으로 서버 장애를 단정하면 안 된다

ping은 ICMP 에코 요청(Echo Request)을 사용한다. 서버나 중간 방화벽이 ICMP를 차단해도 TCP 기반 웹 서비스는 정상일 수 있다. 실제 서비스 포트 연결도 함께 검사해야 한다.

사설 IP 주소는 인터넷에서 직접 라우팅되지 않는다

대표적인 IPv4 사설 주소 범위는 다음과 같다.

범위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

사설 주소의 호스트가 인터넷과 통신하려면 일반적으로 NAT를 거친다.

8. 핵심 정리

  • 네트워크 계층(Network Layer)은 IP 주소와 라우팅으로 서로 다른 네트워크를 연결한다.
  • 호스트는 서브넷 마스크로 목적지가 같은 네트워크인지 판단하고, 다른 네트워크면 기본 게이트웨이로 보낸다.
  • 라우터는 라우팅 테이블에서 최장 접두사 일치(Longest Prefix Match) 경로를 선택한다.
  • IP는 최선형 전달(Best-Effort Delivery)을 제공하며 도착, 순서, 재전송을 보장하지 않는다.
  • 목적지 IP 주소는 종단까지 사용되지만 링크별 MAC 주소는 라우터를 통과할 때마다 바뀐다.