[PY-006][기초] 파일·JSON·CSV 안전하게 읽고 쓰기
페이지 정보

본문
[이번 수업]
Python으로 같은 데이터를 JSON·CSV로 저장하고 다시 읽으며 인코딩, 자료형, 줄바꿈 차이를 확인합니다.
[선수지식]
CORE-005의 경로와 PY-003·004의 자료구조·모듈을 알면 됩니다.
[학습목표]
1. Path와 with를 사용해 운영체제에 맞게 파일을 다룬다.
2. JSON과 CSV를 읽고 쓰는 방법과 자료형 차이를 설명한다.
3. 외부 파일의 경로·크기·내용을 방어적으로 검증한다.
[핵심개념]
파일 모드는 읽기 `r`, 덮어쓰기 `w`, 이어쓰기 `a` 등이 있고 `w`는 기존 내용을 지웁니다. 텍스트 인코딩 기본값은 환경마다 달라 `encoding="utf-8"`을 명시합니다. `with` 블록은 예외가 생겨도 파일을 닫습니다.
`pathlib.Path`는 운영체제별 경로 차이를 줄입니다. `/` 연산자로 하위 경로를 만들고 `mkdir(exist_ok=True)`로 폴더를 준비합니다.
JSON은 계층 구조와 자료형을 표현하는 텍스트 형식입니다. `json.dump`·`load`는 파일 객체를, `dumps`·`loads`는 문자열을 다룹니다. `ensure_ascii=False`는 한글을 읽기 쉽게 저장합니다.
CSV는 행과 열로 된 표 형식입니다. `DictWriter`·`DictReader`는 열 이름을 딕셔너리 키처럼 다룹니다. 자료형 정보가 없어 점수 `90`도 문자열 `"90"`으로 읽으므로 `int()`로 변환하고 범위를 확인합니다.
CSV는 `newline=""`으로 열어 모듈이 줄바꿈을 처리하게 합니다. 생략하면 빈 줄이나 따옴표 안 줄바꿈 문제가 생길 수 있습니다.
[따라하기]
다음을 file_demo.py로 저장합니다. 표준 라이브러리만 사용합니다.
```python
from pathlib import Path
import csv
import json
records = [
{"name": "민수", "score": 90},
{"name": "지수", "score": 85},
]
data_dir = Path("data")
data_dir.mkdir(exist_ok=True)
json_path = data_dir / "students.json"
csv_path = data_dir / "students.csv"
json_path.write_text(
json.dumps(records, ensure_ascii=False, indent=2),
encoding="utf-8",
)
with csv_path.open("w", encoding="utf-8", newline="") as file:
writer = csv.DictWriter(file, fieldnames=["name", "score"])
writer.writeheader()
writer.writerows(records)
loaded_json = json.loads(json_path.read_text(encoding="utf-8"))
with csv_path.open("r", encoding="utf-8", newline="") as file:
loaded_csv = list(csv.DictReader(file))
print("JSON score type:", type(loaded_json[0]["score"]).__name__)
print("CSV score type:", type(loaded_csv[0]["score"]).__name__)
print("rows:", len(loaded_csv))
```
macOS·Linux는 `python3 file_demo.py`, Windows는 `py file_demo.py`로 실행합니다. 모두 `data` 폴더에 JSON·CSV가 생기며 예상 출력은 같습니다.
```text
JSON score type: int
CSV score type: str
rows: 2
```
JSON은 숫자, CSV는 문자열로 읽혔습니다.
[흔한 실수]
- 기본 인코딩에 기대어 글자가 깨집니다.
- CSV를 `newline=""` 없이 열어 줄바꿈 문제가 생깁니다.
- CSV 숫자를 변환하지 않고 문자열로 더합니다.
- `w` 모드의 덮어쓰기를 잊습니다.
- 파일을 닫지 않아 기록이 누락되거나 자원이 남습니다.
[보안 주의]
외부 입력을 파일명에 바로 붙이지 말고 저장 위치를 전용 폴더로 고정하세요. 읽기 전 크기·행 수를 제한하고 필수 키, 자료형, 길이, 숫자 범위를 검증합니다. 신뢰하지 않는 JSON은 CPU·메모리를 많이 쓸 수 있으므로 크기를 제한하세요. 신뢰할 수 없는 pickle은 절대 역직렬화하지 말고, 출력 파일 권한도 최소화합니다.
[직접 해볼 과제]
1. 각 레코드에 불리언 `active`를 추가하고 두 파일에 저장한 뒤, JSON과 CSV에서 다시 읽은 자료형을 비교하세요.
2. CSV 점수를 `int()`로 변환해 평균을 출력하되 0~100 범위를 벗어나면 오류로 처리하세요.
[확인문제]
1. 텍스트 파일에 UTF-8 인코딩을 명시하는 이유는 무엇인가요?
2. CSV 파일을 읽은 점수가 문자열이 되는 이유는 무엇인가요?
3. 신뢰하지 않는 JSON을 읽기 전에 제한하고 검증해야 할 것은 무엇인가요?
[다음 학습]
PY-007에서는 파일 오류를 포함한 예외를 처리하고 로그로 원인을 남깁니다.
[공식 참고 자료]
- Python 파일 입출력 튜토리얼: https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files
- pathlib 공식 문서: https://docs.python.org/3/library/pathlib.html
- json 공식 문서: https://docs.python.org/3/library/json.html
- csv 공식 문서: https://docs.python.org/3/library/csv.html
- pickle 보안 경고: https://docs.python.org/3/library/pickle.html
Python으로 같은 데이터를 JSON·CSV로 저장하고 다시 읽으며 인코딩, 자료형, 줄바꿈 차이를 확인합니다.
[선수지식]
CORE-005의 경로와 PY-003·004의 자료구조·모듈을 알면 됩니다.
[학습목표]
1. Path와 with를 사용해 운영체제에 맞게 파일을 다룬다.
2. JSON과 CSV를 읽고 쓰는 방법과 자료형 차이를 설명한다.
3. 외부 파일의 경로·크기·내용을 방어적으로 검증한다.
[핵심개념]
파일 모드는 읽기 `r`, 덮어쓰기 `w`, 이어쓰기 `a` 등이 있고 `w`는 기존 내용을 지웁니다. 텍스트 인코딩 기본값은 환경마다 달라 `encoding="utf-8"`을 명시합니다. `with` 블록은 예외가 생겨도 파일을 닫습니다.
`pathlib.Path`는 운영체제별 경로 차이를 줄입니다. `/` 연산자로 하위 경로를 만들고 `mkdir(exist_ok=True)`로 폴더를 준비합니다.
JSON은 계층 구조와 자료형을 표현하는 텍스트 형식입니다. `json.dump`·`load`는 파일 객체를, `dumps`·`loads`는 문자열을 다룹니다. `ensure_ascii=False`는 한글을 읽기 쉽게 저장합니다.
CSV는 행과 열로 된 표 형식입니다. `DictWriter`·`DictReader`는 열 이름을 딕셔너리 키처럼 다룹니다. 자료형 정보가 없어 점수 `90`도 문자열 `"90"`으로 읽으므로 `int()`로 변환하고 범위를 확인합니다.
CSV는 `newline=""`으로 열어 모듈이 줄바꿈을 처리하게 합니다. 생략하면 빈 줄이나 따옴표 안 줄바꿈 문제가 생길 수 있습니다.
[따라하기]
다음을 file_demo.py로 저장합니다. 표준 라이브러리만 사용합니다.
```python
from pathlib import Path
import csv
import json
records = [
{"name": "민수", "score": 90},
{"name": "지수", "score": 85},
]
data_dir = Path("data")
data_dir.mkdir(exist_ok=True)
json_path = data_dir / "students.json"
csv_path = data_dir / "students.csv"
json_path.write_text(
json.dumps(records, ensure_ascii=False, indent=2),
encoding="utf-8",
)
with csv_path.open("w", encoding="utf-8", newline="") as file:
writer = csv.DictWriter(file, fieldnames=["name", "score"])
writer.writeheader()
writer.writerows(records)
loaded_json = json.loads(json_path.read_text(encoding="utf-8"))
with csv_path.open("r", encoding="utf-8", newline="") as file:
loaded_csv = list(csv.DictReader(file))
print("JSON score type:", type(loaded_json[0]["score"]).__name__)
print("CSV score type:", type(loaded_csv[0]["score"]).__name__)
print("rows:", len(loaded_csv))
```
macOS·Linux는 `python3 file_demo.py`, Windows는 `py file_demo.py`로 실행합니다. 모두 `data` 폴더에 JSON·CSV가 생기며 예상 출력은 같습니다.
```text
JSON score type: int
CSV score type: str
rows: 2
```
JSON은 숫자, CSV는 문자열로 읽혔습니다.
[흔한 실수]
- 기본 인코딩에 기대어 글자가 깨집니다.
- CSV를 `newline=""` 없이 열어 줄바꿈 문제가 생깁니다.
- CSV 숫자를 변환하지 않고 문자열로 더합니다.
- `w` 모드의 덮어쓰기를 잊습니다.
- 파일을 닫지 않아 기록이 누락되거나 자원이 남습니다.
[보안 주의]
외부 입력을 파일명에 바로 붙이지 말고 저장 위치를 전용 폴더로 고정하세요. 읽기 전 크기·행 수를 제한하고 필수 키, 자료형, 길이, 숫자 범위를 검증합니다. 신뢰하지 않는 JSON은 CPU·메모리를 많이 쓸 수 있으므로 크기를 제한하세요. 신뢰할 수 없는 pickle은 절대 역직렬화하지 말고, 출력 파일 권한도 최소화합니다.
[직접 해볼 과제]
1. 각 레코드에 불리언 `active`를 추가하고 두 파일에 저장한 뒤, JSON과 CSV에서 다시 읽은 자료형을 비교하세요.
2. CSV 점수를 `int()`로 변환해 평균을 출력하되 0~100 범위를 벗어나면 오류로 처리하세요.
[확인문제]
1. 텍스트 파일에 UTF-8 인코딩을 명시하는 이유는 무엇인가요?
2. CSV 파일을 읽은 점수가 문자열이 되는 이유는 무엇인가요?
3. 신뢰하지 않는 JSON을 읽기 전에 제한하고 검증해야 할 것은 무엇인가요?
[다음 학습]
PY-007에서는 파일 오류를 포함한 예외를 처리하고 로그로 원인을 남깁니다.
[공식 참고 자료]
- Python 파일 입출력 튜토리얼: https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files
- pathlib 공식 문서: https://docs.python.org/3/library/pathlib.html
- json 공식 문서: https://docs.python.org/3/library/json.html
- csv 공식 문서: https://docs.python.org/3/library/csv.html
- pickle 보안 경고: https://docs.python.org/3/library/pickle.html
- 이전글[JSTS-006][기초] npm·모듈·패키지 한 번에 이해하기 26.09.01
- 다음글[TOOL-006][기초] 원격 저장소와 Pull Request로 협업하기 26.09.01
댓글목록
등록된 댓글이 없습니다.
