🔥 라우팅 테이블: 패킷이 어디로 가는지

2179자
24분

화면 가운데에 라우팅 테이블이라는 한 장의 카드가 떠 있고 그 카드에는 destination CIDR과 target이 한 짝씩 적힌 세 줄이 있다. 카드 위에서 작은 패킷 아이콘이 모든 행을 위에서 아래로 훑어 내려가다가 두 번째 행 0.0.0.0/0에서 부드러운 주황빛 하이라이트가 떨어지며 그쪽으로 빠지는 흐름이 시각화된 그림. 라우팅 테이블이 결국 한 카드 안의 한 줄을 고르는 일이라는 점을 한 장으로 보여 준다

EC2 콘솔은 초록불을 띄우고, Security Group과 NACL도 통과하고, Subnet에는 IP가 정상으로 붙어 있다. 그런데 인터넷은 끊겨 있다. 내가 본 VPC 디버깅의 상당수는 이 상태에서 시작했고, 그중 적지 않은 경우는 라우팅 테이블 한 줄을 고치자 바로 끝났다. 카드는 자동으로 한 장 끼워져 있고, 행을 적는 일은 한 번이면 끝나고, 콘솔도 친절한데 그 친절함이 잘못된 한 줄을 안 잡아 준다.

VPC 안의 라우팅 결정은 라우팅 테이블 한 장이 모두 담는다. AWS 공식 문서는 라우팅 테이블을 "VPC의 트래픽 컨트롤러"라고 부른다(verified 2026-04-25, VPC 사용자 가이드). 카드 한 장에는 route라고 부르는 행이 여러 개 들어가고, 한 행은 destination CIDR과 target 한 쌍을 담는 단위다. Subnet에서 나가는 패킷은 그 카드의 행을 비교한 뒤 가장 구체적으로 맞는 target으로 나간다. 이 카드에 틀린 행 하나만 써도 VPC 전체 상태는 멀쩡해 보여서 초반 확인이 늦어지므로, 오늘은 라우팅 테이블을 어떻게 적어야 사고를 막는지 짚는다.

라우팅 테이블은 'VPC당 카드 한 묶음'이다

VPC를 만들면 AWS가 자동으로 카드 한 장을 끼워 준다. 이게 Main Route Table이다. 사용자가 추가로 만드는 카드는 Custom Route Table이라고 부른다. AWS 표현 그대로 옮기면 다음과 같다. "The main route table is the route table that automatically comes with your VPC. It controls the routing for all subnets that are not explicitly associated with any other route table" (verified 2026-04-25, Route table concepts).

여기서 두 가지가 처음에 눈에 안 들어온다. 하나는 "explicitly associated"라는 단어, 다른 하나는 Main을 지울 수 없다는 사실이다.

먼저 'explicit' 쪽. Subnet은 라우팅 테이블에 묶일 수 있는데(association), 묶이는 방식이 두 가지다.

  • 명시적 연결(explicit): aws ec2 associate-route-table 같은 호출로 내가 "이 Subnet은 이 Route Table을 쓴다"고 직접 지정한 상태다.
  • 묵시적 연결(implicit): Subnet을 만들기만 하고 어떤 RT에도 직접 지정하지 않은 상태. AWS가 알아서 Main에 붙여 준다.

모든 Subnet은 Route Table 하나를 반드시 쓰고, 따로 지정하지 않으면 AWS가 Main Route Table을 붙인다. "내 Subnet에는 라우팅 테이블이 없다"는 상태는 존재하지 않는다. 그래서 초기에 직접 association을 적어 두지 않으면 Main 변경이 다른 Subnet까지 번져 운영자가 원치 않은 영향이 남는다.

다른 하나, Main을 지울 수 없다. 정확한 표현은 다음과 같다. "You can add, remove, and modify routes in the main route table, but you can't delete the main route table" (verified 2026-04-25, Subnet route tables). 그래서 Main이 마음에 안 들면 교체만 가능하다. 보통은 작업 방향이 거꾸로다. 내가 만든 Custom RT를 모든 Subnet에 explicit으로 묶고, Main은 association이 빠진 Subnet의 안전망으로 비워 두는 식이다. 한 발 더 나가서 현재 Main인 카드를 다른 카드로 교체하는 명령(replace-route-table-association)도 있는데, 이건 association ID를 바꿔 끼우는 식의 조작이라 운영 환경에서는 잘 안 쓴다. 보통은 그냥 모든 Subnet을 Custom에 명시적으로 묶고 잊어버리는 쪽이 마음 편하다.

한 VPC 컨테이너 안에 Main Route Table과 Custom RT 두 장이 떠 있고, 그 아래 다섯 개의 Subnet 박스가 줄지어 놓여 있다. Subnet 1·3·5는 솔리드 화살표로 Custom RT에 연결돼 explicit association이라 표시되고, Subnet 2·4는 점선 화살표로 Main Route Table에 implicit association으로 자동 연결되는 모습. 명시적 연결이 끊긴 Subnet은 자동으로 Main에 묶인다는 사실을 한 장으로 보여 주는 다이어그램

Subnet과 Route Table의 관계는 1:N이다: Subnet은 한 번에 카드 하나만 쓴다

내가 자주 혼동했던 지점이 있다. Subnet이 두 개의 라우팅 테이블에 동시에 연결될 수 있는가. 그렇지 않다. AWS는 한 시점에 한 Subnet을 정확히 하나의 Route Table에만 연결한다. 그 카드가 Main이든 Custom이든 그건 별개이며, 동시에 두 카드를 참조하는 일은 없다.

반대 방향은 자유롭다. 한 라우팅 테이블이 여러 Subnet에 연결되는 경우가 흔하다. 같은 라우팅 정책을 쓰는 Subnet 묶음, 예를 들어 3-AZ에 흩뿌린 Public Subnet 셋은 같은 Public RT 한 장에 함께 연결해 두는 게 일반적이다. 이렇게 하면 라우팅 정책을 바꿀 때 한 카드만 고치면 된다.

이 1:N 구조는 처음 그릴 때 흐릿하면 나중에 한참 헤맨다. Subnet마다 카드를 따로 만드는 사람도 있고 VPC 전체가 한 카드로 돌아가는 환경도 본다. 어느 쪽이든 동작은 하지만, AZ 격벽과 Public/Private 격벽을 둘 다 의미 있게 가져가려면 역할별로 카드를 나누는 쪽(Public RT 1장 ↔ AZ별 Public Subnet 3개, Private RT 1장 ↔ AZ별 Private Subnet 3개)이 운영 사고를 적게 만든다. AZ별로 카드를 또 쪼개는 건 NAT를 AZ당 하나씩 둘 때처럼 target 자체가 AZ에 의존할 때만 한다.

행이 평가되는 순서: Longest Prefix Match와 Static > Propagated

카드 한 장에는 보통 이런 행들이 들어 있다.

Destination          Target
10.0.0.0/16          local
0.0.0.0/0            igw-0123…   (또는 nat-0abc…)
10.20.0.0/16         pcx-09ee…   (VPC peering)
192.168.10.0/24      vgw-0fff…   (Site-to-Site VPN)
Destination          Target
10.0.0.0/16          local
0.0.0.0/0            igw-0123…   (또는 nat-0abc…)
10.20.0.0/16         pcx-09ee…   (VPC peering)
192.168.10.0/24      vgw-0fff…   (Site-to-Site VPN)

패킷이 들어오면 어느 행을 따라갈까. AWS는 두 단계로 결정한다.

  1. Longest Prefix Match (가장 구체적인 prefix): AWS는 destination IP와 가장 길게 맞는 prefix가 적힌 행을 먼저 고른다. 10.0.5.10에는 /16 local 행이 먼저 맞고, 192.168.10.5에는 /24 VPN 행이 먼저 맞으며, 0.0.0.0/0 행은 앞선 매칭이 하나도 없을 때만 마지막 순서로 남는다. AWS 문서도 "We prioritize the most specific route"라고 명시한다(verified 2026-04-25, Example routing options).
  2. Static > Propagated (같은 길이라면 손으로 적은 행이 우선): 길이가 같으면 내가 콘솔/API로 직접 추가한 static route가 VGW가 BGP로 자동 채워 준 propagated route보다 앞선다. 정확한 표현은 "if the routes match, we prioritize static routes over propagated routes" (출처 동일).

이 두 줄이 잘 안 외워지면 한 가지만 기억해 두면 된다. 기본 경로 0.0.0.0/0은 항상 마지막에 평가하는 행이다. 다른 행이 한 비트라도 더 구체적으로 매칭되면 그 행이 우선하고, 다른 행이 정적으로 적혀 있으면 그 행이 우선한다. 기본 경로는 그저 다른 어디에도 매칭되지 못한 패킷이 마지막으로 들어가는 출구다.

화면 가운데 라우팅 테이블 카드 한 장에 다섯 개의 라우트가 모노스페이스로 적혀 있고, 카드 위에서 destination 192.168.10.5라고 적힌 패킷 아이콘이 떨어지며 모든 행과 매칭되는지 가는 안내선이 부채꼴로 뻗어 내린다. 가장 긴 /24 prefix가 적힌 vgw 행만 부드러운 주황빛으로 하이라이트돼 'WINNER'라고 표시된다. 카드 옆에는 작은 인셋이 같은 destination을 가리키는 static과 propagated 두 줄을 나란히 두고, static 경로가 초록 체크와 함께 맨 위 행에, propagated 경로가 회색 취소선으로 아래 행에 그려져 동률 매칭일 때 static이 우선한다는 규칙을 한 장으로 보여 주는 다이어그램

행 하나는 target 한 개만 가질 수 있다

라우팅 테이블의 한 행에 둘 이상의 target을 넣을 수 없다. 단순한 사실인데 영향이 크다. Active/active 부하 분산은 라우팅 테이블에서 처리하지 않는다. 같은 destination CIDR로 두 개의 다른 NAT Gateway를 동시에 잡고 싶다면 답은 No. 한 destination에 한 target. 부하 분산이나 장애 전환이 필요하면 Application Load Balancer, Network Load Balancer, Route 53 Failover Routing처럼 더 위 계층 도구로 옮겨서 다룬다. Route Table은 layer 3에서 destination IP만 보고, layer 4 이상 판단은 다른 객체가 맡는다. 이 계층 구분이 흐려지면 잘못된 곳에서 잘못된 도구로 문제를 풀게 된다.

Local route: 지워지지 않는 한 줄

모든 라우팅 테이블에는 사용자가 만들지 않아도 local route 한 줄이 처음부터 들어 있다. AWS 문서 표현은 다음과 같다. "A default route for communication within the VPC. If the VPC has both IPv4 and IPV6 addresses, there is a local route for IPv4 and a local route for IPv6" (verified 2026-04-25, Route table concepts).

이 행이 하는 일은 단순하다. VPC CIDR 안의 어떤 IP로 가는 패킷이든 같은 VPC 내부의 next hop으로 보낸다. VPC가 10.0.0.0/16이면 AWS는 카드에 10.0.0.0/16 → local 행을 자동으로 넣고, 사용자는 그 행을 지우지 못한다. VPC에 secondary CIDR이 추가되면 그 CIDR에 대한 local route 한 줄이 또 자동으로 따라붙고, IPv6 CIDR을 켜면 IPv6용 local route가 한 줄 더 들어온다. VPC가 가진 CIDR 수만큼 local 행이 자동으로 늘어난다고 보면 된다.

단 한 가지 예외가 있다. local route를 지우지는 못해도 target은 교체할 수 있다. AWS는 local route의 target을 ENI(network interface)로 갈아 끼우는 동작을 명시적으로 허용한다. VPC 트래픽을 가상 어플라이언스(예: 방화벽, IDS)로 우회시키는 East-West inspection 패턴에서만 쓴다(verified 2026-04-25, Replace or restore the target for a local route). 교체한 뒤 다시 local로 되돌리는 명령도 AWS가 함께 두고 있으니, 일반 운영에서는 손대지 않는 편이 낫다. 시험 삼아 건드리면 같은 VPC 내 인스턴스끼리 통신이 끊겨 한참 헤매는 일이 흔하다. local route는 그냥 가만히 둔다가 99%의 케이스다.

Gateway Route Table: 들어오는 트래픽을 우회시키는 카드

여기까지 다룬 카드는 모두 Subnet에 묶이는 종류이고, 나가는 트래픽의 next hop을 정하는 역할을 한다. 그런데 들어오는 트래픽도 검사 어플라이언스로 한 번 우회시키고 싶을 때가 있다. 이때 쓰는 게 Gateway Route Table이다. IGW나 VGW에 직접 카드를 한 장 묶어 두는 형태다. 이렇게 IGW/VGW에 카드를 묶는 행위 자체를 AWS는 Edge Association이라고 부르고, 그 결과로 동작하는 카드가 Gateway Route Table이다.

AWS 정의 그대로 옮기면 이렇다. "A route table that you use to route inbound VPC traffic to an appliance. You associate a route table with the internet gateway or virtual private gateway, and specify the network interface of your appliance as the target for VPC traffic" (verified 2026-04-25, Route table concepts).

요약하면 IGW나 VGW에 직접 카드를 한 장 붙여서 들어오는 트래픽의 destination 별로 어플라이언스의 ENI로 한 번 보낸다. 처음 VPC를 그릴 땐 만질 일이 없는 고급 도구라 존재만 짚고 넘어간다.

두 장면이 가로 분할로 나란히 놓인 다이어그램. 왼쪽은 Without Edge Association이라고 적혀 있고 인터넷 구름에서 IGW를 거쳐 곧장 Subnet으로 떨어지는 단순한 화살표 한 줄. 오른쪽은 With Gateway Route Table on IGW라고 적혀 있고 IGW 옆에 작은 라우팅 테이블 카드가 'Edge Association' 라벨과 함께 붙어 있어, 들어오는 트래픽이 우선 Security Appliance ENI 박스(방화벽 아이콘)로 우회한 뒤 다시 Subnet으로 들어가는 두 단계 화살표가 그려진다. Edge Association이 들어오는 트래픽을 검사 어플라이언스로 한 번 우회시키는 도구임을 한 장으로 보여 주는 비교 다이어그램

Route Propagation: VGW가 BGP로 카드를 자동으로 채우는 메커니즘

라우팅 테이블의 행은 내가 적는 것(static) 외에 VGW가 자동으로 채워 주는 것(propagated)이 또 있다. 정확한 정의는 다음과 같다. "If you've attached a virtual private gateway to your VPC and enable route propagation, we automatically add routes for your VPN connection to your subnet route tables" (verified 2026-04-25, Route table concepts).

조금 풀어 쓰면 이렇다. Site-to-Site VPN으로 온프레미스와 VPC를 잇는 환경에서, 사용자가 VPN 연결에 직접 추가한 정적 prefix나 온프레미스 라우터가 BGP로 알리는 prefix를 VGW가 받아 카드에 자동으로 줄로 넣어 준다. 이 propagation을 enable 해 두면 카드 한 장에 행이 자동으로 늘어났다 줄었다 한다. 사용자가 매번 손으로 동기화할 필요가 없다는 뜻이다. 같은 destination을 static과 propagated 양쪽이 가질 때 AWS가 static을 우선한다는 규칙은 앞에서 본 대로다.

흔한 함정이 하나 있다. Transit Gateway에 VPC가 붙어 있을 때 TGW가 알아서 Subnet RT를 채워 준다고 오해하는 경우다. 그렇지 않다. TGW propagation은 TGW route table 쪽에서 처리하고, VPC subnet route table에는 사용자가 0.0.0.0/0 → tgw-... 같은 static route를 직접 써야 패킷이 TGW로 간다(verified 2026-04-25, Transit gateway route tables). 설계 초반에 어느 계층에서 어떤 객체가 propagation을 맡는지 적어 두면 이후 점검이 수월하다.

한도: 카드 200장, non-propagated 500줄, propagated 100줄

작성 시점 기본값 기준으로 외울 만한 숫자(verified 2026-04-25, Amazon VPC quotas).

  • VPC당 라우팅 테이블 200장: Main 카드도 포함해서 센다. 조정 가능.
  • 카드당 non-propagated routes 500줄: 내가 손으로 적은 정적 라우트 한도. 조정 가능, 최대 1000까지. 500을 넘기면 네트워크 성능에 영향이 있을 수 있다고 AWS가 명시.
  • 카드당 propagated routes 100줄: VGW가 자동으로 채워 주는 라우트 한도. 조정 불가. 100을 넘는 prefix를 받아야 하면 default route 하나로 묶어 광고하라는 게 AWS의 권고.

200·500·100, 이 세 숫자가 한 카드에 들어가는 정보의 상한이다. 카드를 자꾸 늘리는 환경에선 200에 먼저 부딪히고, 각 카드를 자꾸 두껍게 만드는 환경에선 500과 100에 먼저 부딪힌다. 어느 쪽이든 한도 가까이 가기 시작하면 그건 VPC 토폴로지 설계가 처음부터 과하게 커졌다는 신호로 읽어야 한다. 카드 200장을 다 쓰는 VPC라면 한 VPC 안에서 해결할 범위를 이미 넘겼는지 먼저 의심해야 한다.

'관리형이 감추는 비용': 라우팅의 silent failure

지난 편의 마지막 줄에서 본 사실이 중요한 이유는, 그 한 줄을 틀리게 써도 VPC 콘솔 상태가 계속 정상 신호를 내기 때문이다.

EC2 콘솔, Security Group, NACL, Subnet IP가 모두 멀쩡한데 인터넷만 끊기면, Route Table의 0.0.0.0/0 행 누락, 잘못된 NAT target, Subnet과 RT의 잘못된 연결부터 먼저 의심해야 한다. 이 셋 중 하나가 원인이면 모든 게 정상인데 패킷만 사라지는 상태가 된다. AWS는 이 사실을 굳이 알려 주지 않는다. RT의 한 줄을 잘못 쓴 것은 문법 오류가 아니라 의미 오류고, AWS가 그걸 검증할 이유는 없기 때문이다.

'관리형이 감추는 비용'은 이런 형태로 드러난다. 카드는 자동으로 한 장 끼워져 있고, 행을 적는 일은 한 번이면 끝나고, 콘솔도 친절하다. 그런데 틀린 한 줄을 적었을 때 시스템이 그 사실을 알려 주지 않는다. 라우팅 테이블을 오래 추적한 사람과 그렇지 않은 사람의 VPC 디버깅 시간 차이가 크게 나는 까닭이 여기에 있다.

Route Table 바깥에서 처리하는 일: 다른 계층 도구와 구분하기

라우팅 테이블은 VPC 내부 IP 라우팅을 위한 도구다. 그 바깥의 비슷한 이름이 붙은 도구들은 동작하는 계층이 다르다.

  • DNS 기반 라우팅은 Route 53이 맡는다. Latency·weighted·failover·geolocation 같은 정책은 전부 DNS 응답에서 처리하는 일이고 IP 라우팅이 아니다.
  • HTTP path·host 기반 라우팅은 ALB의 listener rule이 맡는다. 헤더와 path를 보고 나누는 일이라 layer 7이다.
  • 서비스 메시 차원의 트래픽 분배는 App Mesh 같은 layer 7 도구가 맡는다.

Route Table은 layer 3에서 destination IP만 보고, 그 위 계층의 결정은 다른 객체가 맡는다. 위 계층 문제까지 한 도구로 묶어 해결하려 들면 작은 장애 원인도 오래 놓치게 된다. 계층마다 권한과 책임이 다르다는 점은 이후 글에서도 반복해서 등장하는 원칙이다.

다음 편 예고

카드 한 장의 안쪽을 다 봤다. 다음 편은 그 카드의 가장 흔한 target인 Internet Gateway가 도대체 무엇인지에서 시작한다. 0.0.0.0/0이 igw-…를 가리킬 때 IGW는 정확히 어떤 일을 하는가, 어떤 일은 하지 않는가.

참고 자료

YouTube 영상

채널 보기
직교성과 벡터 투영 | 선형대수학
숫자 하나가 AI 모델의 운명을 바꾼다? | 선형대수학
Trie 자료구조 파이썬 구현: Search와 Starts With 연산 | Trie 자료구조 이야기
AI는 데이터를 어떻게 분류할까? 벡터의 거리와 KNN 알고리즘 | 선형대수학
트라이(Trie) 자료구조: 파이썬으로 삽입(Insert) 연산 구현하기 | Trie 자료구조 이야기
트라이(Trie)에서 단어를 삭제하는 방법 | Trie 자료구조 이야기
AI는 왜 수백 차원의 벡터를 사용할까? 고차원 공간과 행렬 | 선형대수학
트라이(Trie)를 이용한 자동 완성 알고리즘 | Trie 자료구조 이야기