몇주전 euc-kr 문자셋으로 DB를 만들었을 때, 확장완성형 글자들이 입력되지 못했던 부분에 대한 버그가 보고 되고 제가 그에 대한 답장을 썼던 기억이 나는데, 그 글을 읽으셨던 분은 그 글 내용을 무시하시길 바랍니다. (잘못된 내용입니다)
오늘 db upgrade 하는데, 저 또한 많은 문제점들을 만나서 어쩔 수 없이, 차근히 다시 소스를 볼 수 밖에 없었습니다.
왜냐하면, mysql놈도 그렇고, oracle 놈도 그렇고(nvarchar는 제외), 특별히 확장완성형에 대한 고려를 하지 않고, 무조건 그저 '2byte 문자다'라고 처리하는데, 유독 postgres놈 만이, 'euc-kr 1글자다'라고 처리해서, 결국 다른 DBMS의 데이터를 못가져오는 사태가 너무도 빈번히 발생하더군요.
(참고로, oracle에서도 nvarchar 자료형을 쓰게 되면, '안녕하세요'를 다섯글자로 인식하지만, 이놈 또한 확장완성형 문자들은 입력을 받을 수 없게됩니다. 아마 이런 문제 때문에, 대부분의 oracle 개발자들도 nvarchar 대신 varchar 자료형을 사용하는가봅니다.)
아무튼, 소스를 보니,
src/backend/utils/mb/wchar.c 파일 안에 있는
pg_verifymbstr() 함수가 문제의 발단이었습니다.
그 소스 안에 주석으로
* we assume that every muti-byte letter consists of bytes
* being the 8th bit set
* 우리(PostgreSQL 개발자)는 여덟번째 비트부터 On 되어있는 문자들을 모든 멀티바이트 문자들로 가정한다.
라고 되어있더군요.
확장 완성형의 글자들이 바로 여기서 걸립니다.
이 기능을 사용하지 않으려면, pg_verifymbstr() 함수 안에 있는
if (i > len || *(mbstr + i) == '\0' ||
/*
* we assume that every muti-byte letter consists of bytes
* being the 8th bit set
*/
((*(mbstr + i) & 0x80) == 0))
{
이 부분은
if (i > len || *(mbstr + i) == '\0')
{
이런 식으로 닫으면 되겠지요.
(이렇게 되면 한글이 반틈 짤려진 잘못 글자 정도는 막을 수 있지만,
사용자의 고의적인 조합형 문자의 입력도 그대로 받아 드릴 듯싶습니다.)
즉, 이것은 원론적으로 문제를 해결하는 방법이 아닌 듯 싶습니다.
이 pg_verifymbstr() 함수의 문제점을 풀 몇가지 제안책.
1. 사용자가 utf8 문자셋을 사용한다. euc-kr 문자셋을 포기한다.
(먼 미래를 내다본다면, 그리고, 완전히 새롭게 시작한다면, 이 방법이 가장 바람직할 듯싶습니다. )
2. 위에서와 같이 pg_verifymbstr() 함수를 해킹해서 쓴다.
(가장 손 쉽게 해결 할 수 있는 방법입니다. 하지만 많은 문제점을 안고 있습니다)
3. pg_verifymbstr() 함수에 euc-kr 문자셋이 아닌, 확장완성형을 고려해서, 다시 만든다.
4. 확장완성형을 포기한다. (과감한 방법이지만, 이것을 도입한다면, 고의적이든, 고의적이지 않던간에, 사용자의 비표준어 글자들을 막을 수는 있습니다)
여기까지입니다. 만일 필요하다면, PostgreSQL 개발자들에게도 이 사실을 알려야 할 듯싶습니다.
|