[Cloudflare 딥다이브 EP.01] L2/L3 네트워킹 — 라우팅·NAT·서브넷 마스크
L2는 MAC 주소 기반 스위칭, L3는 IP 주소 기반 라우팅이다. Vultr VPC의 순수 L2 동작 원리부터 정적 라우팅, NAT, DHCP Option 121 자동 배포까지 정리한다.
ㅂㄹㄱ
2026-04-14 ·
이 글은 개발자의 Cloudflare 인프라 딥다이브 시리즈의 첫 번째 편이다.
이번 편은 서버 내부와 로컬 네트워크에서 패킷이 어떻게 흘러가는지, L2/L3 네트워킹의 기초를 다룬다.
들어가며
Cloudflare Zero Trust로 홈 네트워크와 클라우드 서버를 하나로 묶으려다 보면, 평소 개발 단계에서는 접할 일이 없던 네트워크 용어들이 발목을 잡는다. 도메인을 사서 A 레코드를 찍고 Nginx 설정에서 proxy_pass를 거는 것까지는 익숙하지만, ip route, iptables, subnet mask 같은 단어들이 튀어나오는 순간 핑이 안 가는 원인을 찾는 것조차 힘겨워진다.
"왜 같은 VPC 안에 있는데 핑이 안 가지?", "라우팅을 추가했는데 왜 응답이 안 오지?" 같은 질문에 답하려면 결국 L2(Data Link Layer)와 L3(Network Layer)의 차이를 알아야 한다. 이 글에서는 우리가 실제로 서버를 구축할 때 마주치는 "패킷은 어디로 가야 하는가?"에 대한 의사결정 과정을 정리한다.
L2 vs L3: 누구에게 물어볼 것인가?
네트워크에서 패킷을 전달하는 방식은 크게 두 가지다. 옆집에 직접 줄 것인가(L2), 아니면 우체국에 맡길 것인가(L3).
L2 (Layer 2) — 스위칭 (Switching)
L2는 MAC 주소를 기반으로 패킷(프레임)을 전달한다. 같은 "동네"에 있는 장비들끼리 직접 통신하는 단계다.
- 브로드캐스트 도메인: "야,
10.20.0.3누구야?"라고 소리치면(ARP Request), 해당 장비가 "나야!"라고 대답한다. 이 소리가 들리는 범위가 L2 영역이다. - Vultr VPC: Vultr 같은 클라우드 제공업체의 VPC는 보통 순수 L2로 동작한다. 같은 VPC 내의 서버들은 마치 하나의 스위치에 꽂힌 것처럼 서로의 MAC 주소를 알고 직접 통신할 수 있다.
L3 (Layer 3) — 라우팅 (Routing)
L3는 IP 주소를 기반으로 패킷을 전달한다. 다른 동네로 패킷을 보낼 때, "이 주소는 저쪽 우체국으로 보내"라고 길을 알려주는 과정이다.
- 라우터(Router): 길을 알려주는 장비다. 자신의 동네가 아닌 IP로 가는 패킷을 받아서 다음 목적지(Next Hop)로 넘겨준다.
- 정적 라우팅(Static Routing): 우리가 직접
ip route add 10.30.0.0/24 via 10.20.0.1같이 길을 적어주는 방식이다.
서브넷 마스크: "여기가 우리 동네인가?"
컴퓨터가 패킷을 보낼 때 가장 먼저 하는 고민은 "이 목적지가 나랑 직접 연결된 곳인가?"이다. 이걸 결정하는 게 서브넷 마스크(Subnet Mask)다.
/24 vs /16의 차이
예를 들어 내 IP가 10.10.20.1이고 목적지가 10.10.0.5라고 가정해 보자.
-
서브넷이 /24 (255.255.255.0) 인 경우
- 내 네트워크 범위는
10.10.20.0~10.10.20.255다. - 목적지
10.10.0.5는 우리 동네가 아니다. - 게이트웨이(라우터)에게 패킷을 던지는 L3 통신이 발생한다.
- 내 네트워크 범위는
-
서브넷이 /16 (255.255.0.0) 인 경우
- 내 네트워크 범위는
10.10.0.0~10.10.255.255다. - 목적지
10.10.0.5는 우리 동네에 해당한다. - ARP로 MAC 주소를 찾아서 직접 보내는 L2 통신이 발생한다.
- 내 네트워크 범위는
시리즈 3편에서 다룰 홈 네트워크 구성에서 ipTIME을 /16(10.10.0.0/16)으로 설정하는 이유가 바로 이것이다. 홈 전체를 하나의 L2 브로드캐스트 도메인으로 묶고, 용도별 /24 구분(게스트·호스트·IoT)은 운용 규약으로만 관리한다. 맥미니(10.10.20.1)가 다른 대역 디바이스와 라우팅 없이 스위칭만으로 통신하게 하려는 목적이다.
라우팅 테이블: 길 찾기 지도
내 동네가 아닌 곳으로 갈 때는 라우팅 테이블(Routing Table)을 본다. 리눅스에서 ip route 명령어로 확인할 수 있다.
$ ip route
default via 10.10.0.1 dev eth0
10.20.0.0/22 via 10.20.0.1 dev wg0
10.10.0.0/16 dev eth0 proto kernel scope link src 10.10.20.1
- Longest Prefix Match: 가장 구체적인 룰을 먼저 따른다.
10.20.0.5로 가는 패킷은10.20.0.0/22룰을 탄다. - Default Gateway: 어디에도 해당하지 않으면
default경로(보통 공인 인터넷 방향)로 보낸다.
Next Hop과 Interface
via 10.20.0.1: "이 주소로 패킷을 던져라. 걔가 길을 알 것이다."라는 L3 전달 방식이다.dev wg0: "그냥 이 인터페이스로 패킷을 밀어 넣어라."라는 방식으로 주로 P2P 터널에서 사용한다.
NAT (Network Address Translation): 신분 세탁
사설 IP(10.x.x.x, 192.168.x.x)는 인터넷에서 통용되지 않는다. 그래서 사설망에서 인터넷으로 나갈 때는 공인 IP로 주소를 바꿔야 하는데, 이게 NAT다.
MASQUERADE (매스커레이드)
리눅스 서버를 라우터로 쓸 때 가장 많이 쓰는 설정이다.
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
이 명령은 인터페이스 eth0으로 나가는 모든 패킷의 출발지 주소를 eth0의 IP로 바꾸라는 의미다. 돌아오는 패킷은 커널이 추적하고 있다가 다시 원래의 내부 IP로 돌려준다.
다만 시리즈 3편에서 다룰 Zero Trust 구성에서는 가급적 NAT를 쓰지 않는다. NAT를 쓰면 목적지 서버에서 원본 IP를 알 수 없기 때문이다. 대신 모든 구간을 라우팅으로 뚫어주는 방식을 택한다.
자동화: DHCP Option 121
라우팅을 한두 번 설정하는 건 쉽다. 하지만 서버가 늘어나면 각 서버마다 라우팅을 수동으로 입력할 수 없다. 이때 유용한 것이 DHCP Option 121이다.
보통 DHCP는 IP와 서브넷 마스크, 디폴트 게이트웨이만 알려준다. 하지만 Option 121을 쓰면 특정 대역으로 갈 때 사용할 커스텀 게이트웨이 정보도 함께 뿌려줄 수 있다.
dnsmasq 설정 예시
Vultr VPC 환경에서 dnsmasq를 라우터로 쓸 때 다음과 같이 설정한다.
# 10.30.0.0/16 대역으로 갈 때는 10.20.0.1(게이트웨이)을 써라
dhcp-option=121,10.30.0.0/16,10.20.0.1
이렇게 하면 VPC에 붙은 서버들이 부팅될 때 자동으로 라우팅 테이블이 업데이트된다.
정리
네트워크 패킷의 흐름을 요약하면 다음과 같다.
| 개념 | 역할 | 비유 |
|---|---|---|
| L2 | MAC 주소 기반 직접 전달 | 옆집에 물건 직접 전해주기 |
| L3 | IP 주소 기반 경로 안내 | 우체국 택배로 보내기 |
| 서브넷 마스크 | 동일 네트워크 여부 판단 | 같은 동네인지 확인하기 |
| 라우팅 테이블 | 패킷이 갈 길을 알려주는 지도 | 내비게이션 경로 안내 |
| NAT | 사설 IP를 공인 IP로 변환 | 대표 번호로 발신자 표시 변경 |
graph TD
A[패킷 발생] --> B{목적지가 우리 동네인가?}
B -- Yes: 서브넷 마스크 일치 --> C[L2: 직접 전달]
B -- No: 서브넷 마스크 불일치 --> D[라우팅 테이블 확인]
D -- 경로 있음 --> E[L3: 지정된 게이트웨이로 전송]
D -- 경로 없음 --> F[Default Gateway로 전송]
기본적인 네트워킹 개념을 잡았으니, 다음 편에서는 Cloudflare Zero Trust가 이 원리를 어떻게 활용해서 물리적으로 떨어진 서버들을 하나로 묶는지 알아보자.