개요
데이터를 메모리에만 유지하는 것이 아니라 파일 형태로 영구 저장하는 작업은 소프트웨어 개발의 핵심이다. 파이썬은 단순한 텍스트 파일부터 복잡한 JSON 구조까지 매우 직관적인 인터페이스로 처리할 수 있도록 설계되어 있다. 본 포스팅에서는 기초적인 파일 열기/닫기부터 실무에서 필수적인 'with' 구문의 활용, 그리고 현대적인 경로 관리 방식인 'pathlib'까지 상세히 정리한다.
1. 파일 열기와 닫기: 기초 환경 설정
파일 작업의 시작은 'open()' 함수이며, 작업 완료 후 시스템 자원을 반환하기 위해 'close()'를 호출하는 것이 기본 원칙이다.
파일 열기 주요 모드 정리
| 모드 | 영문 명칭 | 기능 설명 | 비고 |
|---|---|---|---|
| r | Read | 파일 읽기 전용으로 열기 | 파일이 없으면 에러 발생 (기본값) |
| w | Write | 파일 쓰기 전용으로 열기 | 기존 내용 삭제 후 새로 작성 |
| a | Append | 파일 추가 쓰기 모드로 열기 | 기존 내용 뒤에 이어서 작성 |
| b | Binary | 바이너리 모드로 열기 | 이미지, 실행 파일 등 처리 시 사용 |
| t | Text | 텍스트 모드로 열기 | 일반 문자열 데이터 처리 (기본값) |
# 기초적인 쓰기 방식 (명시적 닫기 필요)
f = open('test.txt', 'w', encoding='utf-8')
f.write('Hello Python')
f.close()
2. 파이썬다운 자원 관리: with 구문이란?
'with' 구문은 파이썬의 컨텍스트 매니저(Context Manager) 기능을 활용하여, 자원의 획득과 반환을 자동으로 처리해주는 문법이다. 파일 입출력에서 'close()' 호출을 잊어버려 발생하는 메모리 누수나 파일 잠김 문제를 원천 차단한다.
with 구문의 원형과 예제
기본적인 구조는 다음과 같다.
with open('파일명', '모드') as 변수명:
# 파일을 사용하는 코드 블록
# 블록을 벗어나면 자동으로 close()가 호출된다.
실전 활용 예제:
# 안전한 파일 읽기 예제
with open('data.txt', 'r', encoding='utf-8') as f:
content = f.read()
print(content)
with 구문의 주요 장점
- 안정성 (Reliability): 작업 도중 예외(에러)가 발생하여 프로그램이 비정상 종료되더라도, 파이썬이 내부적으로 파일을 확실하게 닫아준다.
- 간결함 (Simplicity): 'try-finally'와 같은 복잡한 예외 처리 로직 없이도 단 한 줄의 선언으로 안전한 자원 관리가 가능하다.
사용 시 주의점 및 잘못된 예시
'with' 구문 사용 시 가장 흔히 발생하는 실수는 들여쓰기를 벗어난 시점에서 파일 객체에 접근하는 것이다.
# 잘못된 예시: 들여쓰기 및 변수 범위 오류
with open('test.txt', 'r') as f:
data = f.read()
# 에러 발생: f는 이미 닫혔으므로 블록 밖에서 읽을 수 없음
print(f.read())
# 올바른 방식: 데이터 처리는 블록 안에서 하거나, 데이터를 변수에 저장 후 밖에서 활용
with open('test.txt', 'r') as f:
data = f.read()
print(data) # 읽어온 변수 'data'를 사용하는 것은 가능
3. JSON 파일 처리: 데이터 객체 직렬화
파이썬은 표준 라이브러리인 'json' 모듈을 통해 복잡한 구조의 데이터를 파이썬 딕셔너리(dict)와 JSON 파일 사이에서 자유롭게 변환한다.
import json
# 1. JSON 파일 쓰기 (Serialize)
data = {
"user": "python_user",
"settings": {"theme": "dark", "font_size": 14},
"roles": ["admin", "editor"]
}
with open('config.json', 'w', encoding='utf-8') as f:
json.dump(data, f, indent=4)
# 2. JSON 파일 읽기 및 파싱 (Deserialize)
with open('config.json', 'r', encoding='utf-8') as f:
config = json.load(f)
print(config['settings']['theme']) # 별도 파싱 없이 키(Key)로 바로 접근 가능
4. 객체 직렬화와 현대적 경로 관리: 심화 활용
단순 텍스트를 넘어 파이썬 객체를 그대로 저장하는 'pickle'과 객체지향적 경로 관리를 가능케 하는 'pathlib'을 활용해 보자.
pickle을 이용한 객체 저장
import pickle
# 객체를 바이너리 파일로 저장
with open('user.pkl', 'wb') as f:
pickle.dump(data, f)
# 바이너리 파일을 객체로 복구
with open('user.pkl', 'rb') as f:
loaded_data = pickle.load(f)
pathlib을 활용한 경로 관리 (권장 방식)
'pathlib' 모듈은 운영체제(Windows, Linux)에 관계없이 경로를 객체로 다룰 수 있어 문자열 결합보다 훨씬 안전하다.
from pathlib import Path
# Path.cwd(): 현재 작업 디렉터리 경로 객체를 가져온다.
# / 연산자: 문자열이 아닌 경로 객체 간의 결합을 직관적으로 수행한다.
path = Path.cwd() / 'output' / 'result.txt'
# path.parent: 파일의 부모 디렉터리 경로를 가리킨다.
# mkdir(): 디렉터리를 생성한다.
# parents=True: 중간 단계의 폴더가 없으면 함께 생성한다.
# exist_ok=True: 이미 폴더가 있어도 에러를 발생시키지 않는다.
path.parent.mkdir(parents=True, exist_ok=True)
# write_text(): 파일을 열고, 내용을 쓰고, 닫는 과정을 한 번에 처리한다.
path.write_text('Pathlib을 활용한 간결한 쓰기', encoding='utf-8')
5. 대용량 파일 처리와 효율성 유의점
대용량 파일을 처리할 때는 파일 전체를 메모리에 올리는 'read()' 대신 이터레이터를 활용하는 것이 효율적이다.
- 메모리 절약: 파일 객체를 한 줄씩 순회하며 처리하면 기가바이트(GB) 단위의 로그 파일도 안전하게 읽을 수 있다.
- 인코딩 지정: 'utf-8'과 같은 인코딩을 명시하지 않으면 운영체제 설정에 따라 한글이 깨질 수 있으므로 주의해야 한다.
# 대용량 로그 파일 처리 예시
# encoding='utf-8'을 지정하여 한글 깨짐 및 OS별 인코딩 차이 문제를 예방한다.
with open('huge_log.txt', 'r', encoding='utf-8') as f:
for line in f:
if 'ERROR' in line:
print(line.strip())
Conclusion
파이썬의 파일 입출력은 'open'과 'close'의 기초를 넘어 'with' 구문을 통한 자원 관리 자동화에서 진가를 발휘한다. 단순한 텍스트 저장부터 복잡한 JSON과 객체 직렬화까지 마스터한다면 실무에서 마주하는 다양한 데이터 영속성 문제를 해결할 수 있다.
오늘 학습한 'pathlib'의 경로 관리와 'with' 문의 안정성을 습관화하여,
코드의 간결성과 안정성, 그리고 OS 호환성까지 챙기는 숙련된 개발자가 되어보자.
'Dev > Python' 카테고리의 다른 글
| 파이썬 중급 데코레이터 제너레이터 (0) | 2026.01.16 |
|---|---|
| 파이썬 중급: 클래스 정의부터 파이썬다운 객체지향 특징까지 완벽 정리 (0) | 2026.01.15 |
| 파이썬 기초: 표준 라이브러리(Standard Library) 활용하기 (0) | 2026.01.13 |
| 파이썬 기초: 모듈(Module)과 패키지(Package)의 활용 (0) | 2026.01.12 |
| 파이썬 기초: 예외 처리(try-except) 구조 및 주요 내장 예외 활용 (0) | 2026.01.05 |