pharmacy-pos-qr-system/docs/windows-utf8-encoding.md
thug0bin 5042cffb9f feat: AI CRM 어드민 대시보드 + 바텀시트 드래그 닫기 + UTF-8 인코딩 + 문서화
- /admin/ai-crm: AI 업셀링 추천 생성 현황 대시보드 (통계 카드 + 로그 테이블 + 아코디언 상세)
- 마이페이지 바텀시트: 터치 드래그로 닫기 기능 추가 (80px 임계값)
- Windows 콘솔 UTF-8 인코딩 강제 (app.py, clawdbot_client.py)
- admin.html 헤더에 AI CRM 네비 링크 추가
- docs: ai-upselling-crm.md, windows-utf8-encoding.md 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 20:38:04 +09:00

2.6 KiB
Raw Blame History

Windows 콘솔 한글 인코딩 (UTF-8) 가이드

문제

Windows 콘솔 기본 인코딩이 cp949여서 Python에서 한글 출력 시 깨짐 발생. Claude Code bash 터미널, cmd, PowerShell 모두 동일 증상.

# 깨진 출력 예시
{"product": "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>", "message": "<22><EFBFBD><E8BFB5><EFBFBD>, ..."}

해결: 3단계 방어

1단계: Python 파일 상단 — sys.stdout UTF-8 래핑

import sys
import os

if sys.platform == 'win32':
    import io
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
    sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
    os.environ.setdefault('PYTHONIOENCODING', 'utf-8')

적용 위치: app.py, clawdbot_client.py 등 진입점 파일 맨 위 (import 전)

모듈로 import되는 파일은 hasattr(sys.stdout, 'buffer') 체크 추가:

if sys.platform == 'win32':
    import io
    if hasattr(sys.stdout, 'buffer'):
        sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
        sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')

2단계: 환경변수 — PYTHONIOENCODING

# ~/.bashrc (Claude Code bash 세션)
export PYTHONIOENCODING=utf-8

또는 실행 시:

PYTHONIOENCODING=utf-8 python backend/app.py

3단계: json.dumps — ensure_ascii=False

import json
data = {"product": "비타민C", "message": "추천드려요"}
print(json.dumps(data, ensure_ascii=False, indent=2))

ensure_ascii=False 없으면 \uBE44\uD0C0\uBBFCC 같은 유니코드 이스케이프로 출력됨.

프로젝트 내 적용 현황

파일 방식
backend/app.py sys.stdout 래핑 + PYTHONIOENCODING
backend/services/clawdbot_client.py sys.stdout 래핑 (buffer 체크)
backend/ai_tag_products.py sys.stdout 래핑
backend/view_products.py sys.stdout 래핑
backend/import_il1beta_foods.py sys.stdout 래핑
backend/import_products_from_mssql.py sys.stdout 래핑
backend/update_product_category.py sys.stdout 래핑
backend/gui/check_cash.py sys.stdout.reconfigure(encoding='utf-8')
backend/gui/check_sunab.py sys.stdout.reconfigure(encoding='utf-8')
~/.bashrc export PYTHONIOENCODING=utf-8

주의사항

  • Flask 로거(logging.info() 등)도 stderr로 출력하므로 stderr도 반드시 래핑
  • io.TextIOWrapper는 이미 래핑된 스트림에 중복 적용하면 에러남 → hasattr(sys.stdout, 'buffer') 체크
  • PyQt GUI에서는 stdout이 다를 수 있음 → hasattr 가드 필수