컴퓨터가 데이터를 저장하는 기본 원리는 이진수(0과 1) 입니다. 컴퓨터 메모리는 수많은 전구처럼 작동하는 트랜지스터로 구성되어 있으며, 이 트랜지스터는 전류가 흐르거나 흐르지 않는 두 가지 상태를 표현합니다. 이와 같이, 모든 데이터는 결국 0과 1의 조합으로 저장됩니다.
문자 인코딩 (Encoding):
문자를 특정한 숫자(바이트)로 변환하는 과정입니다.
예시: A → 65, B → 66
문자 디코딩 (Decoding):
인코딩된 숫자(바이트)를 원래의 문자로 변환하는 과정입니다.
프로그래밍 언어에서 문자열을 바이트로 변환할 때는 항상 문자 집합(Charset) 을 명시해야 합니다. 예를 들어, 자바에서는 String.getBytes(Charset charset) 메소드를 사용하여 인코딩할 수 있습니다.
문자열을 바이트로 변환할 때는 반드시 사용할 문자 집합(예: UTF-8, EUC-KR, ISO-8859-1)을 지정해야 합니다. 잘못된 문자 집합을 사용할 경우, 특히 한글과 같이 다국어 문자의 경우 문자 깨짐(garbled text) 문제가 발생할 수 있습니다.
EUC-KR과 UTF-8의 호환성 문제:
UTF-8로 인코딩한 한글을 EUC-KR(ms949)로 디코딩하거나, 반대로 EUC-KR로 인코딩한 한글을 UTF-8로 디코딩할 때 문제가 발생합니다.
ISO-8859-1과의 혼용:
EUC-KR이나 UTF-8로 인코딩한 한글을 ISO-8859-1로 디코딩하면, 지원하지 않는 문자로 인해 깨짐 현상이 발생합니다.
예시
package charset;
import java.nio.charset.Charset;
import java.util.Arrays;
import static java.nio.charset.StandardCharsets.*;
public class EncodingMain2 {
private static final Charset EUC_KR = Charset.forName("EUC-KR");
private static final Charset MS_949 = Charset.forName("MS949");
public static void main(String[] args) {
System.out.println("== 영문 ASCII 인코딩 ==");
test("A", US_ASCII, US_ASCII);
test("A", US_ASCII, ISO_8859_1); // ASCII 확장(LATIN-1)
test("A", US_ASCII, EUC_KR); // ASCII 포함
test("A", US_ASCII, MS_949); // ASCII 포함
test("A", US_ASCII, UTF_8); // ASCII 포함
test("A", US_ASCII, UTF_16BE); // UTF_16 디코딩 실패
System.out.println("== 한글 인코딩 - 기본 ==");
test("가", US_ASCII, US_ASCII); // X
test("가", ISO_8859_1, ISO_8859_1); // X
test("가", EUC_KR, EUC_KR);
test("가", MS_949, MS_949);
test("가", UTF_8, UTF_8);
test("가", UTF_16BE, UTF_16BE);
System.out.println("== 한글 인코딩 - 복잡한 문자 ==");
test("뷁", EUC_KR, EUC_KR); // X
test("뷁", MS_949, MS_949);
test("뷁", UTF_8, UTF_8);
test("뷁", UTF_16BE, UTF_16BE);
System.out.println("== 한글 인코딩 - 디코딩이 다른 경우 ==");
test("가", EUC_KR, MS_949);
test("뷁", MS_949, EUC_KR); // 인코딩 가능, 디코딩 X
test("가", EUC_KR, UTF_8); // X
test("가", MS_949, UTF_8); // X
test("가", UTF_8, MS_949); // X
System.out.println("== 영문 인코딩 - 디코딩이 다른 경우 ==");
test("A", EUC_KR, UTF_8);
test("A", MS_949, UTF_8);
test("A", UTF_8, MS_949);
test("A", UTF_8, UTF_16BE); // X
}
private static void test(String text, Charset encodingCharset, Charset decodingCharset){
byte[] encoded = text.getBytes(encodingCharset);
String decoded = new String(encoded, decodingCharset);
System.out.printf("%s -> [%s] 인코딩 -> %s %sbyte -> [%s] 디코딩 -> %s\n",
text, encodingCharset, Arrays.toString(encoded),
encoded.length,
decodingCharset, decoded);
}
}