티스토리 뷰

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 파라미터는 필터로 해결되지 않는다

CharacterEncodingFilterPOST 본문에만 적용된다. 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/콘솔 인코딩 문제

한글 깨짐은 "어디서 깨졌는지"만 특정하면 해결은 금방이다. 반대로 그걸 안 하고 여기저기 설정을 추가하다 보면 시간만 간다.

정리

  • CharacterEncodingFilterPOST 본문만 처리한다
  • forceEncoding=true로 응답까지 강제
  • 인코딩 필터는 가장 먼저 선언
  • GET 파라미터는 톰캣 URIEncoding 설정
  • MySQL은 utf8이 아니라 utf8mb4
  • Spring Boot는 server.servlet.encoding.* 세 줄이면 끝
  • 해결의 핵심은 어느 단계에서 깨지는지 특정하는 것
댓글


최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday