💫 오늘은 데이터-링크 계층에서 사용되는 프로토콜 중 하나인
ARP에 대한 개념부터 어떻게 코드로 구현할 수 있을까에 대해 알아보자!
왜 ARP를 알아야 할까?
TCP/IP 프로토콜 스택이 네트워크 통신에서 중추적인 역할을 하기 때문에
대부분의 주소 결정은 TCP/IP의 ARP를 통해 이루어진다.
이 프로토콜은 노드가 네트워크 상의 다른 노드로 데이터를 전송하고자 할 때, 해당 노드의 물리적 주소(MAC 주소)를 IP 주소로부터 파악하는 데 사용된다.
네트워크 상에서 데이터 패킷은 물리적 주소를 기반으로 전송되기 때문에, ARP는 IP 주소를 물리적 주소로 변환하는 중요한 과정을 담당한다. 따라서 ARP를 이해하는 것은 네트워크의 기본 동작을 이해하는 데 필수적이라고 볼 수 있다.

ARP 패킷의 구조는 아래 그림과 같다.
유의해서 봐야할 부분은 Operation과 아래의 주소들이다.
Operation : Request(요청) - 1, Reply(응답) - 2
Source HW/protocol address : 송신지 데이터-링크/네트워크 계층 주소
Destination HW address : 수신지 데이터-링크 계층 주소 (요청 시에는 empty)
Destination protocol address : 수신지 네트워크 계층 주소

아래는 ARP의 동작 방식이다.
간략하게 말하면 시스템 A에서 Broadcast로 요청을 보낸다.
그리고 요청을 받은 각 호스트에서 ARP 패킷을 확인하고
자신의 주소와 비교 후 일치하면 Destination HW address을 넣어 응답한다.

세부 동작을 알아보기 위해 가져온 예시이다.
데이터-링크 계층 3종류를 지나가고
ARP Operation을 3번(Alice <-> R1, R1 <-> R2, R2 <-> Bob) 수행한다.
Alice <-> R1
Alice에서 ARP로 R1의 데이터-링크 계층의 주소 L1을 받아와서
캡슐화할 때, Destination HW address에 L1을 작성하고 R1으로 데이터를 송신한다.

R1 <-> R2
R1에서 ARP로 R2의 데이터-링크 계층의 주소 L3을 받아와서
캡슐화할 때, Destination HW address에 L3을 작성하고 R2로 데이터를 송신한다.

R2 <-> Bob
R2에서 ARP로 Bob의 데이터-링크 계층의 주소 LB을 받아와서
캡슐화할 때, Destination HW address에 LB을 작성하고 Bob으로 데이터를 송신한다.

Bob
Bob은 받은 데이터 패킷을 역캡슐화해가며 자신의 주소가 맞는지 확인하고 상위계층으로 보낸다.

ARP를 공부하다보면 자주 제기되는 질문이 있다.
시스템 A가 시스템 B의 "링크 계층 주소를 찾기 위해" 프레임을 브로드캐스트할 수 있다면,
왜 시스템 A는 시스템 B에 대한 "데이터그램"을 브로드캐스트 프레임으로 보낼 수 없을까요?
결론부터 말하면 모든 데이터그램을 브로드캐스트하는 것은 비효율적이다.
모든 노드가 네트워크상의 모든 데이터 패킷을 처리해야 하기 때문에, 이는 네트워크 트래픽을 불필요하게 증가시키고, 자원을 낭비하며, 시스템의 성능 저하를 초래할 수 있다.
한 번 ARP를 통해 링크 계층 주소를 알아낸 후에는, 이 주소 정보를 일정 시간 동안 캐싱(저장)하여 사용한다. 이로써, 같은 주소에 데이터를 지속적으로 보낼 때 매번 ARP 요청을 보내는 대신, 캐시된 주소를 사용하여 효율적으로 네트워크 자원을 관리할 수 있다.
이는 네트워크의 전반적인 효율성을 높이는 데 중요한 역할을 한다.
프로그래밍 언어 : C
개발 환경 : Ubuntu 22.04.3 LTS
ifconfig 명령어로 환경의 IP주소와 MAC주소를 확인할 수 있고
루프백 IP를 사용했다.
실행 결과를 보면 데이터 송수신과 캐싱이 잘 작동하는 것을 볼 수 있다.

C코드를 첨부하기엔 길이가 너무 길어질 것 같아서
필자의 Github에 업로드할 예정이다.