본문 바로가기

업무 자동화 · 도구 검증 · 서비스 운영

반복 업무를 줄이는 방법,
직접 시험하고 기록합니다.

예약 명단 정리부터 알림 자동화, 앱 운영까지.
원본 예제와 확인표, 실험 결과를 함께 나눕니다.

첫 번째 실험 · 예약 명단

이름이 같으면
같은 예약일까요?

B102 · 방문자B9월 10일
B103 · 방문자B9월 11일

다른 예약입니다. 둘 다 남겨야 합니다.

가상 명단 12행으로 확인한 결과 →
개발 문제 해결

파이썬 JSON 파일 저장·읽기: 한글과 JSONDecodeError 확인

by 코딩히어로 2026. 9. 12.
300x250
반응형

JSON 파일에 한글이 그대로 보이게 저장하려면 두 곳을 정하면 됩니다. 파일은 UTF-8로 열고, json.dump에는 ensure_ascii=False를 전달합니다. 읽을 때는 json.load를 사용합니다. 문자열을 다루는 dumps·loads와 파일을 다루는 dump·load를 구분하면 코드가 간단해집니다.

설정 파일을 만든 뒤 다시 읽는 예제로 확인하겠습니다. 아래 코드는 Python 표준 라이브러리만 사용합니다. 예제의 한글, 앞자리 0, 참·거짓 값과 문법 오류 위치를 로컬 Python 3.14.6에서 확인했습니다.

1. 한글과 앞자리 0을 유지해서 저장하기

새 연습 폴더에서 실행합니다. 예제는 settings.json이 이미 있으면 멈추도록 x 모드를 사용했습니다. 기존 설정을 덮어쓰는 코드와 구분하기 위해서입니다.

import json

data = {"name": "작업실", "code": "0012", "enabled": True}
with open("settings.json", "x", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

저장된 내용은 다음과 같습니다. 0012는 숫자로 계산할 값이 아니라 식별자이므로 문자열로 만들었습니다.

{
  "name": "작업실",
  "code": "0012",
  "enabled": true
}

ensure_ascii=False는 JSON 안에서 한글을 어떤 모양으로 표현할지 정합니다. encoding="utf-8"은 파일 바이트의 인코딩을 정합니다. 서로 다른 단계라 두 설정을 함께 적었습니다. 기본값으로 저장된 유니코드 이스케이프도 유효한 JSON이며, 읽으면 같은 한글로 돌아옵니다.

2. 파일과 문자열에 맞는 함수 고르기

왼쪽은 입력과 출력 형식, 오른쪽은 사용할 함수입니다.

파이썬 값 → 파일 json.dump
파이썬 값 → JSON 문자열 json.dumps
파일 → 파이썬 값 json.load
JSON 문자열 → 파이썬 값 json.loads
with open("settings.json", encoding="utf-8") as f:
    loaded = json.load(f)
print(loaded["name"])
print(loaded["code"], type(loaded["code"]).__name__)
print(loaded["enabled"])
text = json.dumps(loaded, ensure_ascii=False)
assert json.loads(text) == loaded

출력은 작업실, 0012 str, True입니다. 파일에 적힌 true는 읽은 뒤 파이썬의 True가 됩니다. 파일 경로 자체를 json.loads에 넣으면 해당 파일을 열어 주는 것이 아닙니다. loads는 전달받은 문자열 자체를 JSON으로 해석합니다.

표 데이터를 다룬다면 CSV 파일의 구조와 함께 비교해 보세요. 행과 열 위주로 내보낼지, 중첩된 설정을 보존할지에 따라 형식을 정할 수 있습니다.

3. JSONDecodeError는 줄·열부터 확인하기

JSON 문자열의 키에는 큰따옴표를 씁니다. 마지막 항목 뒤에는 쉼표를 붙이지 않습니다. 파이썬 딕셔너리를 print한 결과가 곧 JSON인 것은 아닙니다.

samples = ['{"count": 1,}', "{'count': 1}", ""]
for text in samples:
    try:
        json.loads(text)
    except json.JSONDecodeError as e:
        print(e.lineno, e.colno, e.msg)

이 세 입력은 모두 JSONDecodeError가 발생했습니다. 각각 마지막 쉼표, 작은따옴표 키, 빈 문자열을 확인하면 됩니다. e.lineno와 e.colno는 파서가 해석을 이어 가지 못한 위치입니다. 원인은 그 직전 문자에 있을 수도 있어 앞뒤를 같이 읽습니다.

API 응답이라면 JSON 파싱에 앞서 상태 코드와 본문을 확인합니다. 인증 안내 HTML이나 빈 본문이 온 경우에는 JSON 문법만 바꿔서는 해결되지 않습니다. 파일이라면 실제 크기가 0인지, 쓰기가 끝난 파일을 읽었는지도 살펴봅니다.

4. 저장한 파일을 다시 읽어서 확인하기

python3 -m json.tool settings.json

명령이 들여쓰기된 내용을 출력하면 JSON 문법을 읽어 낸 것입니다. 다만 문법 통과와 업무 데이터 확인은 별개입니다. code가 문자열인지, 필요한 키가 있는지, 값이 허용 범위 안인지도 확인해야 합니다.

한 파일에 json.dump를 반복 호출해 객체를 이어 붙이면 일반 JSON 문서가 되지 않습니다. 여러 기록을 저장하려면 리스트 하나로 묶어 저장하거나, 한 줄마다 JSON 하나를 기록하는 JSON Lines 형식을 별도로 정합니다. 파일을 공유하는 프로그램끼리는 같은 형식을 사용해야 합니다.

스프레드시트로 옮긴 뒤 식별자의 앞자리 0이 달라졌다면 CSV 가져오기에서 열 형식을 지정하는 방법도 확인하세요. JSON에 문자열로 남아 있는 값과 시트가 해석한 값을 나눠 보면 변환 지점을 찾기 쉽습니다.

자주 묻는 질문

ensure_ascii=False만 넣으면 파일 인코딩도 바뀌나요?

아닙니다. 텍스트 파일 인코딩은 open의 encoding에서 정합니다. 한글을 직접 표시할 때는 두 설정을 함께 명시하면 읽기와 저장 조건을 맞추기 쉽습니다.

UTF-8 BOM이 있는 파일은 어떻게 읽나요?

입력 파일이 UTF-8 BOM 형식임을 확인했다면 encoding="utf-8-sig"로 열 수 있습니다. 모든 디코딩 오류에 같은 설정을 적용하기보다 파일을 만든 프로그램의 내보내기 형식을 먼저 확인합니다.

날짜 객체도 바로 저장할 수 있나요?

datetime 객체는 기본 JSON 인코더가 직접 처리하지 않습니다. 업무에서 사용할 시간대와 문자열 형식을 정한 뒤 isoformat() 등으로 변환합니다. 문자열로 읽힌 날짜를 자동으로 datetime으로 복원해 주는 것도 아닙니다.

함수 동작과 예외의 기준은 Python 공식 json 문서에서 확인할 수 있습니다. 이 글의 실행 확인은 작은 로컬 예제이며, 실제 서비스의 파일 동시 접근이나 대용량 입력까지 시험한 결과는 아닙니다.

300x250
반응형

댓글