SheepDev

인코딩·문자셋

URL의 한글·+·%20을 올바르게 처리하기

사용할 도구

같은 검색어인데 공백이 사라지거나 +가 공백이 됩니다. URL 문제는 변환 횟수뿐 아니라 문자열이 어떤 부분인지에 달렸습니다. 전체 URL에서 남겨야 할 구분자도 값 안에서는 인코딩해야 할 수 있습니다.

URL 인코딩 도구로 짧은 문자열을 하나씩 바꿔 보세요. URL에 방문하지 않고 표기만 확인하며 example.invalid는 예시 주소입니다. 인코딩이 맞아 보여도 자원 존재·링크 안전을 증명하지 않습니다.

공백 하나를 두 방식으로 비교

공백이 포함된 입력
red blue

구성 요소 인코딩은 red%20blue, 폼 모드는 red+blue입니다. 한쪽이 항상 틀린 것이 아니라 규칙이 다릅니다. +는 폼 규칙을 적용하는 곳에서 공백이지 모든 URL 위치에서 그런 것은 아닙니다. 수신 파서 규칙을 확인하세요.

디코딩도 맞는 규칙을 고릅니다. 일반 디코딩은 red+blue의 +를 남기고 폼 +를 공백으로 처리하면 red blue입니다. 결과가 이상하다고 반복 디코딩하기 전에 구성 요소인지 폼 값인지 확인하세요.

C++의 +는 공백이 아닙니다

더하기 기호가 포함된 입력
C++ guide
구성 요소 / 폼 결과
C%2B%2B%20guide
C%2B%2B+guide

폼에서도 원래 +는 %2B가 되어 공백에서 나온 +와 구분됩니다. 인코딩 전 C++ guide를 폼 디코딩하면 원래 +까지 공백이 됩니다. 원본과 이미 인코딩된 값을 섞지 마세요.

&를 남길지는 역할에 달렸습니다

검색어 하나로 보낼 값
tea & cake

구성 요소 결과는 tea%20%26%20cake입니다. 원래 &를 쿼리에 붙이면 매개변수 구분자로 읽힐 수 있습니다. 반대로 완성 URL의 ?·&까지 한 값으로 인코딩하면 구조를 잃습니다. URL 구성과 값 하나 삽입을 구분하세요.

전체 URL 모드는 일부 구조 기호를 남기지만 의도를 추측해 잘못된 URL을 고치지는 않습니다. URL 분해로 호스트·경로·쿼리·fragment를 보세요. 검색 값의 #가 실수로 fragment 시작이 되지 않도록 하세요.

%2520은 두 번째 인코딩의 단서

구성 요소 인코딩 두 번
red blue → red%20blue → red%2520blue

두 번째는 %를 %25로 바꿉니다. 한 번 디코딩해도 red%20blue가 남아 실패처럼 보일 수 있습니다. 실수로 두 번 했는지 문자 %20을 보내려 했는지는 값만으로 모릅니다. 양쪽 변환을 추적하세요.

%가 없어질 때까지 반복 디코딩하지 마세요. 문자로 의도한 %2F가 구분자로 바뀔 수 있습니다. 횟수는 보기 좋은 정도가 아니라 데이터 계약으로 정합니다. 인코딩 전·전송 직전·파싱 후 값을 구분하세요.

일본어 한 글자가 여러 % 표기가 되는 이유

UTF-8 바이트와 URL 표기
あ
UTF-8: e3 81 82
URL: %E3%81%82

각 % 뒤 두 자리는 여기서 UTF-8 한 바이트입니다. あ는 3바이트라 세 묶음이며 코드 포인트 U+3042를 %3042로 쓰는 방식이 아닙니다. 텍스트·바이트 변환으로 문자·바이트·URL 표기 세 단계를 연결해 보세요.

잘린 %E3%81이나 16진수가 아닌 %ZZ는 정상 디코딩할 수 없습니다. 오류를 없애려고 바이트를 추측하지 말고 원본 잘림을 확인하세요. 옛 시스템이 다른 인코딩을 쓰면 이 디코더만으로 원래 문자셋을 자동 확정할 수도 없습니다.

구현으로 돌아가 변환 경계 정하기

원래 검색어·선택 규칙·변환값·수신 규칙을 기록하세요. red blue 통과만으로 C++ guide·tea & cake 문제를 덮지 못합니다. 공백·+·&·#·% 예를 회귀 시험에 남기면 URL 조립 변경 뒤 확인하기 쉽습니다.

구조화된 URL·쿼리 API는 수작업 연결을 줄입니다. 다만 API가 값을 인코딩한다면 미리 같은 변환을 하지 마세요. 실험 목적은 변환을 늘리기가 아니라 어느 계층이 필요한 변환을 담당하는지 찾는 것입니다.

값 안의 &와 Query 구분자 &를 구별하기

검색어 red & blue의 &는 값의 일부입니다. 그대로 붙이면 받는 쪽이 새 파라미터 경계로 읽을 수 있습니다. 구성 요소 인코딩은 red%20%26%20blue, 폼 인코딩은 red+%26+blue입니다. 둘 다 실제 &를 %26으로 보호하고 공백 표현만 다릅니다. Query 구분자를 보존하는 일과 값 안의 문자를 보호하는 일은 별개입니다.

원래 값, 조립한 URL, 받은 값을 나란히 확인하세요. 주소창이 읽기 좋은 형태로 표시할 수 있어 겉모습만으로 이중 인코딩을 판단할 수는 없습니다. URL 분석 도구에서 원래 red & blue로 돌아오는지 확인하며 주소에 접속할 필요는 없습니다. URL 전체를 반복해서 디코딩하면 보호된 %26이 구조적 &로 바뀔 수 있으므로 변환할 계층을 먼저 정하세요.

비ASCII 값만 실패하면 문자 인코딩을 바꾸기 전에 어느 계층이 UTF-8 바이트를 다루는지 보세요. % 뒤 두 자리는 유니코드 문자 번호가 아니라 인코딩된 바이트입니다. 인코딩 문자열이 길어져도 원래 글자가 늘어난 것은 아닙니다. 길이 제한은 원래 값과 완성 URL을 따로 측정해 원인 단계를 좁히세요.

참고 자료

사용할 도구

가이드 →