본문으로 바로가기
2 byte 코드를 사용하는 한글을 데이터베이스에 저장할 때 DB의 잘못되어 있는 캐릭터셋 설정은 많은 개발자와 DBA에게 혼란을 야기한다. 아주 오래전 신입사원시절에 Ingres라는 DB의 기술지원을 할 때도 가끔 한글코드가 잘못 지정되어 있어 DB를 업그레이드하거나 다른 서버로 마이그레이션할 때 불편함을 겪곤 했다.

그리고 15년이 지난 요즘...취미삼아 붙잡고 있는 Apache, PHP, MySql 의 환경에서도 여전히 DB의 한글코드 문제는 이따금씩 발생하곤 한다.

예를 들자면 웹페이지의 한글은 정상적으로 깨지지 않고 표시되는데 웹페이지를 통해 DB에 한글을 저장하고 다시 웹페이지에서 불러오면 DB에 저장한 한글데이터가 깨져보이는 현상이 대표적인 "한글깨짐" 증상이다.

이때 확인해야할 것은

1. 웹브라우저의 캐릭터셋.
2. 웹서버의 캐릭터셋.
3. 데이터베이스 서버의 캐릭터셋.
4. 생성되어 있는 데이터베이스의 캐릭터셋.
5. DB에 접속하는 세션의 캐릭터셋.

크게 4가지라 할 수 있다.

이 네가지 캐릭터셋 설정 중 어느하나가 다른 세개와 다르게 설정되어 있다면 여러가지 증상이 발생할 수 있다. DB에는 정상적으로 저장되는데 웹페이지에서 조회하여 보면 깨져있거나, 웹브라우저 화면에선 정상적으로 DB에 저장되어 있는 것 처럼 보이는데 DB의 쿼리툴에서 조회해보면 깨져서 저장되어 있을 수도 있다. 초심자로서는 잘 이해되지 않는 경우일 수도 있다.

즉, 클라이언트인 웹브라우저의 캐릭터셋부터 DB에 접속하는 세션의 캐릭터셋, 그리고 데이터베이스서버와 데이터베이스 생성시 지정되는 캐릭터셋, 마지막으로 테이블 생성 시 지정된 캐릭터셋이 일관되게 설정되어 있어야만 어떠한 환경에서 저장, 조회하더라도 문제가 발생되지 않는다.

 

먼저 웹브라우저의 캐릭터셋을 보자.

웹브라우저의 캐릭터셋은 서버에 저장되어 있다가 웹브라우저가 호출하는 웹페이지의 소스에서 설정할 수 있다.


meta 태그로 설정되는 charset = "utf-8" 부분이 바로 웹브라우저가 해당 웹페이지를 호출했을 때 설정할 브라우저의 캐릭터셋이다.

다음은 웹서버의 캐릭터셋이다.


아마치의 경우 httpd.conf 파일에서 'AddDefaultCharset' 파라미터에서 캐릭터셋을 설정할 수 있다. 기본적으로 utf-8을 지원하는데 이부분은 특별히 건드리지 않아도 utf-8이나 euckr을 처리해 주는 것 같다. 아직까지는 웹서버의 캐릭터셋으로 인해 DB에 저장되는 데이터의 캐릭터셋 오류는 보지 못했다.
(난 현재 웹이나 DB엔지니는 아니므로 경험부족일지도 모른다.. -.-)

세번째는 데이터베이스 서버의 캐릭터셋 설정이다.

mysql의 경우 이부분이 참 복잡했다. 한글이 깨지는 경우 대부분 서버의 캐릭터셋 환경과 생성된 DB의 캐릭터셋이 틀린 경우인것 같은데 또 꼭 그렇지만도 않은 듯 하다.

먼저 서버의 캐릭터셋 환경을 보면...


왜인지는 모르겠지만 character set client와 character set connection의 Global value가 latin1 으로 되어 있다. 이 의미는 클라이언트 프로그램 즉 브라우저를 통해 DB에 저장할 데이터를 전달받은 아파치 웹서버가 DB에 세션을 맺을 때 특별한 캐릭터셋을 지정하지 않으면 latin1 으로 캐릭터셋을 지정한다는 의미다.
한글은 2바이트 코드이고 latin1은 1바이트 코드다. 따라서 2바이트인 한글을 쪼개서 저장하면 당연히 깨져서 저장이 될 수 밖에 없다. 만약 이런 환경이라면 아무리 데이터베이스를 euckr 이나 utf8로 생성하더라도 클라이언트를 통해 커넥션을 맺고 한글을 저장하면 깨져서 저장될 수 밖에 없다.

네번째, 데이터베이스의 캐릭터셋 설정


각 데이터베이스마다 사용할 캐릭터셋을 다르게 지정할 수 있다.

마지막으로 문제해결의 키를 가진 DB 접속 세션의 캐릭터셋...

DB에 접속하는 세션의 캐릭터셋을 잘 이용하면 한글깨짐의 문제를 해결할 수 있다. 하지만 그 전에 앞에서 설명한 mysql 서버의 캐릭터셋 환경을 utf8로 통일시켜주는 것이 가장 좋은 방법이라는 점을 명심해야한다. mysql의 소스를 가져다 컴파일하여 설치할 때 컴파일옵션에 캐릭터셋을 utf8로 설정하는 것이 가장 좋은 방법이다.

하지만 오래전부터 운영하던 mysql 서버라면 쉽게 서버의 캐릭터셋을 변경할 수는 없을 수도 있다. 이런 경우 mysql 서버의 캐릭터셋 환경이 어떻든 간에 DB를 용도에 따라 euckr 혹은 utf8로 생성하고 각각의 db를 사용하는 웹페이지 소스에서 meta 태그를 이용해 euckr 혹은 utf8로 페이지의 캐릭터셋을 지정할 수 밖에 없다.

그리고 각 db에 접속하는 mysql_connect() 함수가 포함된 소스페이지에서 db에 접속한 세션의 캐릭터셋을 각각 euckr 혹은 utf8로 설정하여 사용할 수 있다.


위의 mysql_query('set names utf8') 함수를 실행하면 접속한 DB세션의 캐릭터셋이 utf8로 설정되고 MySql 서버의  character set client와 character set connection 환경변수보다 우선하게 되어 한글이 깨지지 않고 저장/조회된다. 만약 euckr로 설정하고자 한다면 다음과 같이 utf8 대신 euckr 을 지정하면 된다.

mysql_query('set names euckr');

물론 웹브라우저에서 한글이 깨지지 않도록 php 파일 자체의 캐릭터셋을 utf8 혹은 ansi 코드 중 하나로 저장하는 것도 중요하다. 만약 php 파일 자체의 코드를 맞추지 못하면 DB에서 조회한 데이터뿐만 아니라 HTML 내의 한글도 모두 깨지게 되므로 주의가 필요하다.

2011년 9월의 조금 흐린 어느날.....




신고

댓글을 달아 주세요