모눈종이에 사각사각

한글이 깨져요! 인코딩 문제 해결 과정(UTF-8 vs MS949) 본문

활동기록

한글이 깨져요! 인코딩 문제 해결 과정(UTF-8 vs MS949)

모눈종이씨 2025. 2. 16. 11:25

최근 인프런에서 [김영한의 실전 자바 - 고급 2편]을 수강하고 있습니다.

챕터 1에서는 어떻게보면 가장 기본이고, 꼭 알아야 하지만 시간을 들여 공부할 생각을 하지 못했던 “문자 인코딩”에 대한 내용을 수강했습니다. 이 인코딩 지식을 가지고 회사에서 문제를 해결한 경험을 소개해보겠습니다.

1. 문제 상황

최근 JSP를 통해 외부 시스템과 데이터를 주고받는 작업을 하던 중, Tomcat의 인코딩 설정을 UTF-8로 변경하면 한글이 깨져서 전송되는 문제가 발생했습니다.

기존에는 Tomcat의 인코딩 설정을 MS949로 설정하면 정상 동작했지만, 운영 환경을 UTF-8로 유지하면서도 MS949 기반 시스템과 원활하게 연동해야 했습니다. 따라서, UTF-8 환경에서 한글이 깨지지 않도록 인코딩 변환을 적용하는 방법을 찾아야 했습니다.

문제 코드 분석

1) 서비스단에서 JSP 호출

httpConn.setRequestProperty("Content-Type", "text/html; charset=utf-8");
OutputStream stream = httpConn.getOutputStream();
stream.write(data.getBytes()); 
  • 서비스단에서 jsp로 전송할 때 UTF-8을 사용.

2) JSP에서 요청을 받을 때의 코드

InputStream in = request.getInputStream();
String text = IOUtils.toString(in, "EUC-KR");
byte[] sendArrayResult = messageSendClient.sendMessage(text);
  • UTF-8로 보낸 데이터를 JSP에서 EUC-KR로 해석.

3) 타 시스템과 연동하는 메서드 (sendMessage)

requestMessage.setData(sendData.getBytes("MS949"));
  • sendMessage 메서드는 MS949 인코딩된 데이터를 요구.
  • 연동하려는 시스템에서는 MS949를 요구하기때문에 해당 인코딩은 변경할 수 없음.
  • JSP에서 올바르게 변환해서 전달해야 함.

2. 해결 과정

1) JSP에서 요청 데이터를 올바르게 읽기

// AS-IS
String text = IOUtils.toString(in, "EUC-KR");
// ❌ UTF-8로 전송된 데이터를 EUC-KR로 해석하면, 한글이 깨지는 문제가 발생

// TO-BE
String text = IOUtils.toString(in, "UTF-8");
// ⭕️ 서비스단에서 UTF-8로 보냈기 때문에, 동일한 UTF-8로 읽어야 한다.
  • 서비스단에서 UTF-8로 보낸 데이터를 UTF-8로 읽도록 변경.
    • UTF-8은 한글이 3byte, EUC-KR은 한글이 2byte이기 때문에 호환이 되지 않는다.

2) JSP에서 sendMessage 호출 전, MS949로 변환

// UTF-8로 읽은 후 MS949로 변환
byte[] ms949Bytes = text.getBytes("MS949");
String ms949Text = new String(ms949Bytes, "MS949");

// 타 시스템 호출
byte[] sendArrayResult = messageSendClient.sendMessage(text);

  • UTF-8 → MS949 변환 후 sendMessage 호출.

3. 깨달은 점

이번 문제를 해결하면서, 서버 간 데이터 교환에서 인코딩 변환의 중요성을 깨달았습니다. 특히 UTF-8로 전송된 데이터를 잘못된 방식(EUC-KR)으로 읽으면 문자 깨짐이 발생한다는 것을 명확히 이해했습니다.

 

그럼 문자 인코딩 변환에 대해 살짝 알아보겠습니다.

문자 인코딩 이란?

문자 인코딩은 문자를 컴퓨터가 이해할 수 있는 숫자(byte)로 변경하는 것입니다. 문자를 byte로 변경하려면 문자 집합이 필요하고, 어떤 문자 집합을 참고해서 byte로 변경할지를 정해야 합니다.

 

문자 집합의 종류

  • ASCII : 초기 표준 문자집합. (한글 미지원)
  • ISO-8859-1 : 서유럽 문자를 표현하는 문자 집합이 필요해짐에 따라 만들어짐. (한글 미지원)
  • EUC-KR : 초창기 등장한 한글 문자 집합. 자주 사용하는 한글만 포함. (한글 2바이트)
  • MS949 : EUC-KR을 확장하여 만듦. 더 많은 한글 글자를 포함. (한글 2바이트)
  • UTF-8 : 가변 길이 인코딩을 사용하여 전 세계 모든 문자를 표현 가능. (한글 3바이트)
  • UTF-16 : 자주 사용하는 기본 다국어들은 2byte, 그외 4바이트. (한글 2바이트)

여기서 자주 인코딩 문제가 발생하는 것은 한글입니다.

왜냐하면 영문은 사실 UTF-16 제외하면 다 1바이트이지만, UTF-16은 잘 사용하지 않으므로 한글에서 많은 문제가 발생합니다.

한글이 깨지는 가장 큰 2가지 이유

  • 2byte : EUC-KR(자주 사용하는 한글만), MS949, UTF-16
  • 3byte : UTF-8
  • UTF-8과 MS949(EUC-KR)는 인코딩 방식이 다르므로 깨짐이 발생합니다.
    • UTF-8(한글 3바이트) ↔ MS949(한글 2바이트) 간 변환 시, 바이트 길이가 맞지 않아 문자 해석이 잘못될 수 있음.
    • 따라서, 전송과 수신 단계에서 적절한 인코딩 변환이 필요함.
  • EUC-KR(MS949) 또는 UTF-8로 인코딩한 한글을 ISO-8859-1로 디코딩할 때 발생합니다.
    • ASCII, ISO-8859-1은 한글 미지원.

위와같이 한글의 경우 문자 집합에 따라 2byte로 해석하기도 하고, 3byte로 해석하기도 합니다.

 

인코딩이 일치하지 않으면 바이트 해석이 잘못되어 글자가 깨지는 문제가 발생합니다. 따라서, 데이터가 어떤 인코딩으로 전송되고, 서버에서 어떤 인코딩으로 읽어야 하는지 명확히 정의하는 것이 중요합니다.

4. 마무리

이번 경험을 통해 인코딩 문제를 근본적으로 해결하는 방법을 배웠습니다.

한글이 깨지는 문제는 단순해 보이지만, 요청/응답 인코딩 흐름을 정확히 이해하지 않으면 쉽게 해결되지 않습니다.

물론 인코딩 문제가 발생할 때마다 구글링을 하면서 해결할 수도 있겠지만, 이렇게 한 번 깨지는 이유를 명확히 분석하고, 단계별로 변환 과정을 적용하는 방법을 터득했기 때문에 비슷한 문제가 발생해도 침착하게 해결할 수 있을 것 같습니다.

Comments