ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] 인코딩 디코딩 다시 이해하기
    JAVA 2025. 5. 8. 00:10
    728x90
    반응형

    컴퓨터는 오직 0 or 1 즉 바이트(byte)를 처리할 수 있고 사람이 알아보는 문자는 char 또는 String입니다.

    쉽게 말하면 인코딩은 문자를 바이트로 디코딩은 바이트를 문자로 바꾸는 작업입니다.

    간단한 String 예시

    String message = "콜라 마시고 싶다.";
    
    // 인코딩 올바른 예
    byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
    
    // 인코딩 잘못된 예
    byte[] failBytes = message.getBytes(StandardCharsets.ISO_8859_1);
    
    // 디코딩 올바른 예
    String success = new String(bytes, StandardCharsets.UTF_8);
    
    // 디코딩 잘못된 예
    String fail = new String(bytes, StandardCharsets.ISO_8859_1);
    
    // ISO-8859-1은 유럽계 문자로 구성되어 있어 한글을 표현할 수 없기 때문에 인코딩시 손실이 발생
    
    // 깨진 문자열을 복구
    byte[] recoveredBytes = fail.getBytes(StandardCharsets.ISO_8859_1);
    String recovered = new String(recoveredBytes, StandardCharsets.UTF_8);

    한글의 경우 예시처럼 인코딩 / 디코딩에서 문제가 발생할 수 있지만 만약 영어와 숫자 특정 문자열만을 사용하는 경우에는 인코딩 디코딩의 Charsets가 달라져도 데이터 손실이 없습니다.

    하지만 실제로는 다양한 특수문자와 파일 크기를 고려한다면 Charsets를 일부러 다르게 만들 필요는 없습니다.

    OS 마다 기본 Charsets를 가지고 있다.

    OS 마다 각각 다른 기본적인 Charsets을 가지고 있습니다.

    그렇기 때문에 인코딩 / 디코딩 시 각각 다른 OS일때도 항상 동일한 Charsets를 유지하기 위해 실무에서는 지금 OS 기본 Charsets를 사용하고 있는지 확인이 필요합니다.

    • window (과거 및 일부 설정) : MS 949 (CP 949)
    • linux / mac : UTF_8

    만약 Windows 환경에서 기본 Charset으로 파일을 저장했다면 Linux/mac 환경에서 해당 파일을 UTF-8로 읽을 때 한글이 깨질 수 있습니다.

    // 과거 Window라고 가정한다면 기본 Charsets는 CP949이므로 올바르지 않다.
    Files.write(Path.of("test.txt"), "테스트".getBytes(StandardCharsets.UTF_8));

    이 문제를 해결하기 위해서는 OutputStreamWriter 와 Charsets를 지정해줘야 합니다.

    OutputStreamWriter osw = new OutputStreamWriter(FileOutputStream, StandardCharsets.UTF_8);

    현재 OS의 기본 Charsets 확인하는 방법은 아래와 같습니다.

    Charset.defaultCharset();

    CSV or Excel 같은 외부 파일

    외부 파일인 경우 UTF_8로 지정을 해주더라도 한글은 깨질 수 있기 때문에 BOM(Byte Order Mark) 추가가 필요합니다.

    writer.write("\uFEFF");

    BOM은 UTF 계열 인코딩에서 파일의 시작 부분에 쓰여지는 몇 바이트의 특별한 시퀀스로 해당 파일이 어떤 UTF 인코딩(UTF-8, UTF-16 BE, UTF-16 LE 등)으로 인코딩되었는지 명시하는 역할을 합니다

    하지만 BOM은 UTF 인코딩에서만 의미가 있으며 다른 인코딩(예: MS949)에서는 사용할 수 없습니다.

    API 통신

    내부 / 외부 통신 모두 인코딩 방식을 정확히 파악한 후 Charsets를 명시적으로 지정해주는 습관은 혹시 모를 인코딩 / 디코딩 에러를 미연에 방지 할 수 있도록 도와줍니다.

    DB 통신

    Database의 경우 Database 컬럼 문자셋과 JDBC 문자셋이 일치해야만 정확히 데이터가 저장될 수 있습니다.

    728x90
    반응형
Designed by Tistory.