테이블을 만들면서 varchar(255)를 보고서 이 부분에 대해 조금 더 알아봐야겠다는 생각이 들었다.
- 컴퓨터의 기본 저장 단위는 1 byte (8 bit) 이고, 1 bit가 0 또는 1을 나타낼 수 있으므로 1byte는 (2^8 = )256 개를 표현할 수 있다. 이러한 표현 방법을 특정 문자에 연결해 부호화(encoding) 하는 방법으로 ascii(127) - 영어 알파벳과 숫자만, ansi(256, 1byte), unicode(2byte=2^16)이 있다. 유니코드는 U+0000~U+10FFFF 사이의 코드 포인트 (code point)로 구성되어 있다.
- varchar는 DB와 charactor set 설정에 따라 기본 값이 달라진다.
MySQL 4이하 에서 varchar(N)의 N은 byte(utf-8)을 나타내고 5 이상부터는 unicode character를 나타내기 때문에 단순 글자수(Length) 라고 이해해도 된다. 다시 말해서 MySQL의 varchar(255)라고 하면 영어 255글자, 한글 255글자로 동일하다. postGre 또한 괄호 안의 숫자가 '글자수' 기준이다.
- 유니코드(코드 포인트)를 번역 하는 방법으로 UTF-8 과 UTF-16이 있다. 코드포인트를 표현하는데 최소한 필요한 byte 갯수를 code unit 코드 유닛 이라고 하고, UTF-8의 코드 유닛은 1byte이고, UTF-16의 코드 유닛은 2 byte이다.
- 1 grapheme 은 사람이 인식하는 한 단위의 글자를 말한다. 그래핌은 때에 따라서 여러개의 유니코드(코드 포인트)로 구성할 수 있다. 관련 내용을 아래 참조한 글과 같이 🤦♀️ 를 예시로 사용해 JS 에서 확인해볼 수 있다.
🤦♀️는 grapheme 단위로 1 개이고, 코드포인트(유니코드로 나타냈을 때 유니코드의 갯수)는 4인 non-RGI, 즉 multiple unicode point 이모지이다. (not Recommended For General Interchange). JS로 length를 확인해보면 (JS 또한 utf-16을 사용하므로, 코드유닛: 2byte) 5를 리턴한다. 즉 10byte 짜리의 글자라는 뜻이다. 이 글자를 DB에서 어떻게 처리하는 지 확인해보면 MySQL은 utf-8을 기본으로 하기 때문에 31, PostGre는 unicode를 한 단위로 하기 때문에 4라고 처리한다.
따라서 사용하는 DB와 char-set에 따라 다르겠지만, PostGreSQL은 varchar 뒤에 붙는 숫자가 unicode 기반 글자수이고, 이모지는 경우에 따라서 multiple code point를 가질 수 있으므로 이에 유의해서 글자수를 계산에서 DB에서 잘리지 않도록 처리해야 한다.
const Grapheme = require('grapheme-splitter');
const splitter = new Grapheme();
const complexString = "🤦♀️🤦🎅";
const graphemes = splitter.splitGraphemes(complexString);
const graphemeCounts = splitter.countGraphemes(complexString);
console.log("graphemes: ", graphemes); // graphemes: [ '🤦♀️', '🤦', '🎅' ]
console.log("graphemeCounts: ", graphemeCounts); // graphemeCounts: 3
const result = "🤦♀️";
console.log("result: ", result); // result: 🤦♀️
console.log("result.length: ", result.length); // result.length: 5 (utf16)
// MySQL utf-8
// SELECT LENGTH("🤦♀️";) // utf8 이기 때문에 31이 나온다.
// PostGreSQL
// SELECT
// LENGTH ('🤦♀️'); // 4
MySQL 의 SELECT LENGTH("🤦♀️"); 결과 >>
https://whatisthenext.tistory.com/103
아스키(ASCII)코드와 유니코드(Unicode)의 이해
안철수 의원이 의대생 시절에 다른 분야의 지식을 습득하고 싶으면 '칼럼'을 쓰라는 내용을 읽은 적이 있다. 프로그래밍 언어를 공부하다보면 항상 '아스키코드, 유니코드'와 마주치는 순간이
whatisthenext.tistory.com
https://juneyr.dev/counting-character
글자수 세기의 딜레마, 이 글자의 길이는 DB 상에서 얼마일까?
서론 글자수를 센다는 것은 무엇일까? 이 글을 본 개발자라면 아마도 각자 언어의 length() 함수를 떠올렸을 수도 있겠다. length() 는 개발자가 글자를 세지않아도 빠르게 길이를 알려준다. 그런데
juneyr.dev
How to count the correct length of a string with emojis in javascript?
I've a little problem. I'm using NodeJS as backend. Now, an user has a field "biography", where the user can write something about himself. Suppose that this field has 220 maxlength, and suppose ...
stackoverflow.com
https://stackoverflow.com/questions/68063800/length-of-string-with-emojis-in-postgres
Length of string with emojis in Postgres
I'm trying to ensure that a column in Postgres only holds a single emoji. However, I'm struggling with the length constraint since e.g. length('😁') -- 1 length('🇧🇷') -- 2 length('👩❤️💋👩') -...
stackoverflow.com
'백엔드 개발 > 백엔드 일기' 카테고리의 다른 글
#013. 백엔드 성장일기: [넥스트 스탭] ENUM과 Null Safety (0) | 2022.05.14 |
---|---|
#012. 백엔드 성장일기: [넥스트 스탭] 코틀린의 특징을 살려 리팩터링 하기 (0) | 2022.05.12 |
#010. 백엔드 성장일기: 테이블 스키마 작성하기 (2) | 2022.05.03 |
#009. 백엔드 주간 소식: 모각글 반상회, 깜짝 생일파티, 티코지 (0) | 2022.05.02 |
#008. 백엔드 성장일기: SQL 사용법( INNER OUTER JOIN 등) (0) | 2022.05.02 |