검색 링크를 만들려고 한글 키워드를 URL에 붙였더니, 클릭하면 엉뚱한 페이지로 갑니다. 또는 파라미터 값에 &가 들어가자 그 뒤가 통째로 잘립니다. 원인은 보통 인코딩 함수를 잘못 고른 것입니다. URL 인코딩의 핵심은 함수 두 개의 차이에 있습니다.
component냐 full이냐, 먼저 범위를 정하라
자바스크립트에는 URL 인코딩 함수가 둘입니다. 차이는 예약문자를 건드리느냐입니다.
encodeURIComponent(component 모드)는 / ? # & = 같은 예약문자까지 전부 퍼센트 인코딩합니다. 값 하나, 경로 한 조각을 다룰 때 씁니다. encodeURI(full 모드)는 그 구분자들을 보존합니다. 이미 형태가 잡힌 주소 전체를 인코딩할 때 씁니다. MDN도 둘을 용도로 구분합니다. 잘못 고르는 순간 버그가 시작됩니다.
쿼리 값에 예약문자가 있으면 component
가장 자주 터지는 지점입니다. 파라미터 값 안에 &나 =가 들어갈 때입니다.
값으로 a=1&b=2를 넣는다고 해봅시다. PiPi Worlds URL 인코딩 도구에서 component로 인코딩하면 a%3D1%26b%3D2가 나옵니다. =와 &가 각각 %3D, %26으로 바뀌어 하나의 값으로 안전하게 들어갑니다. 반면 full로 인코딩하면 a=1&b=2 그대로입니다. 이 값을 ?x=a=1&b=2처럼 붙이면 서버는 &b=2를 별개 파라미터로 읽어 데이터가 깨집니다. 값에는 component가 답입니다.
주소 전체를 인코딩할 땐 full
반대 상황도 있습니다. 이미 완성된 URL 전체를 인코딩해야 할 때입니다.
https://pipi-worlds.com/길?q=안녕을 full로 인코딩하면 https://pipi-worlds.com/%EA%B8%B8?q=%EC%95%88%EB%85%95이 됩니다. ://, /, ?, =는 그대로 두고 한글만 퍼센트로 바꿉니다. 여기에 component를 쓰면 https%3A%2F%2Fpipi-worlds.com...처럼 스킴 구분자까지 죄다 인코딩돼 주소 자체가 망가집니다. 범위가 ‘URL 전체’면 full입니다.
’+‘가 공백이 되는 함정
디코딩에서 사람을 헷갈리게 하는 게 +입니다. 같은 a+b가 출처에 따라 다르게 풀립니다.
HTML 폼 전송 규격인 application/x-www-form-urlencoded에서는 공백을 +로 표현합니다. 그러나 일반 URL에서 +는 그냥 더하기 기호입니다. 그래서 도구에서 a+b를 디코딩하면, ’+ 를 공백으로’ 옵션이 꺼져 있으면 a+b, 켜져 있으면 a b가 됩니다. 받은 문자열이 폼에서 왔는지 URL에서 왔는지에 따라 토글을 맞춰야 합니다.
그 퍼센트 덩어리, 정체가 뭔지 모를 때
마지막은 받은 쪽 이야기입니다. 로그나 리다이렉트 URL에서 %EC%95%88... 같은 덩어리를 만났는데, 이게 폼 데이터인지 URL 조각인지, +를 어떻게 봐야 할지 한눈에 알기 어렵습니다.
PiPi Worlds URL 인코딩 도구는 component·full과 ’+ 공백’ 옵션을 바로 토글하며 결과를 비교할 수 있고, 변환이 전부 브라우저 안에서 실행돼 입력이 서버로 전송되지 않습니다. 잘린 %처럼 깨진 시퀀스는 깨진 글자 대신 오류로 알려 줍니다. URL 안의 값이 base64라면 Base64 도구로, JSON 조각이라면 JSON 포맷터로 바로 이어서 확인하면 됩니다.