Indy의 idHTTP.Get에서의 한글 깨짐 회피 방법

indy그저께부터 Delphi/C++Builder 2009/2010 버전에서 Indy가 한글과 관련하여 오작동하는 문제에 대해 파헤치고 있습니다. 2009/2010 Indy의 한글 버그는 2009와 2010이 양상이 좀 다르고, 또 idHTTP와 idFTP, IdTCPClient에서 각각 원인도 좀 다르고 수정해야 할 포인트도 좀 다른 것 같습니다. 따라서 완벽한 해결책을 마련해서 공개해드리려면 1~2주 정도가 더 걸릴 것 같고요. 하지만 당장 답답한 분들이 많을 것이므로 작업 중간중간에 상태를 알려드리려고 합니다.

당장은, 일단 idHTTP와 관련하여 라이브러리 소스들을 수정하지 않고 피해가는 회피책, 즉 workaround 방법을 먼저 알려드리겠습니다. 간단히 말하면, idHTTP에서 Get을 호출해서 한글이 포함된 html 페이지를 한글 깨짐 없이 받아오려면, 다음과 같은 코드를 사용하면 됩니다.

Delphi 코드

C++Builder 코드

 

여기서 한가지 짚고 넘어갈 것이 있습니다. idHTTP를 사용했을 때 한글이 항상 깨지는 것은 아니라는 것입니다. 2009 버전에 번들된 Indy 버전에서는 받아오려는 HTML 페이지의 charset이 ‘utf-8’일 경우 깨지지 않고 ‘euc-kr’이나 ‘ks_c_5601-1987’인 경우에만 깨집니다. 2010 버전에 번들된 Indy의 경우, HTTP 헤더에서 charset을 지정된 경우에는 ‘utf-8’이 아닌 ‘euc-kr’이나 ‘ks_c_5601-1987’인 경우라도 깨지지 않으며 charset 지정이 없는 경우에만 깨집니다. (물론 위 코드를 사용하면 어떤 경우에든 안깨집니다)

한글이 깨어졌던 이유를 간단히 말씀드리자면, Indy 코드가 html 텍스트를 받아오는 과정에서 charset(인코딩)을 제대로 인식하지 못해서 엉뚱한 인코딩으로 풀어버린 것입니다. 그래서 메모리스트림으로 받아서 Indy 라이브러리가 인코딩을 직접 해석하지 않도록 강제한 후, 다시 스트림의 메모리 포인터를 코드페이지를 가지지 않는 무변환 스트링 타입인 RawByteString 타입으로 받아서 강제로 코드페이지를 한글인 949(euc-kr)로 지정합니다.

Delphi/C++Builder 2009 버전에 번들된 Indy에서는 이 charset에 대한 고려가 제대로 되어 있지 않습니다. 반면 2010 버전에서는 charset에 대한 처리가 아주 훌륭하게 되어 있는데요, 그럼에도 한글이 깨어지는 것은, HTTP 헤더에서 charset이 지정되지 않은 경우 기본 디폴트 charset 값의 처리 때문입니다. 그래서 2010 버전에서는 charset을 제대로 지정하면 한글 페이지라도 깨지지 않는 것이구요.

또 한가지 중요한 것. idHTTP로 받아오는 html 페이지가 ‘utf-8’로 되어 있는 경우, 코드페이지 949로 강제해버리면 당연히 깨져버립니다. 그래서 charset이 ‘utf-8’로 지정된 경우에는 ‘utf-8’의 코드페이지인 65001을 지정합니다.

참고로, 이 블로그의 charset은 ‘utf-8’ 이고, 볼랜드포럼의 경우 charset이 ‘ks_c_5601-1987’ 이지만 HTTP 헤더에서 넘겨주지 않구요. 델마당의 경우 charset이 ‘euc-kr’ 이면서 역시 HTTP 헤더에서 charset을 넘겨주지 않습니다. (따라서 위와 같은 회피책을 사용하지 않고 idHTTP를 써서 볼랜드포럼과 델마당의 페이지를 Get 하면 깨지지만 이 블로그의 페이지들은 깨지지 않을 것입니다)

오늘 저녁쯤에는, idHTTP의 Post를 사용했을 때의 문제를 해결하는 코드를 보여드리도록 하겠습니다.

5 comments for “Indy의 idHTTP.Get에서의 한글 깨짐 회피 방법

  1. 2009도 충분히 좋은 버전인데, 다만 2009에 번들된 Indy에 문제가 많을 뿐이랍니다~

답글 남기기

이메일 주소는 공개되지 않습니다.