URL 인코딩 완전 가이드: 퍼센트 인코딩 규칙과 실무 함정

프론트엔드에서는 정상으로 보이던 쿼리 문자열이 백엔드에서 깨져 보이거나, URL에 공백·+·한글이 들어가는 순간 API가 400을 반환하는 경우가 있습니다. 이런 문제는 네트워크 장애가 아니라 URL 인코딩을 잘못된 지점에 적용했기 때문인 경우가 많습니다.

1. URL 인코딩이란 무엇인가

URL은 원래 사용할 수 있는 문자가 제한적입니다. 공백, 유니코드 문자, 이모지, 그리고 &, = 같은 구조 문자를 안전하게 전달하려면 퍼센트 인코딩(Percent-Encoding)이 필요합니다. 형식은 % + 2자리 16진수이며, 공백은 보통 %20으로 표현됩니다.

올바르게 인코딩하지 않으면 값 일부가 구분자로 해석되어 파라미터가 분리되거나 손상될 수 있습니다.

2. 어떤 문자를 인코딩해야 하나

실무에서는 다음 세 범주로 생각하면 명확합니다.

  • Unreserved(대체로 그대로 사용 가능): A-Z, a-z, 0-9, -, _, ., ~
  • Reserved(구조 의미를 가짐): :, /, ?, #, [, ], @, &, =
  • 비 ASCII 문자: UTF-8 바이트로 변환 후 퍼센트 인코딩 필요

핵심은 "전부 인코딩"이 아니라 "URL 컴포넌트별로 필요한 부분만 인코딩"입니다.

3. 공백이 %20일 때도 있고 +일 때도 있는 이유

일반적인 URL 퍼센트 인코딩에서는 공백이 %20입니다. 하지만 application/x-www-form-urlencoded 규칙(HTML 폼 전송)에서는 공백이 +로 표현됩니다.

한 시스템은 +를 공백으로, 다른 시스템은 문자 플러스로 해석하면 데이터 불일치가 생깁니다. 서비스 간 규약을 먼저 맞추는 것이 중요합니다.

4. JavaScript: encodeURI vs encodeURIComponent

둘 다 인코딩 함수지만 사용 목적이 다릅니다.

  • encodeURI: URL 전체용. :, /, ? 같은 구조 문자를 유지합니다.
  • encodeURIComponent: 단일 파라미터 값용. &, =도 인코딩해 쿼리 구조 오염을 막습니다.
const keyword = 'C++ 입문 & 예제';
const url = '/search?q=' + encodeURIComponent(keyword);
// /search?q=C%2B%2B%20%EC%9E%85%EB%AC%B8%20%26%20%EC%98%88%EC%A0%9C

파라미터 값을 encodeURI로 처리하면 &가 새 파라미터 구분자로 해석될 수 있습니다.

5. 대표적 장애: 이중 인코딩(Double Encoding)

프론트엔드, SDK, 게이트웨이, 백엔드가 같은 값을 중복 인코딩하면 이중 인코딩이 발생합니다. 이때 %%25가 되어 데이터가 변형됩니다.

  • 원본: hello world
  • 1회 인코딩: hello%20world
  • 2회 인코딩: hello%2520world

설계 문서에 "누가 인코딩/디코딩을 담당하는지"를 경계별로 명시해야 합니다.

6. Path, Query, Fragment는 분리해서 처리

URL의 각 영역은 규칙이 다릅니다. URL 전체를 하나의 문자열로 처리하면 경로 슬래시가 깨지거나 쿼리 파싱 오류가 생깁니다.

영역 권장 방식 자주 하는 실수
Path 세그먼트 단위 인코딩, 라우팅 구조 유지 전체 경로를 한 번에 인코딩해 라우트 불일치 발생
Query 키와 값을 각각 인코딩 값 안의 &, = 미인코딩
Fragment 프런트 라우터 규칙에 맞춰 처리 서버 쿼리 규칙과 혼용

7. 보안 관점: 인코딩은 방어 그 자체가 아니다

URL 인코딩은 전송 표현을 안전하게 만드는 기술일 뿐, XSS/SQL Injection 방어를 대체하지 않습니다.

  • 수신 후 값 검증(화이트리스트, 길이 제한)을 수행합니다.
  • 출력 맥락(HTML/SQL/Shell)에 맞는 이스케이프를 적용합니다.
  • 디코딩된 값을 DOM에 바로 삽입하지 않습니다.
빠른 점검 체크리스트
먼저 어떤 URL 컴포넌트를 다루는지 확정하고, 그다음 맞는 함수로 인코딩한 뒤, 마지막으로 round-trip 테스트로 원값 복원을 확인하세요.

결론

URL 인코딩의 핵심은 문자표 암기가 아니라 경계와 책임의 일관성입니다. 컴포넌트 단위 규칙을 팀에서 합의하면, 재현하기 어려운 API 버그를 크게 줄일 수 있습니다.