파이썬 표준 라이브러리로 데이터 저장 & 직렬화: json, pickle, csv
데이터를 파일에 저장하거나 네트워크로 전달하려면 직렬화(Serialization) 가 필요합니다.
파이썬은 이를 위해 꽤 성격이 다른 세 가지 표준 도구를 제공합니다: json, pickle, csv.

json: 사람이 읽을 수 있는 텍스트 포맷, 언어 간 교환에 강함pickle: 파이썬 객체를 그대로 저장하는 바이너리 포맷, 강력하지만 위험 요소가 있음csv: 표(테이블) 데이터를 가장 단순하게 담는 텍스트 포맷, 범용성이 높음
이 글에서는 “어떤 데이터를 어디에 쓰려는지”에 따라 세 모듈을 고르는 감각을 정리해 봅니다.
1. JSON
1.1 개요
JSON(JavaScript Object Notation)은 텍스트 기반이며 언어 독립적입니다.
설정 파일, API 응답/요청, 로그 등 “다른 시스템과 주고받기 좋은 형태”로 널리 쓰입니다. 파이썬에서는 json 모듈로 바로 다룹니다.
1.2 핵심 API(자주 쓰는 것만)
json.dump(obj, fp, ...)/json.load(fp, ...): 파일로 저장/읽기json.dumps(obj, ...)/json.loads(s, ...): 문자열로 변환/복원
옵션 중에서 기억해두면 좋은 것:
ensure_ascii=False: ASCII 범위를 벗어나는 국제 문자(예: 라틴 확장, 키릴, CJK 등)를 이스케이프하지 않고 원문 그대로 저장/출력indent=2: 보기 좋게 예쁘게 출력default=...: JSON이 모르는 타입을 변환하는 “우회로” 제공
1.3 사용 예시(기본)
import json
data = {
"name": "Alice",
"age": 30,
"skills": ["Python", "Data Science"]
}
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
with open("data.json", "r", encoding="utf-8") as f:
loaded = json.load(f)
print(loaded)
1.4 JSON의 “타입 제한”을 간편하게 해결하는 법
JSON은 기본적으로 dict, list, str, int/float, bool, None만 자연스럽습니다.
예를 들어 datetime은 그대로는 저장되지 않습니다. 이때 default를 쓰면 깔끔합니다.
default에는 변환 함수(callable) 를 넘깁니다. json이 직렬화하지 못하는 객체를 만나면 그 객체가 함수의 인자로 들어오고,
함수는 str/dict/list처럼 JSON이 이해할 수 있는 타입으로 바꿔 반환하면 됩니다.
변환할 수 없는 타입은 TypeError를 던져 “여기서는 지원하지 않는다”를 명확히 알려주는 패턴이 흔합니다.
import json
from datetime import datetime, timezone
payload = {"created_at": datetime.now(timezone.utc)}
def to_jsonable(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"Not JSON serializable: {type(obj)!r}")
s = json.dumps(payload, default=to_jsonable, ensure_ascii=False)
print(s)
1.5 장단점
장점
- 언어 독립적이라 교환/공유에 강함
- 텍스트라 디버깅이 쉽고 버전 관리(Git)에도 친화적
pickle처럼 로딩만으로 코드가 실행되는 구조가 아님
단점
- 타입 표현력이 제한적(특히
datetime,set,Decimal, 바이너리 데이터 등) - 큰 데이터에서는 용량/속도 면에서 손해를 볼 수 있음
2. Pickle
2.1 개요
pickle은 파이썬 객체를 ‘파이썬 그대로’ 보관하기 위한 직렬화 방식입니다. 결과물은 사람이 읽는 텍스트가 아니라 바이너리 데이터(bytes)이며, 다시 불러오면 거의 동일한 형태의 객체로 복원됩니다.
pickle이 특히 유용한 경우는 이런 때입니다.
- 복잡한 파이썬 객체를 그대로 저장하고 싶을 때 예: 사용자 정의 클래스 인스턴스, 중첩된 자료구조, 학습된 모델/설정 객체(파이썬 객체 형태), 계산 결과 캐시 등
- 다른 언어와 교환할 필요가 없을 때
pickle은 파이썬 전용 포맷이라 “공유/교환” 목적이라면 보통json이 더 적합합니다.
반대로, 다음 상황에는 피하는 편이 좋습니다.
- 신뢰할 수 없는 출처의 데이터를 열어야 할 때 (
pickle.load()는 위험할 수 있음) - 다른 언어/시스템과 데이터를 주고받아야 할 때 (호환성 없음)
2.2 핵심 API(가장 많이 쓰는 4개)
pickle.dump(obj, file, protocol=...): 객체 → 파일(바이너리)로 저장pickle.load(file): 파일에서 읽어 → 객체로 복원pickle.dumps(obj, protocol=...): 객체 → bytes로 변환pickle.loads(data): bytes → 객체로 복원
아래처럼 “파일로 저장/불러오기”가 가장 흔합니다.
import pickle
data = {"a": [1, 2, 3], "b": ("x", "y")}
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
with open("data.pkl", "rb") as f:
loaded = pickle.load(f)
print(loaded)
2.3 protocol이 뭐고, 왜 신경 써야 하나?
protocol은 pickle이 데이터를 저장하는 “포맷 버전” 입니다.
프로토콜 버전에 따라 파일 크기/속도/지원 기능이 달라질 수 있습니다.
protocol을 지정하지 않으면: 파이썬이 “현재 환경에서 가장 적절한 기본값”을 사용합니다.- 보통은 기본값 그대로 두어도 충분합니다.
- 굳이 건드려야 하는 경우는 대개 두 가지입니다:
- 아주 오래된 파이썬 버전과 호환해야 해서 낮은 프로토콜을 강제해야 할 때
- 파일 크기/속도 최적화를 위해 명시적으로 최신 프로토콜을 고정하고 싶을 때
자주 쓰는 패턴은 이렇게 “최신 프로토콜”1을 지정하는 것입니다.
import pickle
with open("data.pkl", "wb") as f:
pickle.dump({"x": 1}, f, protocol=pickle.HIGHEST_PROTOCOL)
요약하면: 처음에는 protocol을 신경 쓰지 말고, 필요해졌을 때 pickle.HIGHEST_PROTOCOL을 떠올리면 됩니다.
2.4 pickle의 진짜 주의점(중요)
pickle.load() / pickle.loads()는 데이터 안에 들어있는 “복원 로직”을 실행할 수 있습니다.
즉, 신뢰할 수 없는 pickle을 로딩하는 순간, 의도치 않은 동작이 발생할 수 있습니다.
- 안전한 쪽 선택: “모르는 출처의
.pkl파일은 열지 않는다” - 공유/교환 목적이라면:
json같은 텍스트 기반 포맷이 기본 선택
2.5 장단점
장점
- 파이썬 객체를 폭넓게 저장(거의 무엇이든)
- 보통
json보다 빠르고 편합니다(특히 복잡한 객체)
단점
- 보안 위험(신뢰할 수 없는 데이터는 절대 로딩 금지)
- 파이썬 전용(다른 언어와 호환 불가)
- 클래스 정의가 바뀌면 과거 pickle이 깨질 수 있음(버전 호환 이슈)
3. CSV
3.1 개요
CSV(Comma-Separated Values)는 표 형태 데이터를 담는 가장 단순한 포맷입니다. 스프레드시트, 데이터 내보내기/가져오기, 간단한 로그 덤프 등에서 자주 등장합니다.
3.2 핵심 API(자주 쓰는 것만)
csv.reader,csv.writer: 리스트 기반csv.DictReader,csv.DictWriter: 딕셔너리 기반(대부분 이쪽이 편함)
3.3 사용 예시(DictWriter/DictReader)
import csv
data = [
{"name": "Alice", "age": 30, "city": "Seoul"},
{"name": "Bob", "age": 25, "city": "Busan"},
]
with open("people.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["name", "age", "city"])
writer.writeheader()
writer.writerows(data)
with open("people.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
loaded = list(reader)
print(loaded)
3.4 CSV 주의점 포인트 3가지
newline=""를 꼭 주기
- 특히 Windows에서 줄바꿈이 두 번 들어가는 문제를 피하기 위해 권장됩니다.
- 타입은 기본적으로 전부 문자열
- 읽어오면
"30"처럼 문자열로 들어옵니다. 필요한 컬럼은 직접 변환해야 합니다.
- 구분자/따옴표/개행이 데이터에 포함될 수 있음
- CSV는 단순해 보이지만 “값에 쉼표가 들어가는 순간”부터 규칙이 생깁니다.
그래서
csv모듈을 쓰는 것이 안전합니다(직접split(",")하면 곧 망가집니다).
3.5 장단점
장점
- 매우 가볍고 범용적(대부분의 도구가 읽고 씀)
- 표 데이터에는 과할 정도로 단순해서 다루기 쉬움
단점
- 중첩 구조(리스트 안의 리스트, 딕셔너리 중첩 등)는 표현이 어려움
- 타입 정보가 없어 변환 비용이 따름
4. 비교 & 선택 가이드
| 항목 | JSON | Pickle | CSV |
|---|---|---|---|
| 언어 호환 | 매우 좋음 | 파이썬 전용 | 매우 좋음 |
| 가독성 | 높음 | 낮음(바이너리) | 높음 |
| 타입 표현력 | 제한적 | 매우 높음 | 제한적 |
| 안전성 | 비교적 안전 | 주의 필요 | 비교적 안전 |
| 데이터 형태 | 트리 구조(중첩) | “파이썬 객체 그대로” | 테이블(행/열) |
고르는 기준을 한 문장으로 줄이면:
- 다른 시스템과 주고받는다 →
json - 파이썬 객체를 통째로 저장한다 →
pickle(단, 로딩 출처는 엄격히) - 행/열 형태로 내보내고 읽는다 →
csv
5. 같은 데이터를 3가지로 저장/복원하기
아래는 동일한 데이터를 json, pickle, csv로 각각 저장하고 다시 읽어오는 예시입니다.
import json, pickle, csv
data = [
{"id": 1, "name": "Alice", "score": 95.5},
{"id": 2, "name": "Bob", "score": 88.0},
]
# 1) JSON
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
with open("data.json", "r", encoding="utf-8") as f:
json_loaded = json.load(f)
# 2) Pickle
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
with open("data.pkl", "rb") as f:
pickle_loaded = pickle.load(f)
# 3) CSV
with open("data.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["id", "name", "score"])
writer.writeheader()
writer.writerows(data)
with open("data.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
csv_loaded = [
{"id": int(row["id"]), "name": row["name"], "score": float(row["score"])}
for row in reader
]
print(json_loaded)
print(pickle_loaded)
print(csv_loaded)
포인트:
- CSV는 읽자마자 숫자 변환을 해줘야 “의도한 타입”으로 돌아옵니다.
- pickle은 편하지만, 로딩 데이터의 출처를 신중히 관리해야 합니다.
6. 마무리
파이썬 표준 라이브러리만으로도 데이터 저장과 직렬화는 놀랄 만큼 넓은 범위를 커버합니다.
- 사람도 읽고, 다른 언어도 읽어야 한다 →
json - 파이썬 객체를 그대로 보관하고 싶다 →
pickle - 표 형태로 간단히 내보내고 싶다 →
csv
이 세 모듈 중에서 저장하고자 하는 데이터 모양과 목적이 무엇인지로 고르면 선택이 빠르고 깔끔해집니다.
-
pickle.HIGHEST_PROTOCOL현재 파이썬이 지원하는 가장 높은 프로토콜 번호를 의미합니다. ↩