본문 바로가기
백엔드 개발/백엔드 일기

#011. 백엔드 성장일기: PostGreSQL에서 🤦‍♀️의 글자수 확인하기

by iamjoy 2022. 5. 7.

테이블을 만들면서 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

https://stackoverflow.com/questions/54369513/how-to-count-the-correct-length-of-a-string-with-emojis-in-javascript/54369605

 

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