엑셀 CSV UTF-8 저장 방법: 한글 깨짐 없는 최적 설정과 자동화 가이드

이 글의 목적은 엑셀에서 CSV 파일을 UTF-8로 정확히 저장하여 한글 깨짐을 방지하고, 버전·운영체제·시스템 요구조건에 따른 예외 상황까지 현장에서 바로 적용할 수 있도록 실무 절차와 점검표, 자동화 스크립트를 제공하는 것이다.

왜 UTF-8인가: 한글 깨짐의 근본 원인 이해

CSV는 구조상 텍스트와 구분자만 포함하는 단순 포맷이라 인코딩을 명시하지 않는다. 윈도우의 오래된 생태계는 기본적으로 ANSI(윈도우-949 등)를 사용한 반면, 웹·클라우드·리눅스 기반 시스템은 UTF-8을 표준으로 채택하는 경향이 크다. 엑셀에서 기본 CSV로 저장하면 시스템/버전에 따라 ANSI나 다른 코드페이지가 적용될 수 있어 한글이 물음표·깨진 문자로 보일 수 있다. UTF-8로 저장하고, 필요 시 BOM(Byte Order Mark) 포함 여부를 맞추면 호환성이 크게 향상된다.

가장 빠른 해결: 최신 엑셀에서 바로 UTF-8로 저장

다음 절차는 Microsoft 365 및 최신 엑셀 버전에 해당한다.

  1. 파일 다른 이름으로 저장 을 선택한다.
  2. 파일 형식 에서 CSV UTF-8(쉼표로 분리)(*.csv) 를 선택한다.
  3. 저장 을 클릭한다.
주의 : 동일 파일을 다시 열어 추가 편집 후 저장하면 서식·수식이 사라질 수 있다. CSV는 텍스트 형식이라 숫자 서식·색상·수식이 보존되지 않기 때문이다. 원본은 항상 .xlsx로 보관하고 CSV는 내보내기 용도로만 생성한다.

맥(Excel for Mac)에서 UTF-8 CSV 저장

  1. 파일 다른 이름으로 저장 또는 사본 저장 을 선택한다.
  2. 파일 형식 에서 CSV UTF-8(쉼표로 분리)(*.csv) 를 선택한다.
  3. 저장 을 클릭한다.

맥 환경에서는 기본 문자셋이 유니코드 기반이라 윈도우 대비 인코딩 충돌이 적지만, 대상 시스템(예: 레거시 ERP, 장비 로거)이 BOM을 싫어하는 경우가 있어 하단의 BOM 제어 방법을 참고한다.

구버전 엑셀·CSV(쉼표로 분리)(*.csv)만 있는 경우 대안

구버전 엑셀에서는 CSV UTF-8 옵션이 보이지 않을 수 있다. 아래 3가지 경로 중 하나를 사용한다.

방법 A. 메모장(또는 코드 편집기)로 재인코딩

  1. 엑셀에서 CSV(쉼표로 분리)(*.csv) 로 저장한다.
  2. 메모장으로 연다 → 다른 이름으로 저장 인코딩 에서 UTF-8 을 선택하고 저장한다.
주의 : 일부 메모장 버전은 UTF-8 저장 시 BOM이 자동 삽입된다. 대상 시스템이 BOM 없는 UTF-8을 요구하면 방법 B 또는 C를 사용한다.

방법 B. PowerShell로 UTF-8(BOM/무BOM) 변환

윈도우에서 명령줄로 정확한 인코딩을 강제할 수 있다.

  
# PowerShell 5.x: 기본 UTF8는 BOM 포함일 수 있음 Get-Content .\input.csv | Set-Content -Encoding UTF8 .\output_utf8_bom.csv
PowerShell 7 이상: BOM 없는 UTF-8 강제
Get-Content .\input.csv | Set-Content -Encoding utf8NoBOM .\output_utf8_nobom.csv

대용량 파일에서는 스트리밍 권장
$reader = [System.IO.StreamReader]::new("input.csv", [System.Text.Encoding]::GetEncoding(949)) # 원본이 ANSI(949) 가정
$writer = [System.IO.StreamWriter]::new("output_utf8_nobom.csv", $false, [System.Text.UTF8Encoding]::new($false))
while (($line = $reader.ReadLine()) -ne $null) { $writer.WriteLine($line) }
$reader.Close(); $writer.Close()

  

방법 C. VBA로 직접 UTF-8 쓰기

엑셀 내부에서 버튼 하나로 CSV를 UTF-8로 내보낼 수 있다.

  
Option Explicit
Sub ExportCsvUtf8_NoBOM()
Dim fso As Object, ts As Object
Dim p As String, r As Long, c As Long, lastR As Long, lastC As Long
Dim lineStr As String, q As String: q = Chr(34)
Dim ws As Worksheet: Set ws = ActiveSheet

lastR = ws.Cells(ws.Rows.Count,
1).End(xlUp).Row
lastC = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column

p = ThisWorkbook.Path & "\export_utf8_nobom.csv"
Set fso = CreateObject("ADODB.Stream")

With fso
    .Type = 2 ' Text
    .Charset = "utf-8"
    .Open
    ' BOM 제거: utf-8로 쓰고 나중에 바이너리 재열어 BOM 3바이트 제거
End With

For r = 1 To lastR
    lineStr = ""
    For c = 1 To lastC
        Dim val As String: val = ws.Cells(r, c).Text
        If InStr(val, q) > 0 Then val = Replace(val, q, q & q)
        If InStr(val, ",") > 0 Or InStr(val, vbLf) > 0 Or InStr(val, vbCr) > 0 Then
            val = q & val & q
        End If
        If c = 1 Then
            lineStr = val
        Else
            lineStr = lineStr & "," & val
        End If
    Next c
    fso.WriteText lineStr & vbCrLf
Next r

' 임시 파일로 저장
fso.SaveToFile p, 2
fso.Close

' BOM 제거 처리
Dim bin As Object: Set bin = CreateObject("ADODB.Stream")
bin.Type = 1: bin.Open
bin.LoadFromFile p
bin.Position = 3 ' BOM 3바이트 스킵
Dim nobom As Object: Set nobom = CreateObject("ADODB.Stream")
nobom.Type = 1: nobom.Open
bin.CopyTo nobom
nobom.SaveToFile Replace(p, ".csv", "_final.csv"), 2
bin.Close: nobom.Close
MsgBox "완료: " & Replace(p, ".csv", "_final.csv")
End Sub

  
주의 : CSV 작성 시 쉼표·줄바꿈·따옴표가 포함된 셀은 RFC 4180 관례에 따라 전체를 큰따옴표로 감싸고 내부 따옴표는 이중으로 이스케이프해야 한다. 위 매크로는 해당 규칙을 반영한다.

BOM 포함 vs 무BOM 선택 기준

대상 시스템 권장 이유
대부분의 웹 서비스, 파이썬 판다스 기본 UTF-8 무BOM BOM을 헤더로 오인하거나 필드 첫 글자에 특수문자()가 섞이는 문제를 예방한다.
윈도우 메모장, 일부 엑셀 자동감지 UTF-8 BOM 파일 오픈 시 문자셋 자동판별에 유리하다.
레거시 ERP/장비 로거 사양 확인 필수 구현에 따라 BOM 처리 방식이 다르므로 테스트가 필요하다.

구분자와 지역 설정: 쉼표, 세미콜론, 탭

CSV의 C는 Comma를 의미하지만, 지역설정의 목록 구분 기호 에 따라 엑셀이 세미콜론을 쓰는 경우가 있다. 한국 로캘에서는 보통 쉼표를 사용한다. 데이터에 쉼표가 많아 가독성이 떨어지면 텍스트(탭으로 분리) 형식 또는 탭 구분(\t)으로 내보내고, 대상 시스템이 TSV를 허용하는지 확인한다.

형식 장점 단점
CSV(쉼표) 대부분 시스템 표준 호환 데이터 내 쉼표 존재 시 인용·이스케이프 필요
CSV(세미콜론) 유럽 로캘에서 숫자 쉼표와 충돌 감소 일부 파서 기본값과 불일치
TSV(탭) 필드 내 쉼표·세미콜론 문제 최소화 공백·탭 혼동 가능, 일부 도구에서 기본 미지원

숫자·날짜·우편번호 보존을 위한 사전 정리

  1. 우편번호·제품코드 등 앞자리 0 유지가 필요한 열은 내보내기 전 텍스트 형식으로 지정한다.
  2. 날짜/시간 은 표준 ISO 8601( YYYY-MM-DD , YYYY-MM-DDTHH:MM:SS )로 변환하여 텍스트로 확정한다.
  3. 줄바꿈 이 있는 셀은 의도된 값인지 점검한다. 엑셀 내부 줄바꿈은 CSV에서 \r\n 으로 출력되며 필드가 큰따옴표로 감싸져야 한다.
  
=TEXT(A2,"yyyy-mm-dd") '날짜 표준화 =TEXT(B2,"0") '앞자리 0 보존 =SUBSTITUTE(C2,CHAR(10)," ") '셀 내부 줄바꿈 제거(필요 시) 
  
주의 : CSV는 서식이 아닌 값만 보존한다. 표시 형식 의존 계산을 해뒀다면 내보내기 전 복사 선택하여 붙여넣기 > 값 으로 고정한다.

검증: 저장 직후 인코딩·필드 확인 체크리스트

항목 체크 방법 합격 기준
인코딩 편집기에서 파일 열기 → 상태바/정보 패널 확인 UTF-8로 표시
BOM 존재 파서 첫 필드 값에 특수문자() 여부 확인 요구사항과 일치(BOM 포함/무BOM)
구분자 한 줄 임의 표본에서 필드 구분 확인 의도한 구분자 사용
인용 규칙 쉼표·따옴표·줄바꿈 포함 필드 확인 필드 전체 인용, 내부 따옴표 이스케이프
숫자 형식 앞자리 0, 자릿수, 소수점 확인 손실 없음

자동화 파이프라인: 대량 내보내기와 재현성

PowerShell 배치 처리

  
# 폴더 내 모든 CSV를 UTF-8 무BOM으로 일괄 변환 (PowerShell 7+) Get-ChildItem -Filter *.csv | ForEach-Object { $in = $_.FullName $out = [System.IO.Path]::ChangeExtension($in, ".utf8.csv") Get-Content $in | Set-Content -Encoding utf8NoBOM $out } 
  

파이썬 판다스로 내보내기

  
import pandas as pd
df = pd.read_excel("data.xlsx", sheet_name=0)

BOM 포함(일부 윈도우 앱 호환성 ↑)
df.to_csv("export_utf8_bom.csv", index=False, encoding="utf-8-sig")

BOM 없음(웹/리눅스 파이프라인 선호)
df.to_csv("export_utf8_nobom.csv", index=False, encoding="utf-8")

  
주의 : 대상 시스템이 특정 줄끝(EOL)을 요구할 수 있다. 윈도우는 \r\n , 유닉스는 \n 을 사용한다. 파이썬의 to_csv 는 기본적으로 OS의 EOL을 따른다.

엑셀에서 CSV 열 때 발생하는 오해 방지

CSV를 다시 엑셀로 열면 보이는 형식은 엑셀이 임의로 추론한 결과이다. 앞자리 0 제거, 긴 숫자 자릿수 반올림, 날짜 자동변환 등은 파일 문제라기보다 엑셀의 자동 서식 때문이다. 데이터 품질을 확인하려면 코드 편집기로 텍스트를 확인하거나, 엑셀에서 데이터 > 텍스트/CSV에서 를 사용해 데이터 형식 파일 원본 을 수동 지정한다.

프로덕션 투입 전 사양 확인 체크리스트

  • 문자셋: UTF-8 with/without BOM 명시 필요하다.
  • 구분자: 쉼표/세미콜론/탭 중 요구사항 확인한다.
  • 행 끝(EOL): \r\n vs \n 확인한다.
  • 헤더 행 포함 여부와 컬럼 순서 고정 규칙을 문서화한다.
  • 인용 규칙: 줄바꿈·구분자·따옴표 포함 필드 처리 명시한다.

문제 해결: 증상별 원인과 해결

증상 가능 원인 해결
한글이 ????? 로 보임 ANSI 저장 CSV UTF-8로 저장하거나 PowerShell/메모장으로 UTF-8 재인코딩
첫 컬럼에  문자가 붙음 BOM 포함 무BOM으로 재저장 또는 파서의 BOM 처리 옵션 사용
열 개수가 맞지 않음 구분자와 데이터 내 문자 충돌 문제 필드 인용(큰따옴표) 및 이스케이프 확인
앞자리 0 사라짐 엑셀 자동 서식 텍스트 형식 지정 후 저장 또는 파서에서 문자열로 강제
긴 숫자 반올림 표시 자릿수 제한 텍스트로 변환 후 저장, 원본은 문자열로 유지

현장 적용 템플릿: 내보내기 전 1분 점검

  1. 원본 .xlsx 백업 생성 완료하다.
  2. 텍스트로 유지할 열 포맷 확정하다.
  3. 날짜/시간 ISO 8601로 변환하다.
  4. CSV UTF-8로 저장하다.
  5. 편집기로 열어 인코딩·구분자·인용 규칙 확인하다.
  6. 대상 시스템에 시험 업로드 후 레코드 카운트·샘플 필드 검증하다.

FAQ

CSV UTF-8로 저장했는데도 웹에서 깨져 보인다. 왜 그런가?

대상 웹 서비스가 업로드 후 서버 내부에서 다른 인코딩으로 다시 해석하거나, 파일의 BOM 여부를 가정하는 경우가 있다. 무BOM/with BOM을 바꿔서 테스트하고, 서비스의 CSV 사양 문서를 확인하여 구분자·인용 규칙까지 일치시키는 것이 중요하다.

엑셀에서 TSV(탭)로 저장하는 것이 더 안전한가?

데이터에 쉼표가 매우 많고 파서가 TSV를 지원한다면 탭이 안전할 수 있다. 다만 많은 시스템이 기본 입력을 CSV로 가정하므로 사양을 먼저 확인해야 한다.

수식 결과만 내보내고 싶다. 어떻게 하나?

내보내기 전 전체 범위를 복사 후 선택하여 붙여넣기 > 값 으로 고정한 뒤 CSV로 저장한다. 또는 파워쿼리/파이썬으로 연산 결과를 생성해 바로 CSV로 기록한다.

대용량 데이터에서 엑셀이 멈춘다. 대안은?

엑셀 대신 파이썬 판다스나 PowerShell 스트리밍으로 직접 CSV를 생성한다. 메모리 사용량과 속도가 유리하다.

열 구분을 세미콜론으로 강제할 수 있나?

엑셀의 지역 설정에 따른 목록 구분 기호를 변경하거나, VBA/파이썬 등으로 원하는 구분자를 직접 기록한다. 대상 시스템이 세미콜론 CSV를 허용하는지 확인해야 한다.