MenuIcon

Owl-Networks Archive

LoginIcon

Win32 / SQLite : SQLite DB 경로에 한글이 들어가 있는 경우

| 분류: Perl | 최초 작성: 2012-03-26 00:30:14 |


이 글은 같은 제목으로, 네이버 카페 "Perl Community & Study" 카페에 먼저 등록(2012/01/09)되었던 글을 일부 수정보완한 것입니다.



다른 분들은 어떻게 하시는지 모르겠습니다만, 저는 Win32 환경에서 돌아가는 스크립트를 짤 때는 스크립트 파일의 인코딩을 ANSI (CP949) 로 설정하고 코드를 짭니다. (물론, 제 홈페이지에서 돌아가는 CGI 를 짤 때는 UTF-8 로 짭니다.) 코드 내에서 한글로 된 파일명/폴더명을 처리하는 경우, 코드가 UTF-8 로 되어 있으면..

(1) Win32::Unicode 모듈을 사용해서 파일/폴더를 다루거나
(2) 출력단계에서 인코딩을 CP949로 변경해줘야..


하기 때문에, 은근히 번거롭기 때문입니다. 그리고, 이런 귀차니즘은 결국 사단을 만들고 맙니다.

DB를 모를 때는 거의 대부분의 자료를 파일 시스템을 사용해서 관리했습니다. 그러나 SQL 문법을 알게 되니, 이제는 일일이 데이터 파일을 다루는 것이 은근히 귀찮아졌습니다. 그래서 데이터 파일이 필요한 코드를 짜는데 DBMS를 사용하기 시작했습니다. SQLite 라는 가벼운 단일 파일 형태의 DBMS가 있었기 때문에 가능한 일이죠.

확실히 DBMS 를 사용하면 덩치가 좀 커지긴 해도, 여러가지 복잡한 자료처리 코드를 만들 필요가 없어져서 코딩 자체는 정말 편해집니다. 다만, SQLite 의 내부 인코딩은 모두 UTF-8 을 사용하는 것이 원칙이기 때문에, 데이터베이스에 한글 등 텍스트 자료를 저장할 때에는 인코딩을 UTF-8 로 변환한 후에 넘겨줘야만 합니다. (내부 인코딩의 UTF-8이건, UTF-8 인코딩의 바이트스트림이건 상관 없습니다. 그냥 UTF-8이기만 하면 됩니다.) 윈도우에서는 한글 처리를 위해 보통 CP949 인코딩을 사용하기 때문에 보통은 얻어온 값의 인코딩은 CP949일 것이어서, 저장 전에 저장할 내용을 CP949 → UTF-8 로 일괄적으로 인코딩을 변환하여 사용하면 됩니다. 조금 더 안전하게 사용하려면 Encode::Guess 모듈을 사용하여 인코딩을 확인한 후 decode하고, 이미 내부 UTF-8 플래그가 붙어 있는 데이터를 다시 decode 함으로써 발생할 수 있는 Encode 모듈의 crash 를 막기 위해서는  Encode 모듈의 is_utf8 을 사용하여 인코딩 변환 전 검사를 거치게 됩니다.

그런데, 예상치 못한 곳에서 문제가 생겼습니다. 스크립트의 위치와 데이터베이스 파일의 위치가 서로 달랐기 때문에 데이터베이스를 열기 위해서 데이터베이스까지의 경로를 함께 넘겨주어야 했는데, 이 SQLite DB 파일이 존재하는 폴더까지의 경로에 한글이 끼어 있으면 데이터베이스 접근에 실패하는 문제가 발생했습니다.

우연히 지인의 집에서 제가 만든 프로그램을 테스트하는데, 이게 돌아가지를 않더군요. PAR::Packer 와 관련해서 발생하던 한글 사용자 이름 문제도 해결된 버전이었기 때문에 오류가 날 이유가 없는데 말입니다. 에러 메시지가 나오도록 하여 콘솔상에서 체크해 보니, 첫 실행에서 DBI 가 DB 파일을 만들지 못하고 오류를 내면서 죽는 것이었습니다. 게다가 해당 경로에 미리 만들어 둔 DB 파일을 넣어줘도 읽지를 못하더군요.


처음엔 한글 문제인 줄 모르고, 이게 왜 이러지? 하고 한참 고민했습니다. 그러다가, 파일까지의 경로 중간에 한글이 있다는 것을 발견한 후, 혹시 이것도 한글 인코딩 문제인가 싶어서 경로의 인코딩을 UTF-8 로 변경해서 DBI에 던져주니 데이터베이스 파일을 아주 잘 찾아가더군요.

결국, 데이터베이스까지의 경로값(파일명으로 쓰이는 데이터베이스 이름 값도 포함하여)의 인코딩이 CP949 였기 때문에 발생한 문제였습니다. 영문자 및 숫자 뿐이라면 CP949와 UTF-8의 코드값이 같기 때문에 문제가 되지 않지만, 한글이 포함되어 있다면 두 코드값이 달라지기 때문에 전혀 엉뚱한 경로를 찾아가게 되는 거죠.

따라서, 데이터베이스를 열고 닫기 위해 DBI 모듈에 경로를 포함한 데이터베이스 파일명을 보낼 때에는, 여기에 한글이 포함되어 있을 가능성을 항상 염두에 두고, 넘어가는 값의 인코딩이 UTF-8인지를 꼭 확인해야 합니다. 특히 스크립트 파일의 인코딩이 UTF-8이 아니라면 거의 100% 인코딩을 명시적으로 해 주어야 할 것입니다.

예를 들어,

use DBI;
my $dbname = "데이터.db";
my $dbh = DBI->connect( "dbi:SQLite:dbname=$dbname", "", "" );

이 코드를 UTF-8 인코딩의 스크립트(use utf8 프라그마가 붙어있는지 무관하게)에서 실행하면 정상적으로 "데이터.db" 파일이 만들어지지만, CP949 인코딩의 스크립트에서 실행하면 파일명이 깨진 상태로 db 파일이 만들어집니다. 만약 CP949 인코딩의 스크립트에서 이 코드를 제대로 실행하기 위해서는,

use DBI;
use Encode;
my $dbname = decode( "cp949", "데이터.db" );
my $dbh = DBI->connect( "dbi:SQLite:dbname=$dbname", "", "" );

위와 같이 데이터 파일명/경로를 UTF-8 로 바꾸어 주어야만 합니다. (내부 인코딩의 UTF-8이라도 상관없으므로 위와 같이 decode 만 해도 됩니다. 물론 Perl 의 유니코드 FAQ 에 보면, "내부 인코딩이 UTF-8이라는 것을 자신의 이익으로 이용하지 말라[Don't use the fact that Perl's internal format is UTF-8 to your advantage.]"고 합니다만...)


윈도우 환경에서 UTF-8 인코딩이 문제를 일으키는 경우가 많아서 이를 회피하려다가, 되레 UTF-8이 아니어서 문제를 일으키는 경우에 맞닥뜨린 셈입니다.




한 줄 요약 : SQLite 를 사용하는 (범용) 스크립트를 짤 때는 데이터베이스 경로에 한글이 들어가지 않도록 하거나, 들어가야 한다면(들어갈 가능성이 있다면) 경로를 UTF-8로 인코딩해서 DBI 에 던져주세요.

☞ 태그: Unicode, DBD::SQLite, CP949, Win32, 한글 경로, SQLite,

☞ 트랙백 접수 모듈이 설치되지 않았습니다.

☞ 덧글이 없고, 트랙백이 없습니다.

덧글을 남기시려면 여기를 클릭하십시오.
[483] < [429] [426] [424] [423] [422] ... [421] ... [420] [419] [418] [416] [415] > [19]

(C) 2000-2018, Owl-Networks. Powered by Perl. 이 페이지는 HTML 5 표준에 따라 작성되었습니다.