▣ PART · MVC

한글 깨짐 필터

「???? 글자」 의 정체

학습 목표

  • 한글이 「????」 로 깨지는 원인을 안다
  • CharacterEncodingFilter 의 역할을 안다
  • UTF-8 일관성이 필요한 4 곳을 안다

⚠️ 학생이 가장 먼저 만나는 좌절

한글로 글을 썼는데...

제목에 「안녕하세요」 입력 → 등록 → 목록에 「?????」 표시.

코드는 분명 맞는데 화면이 이상해 보입니다. 첫 며칠을 헤매는 단골 함정.

왜 ???? 가 되는가

브라우저: "안녕" (UTF-8 인코딩, 6 byte) ↓ 요청 바디 전송 ↓ 서버 (Tomcat): 디코딩 시 인코딩 가정 ├─ UTF-8 로 가정 → 정상 "안녕" └─ ISO-8859-1 (라틴) 로 가정 → 깨진 글자 "????" 기본값이 UTF-8 이 아니면 → 깨짐

👉 인코딩 일치가 핵심. 한 곳이라도 다르면 깨짐.

🛠️ CharacterEncodingFilter

Spring 의 인코딩 필터

모든 요청·응답을 강제로 UTF-8 로 처리하는 부품.

DispatcherServlet 보다 먼저 실행되어 request.setCharacterEncoding("UTF-8") 을 자동으로 호출해 줍니다. web.xml 에 한 번만 등록.

CharacterEncodingFilter — web.xml 등록


<!-- 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>

UTF-8 일관성이 필요한 4 곳

설정
① 요청·응답web.xml CharacterEncodingFilter (오늘 차시)
② JSP 페이지<%@ page contentType="text/html; charset=UTF-8" %>
③ JDBC 연결jdbc:mysql://...?characterEncoding=UTF-8
④ DB 테이블CREATE TABLE ... CHARACTER SET utf8mb4

👉 4 곳 모두 UTF-8 이 일치해야 한글이 어디서도 안 깨짐.

JSP 의 page 지시자


<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page pageEncoding="UTF-8" %>

<html>
<head>
    <meta charset="UTF-8" />
    <title>...</title>
</head>
...

👉 JSP 의 위 두 줄과 HTML 의 meta charset — 모두 UTF-8 통일.

JDBC URL — characterEncoding


<property name="jdbcUrl"
    value="jdbc:mysql://localhost:3306/spring_db?characterEncoding=UTF-8&serverTimezone=UTC" />

👉 ?characterEncoding=UTF-8 누락 시 — DB 에 한글 저장은 되지만 가져올 때 깨질 수 있음.

XML 에서 &&amp; 로 표기해야 함 (XML 문법).

DB 테이블 CHARSET


CREATE TABLE board (
    id     INT PRIMARY KEY AUTO_INCREMENT,
    title  VARCHAR(200) NOT NULL,
    content TEXT
)
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

👉 utf8mb4 권장 (이모지 포함). 옛 utf8 은 3 byte 까지만 지원.

실험 — 함정 직접 만들어보기

실험증상
CharacterEncodingFilter 제거요청 한글이 ???? 로 저장
JSP page 의 charset 빠뜨림JSP 자체가 깨져 보임
JDBC URL 의 characterEncoding 누락DB ↔ 자바 사이 깨짐
DB 테이블 CHARSET 다름저장된 데이터가 ???? 로 보임

인코딩 디버깅 알고리즘

"한글이 깨져요" ① 어디서 깨지나? - 입력 직후 (서버 로그) → 요청 인코딩 (web.xml) - DB 에 저장 후 SELECT → DB CHARSET - 화면 출력 → JSP charset - 콘솔 로그 → IDE 콘솔 인코딩 ② 깨진 자리부터 거꾸로 - 화면 ← JSP ← Controller ← DB ← Mapper ← Service ← Controller ← 요청 ③ 각 단계의 인코딩 확인 - 한 곳이라도 UTF-8 아니면 깨짐

🔄 Before / After

전 차시 끝

한글이 깨질 때마다 어디를 봐야 할지 막막.

이번 차시 끝

UTF-8 일관성 4 곳을 외운다. 깨짐 시 어디부터 점검할지 안다.

이번 차시의 데이터 흐름

브라우저 (UTF-8)
CharacterEncodingFilter
Controller (UTF-8)
DB (utf8mb4)
모든 단계 UTF-8 통일 — 깨짐 0

정리

오늘 들고 가는 것

  • 한글 ???? = 인코딩 불일치
  • CharacterEncodingFilter = 요청·응답 UTF-8 강제
  • UTF-8 4 곳: web.xml · JSP · JDBC URL · DB 테이블
  • 깨짐 시 거꾸로 추적