String에는 getBytes 메서드가 있습니다. 이것이 대체 무엇을 하는 함수일까요? 간단하게 말해서, 어떠한 문자열을 aaa 라는 형식으로 인코딩 해서, 그 결과를 byte 배열로 리턴하는 함수입니다. 그런데, getBytes에 아무런 인자도 넣지 않고 호출하는 경우가 있는데요. 이 경우에 어떻게 동작하는지 간단하게 먼저 봅시다. 상세한 부분은 레퍼런스 분석에서 이야기 하도록 하겠습니다.
F5로 호출되는 함수들을 간단하게 봅시다.
먼저, 이 함수 안에 들어가면 StringCoding 클래스의 encode 메소드를 호출합니다. 그러면, 우리는 이런 합리적인 의심이 가능합니다. 이거 encode 하는 함수 아니야? 네. 맞습니다. xxx 라는 형식으로 인코딩 하라는 이야기입니다.
이 함수 내부로 들어가면, csn에 Charset의 defaultCharset()을 호출하게 되는데요. 디폴트 캐릭터 셋이라는 것이 또 있는 모양입니다. 이것을 호출한 다음에, 387번째 줄에 있는 encode 함수를 호출할 겁니다. 그리고, 인코딩한 결과를 byte 배열에 담아서 리턴을 할 겁니다.
만약에, getBytes 메서드에 인자를 넘겨주면 어떻게 될까요? 예를 들어서, "UTF16"을 넘겨줬다고 해 봅시다. 한글은 유니코드 값으로 65536 내에 있습니다. 그리고 '가'는 유니코드로 U+AC00입니다.
만약에 big Endian 형식으로 인코딩이 된다면, '가'는 요렇게 저장이 될 거에요. 여기까지 쓴 내용을 1줄로 정리해 봅시다. String.getBytes는 어떤 함수인가요? 특정한 형식, 예를 들어 UTF8이라던지, UTF16이라던지, CP949라던지. 그러한 형식으로 인코딩을 해서 그 결과를 byte 배열로 리턴하는 함수입니다.
그림으로 그려보면 이렇게 됩니다.
여기서 끝나면 섭섭하니, 추가적인 이야기를 해 보겠습니다. 인코딩 된 바이트 배열을 AAA라는 형식으로 읽어서 디코딩하는 건 없을까요? String 생성자 중에는, byte 배열과, charsetName을 받는 것이 하나 있는데요. 이것은 byte 배열을 charsetName으로 디코딩 하라는 뜻입니다.
그 생성자 안에서, 4개의 인자를 가지는 생성자를 호출하는데요. 2번째와 3번째 인자는 각각 offset과, 길이를 의미합니다. 여기 안으로 들어가 봅시다.
그러면, this.value에 StirngCoding 클래스 안에 있는 decode 함수를 수행한 결과를 넣게 되는데요. 딱 봐도, byte 배열로 넘어온 것을 charsetName으로 디코딩한 결과를 String의 문자 배열에 넣겠다는 이야기가 됩니다.
그러면 상식적으로 AAA라는 인코딩 형식으로 인코딩이 되었다면, 그것을 디코딩 하기 위해서는 AAA로 encode가 되었다는 정보를 주어야 할 겁니다. 그게 맞지 않으면 어떻게 될까요? 당연하게도 글자가 깨질 거에요. 이는 인코딩 형식과 디코딩 형식이 맞지 않기 때문이에요. 저 둘은 쌍이 맞아야 합니다.
Charset.defaultCharset().name()으로 인코딩을 했습니다. 그리고, 디코딩도 Charset.defaultCharset().name()로 했어요. 그러면 둘의 쌍이 서로 맞아요.
그런가요? 따라서, conv를 출력하면 깨짐 없이 그대로 출력되는 것을 볼 수 있어요.
제 환경에서는, Charset의 defaultset이 x-windows-949로 설정되어 있는 모양입니다.
그러면 이건 어떨까요? UTF16으로 인코딩을 하고 UTF8로 풀어버렸어요. 짝이 맞나요? 아닙니다. 기본적으로 UTF16은 한글을 2바이트로, UTF8은 3바이트로 표현합니다. 둘의 형식이 완전히 달라요. 쌍이 맞지 않기 때문에, 이상하게 출력이 될 거에요.
결과 값은 예상대로입니다. 그러면 쌍이 맞다고 한글이 항상 안 깨질까요? 이건 어떨까요?
EUC-KR로 인코딩 하고, 다시 이걸로 디코딩 했다. 글자가 제대로 나올까요? '믜' 라는 글자는 뉴스에서 많이 들어본 거 같은 이름인데, 사실, 작년에 이슈가 되었던 적이 있었습니다. 뉴스를 자주 보시는 분이라면 아실 수도 있습니다만. '믜'라는 것을 EUC-KR은 표현하지 못해요. 실제로, byte 배열을 찍어보면 다음과 같이 나오는데요.
뒤에 두 문자가 깨집니다. 이 친구들에 대한 이야기는 다음에 이야기를 해 보도록 하겠습니다.
'코딩 > Java' 카테고리의 다른 글
java string intern 메서드 : pool이 된다는 것만 기억합시다. (2) | 2019.08.08 |
---|---|
cp949 vs euc-kr : 어떤 차이점이 있는지 간단히 알아봅시다. (0) | 2019.08.04 |
java 참조 타입 vs 기본 타입 : 어떤 값을 저장하는가? (4) | 2019.08.03 |
java char형 : 기본적으로 2바이트를 차지한다. (4) | 2019.07.27 |
얕은 복사 vs 깊은 복사 : 참조가 복사되는가? 내용이 복사되는가? (12) | 2019.07.18 |
최근댓글