문자열과 바이트 문자열의 기본 개념
문자열(string)은 문자(character)들의 연속입니다. 문자는 추상적인 개념이기 때문에 그 자체로는 디스크에 직접 저장할 수 없습니다. 반면 바이트 문자열(byte string)은 바이트의 연속으로, 실제로 디스크에 저장할 수 있는 데이터입니다.
문자열과 바이트 문자열 사이를 연결해 주는 것이 바로 인코딩(encoding)입니다. 인코딩 방식은 매우 다양하고(사실상 무한히 많은 종류가 가능합니다), 변환을 수행하려면 해당 상황에서 어떤 인코딩이 사용되는지 반드시 알아야 합니다. 서로 다른 인코딩은 같은 바이트를 전혀 다른 문자열로 해석할 수 있기 때문입니다.
즉, 동일한 바이트 문자열이라도 인코딩에 따라 두 가지 완전히 다른 문자열로 표현될 수 있습니다.
예시
>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-16')
'蓏
'蓏콯캁澽苏'
>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-8')
'τoρνoς'위 예제에서 볼 수 있듯이, 같은 바이트 시퀀스가 utf-16으로 디코딩하면 의미 없는 글자들이 나오지만, utf-8로 디코딩하면 그리스어 단어 'τoρνoς'가 제대로 출력됩니다.
decode()와 encode() 메서드
어떤 인코딩을 사용해야 하는지 알고 나면, 바이트 문자열의 .decode() 메서드를 호출하여 올바른 문자열을 얻을 수 있습니다. 반대로 문자열의 .encode() 메서드는 정반대 방향의 작업을 수행하며, 문자열을 바이트 문자열로 변환(인코딩)합니다.
참고로 파이썬 3에서는 일반 문자열이 str 타입(유니코드 문자열)이고, 바이트 문자열은 별도의 bytes 타입으로 구분됩니다. 텍스트 파일을 읽거나 네트워크 통신을 할 때 이 두 타입의 차이와 인코딩 개념을 정확히 이해하고 있으면 UnicodeDecodeError 같은 흔한 오류를 예방할 수 있습니다.