객체 직렬화는 데이터 구조를 바이트 스트림으로 변환하는 과정이며, 역직렬화는 이를 원래의 데이터 구조로 복원하는 작업입니다.
pickle 모듈의 주요 함수
dumps 메서드 - 메모리 내 직렬화
pickle.dumps() 함수는 객체를 바이트 형태로 변환하여 반환합니다.
import pickle
user_info = {"username": "manager", "access_code": 456}
byte_stream = pickle.dumps(user_info)
print(byte_stream)
출력 결과:
b'\x80\x04\x95#\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x08username\x94\x8c\x07manager\x94\x8c\x0baccess_code\x94K\xc8u.'
loads 메서드 - 메모리 내 역직렬화
pickle.loads() 함수는 바이트 데이터를 원본 객체로 복원합니다.
restored_data = pickle.loads(byte_stream)
print(restored_data, type(restored_data))
출력 결과:
{'username': 'manager', 'access_code': 456} <class 'dict'>
dump 메서드 - 파일에 직접 저장
pickle.dump() 함수는 직렬화된 데이터를 파일에 직접 기록합니다.
profile = {'employee': 'Alice', 'years': 25, 'location': 'Seoul'}
with open('profile.dat', 'wb') as output_file:
pickle.dump(profile, output_file)
load 메서드 - 파일에서 복원
pickle.load() 함수는 파일에서 직렬화된 데이터를 읽어 객체로 변환합니다.
with open('profile.dat', 'rb') as input_file:
retrieved_profile = pickle.load(input_file)
print(retrieved_profile)
잘못된 접근 방식
다음과 같이 딕셔너리를 직접 문자열로 저장하려는 시도는 오류를 발생시킵니다:
data = {"id": "user001", "level": 5}
file_handle = open("record.txt", "w", encoding="utf-8")
file_handle.write(data) # TypeError 발생
문자열로 변환하여 저장할 수는 있지만, 다시 읽을 때 문제가 발생합니다:
file_handle.write(str(data)) # 실행은 가능하지만...
read_content = open("record.txt", "r", encoding="utf-8").read()
print(read_content, type(read_content)) # 여전히 문자열 타입
위험한 eval() 함수를 사용하는 방법도 있지만 보안상 문제가 있습니다:
converted_dict = eval(read_content) # 보안 위험!
보다 안전한 대안으로는 ast.literal_eval() 또는 JSON 모듈을 사용하는 것입니다:
import json
with open("record.txt", "w", encoding="utf-8") as f:
json.dump(data, f)
with open("record.txt", "r", encoding="utf-8") as f:
safe_data = json.load(f)
print(safe_data, type(safe_data))
권장되는 파일 저장 방식
가장 효율적이고 안전한 방법은 pickle.dump()와 pickle.load()를 사용하는 것입니다:
config = {"theme": "dark", "notifications": True, "volume": 80}
# 저장
with open("settings.cfg", "wb") as config_file:
pickle.dump(config, config_file)
# 로드
with open("settings.cfg", "rb") as config_file:
loaded_config = pickle.load(config_file)
print(loaded_config, type(loaded_config))
이러한 방식을 통해 데이터의 정확한 복원이 가능하며, 복잡한 데이터 구조도 안전하게 처리할 수 있습니다.