본문 바로가기

[JS] encodeURIComponent, encodeURI 이슈

프로젝트에서 겪은 이슈 중 encodeURIComponent 이슈가 있어서 글로 남기게 되었다.

 

서버에서 응답으로 주는 값 중에 URL이 있었다.

{
  encryptUrl: `https://${도메인}?key=${암호화된 값}`
}

 

그 URL은 암호화된 값을 쿼리 스트링으로 포함하고 있고 이 값을 받아 외부 브라우저 환경이 아닌 다른 인앱브라우저(앞으로 A라고 표현하겠다)에서 구동을 해야 하였다.

사내에서 제공하는 url scheme을 사용함
window.location.href = `app://inappbrowser?version=42&url=${encodeURIComponent(
    `${landingUrl}`
)}

 

A로 이동해서 끝이 아니라 받은 URL 쿼리 스트링을 파라미터로 하여 서버로 복호화를 요청해서 복호화된 값을 응답으로 받아야 완료된다.

{
    key: 'key0001'
}

 

그런데 특이한 이슈가 있었다. 외부 브라우저에서 A로 이동이 아닌 A 내부에서 처음부터 끝까지 모든 과정을 진행하면 정상적으로 동작하는데, 유독 외부브라우저에서 A로 진입 후 복호화한 결과가 에러였다.

 

직접 서버에서 받은 파라미터를 찍어보니 발견도 어려운 이슈하나가 있었다.

// url 인코딩된 값
{
  key: 'Bg7%2Bed78ZvdYY5smI5m0ekknZ5UJSAxmeobalPr00UI%3D'
}
// request로 요청된 값
{
  key: 'Bg7 ed78ZvdYY5smI5m0ekknZ5UJSAxmeobalPr00UI='
}

// 원래 암호화된 값
{
  key: 'Bg7+ed78ZvdYY5smI5m0ekknZ5UJSAxmeobalPr00UI='
}

+가 인코딩되면 %2B가 되고, URL에서는 이 값을 공백으로 인식하여 request에 공백이 들어갔었다;

 

+ means a space only in application/x-www-form-urlencoded content,
such as the query part of a URL

 

url에서 자주봤었는데 매번 잊어버리고 그만 그대로 보낸 게 화근이었다.

공백문자를 '+'로 치환하니 해결되었다 😅

const replaceSpaceParams = {
    key: nf.replace(/\s/g, '+'),
    ...params
}
const res = await httpStore.checkValidation({
    ...replaceSpaceParams
})