C.W.K.
Stream
Lesson 05 of 06 · published

인코딩 — UTF-8 디폴트와 엣지 케이스

~15 min · encoding, utf-8, unicode, bom

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

UTF-8 이 95% 맞아

현대 파일 UTF-8. 현대 웹 프로토콜 UTF-8. 현대 소스 코드 UTF-8. 다른 거 쓸 특정 이유 (legacy 데이터, 시스템 제약) 없으면 UTF-8 이 맞는 디폴트. 나머지 5% — Windows legacy 파일, CP949 내뱉는 한국 Windows 도구, 옛 Excel export — 진짜이고 만나, 근데 예외.

BOM — 왜 존재

byte-order mark (BOM) 은 파일 시작의 특수 글자 — 인코딩 신호. UTF-8 은 별로 안 필요 (인코딩이 명확) 하지만 Windows 소프트웨어가 종종 어쨌든 써. utf-8-sig 가 읽기 인코딩이면 있을 시 BOM skip. utf-8 은 데이터 시작에 리터럴 글자로 둠.

뭐 잘못되나 — 증상 읽기

UnicodeDecodeError 가 지정한 인코딩에 유효하지 않은 바이트 디코딩 시도 의미. 흔한 원인 — 파일이 사실 UTF-16 또는 CP1252 인데 UTF-8 시도, 파일이 바이너리인데 텍스트 모드 시도, 멀티바이트 글자가 반으로 잘림. 에러 읽어 — 바이트 위치 + 문제 바이트 알려줘.

chardet — 진짜 모를 때

pip install chardet 가 바이트 샘플에서 인코딩 추측 라이브러리 줘. 미스터리 파일 일회성 import 에 유용. production path 에 두지 마 — 추측은 확률, 보장 X.

원칙: 텍스트 파일 열 때 항상 encoding 지정. 시스템 디폴트는 플랫폼 특정 + 크로스플랫폼 코드 물려. 양쪽 끝 다 제어하면 encoding="utf-8". 아니면 실제 인코딩 매치.

Code

UTF-8 — 현대 디폴트·python
# 한국어 텍스트는 UTF-8 에서 멀티바이트
text = "피파, 안녕"
b = text.encode("utf-8")
print(b)                     # b'\xed\x94\xbc\xed\x8c\x8c, \xec\x95\x88\xeb\x85\x95'
print(len(text))             # 6 글자
print(len(b))                # 17 바이트 — 한글 글자당 3 바이트

# Round-trip
back = b.decode("utf-8")
print(back == text)          # True
BOM — utf-8-sig vs utf-8·python
import io

# BOM 있는 파일 (Windows 메모장이 UTF-8 로 종종)
with_bom = b"\xef\xbb\xbfhello"

# utf-8 — BOM 첫 글자로 남음
print(with_bom.decode("utf-8"))         # '\ufeffhello'

# utf-8-sig — BOM 소비
print(with_bom.decode("utf-8-sig"))     # 'hello'

# BOM 있을 수 있는 파일 읽을 땐 utf-8-sig 선호
# BOM 있고 없고 둘 다 관용
UnicodeDecodeError — 증상 읽기·python
# CP949 = 한국 Windows 인코딩
text = "안녕"
cp949_bytes = text.encode("cp949")
print(cp949_bytes)            # b'\xbe\xc8\xb3\xe7'

# UTF-8 으로 디코드 시도 — 실패
try:
    cp949_bytes.decode("utf-8")
except UnicodeDecodeError as e:
    print("위치:", e.start)
    print("이유:", e.reason)
    # 에러가 디코딩 실패 위치 정확히 알려줘

# 맞는 인코딩으로 — 작동
print(cp949_bytes.decode("cp949"))     # '안녕'
errors= — 디코드 실패 우아하게 처리·python
messy = b"hello \xff world"           # 잘못된 UTF-8 바이트

# strict — raise
try:
    messy.decode("utf-8")
except UnicodeDecodeError as e:
    print("strict:", e)

# replace — 잘못된 바이트가 U+FFFD
print(messy.decode("utf-8", errors="replace"))   # 'hello \ufffd world'

# ignore — 잘못된 바이트 떨어뜨림
print(messy.decode("utf-8", errors="ignore"))    # 'hello  world'

# Backslash-escape — 보이는 표현
print(messy.decode("utf-8", errors="backslashreplace"))   # 'hello \\xff world'

# 표시엔 'replace', 드물게 'ignore', 코드엔 'strict' (디폴트)

External links

Exercise

한국어 ("피파"), 영어 ("hello"), 이모지 ("🌸") 포함 문자열. UTF-8 로 인코드 + 바이트 길이 + 글자 길이 출력. UTF-16 으로 인코드 + 길이 비교. UTF-8 바이트 손상 (한 mid-character 바이트를 0xFF 로 교체) + 디코드 시도 — UnicodeDecodeError 관찰, errors='replace' 로 다시 디코드해서 U+FFFD 글자 봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.