목록으로
유틸리티

UTF-8 사용법 완벽 정리, 한글 깨짐 막는 5단계 점검법

UTF-8 사용법만 제대로 익혀두어도 한글 깨짐 문제의 대부분은 사라집니다. 웹 페이지, 데이터베이스, 로그 파일, API 응답까지 문자 인코딩은 시스템 전 구간에 걸쳐 있고, 그중 한 군데만 어긋나도 화면에는 물음표나 알아볼 수 없는 글자가 남습니다.

중요한 점은 인코딩이 파일에 저장할 때, 네트워크로 전송할 때, 화면에 그릴 때 각각 따로 지정된다는 사실입니다. 이 세 지점을 모두 UTF-8로 맞추는 것이 이 글의 핵심입니다.

UTF-8이 사실상 표준이 된 이유

UTF-8은 유니코드 문자를 1바이트에서 4바이트까지 가변 길이로 저장하는 인코딩 방식입니다. 영문과 숫자는 1바이트, 한글은 3바이트, 일부 이모지 계열 문자는 4바이트를 씁니다. ASCII 영역과 완전히 호환되기 때문에 기존 영문 기반 시스템을 손대지 않고도 전 세계 문자를 담을 수 있다는 점이 결정적인 장점이었습니다.

인코딩한글 1자 크기ASCII 호환현재 권장도
EUC-KR (CP949)2바이트부분 호환레거시 연동 시에만
UTF-83바이트완전 호환기본값으로 권장
UTF-162바이트비호환일부 내부 처리용
참고: EUC-KR은 완성형 한글 2,350자만 표현합니다. "똠", "뷁" 같은 조합형 글자나 중국어, 이모지를 넣으면 저장 단계에서 값이 손실됩니다. 한 번 손실된 글자는 나중에 UTF-8로 바꿔도 복구되지 않습니다.

환경별 UTF-8 설정 방법

설정 위치는 언어와 플랫폼마다 다르지만, 원칙은 같습니다. 데이터가 지나가는 모든 경계에 UTF-8을 명시하는 것입니다.

  • HTML: <head> 최상단에 <meta charset="UTF-8">를 넣습니다. 브라우저는 문서 앞부분 1,024바이트 안에서 이 선언을 찾기 때문에 위치가 뒤로 밀리면 무시될 수 있습니다.
  • HTTP 헤더: Content-Type: text/html; charset=utf-8. 헤더 선언이 meta 태그보다 우선하므로 서버 설정이 잘못되면 HTML을 아무리 고쳐도 소용이 없습니다.
  • MySQL / MariaDB: 문자셋은 utf8mb4, 정렬은 utf8mb4_unicode_ci를 씁니다. 연결 단계에서도 SET NAMES utf8mb4가 필요합니다.
  • PHP: php.inidefault_charset = "UTF-8"mb_internal_encoding('UTF-8')을 함께 설정합니다.
  • 파이썬: open(path, encoding='utf-8')처럼 파일을 열 때 인코딩을 명시합니다. 생략하면 윈도우에서는 CP949가 기본값이 되어 같은 코드가 OS별로 다르게 동작합니다.
  • 리눅스 서버: LANG=ko_KR.UTF-8, LC_ALL=ko_KR.UTF-8을 지정합니다. 크론에서 실행되는 스크립트만 한글이 깨진다면 대부분 로케일이 원인입니다.
  • 에디터: VS Code 기준으로 우측 하단 인코딩 표시를 눌러 "Save with Encoding"에서 UTF-8을 선택합니다.
팁: 리눅스에서 파일의 실제 인코딩이 궁금하면 file -i 파일명을 실행해 보세요. charset=iso-8859-1이나 charset=unknown-8bit으로 나온다면 UTF-8이 아닙니다. 변환은 iconv -f euc-kr -t utf-8 원본 > 결과로 처리합니다.

가장 많이 걸리는 함정, BOM과 utf8mb4

UTF-8로 맞췄는데도 문제가 남는다면 대개 이 두 가지입니다.

BOM(Byte Order Mark)은 파일 맨 앞에 붙는 EF BB BF 3바이트 표식입니다. 화면에는 보이지 않지만 PHP에서는 헤더 전송 전 출력으로 취급되어 "headers already sent" 오류를 일으키고, CSV를 파싱할 때는 첫 번째 컬럼명 앞에 정체불명의 문자가 붙습니다. 웹 개발에서는 UTF-8 without BOM을 기본으로 쓰는 편이 안전합니다. 다만 엑셀에서 CSV를 열 때는 BOM이 있어야 한글이 정상 표시되므로, 엑셀 다운로드용 파일에는 의도적으로 BOM을 붙이기도 합니다.

MySQL의 utf8은 이름과 달리 문자당 최대 3바이트만 저장하는 불완전한 구현입니다. 4바이트가 필요한 이모지나 일부 한자를 넣으면 Incorrect string value 오류가 발생합니다. 진짜 UTF-8은 utf8mb4입니다.

주의: 테이블 문자셋만 utf8mb4로 바꾸고 컬럼 문자셋을 그대로 두면 기존 컬럼은 여전히 utf8입니다. ALTER TABLE 테이블명 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;로 컬럼까지 함께 변환해야 하며, 인덱스가 걸린 VARCHAR 컬럼은 최대 길이 제한에 걸릴 수 있으니 작업 전 반드시 백업하세요.

한글이 깨졌을 때 원인 좁히는 5단계

인코딩 문제는 추측으로 접근하면 시간만 소모됩니다. 데이터가 흐르는 순서대로 한 단계씩 확인하는 편이 훨씬 빠릅니다.

  1. 원본 파일 확인: 소스 코드나 데이터 파일 자체가 UTF-8인지 봅니다. 여기서 이미 깨져 있으면 뒤의 설정은 의미가 없습니다.
  2. 입력 경로 확인: 폼 전송, 파일 업로드, 외부 API 응답 중 어디로 들어온 값인지 구분하고 해당 지점의 인코딩 선언을 봅니다.
  3. 저장소 확인: DB에 들어간 값을 콘솔에서 직접 조회합니다. 콘솔에서 정상인데 웹에서만 깨진다면 출력 단계 문제입니다.
  4. 출력 헤더 확인: 브라우저 개발자 도구 네트워크 탭에서 응답 헤더의 charset 값을 봅니다.
  5. 렌더링 확인: meta 태그와 폰트를 점검합니다. 특정 글자만 네모로 보인다면 인코딩이 아니라 폰트 문제입니다.

재현 테스트를 할 때는 매번 다른 고유 문자열을 함께 넣어두면 추적이 쉬워집니다. UUID 생성기로 만든 값 뒤에 "한글테스트" 같은 문구를 붙여 흘려보내면, 로그에서 어느 구간부터 값이 변형되었는지 한눈에 드러납니다.

인코딩 문제는 한 곳을 고치는 일이 아니라, 데이터가 지나가는 모든 관문을 같은 값으로 맞추는 일입니다.

실무 적용 체크리스트

새 프로젝트를 시작하거나 기존 시스템을 점검할 때 아래 항목을 순서대로 확인하면 대부분의 문제를 예방할 수 있습니다.

  • 에디터 기본 저장 인코딩을 UTF-8 without BOM으로 고정했는가
  • 모든 HTML 문서 상단에 charset 선언이 있는가
  • 웹 서버와 애플리케이션의 기본 응답 charset이 utf-8인가
  • DB, 테이블, 컬럼, 커넥션 네 곳 모두 utf8mb4인가
  • 파일 입출력 코드에 encoding 인자를 명시했는가
  • 배치나 크론 실행 환경의 LANG 값이 UTF-8 로케일인가
  • 외부 시스템 연동 시 상대 인코딩을 문서로 확인했는가

특히 마지막 항목은 자주 놓칩니다. 관공서나 오래된 기업 시스템은 아직 EUC-KR로 데이터를 내려주는 경우가 있어, 받는 즉시 UTF-8로 변환한 뒤 내부 로직에 넘기는 구조를 만들어 두는 편이 안전합니다. 변환 지점을 한 곳으로 모아두면 나중에 인코딩이 바뀌어도 수정할 코드가 하나로 줄어듭니다.

자동차 수리가 필요하신가요?

대전 사고차 수리 전문 - 남대전자동차공업사

무료 견적받기