포스트

macOS에서 Wi-Fi 전환 직후 정적 라우트가 잘못 잡힐 때

Ethernet과 Wi-Fi를 동시에 쓰는 멀티홈 환경에서 Wi-Fi 전환 직후 정적 라우트를 추가하면 내부망 접속이 실패하는 원인과, 인터페이스 상태가 아니라 실제 도달성으로 검증하는 해결 패턴을 정리한다.

macOS에서 Wi-Fi 전환 직후 정적 라우트가 잘못 잡힐 때

Ethernet은 인터넷용, Wi-Fi는 내부망용으로 동시에 사용하는 macOS 멀티홈 환경에서 Wi-Fi를 CLI로 전환한 직후 정적 라우트를 추가하면 내부망 접속이 실패할 수 있다.

처음에는 라우트가 나중에 다른 인터페이스로 “드리프트”하는 문제처럼 보였지만, 실제로는 Wi-Fi 연결이 완전히 준비되기 전에 라우트를 적용한 타이밍 문제였다.

아래 IP는 문서용 예시 대역인 192.0.2.0/24, 198.51.100.0/24를 사용한다.

증상

구성은 다음과 같다.

1
2
3
4
5
6
Ethernet
→ 인터넷

Wi-Fi
→ 내부망 Gateway 192.0.2.1
→ 내부 서버 198.51.100.22

Wi-Fi를 전환한 뒤 곧바로 다음과 같이 설정한다.

1
2
sudo networksetup -setmanual "Wi-Fi" 192.0.2.50 255.255.255.0 192.0.2.1
sudo route -n add -net 198.51.100.0/24 192.0.2.1

그런데 첫 실행에서는 내부 서버에 접속하지 못하고 같은 작업을 다시 실행하면 정상 동작하는 현상이 나타났다.

1
2
3
4
5
6
7
8
9
10
11
12
13
첫 실행
Wi-Fi 전환 시작
   ↓
라우트 적용
   ↓
내부망 실패

두 번째 실행
이미 Wi-Fi 연결 완료
   ↓
라우트 적용
   ↓
정상

원인 — Wi-Fi 전환 완료와 명령 종료는 같은 시점이 아니다

networksetup -setairportnetwork로 SSID를 바꾸는 작업에는 association과 인증 과정이 뒤따른다. 명령이 반환된 직후에도 실제 네트워크 경로가 완전히 준비되지 않았을 수 있다.

정적 라우트가 사용하는 Gateway가 Wi-Fi를 통해 아직 정상적으로 도달할 수 없는 시점에 라우트를 추가하면 기대한 경로가 만들어지지 않거나 실제 통신이 실패할 수 있다.

핵심은 다음 순서다.

1
2
3
4
5
6
7
Wi-Fi 전환 요청
   ↓
Association / 인증 / IP·Gateway 경로 준비
   ↓
내부망 실제 도달 가능
   ↓
정적 Route 적용

문제 상황에서는 두 번째 단계가 끝나기 전에 마지막 단계를 실행하고 있었다.

왜 처음에는 Route Drift처럼 보였나

route get이나 라우트 테이블을 너무 이른 시점에 확인하면 기대한 인터페이스가 잠시 보이더라도 실제 내부 서버까지 통신이 되지 않을 수 있다.

그래서 다음 현상만 보고:

1
2
처음 확인 → Wi-Fi처럼 보임
잠시 후   → 원하는 통신 실패

“macOS가 라우트를 다른 인터페이스로 다시 옮긴다”고 판단하기 쉬웠다.

하지만 이 사례에서 더 중요한 사실은 라우트 테이블의 순간 상태보다 실제 목적지 도달 여부였다.

진단 — 세 층으로 나눠 확인한다

1. 현재 라우트 선택

1
route get 198.51.100.22 | grep -E 'gateway|interface'

실제 목적지 IP를 사용한다. 네트워크 주소인 198.51.100.0을 조회하는 것보다 실제 통신할 Host를 확인하는 편이 의미가 명확하다.

2. 라우트 테이블

1
netstat -rn -f inet | grep -E '198.51.100|^default'

정적 라우트와 Default Route가 어떻게 잡혀 있는지 확인한다.

3. 실제 도달성

최종 판정은 실제 서비스 연결로 한다.

1
nc -z -G2 -w2 198.51.100.22 443
1
2
3
4
5
Interface 상태
        ↓
Route 상태
        ↓
실제 목적지 도달

앞의 두 상태가 정상처럼 보여도 마지막 단계가 실패하면 네트워크 준비가 끝났다고 간주하지 않는다.

해결 — 고정 Sleep보다 조건 기반 재시도

Wi-Fi 연결 시간은 환경마다 달라질 수 있으므로 sleep 3, sleep 5처럼 특정 시간을 정답으로 두면 다시 실패할 수 있다.

대신 설정 적용 → 실제 도달 확인 → 실패하면 재시도 구조로 만든다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for i in $(seq 1 10); do
  sudo networksetup -setmanual \
    "Wi-Fi" 192.0.2.50 255.255.255.0 192.0.2.1

  sudo route -n delete -net 198.51.100.0/24 >/dev/null 2>&1 || true
  sudo route -n add -net 198.51.100.0/24 192.0.2.1

  if nc -z -G2 -w2 198.51.100.22 443; then
    echo "internal network ready"
    break
  fi

  sleep 2
done

여기서 핵심은 반복 횟수나 sleep 2가 아니라 성공 조건을 실제 도달성으로 둔 것이다.

이미 원하는 Wi-Fi에 연결되어 있다면

SSID를 매번 다시 전환할 필요가 없다면 네트워크 전환 단계를 건너뛰고 IP와 라우트만 적용하는 편이 단순하다.

1
2
3
4
5
불필요한 Wi-Fi 전환 제거
   ↓
비동기적인 연결 준비 구간 제거
   ↓
Route 설정 안정화

즉 문제를 해결하는 가장 좋은 방법이 항상 재시도 로직을 늘리는 것은 아니다. 애초에 네트워크 전환이 필요 없는 흐름이라면 그 단계를 없애는 편이 낫다.

주의할 점

networksetup -getairportnetwork, route get, ARP 상태 등은 각각 다른 상태를 보여준다. 어느 하나를 “연결 완료의 절대적인 신호”로 취급하지 않는다.

이 사례에서 필요한 성공 조건은 내부 서버에 실제로 접속할 수 있는지였으므로 그 조건을 직접 검사했다.

1
2
3
4
5
6
7
8
내가 확인하려는 상태는 무엇인가?
        ↓
Wi-Fi Association?
Route 선택?
Gateway 도달?
실제 Service 도달?
        ↓
목적과 같은 층의 신호로 검증

정리

문제의 핵심은 “라우트가 저절로 다른 인터페이스로 이동한다”가 아니었다.

1
2
3
4
5
6
7
Wi-Fi 전환 직후
   ↓
네트워크 경로가 아직 준비 중
   ↓
정적 Route를 너무 일찍 적용
   ↓
내부망 통신 실패

따라서 해결도 route add 명령 자체를 바꾸는 것보다 네트워크 준비 완료를 실제 도달성으로 확인하고, 실패하면 설정을 다시 적용하는 흐름으로 만드는 것이 중요하다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.