티스토리 뷰
Java Spring 초기 설정에서 가장 먼저 만나는 문제가 한글 깨짐이다. 폼으로 넘긴 한글이 ??? 나 ë°ì´í° 같은 형태로 들어오는 상황이다.
web.xml 설정
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
각 설정의 의미
encoding=UTF-8— 요청 본문을 읽을 때 사용할 인코딩forceEncoding=true— 응답에도 같은 인코딩을 강제한다. 이걸false로 두면 요청만 처리되고 응답이 깨질 수 있다
url-pattern을 /*로 하는 것도 중요하다. /만 쓰면 일부 요청이 필터를 안 탄다.
필터 순서 주의
web.xml에서 필터는 선언된 순서대로 적용된다. 인코딩 필터는 가장 먼저 선언해야 한다. 다른 필터가 먼저 요청 본문을 읽어버리면 인코딩 설정이 소용없어진다.
그래도 깨진다면: 체크리스트
필터를 넣었는데도 깨지는 경우가 있다. 한글 깨짐은 원인이 한 곳이 아니라 여러 단계에 걸쳐 있기 때문이다.
1. GET 파라미터는 필터로 해결되지 않는다
CharacterEncodingFilter는 POST 본문에만 적용된다. URL 쿼리스트링은 WAS(톰캣)가 파싱하므로 서버 설정을 따로 해야 한다.
<!-- tomcat/conf/server.xml -->
<Connector port="8080" URIEncoding="UTF-8" ... />
톰캣 8 이상은 기본값이 UTF-8이라 대부분 문제없지만, 구버전은 ISO-8859-1이 기본이었다. 레거시 환경이라면 확인이 필요하다.
2. JSP 페이지 인코딩
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
contentType은 브라우저에 알려주는 값이고, pageEncoding은 JSP 파일 자체의 인코딩이다. 둘 다 필요하다.
3. HTML meta 태그
<meta charset="UTF-8">
4. DB 연결 문자열
jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF-8
DB에 잘 들어갔는데 조회하면 깨지는 경우, 혹은 반대의 경우 여기가 원인이다.
5. DB 스키마 콜레이션
ALTER DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
MySQL의 utf8은 사실 3바이트짜리라 이모지를 저장할 수 없다. utf8mb4를 써야 한다. 한글은 3바이트라 utf8로도 되지만, 사용자가 이모지를 입력하는 순간 에러가 난다.
6. 소스 파일 인코딩과 빌드 설정
<!-- Maven -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
소스에 한글 문자열이 있는데 컴파일 인코딩이 다르면 클래스 파일에 깨진 채로 들어간다.
7. JVM 기본 인코딩
java -Dfile.encoding=UTF-8 -jar app.jar
파일 입출력이나 로그에서 깨질 때 확인한다. Java 18부터는 기본이 UTF-8로 바뀌었다.
Spring Boot에서는
Spring Boot는 이 설정이 기본으로 들어가 있어서 대부분 신경 쓸 일이 없다. 필요하면 application.properties에서 조정한다.
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
web.xml 방식은 레거시 Spring MVC 프로젝트에서 쓰인다. 신규 프로젝트라면 Spring Boot를 쓰게 되므로 위 세 줄이면 끝난다.
디버깅 요령
어느 단계에서 깨지는지 찾는 게 핵심이다. 위에서부터 하나씩 좁혀 들어간다.
- 컨트롤러에 들어온 파라미터를 로그로 찍어본다. 여기서 이미 깨졌으면 필터·톰캣 문제
- 컨트롤러에서는 멀쩡한데 DB 저장 후 깨지면 커넥션 또는 스키마 문제
- DB에는 잘 있는데 화면에서 깨지면 JSP·meta 태그 문제
- 로그 자체가 깨지면 JVM/콘솔 인코딩 문제
한글 깨짐은 "어디서 깨졌는지"만 특정하면 해결은 금방이다. 반대로 그걸 안 하고 여기저기 설정을 추가하다 보면 시간만 간다.
정리
CharacterEncodingFilter는 POST 본문만 처리한다forceEncoding=true로 응답까지 강제- 인코딩 필터는 가장 먼저 선언
- GET 파라미터는 톰캣
URIEncoding설정 - MySQL은
utf8이 아니라utf8mb4 - Spring Boot는
server.servlet.encoding.*세 줄이면 끝 - 해결의 핵심은 어느 단계에서 깨지는지 특정하는 것
