Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Python
Code

파이썬 객체의 직렬화와 역직렬화: 1부

by
Difficulty:IntermediateLength:MediumLanguages:

Korean (한국어) translation by Dae-yeop Lee (you can also view the original English article)

파이썬 객체 직렬화와 역직렬화는 평범한 프로그램의 한 가지 중요한 측면입니다. 파이썬에서 뭔가를 파일에 저장하는 경우나 설정 파일을 읽거나 HTTP 요청에 응답할 경우 객체 직렬화 및 역직렬화를 수행하게 됩니다.

어떤 의미에서 직렬화 및 역직렬화는 세상에서 가장 지루한 작업입니다. 모든 형식과 프로토콜에 누가 신경 쓰겠습니까? 단지 여러분은 파이썬 객체를 저장하거나 스트리밍하고 나중에 다시 가져오고 싶을 것입니다.

이것은 개념적인 차원에서 세상을 바라보는 매우 건강한 방법입니다. 그러나 실용적인 수준에서는 어떤 직렬화 체계나 형식, 또는 프로토콜을 선택하느냐에 따라 프로그램이 얼마나 빠르게 동작하는지, 얼마나 안전한지, 상태 관리가 얼마나 자유로운지, 그리고 다른 시스템과 얼마나 잘 상호작용하는지 결정됩니다.

이러한 여러 옵션이 있는 이유는 상황마다 솔루션도 다르기 때문입니다. 즉, 모든 문제를 해결하는 단 하나의 해답은 없습니다. 1, 2부로 나눠진 이번 튜토리얼에서는 가장 성공적인 직렬화 및 역직렬화 체계의 장단점을 살펴보고 이를 사용하는 방법을 보여주고 특정 사용 사례에 직면했을 때 특정 체계를 선택하기 위한 지침을 제공합니다.

예제 실행하기

이어지는 절에서는 다양한 직렬화기를 사용해 동일한 파이썬 객체 그래프를 직렬화 및 역직렬화하겠습니다. 내용 반복을 피하기 위해 먼저 객체 그래프를 정의하겠습니다.

간단한 객체 그래프

여기서 다룰 간단한 객체 그래프는 정수, 문자열, 부동 소수점 수, 부울 및 None의 리스트를 담은 딕셔너리입니다.

복잡한 객체 그래프

복잡한 객체 그래프도 딕셔너리지만 datetime 개체를 비롯해 간단한 객체 그래프로 설정된 self.simple 속성을 가진 사용자 정의 클래스 인스턴스를 담고 있습니다.

피클

피클은 주요 요소입니다. 피클은 네이티브 파이썬 객체 직렬화 형식입니다. pickle 인터페이스는 dump, dumps, load, loads라는 4가지 메서드를 제공합니다. dump() 메서드는 열린 파일(파일과 유사한 객체)로 직렬화합니다. dumps() 메서드는 문자열로 직렬화합니다. load() 메서드는 열려 있는 파일과 유사한 객체로부터 역직렬화합니다. loads() 메서드는 문자열로부터 역직렬화합니다.

피클은 기본적으로 텍스트 프로토콜을 지원하지만 바이너리 프로토콜도 지원합니다. 바이너리 프로토콜은 더 효율적이지만 사람이 읽을 수 없는 형식입니다(반면 디버깅할 때는 유용함).

다음은 두 프로토콜을 사용해 파이썬 객체 그래프를 문자열과 파일로 피클하는 방법입니다.

바이너리 표현은 내용이 더 많아 보일 수 있지만 이는 표현 방식 탓에 그렇게 보일 뿐입니다. 파일로 덤프할 경우 텍스트 프로토콜은 130바이트인 반면 바이너리 프로토콜은 85바이트에 불과합니다.

문자열을 언피클하는 것은 다음과 같이 간단합니다.

참고로 피클은 프로토콜을 자동으로 알아낼 수 있습니다. 바이너리 프로토콜의 경우에도 프로토콜을 지정할 필요가 없습니다.

파일로부터 언피클하는 것도 마찬가지로 쉽습니다. 열린 파일만 제공하면 됩니다.

문서에 따르면 'rb' 모드를 사용해서 바이너리 피클을 열어야 하지만 보다시피 그렇게 하든, 그렇게 하지 않든 예제가 동작하는 것을 확인할 수 있습니다.

이번에는 피클이 복잡한 객체 그래프를 어떻게 다루는지 살펴봅시다.

바이너리 프로토콜의 효율성은 복잡한 객체 그래프에서 훨씬 더 두드러집니다.

JSON

JSON(JavaScript Object Notation)은 파이썬 2.5부터 파이썬 표준 라이브러리에 포함됐습니다. 여기서는 JSON을 네이티브 형식으로 간주할 것입니다. JSON은 텍스트 기반 형식이며, 객체 직렬화 부문에서는 웹의 비공식적인 최고의 기술입니다. JSON의 타입 체계는 태생적으로 자바스크립트를 따르기 때문에 매우 제한적입니다.

간단하고 복잡한 객체 그래프를 직렬화 및 역직렬화하면서 어떤 일이 발생하는지 봅시다. 인터페이스는 피클 인터페이스와 거의 동일합니다. dump(), dumps(), load(), loads() 함수를 사용할 수 있습니다. 그러나 선택할 프로토콜이 없고 직렬화/역직렬화 과정을 제어하기 위한 선택적 인수가 많습니다. 특별한 인자 없이 간단한 객체 그래프를 덤프해 보면서 간단하게 시작해 봅시다.

출력 결과는 꽤 읽기 쉽지만 들여쓰기가 돼 있지 않습니다. 규모가 큰 객체 그래프의 경우 이것은 문제가 될 수 있습니다. 이번에는 출력 결과를 들여쓰기해 봅시다.

훨씬 더 보기 좋습니다. 이제 복잡한 객체 그래프로 넘어갑시다.

이런! 전혀 좋아 보이지 않습니다. 무슨 일이 일어난 걸까요? 오류 메시지에는 A 객체가 JSON으로 직렬화할 수 없다고 나와 있습니다. JSON은 매우 제한된 타입 체계를 가지고 있으며, 사용자 정의 클래스를 자동으로 직렬화할 수 없다는 것을 기억하십시오. 이 문제를 해결하는 방법은 JSON 모듈에서 사용하는 JSONEncoder 클래스의 하위 클래스를 만들고 JSON 인코더가 직렬화할 수 없는 객체에 대해 실행될 때마다 호출되는 default()를 구현하는 것입니다.

사용자 정의 인코더가 하는 일은 그러한 객체를 JSON 인코더가 인코딩할 수 있는 파이썬 객체 그래프로 변환하는 것입니다. 이 경우 특별한 인코딩이 필요한 두 개의 객체로 datetime 객체와 A 클래스가 있습니다. 다음 인코더가 바로 그러한 작업을 수행합니다. 각 특수 객체는 dict로 변환됩니다. 여기서 키는 이중 밑줄(dunders; double underscores)로 둘러싸인 타입의 이름입니다. 이것은 디코딩하는 데 중요할 것입니다.

이제 직접 정의한 인코더로 다시 시도해 보겠습니다.

멋집니다. 복잡한 객체 그래프가 제대로 직렬화됐고, 구성 요소의 원래 타입 정보가 "__A__"와 "__datetime__"라는 키를 통해 유지됐습니다. 만약 여러분의 이름에 이중 밑줄을 사용한다면 특별한 타입임을 나타내기 위해 다른 관례를 생각해내야 할 것입니다.

복잡한 객체 그래프를 디코딩해봅시다.

흠, 역직렬화가 작동했는데(오류 없음), 앞서 직렬화했던 원래의 복잡한 객체 그래프와 다릅니다. 뭔가가 잘못됐습니다. 역직렬화된 객체 그래프를 살펴봅시다. 여기서는 출력 결과를 깔끔하게 만들기 위해 pprint 모듈의 pprint 함수를 사용하겠습니다.

좋습니다. 문제는 json 모듈이 A 클래스나 심지어 표준 datetime 객체에 대해 아무것도 모른다는 것입니다. 기본적으로 json 모듈은 모든 것을 파이썬의 타입 체계와 일치하는 파이썬 객체로 역직렬화합니다. 풍부한 파이썬 객체 그래프로 되돌아가려면 사용자 정의 디코딩이 필요합니다.

사용자 정의 디코더 하위 클래스는 필요 없습니다. load()loads() 함수는 딕셔너리를 객체로 변환하는 사용자 정의 함수를 제공할 수 있게 해주는 "object_hook" 매개변수를 제공합니다.

decode_object() 함수를 loads() object_hook 매개변수의 매개변수로 사용해서 디코딩을 시도해 봅시다.

결론

이 튜토리얼의 1부에서는 파이썬 객체의 직렬화 및 역직렬화의 일반적인 개념을 배우고 피클과 JSON을 사용해 파이썬 객체를 직렬화하는 것에 대해 알아봤습니다.

2부에서는 YAML과 성능 및 보안 관심사에 대해 배우고 추가적인 직렬화 체계에 대해 간략하게 검토하겠습니다.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.