직렬화(Serialization)
오브젝트나 연결된 오브젝트 묶음(오브젝트 그래프)을 바이트 스트림으로 변환하는 과정
복잡한 데이터를 일렬로 세우기 때문에 직렬화라 부름
현재 프로그램 상태를 저장하고 복원할 수 있음 (게임 저장)
현재 객체의 정보를 클립보드에 복사해서 다른 프로그램으로 전송가능
네트워크를 통해 현재 프로그램의 상태를 다른 프로그램에 복원 (멀티플레이 게임)
데이터 압축, 암호화를 통해 데이터를 효율적이고 안전하게 보관
구현시 고려할 점
데이터 레이아웃 : 오브젝트가 소유한 다양한 데이터를 어떤 식으로 일렬로 세울 것인가
이식성 : 서로 다른 시스템에서 전송이 가능한가
버전 관리
새로운 기능이 추가될 때 이를 어떻게 확장하고 처리할 것인가
새로운 기능이 추가될 때 데이터 레이아웃이 변경됨
성능 : 네트워크 비용을 줄이기 위해 어떤 데이터 형식을 사용할 것인가
보안 : 데이터를 어떻게 보호할 것인가
에러 처리 : 전송 과정에서 문제가 발생할 경우 어떻게 인식하고 처리할 것인가
Deserialization : 바이트 스트림에서 오브젝트 그래프로 변환
언리얼 직렬화 시스템
FArchive 클래스 사용, shift(<<) operator 지원해야 함
메모리 아카이브(FMemoryReader, FMemoryWriter)
파일 아카이브(FArchiveFileReaderGeneric, FArchiveFileWriterGeneric)
기타 언리얼 오브젝트와 관련된 아카이브(FArchiveUObject)
Json(JavaScript Object Notation) 직렬화 기능
Json 직렬화 기능
웹 통신의 표준으로, 웹 환경에서 서버와 클라이언트 사이에 데이터를 주고받을 때 사용하는 텍스트 기반 데이터 포맷
텍스트임에도 데이터 크기가 가벼움
읽기 편해서 데이터를 보고 이해할 수 있음
지원하는 타입이 별로 안되므로(문자, 숫자, 불리언, 널, 배열, 오브젝트만 가능) 숫자의 타입을 구분하기 힘듦
텍스트 형식으로만 사용 가능하므로 네트워크 통신에서 효율 추구 불가
언리얼 엔진의 Json, JsonUtilities 라이브러리 활용
데이터 유형
오브젝트 : 오브젝트 내 데이터 키, 밸류 조합으로 구성됨 { "key" : 10 }
배열 : 배열 내 데이터는 밸류로만 구성됨 [ "value1", "value2", "value3" ]
기타 데이터 : 문자열("string"), 숫자(10), 불리언(true/false), 널(null)
JsonObjectConverter.h include해야 함
프로젝트.build.cs 파일에 Json 관련 라이브러리(모듈)를 연동해야 함
// Json, JsonUtilties를 추가해야 함
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Json", "JsonUtilties" });
// 프로젝트 경로 가져오기 및 경로 설정
const FString SavedDir = FPaths::Combine(FPlatformMisc::ProjectDir(), TEXT("Saved"));
// 프로젝트 상위 폴더들이 /../로 표시되므로 이를 정확히 표시하는 함수
FPaths::MakeStandardFilename(RawDataAbsolutePath);
// WriterArchive 생성
FArchive* RawFileWriterAr = IFileManager::Get().CreateFileWriter(*RawDataAbsolutePath);
// ReaderArchive 생성
FArchive* RawFileReaderAr = IFileManager::Get().CreateFileReader(*RawDataAbsolutePath);
// 일반 C++ 데이터 Serialize
// 일일이 멤버를 넣으면 번거로우므로 operator<< 함수 구현
// 프로퍼티의 순번만 지정해주면 됨
friend FArchive& operator<< (FArchive& Ar, FStudnetData& InStudnetData)
{
Ar << InStudnetData.Order;
Ar << InStudnetData.Name;
return Ar;
}
// 파일 읽을 때도 동일한 연산 사용
*RawFileReaderAr << RawDataDest;
// 파일을 읽거나 쓰는 것을 모두 완료했다면 닫아야함
FileWriteAr->Close();
// 언리얼 오브젝트 Serialize
//읽기
TArray<uint8> BufferArray; // 직렬화를 위한 버퍼
FMemoryWriter MemoryWriterAr(BufferArray);
StudentSrc->Serialize(MemoryWriterAr);
//쓰기
FMemoryReader MemoryReaderAr(BufferArrayFromFile);
TObjectPtr<UStudent> StudentDest(NewObject<UStudent>());
StudentDest->Serialize(MemoryReaderAr);
//Json 변환
TSharedRef<FJsonObject> JsonObjectSrc = MakeShared<FJsonObject>();
FJsonObjectConverter::UStructToJsonObject(StudentSrc->GetClass(), StudentSrc, JsonObjectSrc);
//Json Serialize
FString JsonOutString;
TSharedRef<TJsonWriter<TCHAR>> JsonWriterAr = TJsonWriterFactory<TCHAR>::Create(&JsonOutString);
if (FJsonSerializer::Serialize(JsonObjectSrc, JsonWriterAr))
{
FFileHelper::SaveStringToFile(JsonOutString, *JsonDataAbsolutePath);
FString JsonInString;
FFileHelper::LoadFileToString(JsonInString, *JsonDataAbsolutePath);
// 문자열이 이상한 값이 들어오면 안 만들어지면 null이기 때문에 포인터로
TSharedRef<TJsonReader<TCHAR>> JsonReaderAr = TJsonReaderFactory<TCHAR>::Create(JsonInString);
//Json Deserialize
TSharedPtr<FJsonObject> JsonObjectDest;
if (FJsonSerializer::Deserialize(JsonReaderAr, JsonObjectDest))
{
TObjectPtr<UStudent> JsonStudentDest(NewObject<UStudent>());
if (FJsonObjectConverter::JsonObjectToUStruct(JsonObjectDest.ToSharedRef(), JsonStudentDest->GetClass(), JsonStudentDest.Get()))
{
PrintStudentInfo(JsonStudentDest.Get(), TEXT("JsonData"));
}
}
}
'언리얼 > 언리얼 C++ 및 개념' 카테고리의 다른 글
언리얼 빌드 시스템 (0) | 2024.07.24 |
---|---|
언리얼 오브젝트 패키지 (0) | 2024.07.23 |
언리얼 가비지 컬렉션 (0) | 2024.07.18 |
언리얼 컨테이너 라이브러리 - Array, Set, Map, Struct (0) | 2024.07.12 |
언리얼 C++ 델리게이트 (0) | 2024.07.11 |