정의 및 사용 방법
codePointAt() 함수는 문자열에서 지정한 인덱스에 위치한 문자의 유니코드 코드 포인트 값을 반환합니다.
이 함수가 반환하는 유니코드 코드 포인트 값은 해당 문자에 할당된 **유니코드 코드 포인트**를 기준으로 하며, 10진수로 나타냅니다.
- 유니코드 코드 포인트(Code Point)
- 컴퓨터는 문자를 숫자로 인식합니다. 이러한 문자와 숫자의 대응 관계를 표준화한 체계가
Unicode(유니코드)입니다.
전 세계의 다양한 문자, 숫자, 이모지(예: 😃, 🎉, ❤️) 등 각 문자 하나에 고유하게 할당된 숫자 값을 의미합니다.
codePointAt() 함수는 알파벳, 숫자, 한글, 이모지 등 모든 유효한 문자를 비교하거나 조건으로 판단하는 등, 문자를 숫자 값으로 직접 다뤄야 하는 상황에서 매우 유용합니다.
기본 예제
/* 문자열.codePointAt(index) */
const str = "ABCDE🎄🎁";
// 1. 일반 문자 확인
const index = 1; // 인덱스 1에 위치한 문자는 "B" (문자열 인덱스는 0부터 시작)
const resultCodePoint = str.codePointAt(index);
console.log(resultCodePoint); // 출력: 66
// 2. 이모지 확인
const emojiIndex = 5; // 인덱스 5에 위치한 문자는 "🎄"
const resultEmojiCode = str.codePointAt(emojiIndex);
console.log(resultEmojiCode); // 출력: 127876
구문
str.codePointAt(index)
str은 codePointAt() 함수를 적용할 문자열입니다.
매개변수
index |
0부터 시작하는 인덱스를 지정합니다.
|
|---|
반환 값
index에 위치한 문자의 유니코드 코드 포인트를 반환합니다.
단, index가 문자열의 유효한 범위를 벗어날 경우 undefined를 반환합니다.
매개변수와 반환 값 참고 사항
codePointAt() 함수는 일반적인 알파벳이나 한글이 아닌, 이모지(예: 😃, 🎉, ❤️)나 일부 희귀 한자(예: 𠮷 - '길'의 옛 글자), 아주 특수한 수학적 기호(예: 𝝅, Mathematical Italic Small Pi)처럼 **UTF-16 코드 유닛** 하나로 표현할 수 없는 문자(서로게이트 쌍, Surrogate Pair)를 다룰 때 다음과 같은 특징이 있습니다.
- UTF-16 코드 유닛(Code Unit)과 서로게이트 쌍(Surrogate Pair)
- 자바스크립트는 문자열을 처리할 때 'UTF-16 코드 유닛'을 기준으로 합니다.
UTF-16에서 코드 유닛이란, 문자열을 내부적으로 저장하고 처리하기 위해 사용하는 16비트(2바이트) 크기의 단위를 의미합니다. 영어 문자, 숫자, 그리고 일반적인 한글은 하나의 'UTF-16 코드 유닛'으로 표현되므로, 문자열의 길이와 인덱스에서도 각각 1로 계산됩니다.
반면, 'UTF-16 코드 유닛' 하나로 표현할 수 없는 이모지, 일부 희귀 한자, 특수한 수학적 기호 등은 두 개의 코드 유닛을 한 쌍으로 조합해 하나의 문자로 처리됩니다. 이러한 두 코드 유닛의 조합을 '서로게이트 쌍(Surrogate Pair)'이라고 부릅니다.
서로게이트 쌍이 포함된 문자열에서의 문제점
서로게이트 쌍이 포함된 문자열에서 codePointAt() 함수를 사용할 때 얼핏보면, 이해가 가지 않는 index에 위치한 해당 문자나, 반환하는 값이 이상한 것처럼 느껴질 수 있습니다. 다음의 예제로 살펴보겠습니다.
const str = "🎄";
console.log(str.codePointAt(0)); // 127876 (정상)
console.log(str.codePointAt(1)); // 56836 (어라? 이건 뭐지?)
위 예제처럼, 서로게이트 쌍으로 구성된 이모지("🎄") 문자는 실제로 한 글자이지만, 문자열 인덱스 상으로는 2칸을 차지합니다.
그렇다면 왜 이런 현상이 발생하는 걸까요?
이유는 자바스크립트가 문자열을 다루는 기본 단위인 **'코드 유닛(Code Unit)'**과 우리가 실제로 보는 문자인 **'코드 포인트(Code Point)'**의 차이에 있습니다.
- 코드 포인트(Code Point) vs. 코드 유닛(Code Unit)
- 자바스크립트는 문자열을 내부적으로 처리할 때 16비트 단위인 '코드 유닛(Code Unit)'을 사용합니다.하지만 이모지처럼 서로게이트 쌍으로 구성된 문자는 하나의 코드 유닛으로 표현되지 않고 두 개의 코드 유닛으로 나뉘어 처리됩니다.
반면 '코드 포인트(Code Point)'는 문자에 할당된 전체 숫자 번호를 의미합니다.
codePointAt()에 전달하는 index는 **'코드 유닛(Code Unit)'**로 계산되므로, 서로게이트 쌍의 두 번째 코드 유닛을 참조하면 예상치 못한 숫자가 반환됩니다.
예를 들어, 🎄 이모지는 하나의 글자이지만 내부적으로는 두 개의 코드 유닛으로 구성되어 있습니다.
str.codePointAt(0)는 이모지 전체 코드 포인트 값을 반환하지만, str.codePointAt(1)는 이모지의 두 번째 코드 유닛을 단독으로 읽기 때문에, 의미 없는 값이 반환되는 것입니다.
즉, 문자 단위가 아닌 UTF-16 '코드 유닛' 단위로 인덱스가 계산되기 때문에, 서로게이트 쌍을 포함한 문자열에서는 index와 반환 값이 헷갈릴 수 있습니다.
서로게이트 쌍이 포함된 문자열 다루기
앞서 살펴본 것처럼, 서로게이트 쌍을 포함한 문자열은 일반적인 문자처럼 단일 인덱스로 처리하기 어렵기 때문에, 문자열을 반복하거나 특정 문자의 코드 포인트를 읽을 때 주의가 필요합니다.
서로게이트 쌍이 포함된 문자열을 codePointAt()로 안전하게 다루려면, 문자열을 '코드 포인트' 단위로 처리해야 합니다. 자바스크립트에서 문자열의 각 인덱스는 기본적으로 '코드 유닛(Code Unit)' 단위로 계산되지만, 문자열을 순회하거나 배열로 변환하면 '코드 포인트(Code Point)' 단위로 각 문자를 정확히 다룰 수 있습니다.
문자열을 순회하는 for 문의 예제와, 문자열을 배열로 변환하는 스프레드 구문(...) 예제로 서로게이트 쌍이 포함된 문자열을 어떻게 다루는지 살펴보겠습니다.
for 문으로 서로게이트 쌍이 포함된 문자열 다루기
for 문은 자바스크립트 내부적으로 서로게이트 쌍을 인식하여 하나의 온전한 문자(코드 포인트) 단위로 순회합니다. 매개변수인 인덱스(index)를 직접 적용할 수 있어서 매우 직관적입니다.
/**
* 문자열에서 서로게이트 쌍을 고려하여 N번째 문자의 코드 포인트를 반환합니다.
* @param {string} str - 대상 문자열
* @param {number} charIndex - 가져오려는 문자의 순서 (0부터 시작)
*/
function getSafeCodePoint(str, charIndex) {
let count = 0;
for (let char of str) {
if (count === charIndex) {
return char.codePointAt(0);
}
count++;
}
return undefined; // 인덱스를 벗어난 경우
}
const text = "A🎄B";
console.log(getSafeCodePoint(text, 0)); // 65 (A)
console.log(getSafeCodePoint(text, 1)); // 127876 (🎄 - 인덱스 1, 2를 합쳐서 1번째 문자로 인식)
console.log(getSafeCodePoint(text, 2)); // 66 (B - 실제 문자열 인덱스는 3이지만 2번째 문자로 인식)
스프레드 구문(...)으로 서로게이트 쌍이 포함된 문자열 다루기
문자열을 배열로 변환하는 스프레드 구문(...)을 사용해서 문자열을 하나하나의 배열 요소로 변환하면 '코드 포인트(Code Point)' 단위로 각 문자를 정확히 다룰 수 있습니다.
아래의 함수는 문자열을 '코드 포인트 단위'의 배열로 먼저 바꾼 뒤, 배열의 인덱스를 매개변수로 받아 해당 위치의 값을 반환합니다.
/**
* 문자열을 배열로 변환하여, 실제 문자 순서(index)에 맞는 코드 포인트를 반환합니다.
* @param {string} str - 대상 문자열
* @param {number} charIndex - 가져오려는 문자의 순서 (0부터 시작)
*/
function getCodePointByIndex(str, charIndex) {
// 1. 문자열을 코드 포인트 단위의 배열로 변환 (이모지도 한 칸으로 합쳐짐)
const charArray = [...str];
// 2. 배열의 인덱스는 우리가 눈으로 보는 문자 순서와 정확히 일치합니다.
const targetChar = charArray[charIndex];
// 3. 해당 문자가 존재하면 코드 포인트를 반환합니다.
return targetChar ? targetChar.codePointAt(0) : undefined;
}
const text = "A🎄B"; // 실제 문자 구성: [0]번 'A', [1]번 '🎄', [2]번 'B'
console.log(getCodePointByIndex(text, 1)); // 127876 (🎄의 온전한 값 반환)
console.log(getCodePointByIndex(text, 2)); // 66 (B의 값 반환)
사용법 참고 사항
codePointAt() 함수가 반환하는 숫자 값은 단순한 결과값이 아니라, 문자를 비교하거나 조건으로 판단하는 등 문자를 숫자로 다뤄야 하는 상황에서 중요한 의미를 갖습니다.
문자의 유니코드 코드 포인트 값이 어떤 기준으로 정해지며, 어떤 상황에서 활용되는지에 대해 살펴봅니다.
유니코드 코드 포인트 값은 범위가 있다.
유니코드 코드 포인트 값에서는 영어 문자, 숫자, 특수 문자, 이모지, 그리고 각 언어의 문자마다 서로 다른 **숫자 값의 범위**가 정해져 있습니다.
예를 들면 다음의 표와 같습니다.
| 구분 | 문자 범위 | 유니코드 코드 포인트 값 (10진수) |
|---|---|---|
| 영어 대문자 | A ~ Z |
65 ~ 90 |
| 영어 소문자 | a ~ z |
97 ~ 122 |
| 숫자 | 0 ~ 9 |
48 ~ 57 |
| 한글 음절 | 가 ~ 힣 |
44032 ~ 55203 |
| 이모지(여러 이모지 중 Emoticons 블록만 발췌함) | 😃 ~ 🙊 |
128512 ~ 128586 |
이러한 숫자 값의 범위는 한국어를 포함하여 언어별로도 규격화되어 있다는 것입니다.
반환되는 유니코드 코드 값을 알면, 해당 문자가 영어 대문자인지 소문자인지, 숫자인지 또는 이모지인지 한국어 문자인지를 이렇게 정해진 범위를 기준으로 판단할 수 있습니다.
유니코드 코드 포인트 값은 문자 정렬의 기준이 된다.
문자는 자바스크립트에서 내부적으로 숫자 값(유니코드 유니코드 코드 포인트 값 )을 인식할 수 있기 때문에, 문자를 비교하거나 정렬할 때는 결국 이 **숫자의 크기**를 기준으로 판단하게 됩니다.
예를 들면 다음의 표와 같습니다.
| 구분 | 문자 | 유니코드 코드 포인트 값(10진수) |
|---|---|---|
| 영어 대문자 | A |
65 |
| 영어 대문자 | B |
66 |
| 영어 대문자 | C |
67 |
| 영어 소문자 | a |
97 |
| 영어 소문자 | b |
98 |
| 영어 소문자 | c |
99 |
| 숫자 | 0 |
48 |
| 숫자 | 1 |
49 |
| 숫자 | 2 |
50 |
| 한글 음절 | 가 |
44032 |
| 한글 음절 | 나 |
45208 |
| 한글 음절 | 다 |
45796 |
| 이모지 | 😃 |
128512 |
| 이모지 | 🙊 |
128586 |
이러한 유니코드 코드 포인트 값의 정렬은 한국어를 포함하여 언어별로도 규격화되어 있다는 것입니다.
반환되는 유니코드 코드 포인트 값을 알면, 문자열을 사전식으로 정렬하거나 특정 문자끼리의 정렬 순서를 비교할 수 있습니다.
유니코드 코드 포인트 값을 알려면
위키백과의 List of Unicode characters를 참고하세요.
활용 예제
다음은 codePointAt() 함수를 사용하여 반환되는 유니코드 코드 포인트 값을 실제 어떻게 활용하는지에 대한 예제입니다.
문자 종류 판별 예제
function checkCharacterType(char) {
// 0번 인덱스의 코드 포인트 값을 읽어옵니다.
// 이모지(서로게이트 쌍)도 온전한 하나의 숫자로 읽어냅니다.
const code = char.codePointAt(0);
// 빈 문자열이 전달된 경우를 방어하기 위한 처리
if (code === undefined) {
return "유효하지 않은 문자";
}
switch (true) {
case (code >= 65 && code <= 90):
return "영어 대문자";
case (code >= 97 && code <= 122):
return "영어 소문자";
case (code >= 48 && code <= 57):
return "숫자";
case (code >= 44032 && code <= 55203):
return "한글(가~힣)";
// Emoticons 블록(대표적인 표정 이모지) 범위 체크
case (code >= 128512 && code <= 128586):
return "이모지(Emoticons)";
default:
return "기타 문자 또는 특수 기호";
}
}
// 결과 확인
console.log(checkCharacterType("A")); // 출력: 영어 대문자
console.log(checkCharacterType("7")); // 출력: 숫자
console.log(checkCharacterType("코")); // 출력: 한글(가~힣)
console.log(checkCharacterType("😃")); // 출력: 이모지
문자를 사전식 정렬 예제
/**
* 두 문자의 유니코드 코드 포인트 값을 비교하여 정렬 순서를 반환합니다.
* 결과값이 음수이면 첫 번째 문자가 앞서고, 양수이면 뒤에 옵니다.
*/
function compareCharacters(char1, char2) {
// codePointAt을 사용하여 이모지를 포함한 모든 문자의 온전한 값을 읽어옵니다.
const code1 = char1.codePointAt(0);
const code2 = char2.codePointAt(0);
// 두 코드 포인트 값의 차이를 반환하여 정렬 순서를 결정합니다.
return code1 - code2;
}
// 1. 영어 대문자 비교
const result1 = compareCharacters("A", "B");
console.log(result1); // -1 (65 - 66): 'A'가 'B'보다 앞섬
// 2. 영어 소문자 비교
const result2 = compareCharacters("b", "a");
console.log(result2); // 1 (98 - 97): 'b'가 'a'보다 뒤에 옴
// 3. 대소문자 비교
const result3 = compareCharacters("A", "a");
console.log(result3); // -32 (65 - 97): 대문자가 소문자보다 앞섬
// 4. 이모지가 포함된 비교
const result4 = compareCharacters("😃", "A");
console.log(result4); // 128447 (128512 - 65): 이모지는 영어보다 훨씬 뒤에 정렬됨
명세서
| 명세서 사양 | |
|---|---|
codePointAt()
|
ECMAScript® 2026 Language Specification #sec-string.prototype.codepointat |
호환성
| 메서드 |
데스크탑 Chrome
|
데스크탑데스크탑 Edge
|
데스크탑 Firefox
|
Safari
|
Node.js
|
|---|---|---|---|---|---|
codePointAt()
|
41 | 12 | 29 | 9 | 4 |