자바스크립트 문자열 표현하기 2020. 05. 01. 13:47 study/gardenist#javascript#string 문자열은 텍스트를 다루기 위한 데이터입니다. 문서의 제목, 내용, 사용자의 ID, 비밀번호, 게시글에 보이는 내용 등 글자로 된 것들 그리고 지금 쓰고 있는 이 문서도 텍스트이고 문자열로 표현될 수 있습니다. 자바스크립트에서의 문자열은 문자열 리터럴(작은 따옴표 또는 큰 따옴표로 묶인 텍스트), String 함수, 또는 다른 객체의 toString() 메서드를 호출하여 표현할 수 있습니다. // 문자열 리터럴 let literalString = "Hello, String!" // String 함수 let stringFunction = String("Hello, String"); // String 함수에 문자열 리터럴을 전달 let stringFunction2 = String(1); // "1"이 됩니다. // toString() 메서드 호출 let number = 123; let toStringResult = number.toString(); // "123"이 됩니다. 단순히 원하는 텍스트를 따옴표 안에 넣음으로써 문자열을 표현할 수도 있지만, 줄바꿈, 탭과 같은 문자는 역슬래시()기호를 붙인 문자로 표현할 수 있습니다. 이를 이스케이프(Escape)라고 합니다. let tab = "\t"; // Tab 문자 let newLine = "\n"; // 줄바꿈 문자 let singleQuote = '\''; // 작은 따옴표(')로 둘러싼 문자열 안에서 작은 따옴표를 글자 그대로 쓰기 let noProblem = "'"; // 큰 따옴표 안의 작은 따옴표는 이스케이프 하지 않아도 됩니다. let doubleQuote = "\""; // 큰 따움표(")로 둘러싼 문자열 안에서 큰 따옴표를 글자 그대로 쓰기 줄바꿈의 경우에는 운영체제나 환경에 따라 Carriage Return 이라는 문자를 줄바꿈에 같이 쓰기도 합니다. 타자기에서는 줄을 바꿀 때 잉크가 묻은 카트리지가 좌우로 움직이게 하는 캐리지를 줄 끝에서 다시 줄 처음으로 되돌려야 하고, 이를 캐리지 리턴이라고 합니다. 그리고 난 후 새로운 줄의 입력을 위해 종이를 밀어 올리는 Line Feed를 해줍니다. 이를 줄여서 캐리지 리턴을 CR, 라인 피드를 LF라고 하며, 이스케이프된 문자로는 각각 \r, \n 입니다. 그래서 간혹 텍스트 파일의 줄바꿈의 표현에 CR과 LF가 함께 있는 경우가 있어 파일을 읽은 후 줄 단위의 처리를 할 때 \r\n 형식으로 해줄 때도 있습니다. 이스케이프 문자 외에 한국어 키보드에 없는 다른 국가의 문자나 이모지를 입력하려면 유니코드를 활용할 수 있습니다. 유니코드를 입력하기 위해서는 \u와 함께 16진수 4자리의 유니코드 값을 적어줍니다. // 제 성인 "이"의 한자를 유니코드 16진수로 표기하면 아래와 같습니다. let lastName = "\u674e"; console.log(lastName); // "李" 출력 객체를 문자열로 표현하기 위해서 toString() 메서드를 호출하여 문자열을 얻을 수 있습니다. 객체 중 숫자(Number) 타입의 경우 toString() 메서드에 몇 진수로 표현할 것인지 인자로 전달할 수 있습니다. let number = 1234; console.log(number.toString()); // "1234" -> 10진수 그대로 문자열로 변환 console.log(number.toString(2)); // "10011010010" -> 2진수로 표현된 1234 console.log(number.toString(8)); // "2322" -> 8진수로 표현된 1234 console.log(number.toString(16)); // "4d2" -> 16진수로 표현된 1234 10진수 이상은 알파벳을 사용하여 표현하며 toString의 인자로 최대 36까지 전달할 수 있으며, 36진수의 경우에는 숫자 0~9, 알파벳 a~z(26문자)로 구성됩니다. 2보다 적은 수 또는 36보다 큰 수를 전달하면 오류가 발생합니다. 유니코드 중 이모지의 경우에는 조금 더 복잡합니다. 자바스크립트는 하나의 글자를 위해 2byte를 사용합니다. 하지만 이모지는 4byte입니다. 그러므로 이모지는 보여지는 것은 한 글자이지만, 자바스크립트 내부적으로는 두 글자입니다. let smile = "😀"; console.log(smile.length); // 한 글자이지만 2를 출력합니다. // charCodeAt console.log(smile.charCodeAt(0)); // 55357 출력 console.log(smile.charCodeAt(1)); // 56832 출력 // codePointAt console.log(smile.codePointAt(0)); // 128512 출력 console.log(smile.codePointAt(1)); // 56832 출력 문자와 문자열의 내부에서 charCodeAt은 UTF-16의 값을 반환하고, codePointAt은 유니코드 값을 반환한다고 했습니다. 스마일 이모지는 유니코드에는 하나의 글자와 값으로 정의하지만, UTF-16에는 Surrogate라는 방식으로 2byte 2개로 나누어 표현합니다. (아래는 깊게 보지 않아도 됩니다.) UTF-16에서 유니코드의 코드 값이 16진수 값으로 0x10000이 넘는 값은 코드 값에서 0x10000을 빼고, 뒤에서 10비트, 나머지 비트를 UTF-16의 “상위/하위 대체 영역”으로 표시된 Surrogate(상위 U+D800~U+DBFF, 하위 U+DC00~U+DFFF) 범위로 다시 대응시킵니다. 위의 스마일의 codePointAt()의 호출 결과로 128512의 값을 얻었는데, 이를 Surrogate에 대응하기 위해서는 아래와 같이 계산합니다. 유니코드 값 128512에서 0x10000(십진수로 65536) 을 뺍니다. → 62976 하위 10비트의 값을 구하기 위해 1024로 나눈 나머지를 구합니다 → 512 나머지 비트의 값을 구하기 위해 1024로 나누고 소수점은 버립니다 → 61 상위 Surrogate의 시작 값인 U+D800에 나머지 비트의 값인 61을 더합니다. 하위 Surrogate의 시작 값인 U+DC00에 하위 10비트의 값인 512를 구합니다. 이를 유니코드 이스케이프(\u16진수)로 표현해줍니다. 이를 코드로 옮기면 아래와 같습니다. let smile = "😀"; let codePoint = smile.codePointAt(0); // 유니코드 값을 얻습니다. let rebase = codePoint - 0x10000; // 0x10000을 빼줍니다. -> 62976 let highSurrogate = Math.floor(rebase / 1024); // 1024로 나눈 후 소수점 이하 버림 let lowSurrogate = rebase % 1024; // 1024로 나눈 나머지를 구함 highSurrogate += 0xD800; // 0xD800을 더함 lowSurrogate += 0xDC00; // 0xDC00을 더함 // 결과를 16진수로 출력 console.log(highSurrogate.toString(16)); // d83d 출력 console.log(lowSurrogate.toString(16)); // de00 출력 // 결과를 유니코드 이스케이프로 출력 console.log("\ud83d\ude00"); // 😀이 출력됩니다. 조금 복잡한 내용을 다루었는데, UTF-16와 유니코드의 관계는 아래 문서에서 별도로 다루고 있습니다. 문자 인코딩, 문자셋, 유니코드 References https://thekevinscott.com/emojis-in-javascript/ https://unicode.org/emoji/charts/full-emoji-list.html 문자와 인코딩 개념 정리 https://devhoma.tistory.com/95 유니코드의 Surrogate Pair, Supplementary Character가 뭘까요? https://www.sysnet.pe.kr/2/0/1710 Unicode Code Point와 Surrogates Pair https://rookiecj.tistory.com/299 위키피디아 - UTF-8 https://ko.wikipedia.org/wiki/UTF-8 나무위키 - 유니코드 https://namu.wiki/w/유니코드