내일배움캠프 32일차 TIL - 직렬화 기초

권태하·2024년 5월 30일
post-thumbnail

직렬화와 역직렬화

직렬화(Serialization)는 데이터 구조나 오브젝트 상태를 저장하거나 전송할 수 있는 형식으로 변환하는 과정을 말한다. 이 변환된 형식은 파일에 저장하거나 네트워크를 통해 전송할 수 있다. 직렬화의 주요 목적은 데이터 구조를 쉽게 공유하고 사용할 수 있도록 하는 것이다.

역직렬화(Deserialization)는 직렬화의 반대 과정으로, 직렬화된 데이터를 원래의 데이터 구조나 오브젝트 상태로 복원하는 것을 말한다.

직렬화와 역직렬화는 데이터를 저장하고 전송하는 데 매우 중요한 역할을 한다. 이를 통해 다양한 시스템과 언어 간에 데이터를 쉽게 공유할 수 있다.

어딘가에 정보를 올려놨다가 (직렬화)
그걸 다시 그대로 가져올 수 있다 (역직렬화)

PlayerPrefs

유니티에서 실습하며 많이 사용했던 PlayerPrefs도 직렬화하는 방식이다.
String형식으로 저장하고 Split을 통해 역직렬화 할 수 있지만 보안에 취약하다.

직렬화
  
- Player Data
    1. Nickname
    2. Lv
    3. Hp
    
    ⇒ string PlayerData = Nickname + ‘,’ + Lv + ‘,’ + Hp
    
- PositionData
    1. Vector3을 x,y,z값으로 변환하여 문자열로 만들고 저장
    
역질렬화

- String.Split(',') 이용

CSV (comma separated values)

엑셀을 통해 자료를 불러오기 때문에 아이템 데이터 베이스를 이용한다거나 기획자랑 협업할 때 편리하게 이용할 수 있다.

PlayerPrefs와 같이 Split을 이용하되, 행간 구분을 위해 '\n'을 이용해 두 번 역직렬화를 해야한다.

역직렬화
TextAsset csvData = Resources.Load<TextAsset>(”CSVData”);

TrimEnd()를 통해 끝쪽 빈 공백을 날릴 수 있음.

XML

정보의 구조를 쉽게 알아볼 수 있지만 작성이 까다롭다. 정해진 포맷이 정확하게 일치해야함

using System.Xml;
using UnityEngine;

public class XMLTest : MonoBehaviour
{
    Player player;
    void CreateXML()
    {
        XmlDocument xmlDoc = new XmlDocument();
        // 헤더 (없어도 됨)
        xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "yes"));

        //---------- 구조 ----------//
        // 루트 노드
        XmlNode root = xmlDoc.CreateNode(XmlNodeType.Element, "GameData", string.Empty);
        xmlDoc.AppendChild(root);

        // 자식 노드
        XmlNode child = xmlDoc.CreateNode(XmlNodeType.Element, "PlayerData", string.Empty);
        xmlDoc.AppendChild(child);
        //--------------------------//

        //---------- 내용 -----------//
        XmlElement nickname = xmlDoc.CreateElement("nickname");
        nickname.InnerText = player.name;
        child.AppendChild(nickname);

        // 데이터 추가 가능
        //--------------------------//

        // 저장
        xmlDoc.Save("./Assets/Resources/GameDatas.xml");

        // 불러오기
        void LoadXML()
        {
            // 저장됐던 데이터를 그대로 가져온다.
            var t = Resources.Load<TextAsset>("GameDatas");

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(t.text);

            // 미리 구조화된 Xml에서 원하는 부분을 정해 가져올 수 있다.
            XmlNodeList nodes = xmlDoc.SelectNodes("GameData/PlayerData");

            XmlNode playerData = nodes[0];
            player.name = playerData.SelectSingleNode("nickName").InnerText;
        }
    }
}

JSON

가장 편리하고 가장 많이 쓰인다. 여러가지 방법이 있는데 대표적 방법 3가지

Newonsoft
LitJson
JsonUtility

유니티에서는 JsonUtility가 특화되어 있기 때문에 정말 특별한 경우가 아니라면 현업에서도 JsonUtility를 사용한다고 한다.

using System.Collections.Generic;
using UnityEngine;

public class Character : MonoBehaviour
{
    public UserData data;
    private void Start()
    {
        // 직렬화 끝
        var t = JsonUtility.ToJson(data);
    }
}

// 유니티 에디터에서 직렬화하기위해서
[System.Serializable]
public class UserData
{
    public string nickName;
    public int lv;
    public float hp;

    // Serializable된 데이터들을 확장하기 용이하다.
    public List<string> friends = new List<string>();
    public List<Inventory> inventories = new List<Inventory>();
    // 추가 정보들
}

[System.Serializable]
public class Inventory
{
    public int size;
    public List<int> itemIds = new List<int>();
}

저장과 불러오기가 굉장히 간단하다.

JSON은 특히나 서버와의 통신을 위해 많이 쓰이게 된다고 한다.

서버 통신 없이 로컬에 저장되는 JSON은 쉽게 접근이 가능하므로, 플레이어의 정보등을 담아둬선 안되며, 서버를 쓸 수 없는 상황이라면 꼭 암호화를 거쳐서 저장하는것이 좋다.

Scriptable Object

SO는 JSON으로 직렬화가 불가능한 유니티의 거의 모든 것들을 직렬화 할 수 있다.

다만, SO로 저장된 데이터는 프로그램에선 데이터가 변동되어도 잘 작동하지만 Build했을 때는 데이터가
처음에 셋팅한 값으로 고정되어 프로그램을 껐다 키면 원래대로 돌아간다고 한다.

따라서 몬스터의 초기값등 고정된 값에만 쓰고, 플레이어의 상태등 변동하는 데이터는 SO를 이용해선 안된다.

profile
스터디 로그

0개의 댓글