Skip to content
isdnetworks
Go back

보낼 때와 받을 때가 달랐다

한글로 검색하면 결과가 안 나왔다. 영문으로는 나온다.

Table of contents

Open Table of contents

어디서 깨지는지 찾았다

log4j 로 값이 지나가는 자리마다 찍어 봤다. 컨트롤러에 들어올 때 이미 깨져 있었다. MySQL 문제가 아니라 그 앞이라는 뜻이다.

한글이 지나가는 자리를 세어 보니 브라우저에서 서버로 오는 구간, 애플리케이션 안, DB까지 셋이었다. 각 자리의 설정을 하나씩 봤다.

JSP 는 pageEncoding="UTF-8" 이었다. Tomcat server.xml<Connector>URIEncoding 이 없었다. 안 적으면 기본값 ISO-8859-1 로 읽는다. 브라우저는 UTF-8 로 보내는데 서버는 다른 것으로 읽고 있었다.

방식마다 다른 자리에서 정해진다

고치고 나서 폼으로 보낼 때는 여전히 깨졌다. 주소줄로 보내는 것과 폼으로 보내는 것이 다른 설정을 탄다는 것을 그때 알았다.

GET 의 쿼리스트링은 URIEncoding 을 따르고, POST 는 요청 본문이라 setCharacterEncoding() 으로 정해 줘야 한다. useBodyEncodingForURI="true" 로 둘을 맞추는 방법도 있다. 매 요청마다 하기 어려워 Filter 로 처리했다.

req.setCharacterEncoding("UTF-8");
res.setCharacterEncoding("UTF-8");
chain.doFilter(req, res);

web.xml 의 필터 순서가 중요했다. 앞의 필터가 getParameter() 를 한 번이라도 부르면 그 뒤에 setCharacterEncoding() 을 해도 안 먹는다. 가장 앞에 뒀다.

DB 연결 문자셋도 달랐다

DB 쪽 변수를 봤더니 테이블은 UTF-8인데 연결이 다른 문자셋이었다.

character_set_client     latin1
character_set_connection latin1
character_set_database   utf8
character_set_results    latin1

테이블 문자셋과 연결 문자셋이 따로라는 것을 여기서 알았다. 연결 문자열에 문자셋을 넣어 맞췄다.

이미 깨진 것과 확인 방법

설정을 고치기 전에 들어간 값이 남아 있었다. 깨진 채로 저장된 것은 되살릴 수 있는 것과 없는 것이 갈렸다.

바이트가 남아 있으면 다시 해석해서 되살릴 수 있지만, 물음표로 바뀐 것은 원래 바이트가 사라져서 무슨 글자였는지 알 방법이 없다. 되살릴 수 있는 것만 고치고 나머지는 그대로 두되 무엇을 못 고쳤는지 적어 뒀다.

설정을 다 고친 뒤에는 한 글자를 끝까지 따라가 봤다. 브라우저에서 입력하고 서버 로그에서 값을 보고 DB에 들어간 값을 바이트로 확인하고 화면에 다시 나오는지 봤다.

SELECT HEX(title) FROM board WHERE no = 1;
-- EAB080

화면에서 화면까지만 보면 안 된다. 보내는 쪽과 받는 쪽이 같은 방식으로 깨지면 화면에는 정상으로 보이기 때문이다. 중간의 바이트를 봐야 실제로 맞는지 안다.

정리


Share this post on:

Previous Post
한꺼번에 바꿨더니 문의가 들어왔다
Next Post
처음 세운 리눅스 웹 서버