더하기 기호는 항상 공백이 아닙니다

Moyoutil URL 도구는 URI 구성 요소를 변환합니다. 디코딩은 decodeURIComponent를 사용하므로 +를 그대로 유지합니다. 반면 URLSearchParams는 application/x-www-form-urlencoded 규칙으로 쿼리를 읽으며 원래 문자열의 +를 공백으로 바꾼 뒤 퍼센트 디코딩합니다. %2B로 표현한 더하기 기호는 이 순서 때문에 +로 남습니다.

WHATWG URL: 폼 방식 파싱

ECMAScript: decodeURIComponent

같은 입력을 두 경로에서 실행한 결과

2026년 10월 5일 프로젝트의 urlComponent 함수와 JavaScript URLSearchParams로 실행한 결과입니다. 표의 따옴표는 공백을 보이게 하는 JSON 표시이며 결과에 포함되는 문자가 아닙니다. 쿼리 파싱에서는 각 입력 앞에 q=를 붙였습니다.

구성 요소 디코딩과 쿼리 값 파싱 비교
입력Moyoutil 디코딩URLSearchParams
C++"C++""C "
C%2B%2B"C++""C++"
a+b"a+b""a b"
a%20b"a b""a b"
C++와 C%2B%2B의 두 디코딩 경로 비교. q=C++를 쿼리로 읽으면 공백 두 개가 됩니다.
직접 재현한 코드 출력을 설명하는 자체 제작 도식입니다. 0x20은 공백, 0x2B는 더하기 기호의 문자 코드입니다. 실제 화면 캡처가 아닙니다.

검색어를 보존하려면 원문 값으로 쿼리를 만드세요

아래 예시는 외부 서버에 요청하지 않고 문자열만 만듭니다. URLSearchParams에 원문 값 C++ guide를 넣으면 더하기 기호는 %2B로, 공백은 +로 직렬화됩니다. encodeURIComponent로 값 하나를 변환하면 같은 공백은 %20이 됩니다. 두 결과 모두 이 예시의 쿼리 파싱에서는 원문으로 돌아옵니다.

const original = "C++ guide";
const query = new URLSearchParams({ q: original }).toString();
// q=C%2B%2B+guide
const component = encodeURIComponent(original);
// C%2B%2B%20guide
new URLSearchParams(query).get("q");
// C++ guide

WHATWG URL: URLSearchParams 직렬화

현재 Moyoutil URL 도구에는 쿼리 이름·값을 조립하는 입력란이나 폼 방식 디코딩 모드가 없습니다. 값 하나를 검사하려면 인코딩으로 C++ guide를 변환한 뒤 결과를 디코딩해 원문을 확인하세요. 전체 주소를 값 변환란에 넣지 마세요. 실제 API에서는 해당 API가 요구하는 인코딩 규칙을 확인해야 합니다.

이미 인코딩한 값을 넣으면 퍼센트 기호도 변환됩니다

URLSearchParams의 객체 입력에는 인코딩되지 않은 원문 값을 넣습니다. 먼저 encodeURIComponent로 변환한 값을 넣으면 %가 %25로 다시 인코딩됩니다. 아래 쿼리를 한 번 파싱한 값은 C++가 아니라 C%2B%2B입니다. 반복 디코딩으로 맞추기 전에 송신·수신 단계의 역할을 확인하세요.

const encoded = encodeURIComponent("C++");
// C%2B%2B
const query = new URLSearchParams({ q: encoded }).toString();
// q=C%252B%252B
new URLSearchParams(query).get("q");
// C%2B%2B

문제 있는 링크를 검사하는 순서

  1. 원래 검색어와 전달된 쿼리 문자열을 함께 보관합니다. C++와 C%2B%2B를 구분합니다.
  2. 수신 코드가 decodeURIComponent인지 폼 방식 쿼리 파서인지 확인합니다. Moyoutil의 디코딩 결과만으로 서버 결과를 단정하지 않습니다.
  3. 원문 값으로 쿼리를 다시 구성한 뒤 파싱 결과와 비교합니다. 예시 코드와 실제 API의 규칙을 구분합니다.

%나 %2처럼 불완전한 퍼센트 표기는 Moyoutil에서 오류입니다. %FF도 유효한 UTF-8 텍스트가 아니어서 오류입니다. 이 검사는 다른 파서의 오류 처리까지 같다는 뜻이 아니며, 원문을 자동 복구하는 기능도 아닙니다.

자주 묻는 질문

%20과 + 중 무엇을 써야 하나요?

값 하나를 Moyoutil에서 인코딩하면 공백은 %20입니다. URLSearchParams 직렬화에서는 +입니다. 받는 쪽의 규칙을 확인하고 원문으로 왕복하는지 검사하세요.

원래 더하기 기호를 모두 공백으로 바꿔도 되나요?

안 됩니다. C++ 같은 값의 의미가 달라집니다. 폼 방식으로 받은 문자열에만 해당 파싱 규칙을 적용하며, 인코딩 전 원문을 임의로 바꾸지 마세요.