encodeURI와 encodeURIComponent의 차이점

2024. 9. 4. 01:46프로그래밍/JavaScript

개요

Javascript의 빌트인 전역 함수인 encodeURI와 encodeURIComponent의 차이점에 대해 이해하고 올바른 사용법에 대해 알아본다.

 

URL을 인코딩 해야하는 이유?

URI는 우리가 서버 간 통신에서 서로를 식별할 수 있는 유일한 식별자이다. 따라서 영어가 세계 공통 언어이듯이 URI도 이에 맞게 통일 시켜줘야 한다. URI가 변환될 경우 원치 않은 동작이 일어날 수 있기 때문이다. 

예를 들어 URL에 한글이 포함돼있는 경우를 생각해보자. 영어를 제외한 다른 나라의 언어는 UTF-8의 형태로 인코딩 돼야만 다른 환경에서도 올바르게 한글로 된 URI를 인식할 수 있을 것이다. 따라서 URL은 아스키 문자로 인코딩 해야 안전한 URI라고 할 수 있다.

encodeURI

encodeURI는 URI 자체는 완전할 경우에 전체 URI에 대해 인코딩을 진행한다. 이 때 인코딩하는 것을 이스케이프 처리 라고 하는데 이스케이프 처리에서 제외되는 문자들이 있다. 문서를 참고해보면 상세히 나와있다.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI

 

encodeURI() - JavaScript | MDN

The encodeURI() function encodes a URI by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character (will only be four escape sequences for characters composed of two surroga

developer.mozilla.org

encodeURI 같은 경우 쿼리 스트링에 사용될 수 있는 ?, &, = 과 같은 특수문자는 인코딩하지 않는다. 즉 쿼리스트링이 없거나 쿼리스트링이 완벽한 상황에서 전체 URI를 필요한 부분만 인코딩 하는 것이다.

 

encodeURIComponent

이 함수는 encodeURI와는 다르게 동작한다. 즉 인수로 주어지는 URI가 URI전체가 아닌 쿼리 스트링의 일부로 인식하고 인코딩한다. 따라서 encodeURI에서는 이스케이프 처리에서 제외됐던 ?, &, = 과 같은 특수문자도 모두 인코딩 한다. 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent

 

encodeURIComponent() - JavaScript | MDN

The encodeURIComponent() function encodes a URI by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character (will only be four escape sequences for characters composed of tw

developer.mozilla.org

 

설명만 들었을 때는 크게 두 함수의 차이점이 와닿지 않는다. 그럼 다음과 같은 상황을 가정해보자.

 

증명

사용자에게 입력값을 전달받고 이를 쿼리 스트링을 이용해 서버로 요청을 보낸다면 다음과 같은 형식일 것이다.

window.location.href = 'http://example.com?title=안녕하세요? 저는 OO입니다.&body=저는&10살입니다.=1살입니다.';

위와 같이 페이지 이동을 할 경우 어떻게 될까?

사용자의 입력값은 예측할 수 없기 때문에 위와 같은 상황은 충분히 발생할 수 있다.

위 URI의 쿼리스트링은 다음과 같이 분석된다.

title=안녕하세요? 저는 OO입니다.

body=저는

10살입니다.=1살입니다.

 

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1><%= title %></h1>
    <a onclick = callApi()>Button</a>
  </body>
  <script>
    const callApi = ()=>{
      
      window.location.href = 'http://localhost:3000/test?title=hi?my name is OO.&body=i am&10 years old.=1 years old..'

    }
  </script>
</html>

위와 같은 결과를 얻을 수 있다. 아마 이 부분은 프레임워크마다 상이할 수 있는데 express로 테스트 한 결과 encodeURI로 URI를 변환한 후에 페이지 이동을 시키는 것을 확인할 수 있었다.

전송된 URI : /test?title=hi?my%20name%20is%20OO.&body=i%20am&10%20years%20old.=1%20years%20old..

 

그렇다면 위 코드의 URI를 다음과 같이 변경해보자.

window.location.href = `http://localhost:3000/test?title=hi?my name is OO.&body=${encodeURIComponent('i am&10 years old.=1 years old..')}`

위와 같이 쿼리 스트링의 'body' query를 정상적으로 넘겨받는 것을 확인할 수 있다.

전송된 URI : /test?title=hi?my%20name%20is%20OO.&body=i%20am%2610%20years%20old.%3D1%20years%20old.. 

위에서 설명했듯 encodeURIComponent는 =까지 이스케이프 처리하기 때문에 안전하게 동작할 수 있었던 것이다.

 

결론

1. encodeURIComponent는 사용자로부터 입력을 받거나 동적으로 변할 수 있는 쿼리 스트링의 value에 사용하도록 한다. 쿼리 스트링이 아닌 URI에 포함되는 공백이나 특수문자의 경우 어차피 encodeURI를 통해 안전하게 이스케이프 처리 되기 때문이다.

2. 사용자로부터 특수문자와 같은 예외 케이스로 URI가 결정되지 않는다면, 즉 서버에서 URI를 생성하거나 ?, &, =과 같은 특수문자가 포함되지 않은 URI를 생성하는 것이 보장될 때(완전한 URI)는 encodeURI를 통해 변환하는 것이 안전하다고 생각한다.