5편에서 함수와 모듈로 코드를 나눴다면, 이제는 그 코드가 다룰 외부 데이터를 안정적으로 주고받아야 합니다. 실제 업무 자동화를 하다 보면 파일을 읽어서 처리하고, 결과를 다른 파일로 저장해야 할 때가 많습니다. Python은 표준 라이브러리만으로도 텍스트 파일, CSV, JSON을 쉽게 다룰 수 있습니다. 이번 글에서는 pathlib와 json 모듈을 활용해 파일 경로를 안전하게 관리하고 데이터를 읽고 쓰는 방법을 살펴봅니다.
이번 글에서 새로 나오는 용어
- pathlib.Path: 문자열 대신 객체로 경로를 다루게 해 주는 표준 라이브러리 도구
- 직렬화: 메모리에 있는 데이터를 파일이나 문자열 형태로 변환해 저장하거나 전송하는 과정
- JSON Lines: JSON 객체 하나를 한 줄에 기록하는 로그 형식으로
.jsonl확장자로 많이 사용
핵심 개념
학습 메모
- 소요 시간: 60분
- 준비물: 함수·모듈 기반 프로젝트, 기본 자료형·조건문 감각
- 학습 목표:
pathlib와json을 이용해 파일에서 데이터를 읽고 쓰는 루틴 만들기
경로 관리는 Path 객체로, 직렬화는 JSON으로 맡기면 자동화 스크립트가 OS에 덜 의존하게 됩니다.
코드로 따라하기
pathlib로 경로 관리
문자열 대신 Path 객체를 사용하면 운영체제마다 다른 경로 구분자를 신경 쓰지 않아도 됩니다.
from pathlib import Path
data_dir = Path("data")
log_file = data_dir / "logs.txt"
print(log_file)
Path.mkdir(exist_ok=True)는 폴더가 없으면 만들고, 이미 있어도 에러를 내지 않습니다.
텍스트 파일 읽고 쓰기
log_file.write_text("배포 완료\n", encoding="utf-8")
content = log_file.read_text(encoding="utf-8")
print(content)
여러 줄을 조금 더 세밀하게 다루고 싶다면 open() 컨텍스트 매니저를 사용합니다.
with log_file.open("a", encoding="utf-8") as fp:
fp.write("모니터링 시작\n")
with log_file.open("r", encoding="utf-8") as fp:
for line in fp:
print(line.strip())
JSON 읽고 쓰기
JSON은 API, 설정 파일, 로그 등 다양한 곳에서 쓰이는 구조입니다.
config = {
"slack_webhook": "https://hooks.slack.com/...",
"channels": ["deploy", "alert"],
}
config_file = data_dir / "config.json"
config_file.write_text(json.dumps(config, ensure_ascii=False, indent=2), encoding="utf-8")
loaded = json.loads(config_file.read_text(encoding="utf-8"))
print(loaded["channels"])
ensure_ascii=False를 설정하면 한글도 깨지지 않고 저장됩니다.
예외 처리 패턴
파일 작업에서는 경로가 없거나 권한 문제가 생길 수 있으므로 예외를 적절히 처리해야 합니다.
try:
report_text = (data_dir / "report.txt").read_text(encoding="utf-8")
except FileNotFoundError:
report_text = "보고서 파일이 아직 생성되지 않았습니다."
print(report_text)
이렇게 하면 파일이 없을 때도 프로그램이 중단되지 않고 안내 메시지를 출력할 수 있습니다.
미니 프로젝트: JSON 기반 TODO 저장소
from pathlib import Path
db_file = Path("data/todos.json")
def load_todos() -> list[dict]:
if not db_file.exists():
return []
return json.loads(db_file.read_text(encoding="utf-8"))
def save_todos(todos: list[dict]) -> None:
db_file.write_text(json.dumps(todos, ensure_ascii=False, indent=2), encoding="utf-8")
def add_todo(title: str):
todos = load_todos()
todos.append({"title": title, "done": False})
save_todos(todos)
add_todo("보고서 초안 작성")
print(load_todos())
이 예제는 파일과 JSON을 함께 다루면서 데이터 저장 흐름을 단단하게 만들 수 있는 기본 틀을 보여 줍니다.
Path와 JSON 함수를 이렇게 연결해 생각하면, 어디서 경로를 만들고 어디서 직렬화를 담당하는지 명확히 보입니다.
실전 예시: JSON Lines로 배포 로그 작성
API 서버 배포 로그를 JSON Lines(.jsonl) 형식으로 남기면 OpenSearch나 ClickHouse로 바로 적재할 수 있습니다.
📄 JSON Lines란? JSON 개체 하나를 한 줄에 기록하는 방식입니다. 대용량 로그를 스트림으로 처리하거나, 로그 수집기가 한 줄씩 읽어야 할 때 가장 단순한 규격입니다.
from datetime import datetime
from pathlib import Path
log_file = Path("data/deploy.jsonl")
def write_entry(level: str, message: str, **context):
entry = {
"timestamp": datetime.utcnow().isoformat(),
"level": level,
"message": message,
**context,
}
with log_file.open("a", encoding="utf-8") as fp:
fp.write(json.dumps(entry, ensure_ascii=False) + "\n")
write_entry("INFO", "배포 완료", service="attendance", version="1.4.2")
이 패턴은 학교 업무 자동화부터 데이터 파이프라인 구축까지 폭넓게 응용할 수 있고, 다음 편에서 다룰 Requests 자동화 예제에서도 바로 API 응답을 기록하는 데 사용합니다.
왜 중요한가
학교 리포트, 동아리 출석부, 간단한 자동화 스크립트 모두 파일을 읽고 쓰는 흐름 위에 올라갑니다. 경로를 안전하게 다루면 실수로 다른 폴더를 지우는 일을 줄일 수 있고, JSON으로 데이터를 저장하면 다른 언어나 도구에서도 쉽게 불러올 수 있습니다.
실습
- 따라 하기:
data폴더를 만들고 TODO JSON 저장소 예제를 그대로 따라 하며 파일이 생성되는지 확인합니다. - 확장하기: JSON Lines 로거를 활용해
level별로 다른 파일에 기록하거나,ensure_ascii값을 바꿔 한글이 깨지는 상황을 실험합니다. - 디버깅: 일부러 없는 경로를 읽어
FileNotFoundError를 만든 뒤Path.mkdir(exist_ok=True)또는 예외 처리로 복구합니다. - 완료 기준: 텍스트·JSON을 모두 읽고 쓰며 경로를 안전하게 관리하는 함수를 작성해 반복 사용 가능할 때입니다.
마무리
파일과 JSON을 자유롭게 읽고 쓸 수 있으면 자동화 스크립트의 활용 범위가 크게 넓어집니다. 다음 글에서는 requests로 외부 API를 호출하고, 파일 입출력과 결합해 간단한 자동화를 만드는 방법을 다뤄보겠습니다.
💬 댓글
이 글에 대한 의견을 남겨주세요