Packet Forwarding
목적지 IP까지 경로 추적하기 글에서 L3(라우팅)와 L2(스위칭) 두 계층에서 경로를 찾아가는 과정을 정리했다면, 이 글에서는 두 계층 사이에서 패킷이 어떻게 포워딩되는지를 정리한다. 이 과정을 이해하면 왜 라우팅 테이블과 MAC 테이블을 차례로 보면서 호스트까지 찾아가는지를 자연스럽게 이해할 수 있다.
0. Decapsulation
데이터는 보낼 때 위 계층에서 아래 계층으로 내려가며 헤더가 하나씩 덧붙는다(encapsulation). 받을 때는 반대로 아래에서 위로 올라가며 헤더를 하나씩 벗긴다(decapsulation).
| 계층 | PDU | 붙는 헤더 | 핵심 주소 |
|---|---|---|---|
| L7~L5 | Data | - | - |
| L4 | Segment | TCP/UDP 헤더 | Port |
| L3 | Packet | IP 헤더 | IP 주소 |
| L2 | Frame | Ethernet 헤더 + FCS | MAC 주소 |
| L1 | Bits | - | - |
L2에서 만들어지는 이더넷 프레임의 구조는 다음과 같다. 출발지와 목적지 MAC, 오류 검출용 FCS(Frame Check Sequence = CRC, Cyclic Redundancy Check)가 있다.

1. 라우터가 패킷을 받았을 때의 decapsulation
라우터(혹은 L3 스위치)가 프레임을 수신하면 아래 순서로 헤더를 벗기고 검사한다.
1) 이더넷 헤더 확인 — "이거 나한테 온 거 맞아?"
가장 먼저 보는 건 L2, 즉 Ethernet 헤더의 목적지 MAC 주소다.
- 목적지 MAC이 수신 인터페이스의 MAC(또는 브로드캐스트/해당 멀티캐스트)이면 → "나에게 온 프레임"으로 보고 처리를 이어간다.
- 목적지 MAC이 내 것이 아니면 → L3까지 올라가지 않고 그냥 폐기한다. (단, 스위치라면 폐기 대신 MAC 테이블을 보고 해당 포트로 그대로 흘려보낸다. 이게 L2 스위칭이다.)
이때 끝에 붙은 FCS로 프레임이 전송 중 깨지지 않았는지 검사하고, 이상 없으면 L2 헤더를 벗긴다. → decapsulation 1단계 완료
포인트: 라우터는 "내 MAC으로 온 프레임"만 L3로 올린다. 그래서 호스트는 다른 서브넷으로 보낼 때 목적지 IP는 최종 목적지로 두되, 목적지 MAC은 게이트웨이의 MAC으로 채워 보낸다.
2) IP 헤더 확인 — "그래서 어디로 가야 하지?"
L2 헤더를 벗기면 IP 헤더(L3) 가 드러난다. 라우터는 여기서 목적지 IP 주소를 꺼내 라우팅 테이블을 조회한다.
이 단계에서 라우터가 하는 일:
- TTL 1 감소 → 0이 되면 폐기하고 ICMP Time Exceeded 응답 (traceroute가 동작하는 원리)
- 목적지 IP로 라우팅 테이블 검색 → longest prefix match로 가장 구체적인 경로 선택
- TTL이 바뀌었으니 IP 헤더 체크섬 재계산
2. 라우팅 테이블 조회 — L3 경로 결정
라우팅 테이블 조회 결과는 두 갈래다.
| 결과 | 의미 | 다음 동작 |
|---|---|---|
| next-hop = 다른 라우터 | 목적지가 아직 멀리 있음 | 그 라우터로 포워딩 (hop 반복) |
| directly connected | 목적지가 내가 물고 있는 서브넷(VLAN) 안에 있음 | 이제 L2로 직접 전달 |
directly connected에 도달했다는 건 "이 라우터가 목적지 VLAN의 게이트웨이(SVI)" 라는 뜻이다. 더 이상 라우팅할 필요 없이 같은 서브넷 안에서 호스트를 직접 찾으면 된다.
"directly connected"는 케이블로 직접 연결됐다는 게 아니라 같은 서브넷(VLAN) 안에 있다는 L3상의 의미다. 실제로는 그 아래 여러 대의 L2 스위치를 거칠 수 있다.
3. ARP — IP는 아는데 MAC을 모를 때
목적지가 같은 서브넷에 있다는 걸 알았으니, 이제 그 IP를 가진 호스트의 MAC 주소가 필요하다. 그런데 보내는 쪽은 목적지 IP만 알 뿐 MAC은 모른다. 이때 사용하는 프로토콜이 ARP(Address Resolution Protocol) 이다.
1) ARP Request — 브로드캐스트로 "이 IP 누구야?"
먼저 ARP 캐시(ARP 테이블) 를 확인한다. 없으면 ARP Request를 만들어 브로드캐스트한다.
ARP Request 프레임의 주소 칸은 이렇게 채워진다.
| 칸 | 값 | 의미 |
|---|---|---|
| L2 출발지 MAC | 나(요청자)의 MAC | 내가 보냈다 |
| L2 목적지 MAC | FF:FF:FF:FF:FF:FF | 브로드캐스트 (서브넷 전체에 뿌림) |
| ARP Sender IP/MAC | 나의 IP / 나의 MAC | 응답을 어디로 돌려줄지 |
| ARP Target IP | 찾는 상대의 IP | "이 IP 가진 사람?" |
| ARP Target MAC | 00:00:00:00:00:00 | 아직 모름 (이걸 알려고 묻는 것) |
목적지 MAC을 모르니 목적지 MAC 칸을 브로드캐스트(FF:FF...)로 채워 같은 서브넷의 모두에게 "이 IP 가진 사람 MAC 좀 알려줘"라고 외치는 것이다. 스위치는 브로드캐스트 프레임이라 모든 포트로 플러딩한다.
2) ARP Reply — 유니캐스트로 "나야, 내 MAC은 이거야"
서브넷의 모든 호스트가 이 Request를 받지만, Target IP가 자기 IP와 일치하는 호스트만 응답한다. 나머지는 버린다. 응답하는 호스트는 ARP Reply를 만드는데, 이번엔 유니캐스트다 (상대 MAC을 이미 Request에서 알았으니까).
| 칸 | 값 |
|---|---|
| L2 출발지 MAC | 응답자(목적지 호스트)의 MAC |
| L2 목적지 MAC | 최초 요청자의 MAC (유니캐스트) |
| ARP Sender IP/MAC | 응답자의 IP / 응답자의 MAC ← 이게 핵심 정보 |
| ARP Target IP/MAC | 최초 요청자의 IP / MAC |
3) ARP 테이블 학습 — 한 번 알면 캐싱
요청자는 Reply의 Sender IP/MAC을 보고 IP ↔ MAC 매핑을 ARP 테이블에 저장한다. 이러면 다음번 같은 목적지로 보낼 때는 브로드캐스트 없이 캐시에서 바로 꺼내 쓴다.
응답자(B)도 Request 안의 Sender IP/MAC을 보고 A를 자기 ARP 테이블에 학습한다. 어차피 곧 응답을 보내야 하니, 받은 김에 양쪽이 서로를 캐싱한다. ARP 캐시는 보통 수 분 단위 타임아웃 후 삭제되고, 필요해지면 다시 학습한다.
MAC 테이블(CAM)과 헷갈리지 말 것. ARP 테이블은 호스트/라우터가 가진
IP ↔ MAC매핑이고(L3↔L2 연결), MAC 테이블은 스위치가 가진MAC ↔ 포트매핑이다(어느 포트로 보낼지). 학습 주체도 저장하는 내용도 다르다.
4. MAC 테이블 — 알아낸 MAC으로 호스트 포트 찾기
ARP로 호스트의 MAC을 알아냈으니, 라우터는 이제 새 Ethernet 헤더를 작성한다.
- 출발지 MAC = 자기(게이트웨이) 인터페이스 MAC
- 목적지 MAC = 방금 ARP로 알아낸 호스트의 MAC
그리고 다시 L2 프레임으로 재캡슐화(re-encapsulation) 해서 내보낸다.
이 프레임이 스위치에 도착하면, 스위치는 **MAC 테이블(CAM 테이블)**에서 목적지 MAC을 찾아 정확히 그 포트로만 프레임을 보낸다. (스위치도 들어온 프레임의 출발지 MAC과 들어온 포트를 보고 MAC 테이블을 학습한다. 목적지 MAC이 테이블에 없으면 일단 플러딩 후, 응답이 돌아올 때 학습한다.) 스위치가 여러 대 연결돼 있어도 각 스위치가 자기 MAC 테이블을 보고 다음 스위치 → 결국 호스트가 물린 엣지 포트까지 전달한다.
5. 정리 — 패킷 포워딩 시 헤더 값 변화
지금까지의 과정을 보면, L2 헤더(MAC)는 구간마다 바뀌고 L3 헤더(IP)는 그대로인 것을 알 수 있다.
다음은 호스트 A(10.0.0.10)가 다른 서브넷의 호스트 B(192.168.1.20)로 보내는 상황이다.
각 구간을 지날 때 프레임 헤더에 실제로 채워지는 값은 다음과 같다.
| 구간 | 🔁 src MAC | 🔁 dst MAC | 🔒 src IP | 🔒 dst IP |
|---|---|---|---|---|
| ① A → R1 | AA:AA (A) | 11:11 (R1) | 10.0.0.10 (A) | 192.168.1.20 (B) |
| ② R1 → R2 | 22:22 (R1) | 33:33 (R2) | 10.0.0.10 (A) | 192.168.1.20 (B) |
| ③ R2 → B | 44:44 (R2) | BB:BB (B) | 10.0.0.10 (A) | 192.168.1.20 (B) |
- 🔒 출발지·목적지 IP — 최초 송신지(A)와 최종 목적지(B) 값으로 종단 간 고정. 라우터는 IP를 보고 경로만 정할 뿐 값 자체는 바꾸지 않는다. (TTL 감소와 그에 따른 체크섬 재계산만 일어난다.)
- 🔁 출발지·목적지 MAC — 매 구간 그 링크 양 끝 장비의 MAC으로 새로 채워진다. 그래서 홉마다 라우터가 L2 헤더를 벗겼다가(decapsulation) 다시 씌운다(re-encapsulation).
- 구간 ①·③처럼 목적지가 같은 서브넷 안이면 목적지 MAC은 ARP로 알아낸 호스트의 MAC, 구간 ②처럼 아직 다른 서브넷이면 다음 홉 라우터의 MAC이 들어간다.
즉 패킷 포워딩은 라우터마다 L2 헤더를 벗기고(decapsulation) 목적지 IP로 라우팅 테이블을 보고, 경계 라우터에서 ARP로 MAC을 알아내 새 헤더를 씌우고(re-encapsulation), 스위치가 MAC 테이블로 마지막 포트를 찾는 일련의 과정이다. 그래서 경로 추적을 라우팅 테이블 → MAC 테이블 순서로 보면서 진행하게 되는 것이다.