encodeURI VS encodeURIComponent

yonadev·2024년 2월 20일
0

웹개발에서 API 쿼리 요청을 날릴 때 특수문자열을 포함한 URI를 사용하게 되는 경우가 있다. 이 때는 인코딩을 통해 특수문자나 예약어에 의해 방해를 받거나 요청이 의도와 반대로 처리되는 경우를 막아야 한다. 자바스크립트에서 URI 인코딩을 지원하는 함수는 encodeURI와 encodeURIComponent가 있는데 이름도 비슷하고 하는 일도 비슷해 보인다. 하지만 구별해서 사용해야하기 때문에 여기서 차이를 짚어보겠다.

encodeURI

이스케이프 하지 않는 문자:

    A-Z a-z 0-9 ; , / ? : @ & = + $ - _ . ! ~ * ' ( ) #

이스케이프 하지 않는 문자가 너무 많다 😱 헷갈린다면 이렇게 기억하기! encodeURI는 몇몇의 특별한 뜻과 역할을 가진 문자는 인코딩 하지 않는다. 가령, :는 프로토콜에 사용되며(http://), /는 패스(velog.io/write), ?와, &는 쿼리 문자열, #는 URI의 fragment에 해당한다. 그래서 URI을 통째로 파라미터에 넣어서 인코딩된 결과를 넣고 싶을 때 사용한다. 예약어같이 특별한 뜻을 가진 문자는 인코딩 되지 않기 때문이다.

const uri = 'https://mozilla.org/?x=шеллы';
const encoded = encodeURI(uri);
console.log(encoded);
// expected output: "https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"

try {
  console.log(decodeURI(encoded));
  // expected output: "https://mozilla.org/?x=шеллы"
} catch (e) { // catches a malformed URI
  console.error(e);
}

encodeURIComponent

encodeURIComponent는 encodeURI보다 더 광범위한 문자를 인코딩한다. 클라이언트에서 서버로 POST 요청을 보내는 경우, 가령 &(ampersand) 문자는 서버에서 순수한 문자열로 인식되지 않고 새로운 문자열의 시작으로 인식될 가능성이 있기 때문에 인코딩이 필요하다.


var set1 = ";,/?:@&=+$#"; // 예약 문자, 이스케이프 한다.
var set2 = "-_.!~*'()";   // 비예약 표식, 이스케이프 하지 않는다
var set3 = "ABC abc 123"; // 알파벳 및 숫자, 공백, 이스케이프 한다.

console.log(encodeURIComponent(set1)); // %3B%2C%2F%3F%3A%40%26%3D%2B%24%23
console.log(encodeURIComponent(set2)); // -_.!~*'()
console.log(encodeURIComponent(set3)); // ABC%20abc%20123 (공백은 %20으로 인코딩)

예를 들어 쿼리 스트링 밸류 값에 넘겨지는 값이 아래와 같다면 encodeURIencodeURIComponent를 썼을때의 결과는 달라지게 된다.

const title = "안녕하세요?여러분 ;) 반갑습니다"
encodeURIComponent(title); // ?와 ;를 이스케이프한다
// '%EC%95%88%EB%85%95%ED%95%98%EC%84%B8%EC%9A%94%3F%EC%97%AC%EB%9F%AC%EB%B6%84%20%3B)%20%EB%B0%98%EA%B0%91%EC%8A%B5%EB%8B%88%EB%8B%A4'
encodeURI(title); // ?와 ;를 이스케이프하지 않는다.
// '%EC%95%88%EB%85%95%ED%95%98%EC%84%B8%EC%9A%94?%EC%97%AC%EB%9F%AC%EB%B6%84%20;)%20%EB%B0%98%EA%B0%91%EC%8A%B5%EB%8B%88%EB%8B%A4'

encodeURIComponent는 이런 특수한 문자들을 모두 이스케이프 시키기 때문에 감쌀때 모든 uri를 감싸면 &, = 같은 쿼리스트링을 구성하는 문자도 이스케이핑 처리된다. 따라서 밸류 값에만 encodeURIComponent를 감싸주도록 하자!

예를 들어서 다음과 같은 url을 전달한다고 할 때

https://velog.io/blog/?location=서울&title=헬로?&하_이!^^

query string을 구성하는 예약어(=, ?)까지 이스케이핑을 하면 안된다. 따라서 쿼리 스트링의 밸류 값에 해당하는 값만 encodeURIComponent를 사용해 이스케이핑한다. (따로 따로 인코딩을 해줘야 하기 때문에 이름이 encodeURIComponent가 된걸까? 싶다ㅋㅋ)

const url = "https://velog.io/blog/?";
const locationVal = "서울";
const titleVal = "헬로?&하_이!^^"
const wholeUrl = `${url}location=${encodeURIComponent(locationVal)}&title=${encodeURIComponent(titleVal)}`;

console.log(wholeUrl);
// 'https://velog.io/blog/?location=%EC%84%9C%EC%9A%B8&title=%ED%97%AC%EB%A1%9C%3F%26%ED%95%98_%EC%9D%B4!%5E%5E'

결론:
encodeURI는 예약문자에 대해 이스케이프 하지 않기 때문에 url 전체에 대해서 적용할 수 있다. 그러나 params 값에 이스케이핑 할 문자가 포함되지 않는지 주의해서 사용하도록 한다. (개인적으로 개발을 할 때는 주로 encodeURIComponent를 사용했다.)

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

profile
Frontend Developer

0개의 댓글