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 문서에서 확인할 수 있습니다. 이 글의 실행 확인은 작은 로컬 예제이며, 실제 서비스의 파일 동시 접근이나 대용량 입력까지 시험한 결과는 아닙니다.
'개발 문제 해결' 카테고리의 다른 글
| Docker 로그 확인: 최근 100줄·시간 범위·Compose 조회 (0) | 2026.09.12 |
|---|---|
| curl 응답 확인: 상태 코드·헤더·본문·종료 코드 구분하기 (0) | 2026.09.12 |
| 리눅스 용량 큰 파일 찾기: df·du·find로 범인 잡는 순서 (0) | 2026.09.11 |
| adb 명령어 모음: 기기 연결 안 될 때부터 apk 설치와 로그 추출까지 (0) | 2026.09.11 |
| MySQL 오류 코드 1064 해결: near 뒤 문자열로 원인 찾는 순서 (0) | 2026.09.11 |
댓글