오류 해결 과정

Windows + PostgreSQL에서 `UnicodeDecodeError` 해결기

필만이 2025. 4. 26. 23:26

1. 증상

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xB8 …
  • 상황
    pandas.DataFrame.to_sql() 로 한글 컬럼이 포함된 데이터를 PostgreSQL(pgadmin) 로 넣을 때 위 오류 발생
  • 환경
    • Windows 11
    • PostgreSQL 17 (설치 시 기본 “Korean_Windows” 로케일)
    • SQLAlchemy + psycopg2 + pandas

2. 원인 - “DB 클러스터 인코딩이 EUC-KR”

  • PostgreSQL은 클러스터를 만들 때 지정한 로케일/인코딩으로만 내부 데이터를 저장한다. 기본 설치를 그대로 두면 윈도우의 Korean_Windows(EUC-KR) 가 설정된다.
  • Python, pandas, SQLAlchemy는 모두 기본이 UTF-8이다. 따라서, db에 데이터를 넣을때 디코딩 충돌이 일어난다.

3. 작업 순서

3-1. UTF-8 로 새 데이터 디렉터리(클러스터) 생성

  • 이유 : PostgreSQL은 "클러스터"라는 단위로 데이터 저장 방식을 정해. (클러스터 = 데이터베이스 파일 저장 폴더) 그래서 UTF-8로 새 클러스터를 만듦
# PowerShell 관리자 모드
$pg = "C:\Program Files\PostgreSQL\17\bin"
& "$pg\initdb.exe" -D "C:\pgsql\data_utf8" -E UTF8 --locale=en_US.UTF-8

3-2. standalone 백엔드로 superuser 생성

  • 이유 : 새 클러스터를 만들면 아무 사용자도 없는 깨끗한 상태. 기존에 쓰던 postgres 슈퍼유저 계정도 새로 만들어줘야 DB 관리·접속

    & "$pg\postgres.exe" --single -D "C:\pgsql\data_utf8" postgres
    # 프롬프트 전환 → 한 줄 입력
    CREATE ROLE postgres SUPERUSER CREATEDB CREATEROLE LOGIN PASSWORD 'postgres';
    \q   -- 종료

3-3. 새 클러스터로 서버 실행 & 자동시작 등록 (기존 서비스는 그대로 둬도 됨)

  • 이유 : 새로 만든 UTF-8 클러스터를 서버로 기동해야 실제 접속해서 쓸 수 있다. 그리고 Windows에선 서비스 등록(pg_ctl register)까지 하면 컴퓨터 켤 때 자동으로 PostgreSQL 서버가 켜지게함

    & "$pg\pg_ctl.exe" start -D "C:\pgsql\data_utf8"

필요하면 pg_ctl register 로 Windows 서비스 등록도 가능.

3-4. 테스트 접속

& "$pg\psql.exe" -h localhost -U postgres

4. 파이썬 코드 수정(SQLAlchemy DSN을 client_encoding=utf8 로 수정)

  • 이유 : 서버 인코딩이 UTF-8이어도, 클라이언트(파이썬 드라이버)가 정확히 같은 UTF-8로 통신한다고 명시

    from sqlalchemy import create_engine
    dsn = (
      "postgresql+psycopg2://postgres:poetgres@localhost:5432/postgres"
      "?client_encoding=utf8"          # 반드시 UTF-8
    )
    engine = create_engine(dsn, echo=False, pool_pre_ping=True)

5. 서비스 일시 중지

Stop-Service -Name postgresql-x64-17

6. 서비스 데이터 디렉터리 변경

$newPath = '"C:\Program Files\PostgreSQL\17\bin\pg_ctl.exe" runservice -N "postgresql-x64-17" -D "C:\pgsql\data_utf8"'
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\postgresql-x64-17" -Name ImagePath -Value $newPath

7. 서비스 실행

Start-Service -Name postgresql-x64-17