< 직렬화(Serialization) >
- 프로그램은 메모리에 올라가게 됨. 그러니 프로그램 내의 객체들도 메모리에 올라가 있을 것임. 그런데 그 객체들이 메모리에 어떤 형태로 올라가 있는지는 알 수 없음. 컴퓨터가 메모리를 관리하면서 배정하므로, 하나의 객체라도 연속적으로 모여있다고 단정지을 수 없다. 운 좋게 한 곳에 모두 모여 있는 경우도 있을테지만, 반대로 여기저기 심하게 파편화되어 있을 수도 있음
- 이 객체의 데이터를 전송/저장하기 위해서는, 우선 메모리의 어디에 어떻게 위치할지 모를 객체의 데이터들을 모아야 할 것이다. 이것이 직렬화임
- 데이터를 모으고 전송하기 위해 패키징하는 작업을 의미
- 현재 객체의 상태를 온전히 동일한 형태로 전송/저장하기 위한 프로세스다
- 현재 오브젝트의 상태를 보관하고, 이를 다른 컴퓨터 환경에서 불러와 동일한 상황으로 만들어주는 기법
- ex) 한 오브젝트를 다른 공간으로 완벽하게 옮기기 위해 분해한 후, 분해한 데이터를 전송하여 다른 공간에서 다시 완벽하게 복원해주는 것
- ex) 한 오브젝트를 다른 공간으로 완벽하게 옮기기 위해 분해한 후, 분해한 데이터를 전송하여 다른 공간에서 다시 완벽하게 복원해주는 것
- 직렬화의 개념이 성립하기 위해서는, 단일 데이터를 주고받는 것이 아니라, 텔레포터처럼 아예 객체를 안전하게 보내고 받을 수 있어야 함
- 그래서 C++에서는 연산자 오버로딩과 friend 키워드를 사용하여 객체 데이터를 주고 받는 방법을 많이 사용함
- 오브젝트나 연결된 오브젝트 묶음(오브젝트 그래프)을 바이트 스트림으로 변환(바이트화)하여 메모리/데이터베이스/파일 등에 저장하거나 전송하는 프로세스
- 복잡한 데이터를 일렬로 세우기 때문에 직렬화라고 함
- 묶어둔 직렬화된 데이터를 거꾸로 복구시키는(패키지를 푸는) 과정 또한 이에 포함된다
- Serialization(직렬화) : 오브젝트 그래프 → 바이트 스트림
- Deserialization(역 직렬화) : 바이트 스트림 → 오브젝트 그래프
- C++은 객체를 옮겨주는 직렬화 기능을 지원하지 않음
- 장점
- 현재 프로그램의 상태를 저장하고, 필요한 때 복원 가능 (ex. 게임 저장)
- 현재 객체의 정보를 클립보드에 복사해서, 다른 프로그램에 전송 가능
- 네트워크를 통해 현재 프로그램의 상태를 다른 컴퓨터에 복원 가능 (ex. 멀티플레이어 게임)
- 데이터 압축/암호화를 통해, 데이터를 효율적이고 안전하게 보관 가능
- 직렬화 구현 시, 고려할 점들
- 데이터 레이아웃 : 오브젝트가 소유한 다양한 데이터를 변환할 것인가?
- 이식성 : 서로 다른 시스템에 전송해도 이식 가능?
- 버전 관리 : 새로운 기능이 추가될 때, 이를 어떻게 확장하고 처리할 것인가?
- 성능 : 네트워크 비용을 줄이기 위해 어떤 데이터 형식을 사용할 것인가?
- 보안 : 데이터를 어떻게 안전하게 보호할 것인가?
- 에러 처리 : 전송 과정에서 문제가 발생할 경우, 이를 어떻게 인식하고 처리할 것인가?
< 언리얼 엔진의 직렬화 시스템 >
- 언리얼 오브젝트 객체를 지정된 포맷에 맞게 저장하거나 불러들이는 것을 일괄적으로 진행
- 저장되는 정보들은 UPROPERTY로 명시해줘야 이것들만 언리얼 오브젝트에서 빼내서 디스크에 저장하고 불러들일 수 있게 됨.
- 저장되는 정보들은 UPROPERTY로 명시해줘야 이것들만 언리얼 오브젝트에서 빼내서 디스크에 저장하고 불러들일 수 있게 됨.
- 언리얼 엔진은 위의 직렬화 구현 시 고려할 점들을 모두 고려한 직렬화 시스템을 자체적으로 제공
- 아카이브 클래스 (FArchive) 객체를 통해 입출력 스트림을 제어함
- C++의 stream 클래스와 비슷한 느낌으로 사용
- C++의 stream 클래스와 비슷한 느낌으로 사용
- 입출력 모두에 항상 << (왼쪽 Shift 연산자)만을 사용하여 아카이브 클래스에 데이터를 전송
- C++의 stream은 입력(<<) / 출력(>>) 연산자를 구분해서 사용함
- C++의 stream은 입력(<<) / 출력(>>) 연산자를 구분해서 사용함
- 모든 객체는 FArchive를 통해 스트림화하여 메모리/데이터베이스/파일 등에 사용됨
- 언리얼 엔진에서 파일, 메모리 등, 데이터를 전송하는 모든 매체는 아카이브 클래스 FArchive를 상속받아서 구현함
- 게임이 동작할 플랫폼에 맞도록 디스크나 메모리 및 다양한 매체 등으로 객체를 전송해야 하는데, 언리얼 엔진이 이를 위해 직접 만든 멀티플랫폼에서 동작하는 매체의 규약이 FArchive임
- 아카이브 클래스 (FArchive) 객체를 통해 입출력 스트림을 제어함
- 다양한 아카이브 클래스 제공
- 메모리 아카이브 (FMemoryReader, FMemoryWriter)
- 파일 아카이브 (FArchiveFileReaderGeneric, FArchiveFileWriterGeneric)
- 기타 언리얼 오브젝트와 관련된 아카이브 클래스 (FArchiveUObject)
- Json 직렬화 기능 또한, 별도의 라이브러리를 통해 제공
< Json 직렬화 >
- Json (JavaScript Object Notation) : 웹 환경에서 서버와 클라이언트 사이에 데이터를 주고받을 때 사용하는 텍스트 기반 데이터 포맷
- Json / JsonUtilities 라이브러리를 활용하여 사용 가능
- 장점
- 텍스트임에도 데이터 크기가 가벼움
- 읽기 편해서 데이터를 보고 이해할 수 있음
- 사실 상 웹 통신의 표준으로, 널리 사용됨
- 단점
- 지원하는 타입이 몇 가지 안됨 (문자 / 숫자 / boolean / null / 배열 / 오브젝트만 사용 가능)
- 텍스트 형식으로만 사용 가능
- 데이터 유형
- 오브젝트 : { }
- 오브젝트 내 데이터는 키/밸류 조합으로 구성됨.
ex) { "key" : 10 }
- 오브젝트 내 데이터는 키/밸류 조합으로 구성됨.
- 배열 : [ ]
- 배열 내 데이터는 밸류로만 구성됨.
ex) [ "value1", "value2", "value3" ]
- 배열 내 데이터는 밸류로만 구성됨.
- 이외 데이터
- 문자열("string") , 숫자 (10 or 3.14) , boolean (true or false) , null 로 구성됨
- 오브젝트 : { }
< UObject 직렬화 >
- void Serialize (FArchive& Ar) 인터페이스를 사용하여 구현함
- 입력 / 출력의 연산자가 <<로 동일하므로, Serialize 인터페이스의 구현 내용을 입력용 / 출력용으로 구분하여 구현하지 않고, Serialize() 함수 하나로 입/출력을 모두 처리함
- Serialize 동작이 입력인지 출력인지는 매개변수로 넘어오는 FArchive 객체의 상태에 따름
'Base > Unreal C++' 카테고리의 다른 글
Composition (0) | 2024.07.04 |
---|---|
프로젝트 간, 스크립트 이동 (0) | 2024.07.04 |
향상된 열거형 (0) | 2024.07.03 |
Reflection (0) | 2024.07.03 |
CDO (Class Default Object) (0) | 2024.07.03 |