Skip to content
isdnetworks
Go back

한 곳에서만 깨지던 글자

한글이 대부분의 화면에서는 잘 나오는데 한 화면에서만 물음표로 깨져 나왔다. 저장할 때 그 문자셋으로 표현이 안 되면 MySQL? 로 바꿔 넣는다. 같은 코드가 다른 화면에서는 멀쩡하니 코드 문제로 보이지 않았다. 무엇이 다른지부터 찾아야 했다.

Table of contents

Open Table of contents

값이 지나는 자리를 찍어 봤다

설정을 다 열어 보기 전에 값이 어디서 깨지는지 먼저 봤다.

입력받은 직후    정상
DB 넣기 직전     정상
DB 에서 읽음     깨짐

앞의 둘은 정상이고 읽어 온 값만 깨져 있었다. 그러면 저장과 읽기 사이에서 깨진 것이다.

확인할 범위가 세 자리에서 한 자리로 줄었다. 설정을 전부 뒤지는 것보다 이 방법이 훨씬 빨랐다.

세 자리에 설정이 있었다

글자 설정은 세 자리에 각각 있었다.

파일·화면이 내보내는 Content-Type
DB 테이블·컬럼의 CHARACTER SET
SET NAMES 로 잡는 연결

셋이 다 UTF-8 로 맞아야 값이 온전히 지나간다. 하나만 어긋나도 지나는 길에서 깨진다.

SHOW CREATE TABLE 그_테이블;

문제가 된 테이블을 열어 보니 다른 테이블과 설정이 달랐다.

나중에 추가된 테이블이었고 만들 때 문자셋을 안 적은 것이었다. CREATE TABLE 에 안 적으면 그 서버의 기본값이 붙는데 그 기본값이 나머지와 달랐다. 연결 쪽 설정도 확인해 뒀다.

$db['default']['char_set'] = '...';

여기가 안 맞으면 테이블이 맞아도 깨진다. 세 자리를 한 번에 다 보는 것보다 깨지기 시작한 지점부터 훑는 편이 빨랐다.

설정을 고쳐도 남은 것이 있었다

테이블 설정을 바꿨다.

ALTER TABLE new_table CONVERT TO CHARACTER SET ...;

새로 들어오는 값은 정상이 됐는데 완전히는 아니었다.

설정 변경은 앞으로 들어올 값에만 작용한다. 이미 깨진 채로 저장된 값은 그대로 남아 있었다. 원본이 없어 되살릴 수도 없었다. 건수가 적어서 다시 입력받아 채웠는데 많았으면 이 방법도 쓸 수 없었을 것이다.

판단 기준 — 기본값과 명시 사이

같은 일이 새 테이블마다 반복될 것 같았다.

ALTER DATABASE 이름 CHARACTER SET ...;

기본값을 바꾸면 적지 않아도 맞는 설정이 붙는다.

다만 만들 때 설정을 적는 습관은 그대로 뒀다. 기본값에 기대면 다른 서버로 옮겼을 때 그 서버의 기본값을 따라간다. 명시해 두면 어디로 옮겨도 같은 설정으로 만들어진다. 옮기는 순간에 조용히 달라지는 것을 막는 값이 그 한 줄이었다.

정리


Share this post on:

Previous Post
알림을 줄였더니 다음 건이 묻혔다
Next Post
0건이 통과인지 미측정인지 몰랐다