Java Encoding / Decoding (자바 인코딩 / 디코딩)

발생일: 2009.11.16

문제:
얼마 전 디비 서버 변경 작업이 있었는데
서버 변경 이후로 인터페이스 되는 데이터들 중 한글이 깨지는 것들이 발견됐다.

각 데이터들은 여러 방법으로 인터페이스 된다.
  - 파일로 전송 받아 디비에 업데이트
  - 특정 모듈을 통해 대상 서버에 접속해 그 내용을 파일로 떨군 후에 업데이트
  - 대상 디비로 직접 접근해서 가져온 후 업데이트

unix 서버에서 crontab 에 등록된 쉘 프로그램이
인터페이스 역할을 하는 java 클래스를 실행시켜 가져온 데이터를 디비로 업로드한다.

헌데,.. 하나를 수정하면 하나가 깨지고, 다른 하나를 수정하면 또 기존 것이 깨지고 이런다....

뭐가 문제인 걸까...

해결책:
전체적으로 인코딩/디코딩에 대한 이해가 필요했다.
여러 자료들을 찾아보고 테스트해 본 결과, (무려 3일 동안이나... =_=;;)
인코딩/디코딩의 전체적인 맥락을 알게 됐다.
또한 그 흐름을 알면 개발자가 따로 코딩할 부분이 거의 없다는 것도...
좀 정리를 해볼까.


간단한 결론.
input 으로 가져오려는 데이터의 캐릭터셋과 동일한 캐릭터셋으로 데이터를 가져와야 한다.
또한 출력해서 보여주려는 환경의 캐릭터셋과 동일하게 인코딩 해줘야 한다.

또한, Java 는 내부적으로 데이터를 Unicode 로 변환하여 처리하기 때문에,
처음 내용을 가져올 때 제대로 된 캐릭터셋으로 가져온다면 어떠한 캐릭터셋으로든 변환하여 출력이 가능하다.
'인코딩 변환'을 키워드로 검색으로 했을 때 쉽게 검색되는 new String(str.getBytes(), "UFT-8"); 과 같은 것은
이와 같이 정상적으로 데이터를 읽어온 이후에 사용되어야 한다.

자 그럼, 일단 한글이 깨진다면 '어떻게 하지?' 라고 생각하기 이전에 아래 목록에 대해 스스로에게 질문해보자.


1. 콘솔에서 문자가 깨질 때
  - 자바 소스 파일의 인코딩이 무엇인가?
  - 자바를 실행하는 환경의 인코딩은 무엇인가? (언어 설정)

  [도움말]
     자바 소스 내에 한글이 있고 이 내용을 콘솔에서 출력하려고 할 때에는,
     자바 소스 파일의 인코딩과 컴파일된 파일이 실행되는 환경의 인코딩이 동일해야 한다.
     기본적으로 자바는 OS 환경에 설정되어 있는 기본 인코딩으로 동작하며,
     실행 환경의 인코딩을 따로 설정해주기 위해서는 file.encoding 옵션을 사용하면 된다.

  [도움이 될 만한 포스트]      
     자바서비스넷: 자바 컴파일 환경의 인코딩과 실행 환경의 인코딩 테스트
     유닉스에서 언어 설정 방법
     자바 실행 환경 인코딩 설정 방법: -Dfile.encoding 의 역할
     자바에서 한글 처리 문제 - 아직도냐...

2. 읽어온 파일의 문자가 깨질 때
  - 읽어오려는 파일은 어떤 캐릭터셋으로 인코딩되어 있는가?
  - 자바를 실행하는 환경의 인코딩은 무엇인가?

  [도움말]
     일단 파일을 읽어오기 전에 읽어오려는 파일이 어떤 캐릭터셋으로 인코딩 되어 있는 지 알아야 한다.
     읽어오려는 파일의 인코딩과 동일한 캐릭터셋으로 파일을 읽어와야 하며,
     자바의 FileReader 와 같은 input 객체들은 특별한 설정이 없으면 실행 환경(file.encoding)의 캐릭터셋으로 읽어온다.
     실행 환경의 캐릭터셋과 읽어오려는 파일의 인코딩이 달라 특정 캐릭터셋으로 읽어오려면
     캐릭터셋 설정이 가능한 InputStreamReader 객체를 사용하도록 한다.
     (만약 설정한 캐릭터셋으로 파일을 읽어올 수 없을 경우 MalformedInputException 이 발생한다.)
     출력할 때도 마찬가지로 OutputStreamReader를 통해 원하는 캐릭터셋으로 출력할 수 있다.

  [도움이 될 만한 포스트]
     읽어올 파일의 인코딩 확인 방법(영문)
         또는, EditPlus, UltraEdit 같은 에디터를 통해 인코딩을 바꿔가며 확인해보는 것도 좋겠다.
     InputStreamReader API  /  OutputStreamWriter API
     sun.io.MalformedInputException 이 발생할 경우
     특정 캐릭터셋으로 읽어오는 방법 (InputStreamReader)
     UTF-8 환경에서도 인코딩이 깨졌다는 이야기
   

3. 디비에 문자가 깨질 때
  - DB 에 넣으려는 문자의 캐릭터셋은 무엇인가?
  - DB 의 인코딩은 어떤 캐릭터셋으로 설정되어 있는가?

  [도움말]
     다른 경우와 마찬가지다. Java에서 DB 에 보내는 캐릭터셋과 DB 에 설정되어 있는 캐릭터셋이 동일해야 한다.
     만약 Java 와 DB 의 캐릭터셋이 다르다면, 서버의 설정을 변경하거나 new String() 을 쓰는 방법으로 해결한다.
    
  [도움이 될 만한 포스트]
     DB 인코딩 설정으로 구글링
     PreparedStatement 설정 시 new String() 으로 인코딩을 변경하여 설정


4. 웹 페이지의 문자가 깨질 때
  - 요청된 (request로 들어오는) 내용은 어떤 캐릭터셋으로 인코딩 되어 있는가?
  - 응답으로 주는 페이지의 인코딩은 무엇인가?

  [도움말]
      역시 마찬가지!
      request 로 들어오는 요청의 캐릭터셋을 파악하고 그에 맞게 처리해줘야 한다.
      응답으로 뿌려줄 때도 마찬가지이다.
      이 내용은 검색하면 많이 나오므로 쉽게 찾을 수 있을 듯.
      잘 모를 경우 아래 키워드로 검색해보세요.
         request.setCharacterEncoding
         jsp 헤더, html 헤더에서 contentType 설정
         javascript encodeURI, encodeURL

  [도움이 될 만한 포스트]
      서블릿 엔진에서의 인코딩(자바서비스넷)



그 외 기타 도움이 될 만한 포스트
    Java 와 Charset (추천)
    유니코드(Unicode)에 대한 오해
    Character Set 과 Encodingn 이해하기
    Java Characterset 의 이해 (지식인)
    다국적 인코딩 문제의 위치 및 까발리기 (자바서비스넷) : 길지만 슥~ 읽어보면 좋음



이제, 한글 깨짐 문제에 봉착해도 문제 없이 해결하기를!!!

카테고리

분류 전체보기 (710)
About me. (6)
Daylogs (675)
영어공부 (0)
My works - 추억 (29)
비공개 (0)