
무슨 일이냐면요
URL에 IP 주소를 직접 박아본 적 있으시죠? http://192.168.0.1:8080 이런 식으로요. IPv4는 점 네 개로 끝나서 깔끔한데, IPv6로 넘어가면 이야기가 좀 복잡해져요. 일단 IPv6 주소 자체에 콜론(:)이 잔뜩 들어가거든요. 그런데 URL에서 콜론은 "여기부터 포트 번호예요"라는 신호로도 쓰여요. 그래서 IPv6 주소는 http://[fe80::1]:8080 처럼 대괄호로 감싸는 규칙이 생겼어요. 여기까지는 그럭저럭 받아들일 만해요.
진짜 문제는 "zone ID"라는 녀석이에요. 이번에 한 개발자가 Go 언어로 IPv6 주소를 다루다가 이 zone ID 때문에 단단히 데인 이야기를 공유했는데, 한국 개발자들도 네트워크 코드 짜다 보면 똑같이 만날 수 있는 함정이라 정리해볼게요.
zone ID가 뭐냐면
IPv6에는 link-local 주소라는 게 있어요. fe80::으로 시작하는 주소인데요, 이게 뭐냐면 "우리 집 안에서만 쓰는 별명" 같은 거예요. 전 세계 어디서나 통하는 공인 주소가 아니라, 바로 옆에 붙어 있는 같은 네트워크 구간 안에서만 의미가 있는 주소죠.
문제는 컴퓨터에 랜카드(네트워크 인터페이스)가 여러 개일 수 있다는 거예요. 유선 랜도 있고, 와이파이도 있고, VPN 가상 인터페이스도 있고요. 그런데 fe80::1이라는 link-local 주소는 이 인터페이스마다 똑같이 존재할 수 있어요. 그러니까 운영체제 입장에서는 "fe80::1로 보내라고? 근데 어느 랜카드로 내보내라는 거야?" 하고 헷갈리는 거죠.
그래서 등장한 게 zone ID(또는 scope ID)예요. fe80::1%eth0 처럼 주소 뒤에 퍼센트(%)와 인터페이스 이름을 붙여서 "이 주소는 eth0 랜카드로 가는 거야"라고 콕 집어주는 거예요. 윈도우에서는 인터페이스 번호를 써서 fe80::1%12 같은 형태가 되기도 해요.
% 하나가 일으키는 대참사
눈치 빠른 분은 벌써 불길함을 느끼셨을 거예요. URL에서 퍼센트(%)는 이미 특별한 의미를 가진 글자거든요. URL은 한글이나 공백처럼 직접 못 쓰는 글자를 %20(공백), %ED 같은 식으로 인코딩하는데, 이때 쓰는 탈출 문자가 바로 %예요. 이걸 퍼센트 인코딩이라고 해요.
그러니까 fe80::1%eth0을 URL에 그대로 넣으면, URL 파서는 %et를 "어? 16진수 인코딩이네?" 하고 해석하려다가 et가 16진수가 아니니까 에러를 뱉어요. 규격대로 하자면 % 자체를 %25로 한 번 더 인코딩해서 fe80::1%25eth0이라고 써야 맞아요. 그래서 URL에 들어간 zone ID는 %2512, %25eth0 같은 외계어처럼 보이게 되죠.
여기서 진짜 지옥이 펼쳐져요. 어떤 라이브러리는 이걸 디코딩해주고, 어떤 라이브러리는 안 해줘요. 어떤 함수는 대괄호 안의 %를 인코딩해야 한다고 보고, 어떤 함수는 zone ID는 호스트가 아니라 로컬 정보니까 인코딩 대상이 아니라고 봐요. 글쓴이가 Go의 net/url 패키지를 쓰면서 겪은 게 딱 이거였어요. 주소를 파싱했다가 다시 문자열로 만들면 %가 두 번 인코딩돼서 %2525가 되거나, 반대로 인코딩이 풀려서 깨지는 식으로 왕복(round-trip)이 안 맞는 상황이 벌어진 거죠. 분명 같은 주소인데 파싱→재조립을 거치면 다른 문자열이 튀어나오니, 비교 로직이나 캐시 키가 다 어긋나버려요.
글쓴이의 결론은 단호해요. zone ID는 애초에 URL에 들어갈 만한 물건이 아니다. zone ID는 "이 컴퓨터의 12번 인터페이스"처럼 철저하게 그 머신 안에서만 의미 있는 로컬 정보거든요. 반면 URL은 본질적으로 "누구에게나 전달돼서 똑같이 해석돼야 하는" 전역 주소예요. 내 노트북의 eth0가 상대방 서버한테 무슨 의미가 있겠어요. 성격이 정반대인 두 개념을 한 문자열에 욱여넣으니 표준도, 구현체들도 제각각이 될 수밖에 없는 거예요.
업계 맥락에서 보면
이건 사실 IPv6 표준(RFC 6874와 그 후속 논의)에서 오래 다퉈온 떡밥이에요. zone ID를 URL에 어떻게 표기할지를 두고 표준 자체가 여러 번 갈팡질팡했어요. 브라우저들은 한술 더 떠서 "보안상 위험하다"며 URL 안의 zone ID를 아예 거부하는 쪽으로 가버렸고요. 그래서 "규격에는 표기법이 있는데, 실제 브라우저는 안 받아준다"는 묘한 상태가 돼버렸죠.
비슷한 사례로 URL의 userinfo(user:pass@host 형식)도 보안 문제로 브라우저에서 점점 퇴출당하는 중이에요. 표준에 적혀 있다고 다 환영받는 게 아니라, 실무와 보안 현실에 부딪히면서 "이건 차라리 없는 게 낫다"고 정리되는 기능들이 있는 거예요. zone ID도 그 길을 걷고 있는 셈이고요.
한국 개발자에게 주는 시사점
당장 우리가 IPv6 link-local 주소를 URL에 박을 일은 흔치 않아요. 하지만 두 가지는 챙겨두면 좋아요. 첫째, 네트워크 진단 도구나 IoT 기기 관리 콘솔처럼 같은 LAN 안의 장비에 직접 붙는 코드를 짠다면 zone ID를 마주칠 수 있어요. 이때 URL 라이브러리에 주소를 통째로 넘기지 말고, 호스트 부분과 zone ID를 분리해서 다루는 습관을 들이세요. 둘째, 더 일반적인 교훈으로 "파싱하고 다시 문자열로 만들었을 때 원본과 같은지"를 꼭 테스트하세요. URL뿐 아니라 날짜, 숫자, 인코딩 처리 전반에서 이 round-trip 테스트 하나가 미묘한 버그를 엄청 많이 잡아줘요.
마무리
결국 핵심은 이거예요. 로컬에서만 의미 있는 정보를 전역 식별자에 끼워 넣으면 언젠가 반드시 탈이 난다. % 하나로 시작된 이야기지만, 추상화 경계를 함부로 넘지 말라는 설계 교훈으로 읽으면 더 값져요.
여러분은 IPv6를 실무에서 얼마나 쓰고 계신가요? 아직 IPv4 NAT로 다 해결되니까 미뤄두신 분들도 많을 텐데, 이런 함정을 보면 "역시 천천히 가야지" 싶기도 하네요. 여러분의 IPv6 도입 경험이 궁금해요.
🔗 출처: Hacker News
TTJ 코딩클래스 정규반
월급 외 수입,
코딩으로 만들 수 있습니다
17가지 수익 모델을 직접 실습하고, 1,300만원 상당의 자동화 도구와 소스코드를 받아가세요.
"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"
실제 수강생 후기- 비전공자도 6개월이면 첫 수익
- 20년 경력 개발자 직강
- 자동화 프로그램 + 소스코드 제공