JavaScript / 메모
JavaScript에서 숫자 표시에는 toLocaleString()을, 주소의 한 부분을 인코딩할 때는 encodeURIComponent()를 사용할 수 있습니다. 검색 매개변수가 여러 개라면 URL과 URLSearchParams로 구성하면 구분 문자와 공백 처리를 직접 맞추는 실수를 줄일 수 있습니다. 이 글은 기존 메모의 세 주제인 숫자 표시, 인코딩·디코딩, 선택자 호환성을 현재 코드에서 구분해 활용하도록 정리한 참고용 메모입니다.
천 단위 숫자 표시
(123456789).toLocaleString("ko-KR"); // "123,456,789"
로케일은 언어·지역별 표시 규칙입니다. 쉼표가 필요한 경우 로케일을 지정하고, 결과가 문자열이라는 점을 기억하세요. 소수 자릿수나 통화를 지정하고 표시된 입력을 다시 숫자로 바꾸는 작업은 천 단위 쉼표의 추가와 제거에 자세히 설명되어 있습니다. 여기의 짧은 코드는 표시용으로 사용하고 계산에는 원래 숫자를 유지합니다.
주소 전체와 주소의 한 부분을 다르게 인코딩하기
URI(Uniform Resource Identifier)는 자원을 식별하는 문자열이며 웹 주소인 URL도 여기에 포함됩니다. 인코딩은 주소에서 특별한 의미를 가진 문자나 한글 등을 전송 가능한 표현으로 바꾸는 작업입니다. HTML을 안전하게 출력하는 작업이나 암호화와는 다릅니다.
| 작업 | 함수 | 구분 |
|---|---|---|
| 주소 구조를 유지하면서 전체 URI 처리 | encodeURI() |
:, /, ?, & 같은 구조 문자를 남김 |
| 검색값·경로 조각 등 한 부분 처리 | encodeURIComponent() |
값 안의 &, =, ? 등을 인코딩 |
| encodeURI 결과 복원 | decodeURI() |
주소 구조 문자 처리 규칙에 맞춰 복원 |
| encodeURIComponent 결과 복원 | decodeURIComponent() |
개별 부분을 복원 |
encodeURI("https://example.com/search?q=coffee&sort=new");
// 주소 구조의 ?, =, &는 유지
encodeURIComponent("coffee&tea"); // "coffee%26tea"
decodeURIComponent("coffee%26tea"); // "coffee&tea"
검색값에 &가 있는데 encodeURI를 사용하면 그 문자가 다음 매개변수의 구분자로 해석될 수 있습니다. 개별 값에는 encodeURIComponent를 쓰거나 다음 구역처럼 매개변수 도구를 사용하세요. encodeURI()와 encodeURIComponent()의 인코딩 범위가 다릅니다. 이미 인코딩한 값을 다시 인코딩하면 %가 %25로 바뀌는 중복 인코딩이 생길 수 있습니다.
검색 매개변수는 원래 값을 넣어 구성하기
const url = new URL("https://example.com/search");
url.searchParams.set("q", "coffee & tea");
url.searchParams.set("page", "1");
console.log(url.href);
// https://example.com/search?q=coffee+%26+tea&page=1
URLSearchParams는 검색 매개변수의 이름과 값을 다루는 도구입니다. 원래 값을 넣으면 직렬화할 때 필요한 인코딩을 적용하므로 encodeURIComponent를 먼저 적용하지 않습니다. 이 형식에서는 공백을 +로 표시할 수 있습니다. 읽을 때도 url.searchParams.get("q")를 사용하면 공백과 인코딩을 처리한 값을 얻습니다. URLSearchParams의 직렬화 설명을 참고하세요.
디코딩 실패와 오래된 함수
function decodeComponentSafely(text) {
try {
return decodeURIComponent(text);
} catch (error) {
if (error instanceof URIError) return null;
throw error;
}
}
decodeComponentSafely("%E0%A4%A"); // null: 잘못된 인코딩
외부에서 받은 문자열은 잘못된 퍼센트 표현을 포함할 수 있고, decodeURIComponent는 이때 URIError를 던질 수 있습니다. 실패를 일반 값과 구분해서 처리하세요. 검색 매개변수 전체를 함수로 한 번에 디코딩하면 구분자를 잘못 해석할 수 있으므로 각 값을 읽는 도구를 이용하는 편이 낫습니다. decodeURIComponent()의 예외에 적용 조건이 나와 있습니다.
기존 메모의 escape()와 unescape()는 오래된 호환 기능이며 URI 처리에 권장되는 대체 함수가 아닙니다. 기존 저장값을 읽는 경우에는 과거에 어떤 함수로 인코딩했는지부터 확인해야 합니다. 특히 %uXXXX 형태를 쓰던 데이터를 decodeURIComponent로 무조건 바꾸면 호환되지 않을 수 있습니다. escape()의 사용 범위를 확인하고 새 코드에서는 목적에 맞는 URI 함수를 선택하세요.
IE8용 선택자 보완 메모와 현재 브라우저
기존 메모의 selectivizr는 IE8 같은 오래된 환경에서 CSS 선택자를 보완하기 위한 도구였습니다. 현재 브라우저에서 :last-child나 :nth-child()를 사용할 때 이 도구를 기본으로 추가할 필요는 없습니다. CSS(Cascading Style Sheets)는 화면의 모양을 지정하며, 가상 클래스는 요소의 위치나 상태에 따라 대상을 고르는 선택자입니다.
#items li:nth-child(2) {
color: #a00000;
}
#items li:last-child {
font-weight: bold;
}
CSS 파일이나 style 요소에 위 코드를 넣으면 두 번째 li와 마지막 li에 적용됩니다. :nth-child()는 같은 부모 아래의 전체 요소 형제 순서를 기준으로 계산하므로 다른 종류의 요소가 섞이면 선택 결과를 확인해야 합니다. 같은 태그끼리의 순서가 필요하면 :nth-of-type()과 구분하세요. :nth-child() 설명에 선택 기준과 호환성 정보가 있습니다. IE8을 실제로 유지해야 하는 별도 환경에는 이 글의 최신 JavaScript 문법과 도구를 그대로 적용하지 말고 해당 환경의 지원 범위를 따로 확인해야 합니다.
전체 예제: 검색어를 주소로 구성하고 복원하기
코드를 UTF-8의 javascript-notes.html로 저장하고 현재 브라우저로 여세요. 실제로 검색 요청을 보내지 않고 주소만 표시합니다. 결과는 textContent로 넣으며, JavaScript의 querySelectorAll()로 두 번째 항목에 클래스를 추가하는 예도 포함했습니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>문자열 인코딩과 검색 매개변수</title>
<style>
body { margin: 24px; font: 16px/1.7 sans-serif; }
input, button, select { font: inherit; max-width: 100%; }
label { display: block; margin-top: 12px; }
#output { white-space: pre-wrap; overflow-wrap: anywhere; }
</style>
</head>
<body>
<label for="query">검색어</label>
<input id="query" type="text" value="커피 & 차">
<button id="encode" type="button">주소 만들기</button>
<ul id="items"><li>첫째</li><li>둘째</li><li>셋째</li></ul>
<pre id="output" aria-live="polite"></pre>
<script>
function show() {
const value = document.getElementById("query").value;
const encoded = encodeURIComponent(value);
const url = new URL("https://example.com/search");
url.searchParams.set("q", value);
const lines = [
`부분 인코딩: ${encoded}`,
`디코딩: ${decodeURIComponent(encoded)}`,
`검색 주소: ${url.href}`,
`숫자 표시: ${(123456789).toLocaleString("ko-KR")}`
];
document.getElementById("output").textContent = lines.join("\n");
}
const second = document.querySelectorAll("#items li:nth-child(2)");
for (const item of second) item.classList.add("selected");
document.getElementById("encode").addEventListener("click", show);
show();
</script>
</body>
</html>
“커피 & 차”는 부분 인코딩 결과에서 공백이 %20, 앰퍼샌드가 %26으로 표시됩니다. 디코딩한 줄에는 원래 검색어가 나오며, URLSearchParams가 만든 주소에서는 공백이 +로 보입니다. 두 번째 li에는 selected 클래스가 추가됩니다. 클래스 추가 자체는 색을 만들지 않으므로 강조하고 싶다면 앞의 CSS 예제나 해당 클래스의 스타일을 함께 적용하세요.

