Humility

아무리 노력해도 최고가 되지 못할 수 있다⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀그럼에도 노력하는자가 가장 겸손한 것 아닌가

공부하는 블로그

유니티

[Unity] 유니티 C#) JSON 직렬화 / 역직렬화

새벽_글쓴이 2025. 1. 23. 23:37
반응형

직렬화(Serialization) 란?

데이터 구조나 객체를 저장하거나 전송할 수 있는 형태로 변환하는 과정

 

역직렬화(Deserialization) 란?

저장된 데이터를 다시 프로그램에서 사용할 수 있는 객체로 변환하는 것

 

예시

// 직렬화 전: 메모리의 객체
PlayerData player = new PlayerData{ name = "철수", level = 5 };

// 직렬화 후: JSON 텍스트
{"name": "철수", "level": 5}

직렬화가 필요한 이유

1. 저장

게임의 세이브 데이터처럼 객체를 파일로 저장할 때

 

2. 네트워크 전송

다른 컴퓨터나 서버와 데이터를 주고 받을 때

 

3. 메모리 구조 변환

복잡한 객체 구조를 단순한 형태로 변환해 처리할 때


Unity JsonUtility의 직렬화 가능한 타입

  • 기본 데이터 타입 (int, float, string, bool)
  • 배열과 리스트
  • 직렬화 가능한 클래스와 구조체
  • Vector2, Vector3 같은 Unity 기본 타입
  • Enum
  • Dictionary (별도 처리 필요)

 

단, 직렬화 하려는 클래스나 구조체에는
[System.Serializable] 속성이 필요함

사용 예시

JSON 직렬화/저장
using UnityEngine;
using System.IO;

// 직렬화할 데이터 클래스
[System.Serializable]
public class PlayerData
{
    public string name;
    public int level;
    public float health;
}

public class JsonSaveExample : MonoBehaviour
{
    void SaveData()
    {
        // 데이터 생성
        PlayerData data = new PlayerData
        {
            name = "Player1",
            level = 10,
            health = 100f
        };

        // JSON으로 직렬화
        string json = JsonUtility.ToJson(data);

        // 파일 저장 경로
        string path = Path.Combine(Application.persistentDataPath, "playerData.json");
        
        // 파일로 저장
        File.WriteAllText(path, json);
    }

    void LoadData()
    {
        string path = Path.Combine(Application.persistentDataPath, "playerData.json");
        
        if (File.Exists(path))
        {
            // 파일에서 JSON 읽기
            string json = File.ReadAllText(path);
            
            // JSON을 객체로 역직렬화
            PlayerData data = JsonUtility.FromJson<PlayerData>(json);
        }
    }
}

 

주요 포인트

1. 직렬화할 클래스에 [System.Serializable] 속성 필수

2. JsonUtility.ToJson()으로 직렬화, FromJson<T>()로 역직렬화

3. Application.persistentDataPath는 플랫폼별 적절한 저장 경로 제공


 Application.persistentDataPath를 사용하면
Unity에서 자동으로 플랫폼에 맞춰 저장 한다

 

플랫폼별 경로

  • Windows: C:/Users/[사용자]/AppData/LocalLow/[회사명]/[제품명]
  • Android: /data/data/[패키지명]/files
  • iOS: /var/mobile/Containers/Data/Application/[앱ID]/Documents
  • macOS: ~/Library/Application Support/[회사명]/[제품명]

 

특징

  • 앱 삭제 시 함께 삭제됨
  • 플랫폼에 관계없이 동일한 코드로 접근 가능
  • 읽기/쓰기 권한 보장
  • 앱 업데이트 후에도 데이터 유지

활용 예시

복잡한 데이터 구조 저장
[System.Serializable]
public class GameData
{
    public List<string> inventory = new List<string>();
    public Vector3 playerPosition;
    public Dictionary<string, int> achievements;  // Dictionary는 별도 처리 필요
}

// Dictionary 직렬화를 위한 래퍼 클래스
[System.Serializable]
public class SerializableDictionary
{
    public string[] keys;
    public int[] values;
}

네트워크 전송 예시 (UnityWebRequest 사용)
IEnumerator SendData(PlayerData data)
{
    string json = JsonUtility.ToJson(data);
    
    using (UnityWebRequest request = UnityWebRequest.Post("http://example.com/api", json))
    {
        yield return request.SendWebRequest();
        
        if (request.result == UnityWebRequest.Result.Success)
        {
            Debug.Log("전송 성공");
        }
    }
}

메모리 구조 변환 (깊은 복사)
public PlayerData DeepCopy(PlayerData original)
{
    string json = JsonUtility.ToJson(original);
    return JsonUtility.FromJson<PlayerData>(json);
}

 

깊은 복사(Deep Copy) 란?

객체의 모든 내용을 완전히 새로운 메모리에 복사하는 것

 

예시

// 얕은 복사 (참조만 복사)
PlayerData player1 = new PlayerData();
PlayerData player2 = player1; // player1과 같은 메모리를 가리킴

// 깊은 복사 (새로운 메모리에 완전히 복사)
PlayerData player1 = new PlayerData();
PlayerData player2 = JsonUtility.FromJson<PlayerData>(
    JsonUtility.ToJson(player1)
); // player1과 완전히 독립된 새 객체 생성

 

특징

  • 원본 객체를 변경해도 복사본에 영향 없음
  • 완전히 독립된 객체가 됨
  • 메모리 사용량은 증가하지만 안전한 데이터 관리 가능

배열/리스트 저장
[System.Serializable]
public class InventoryData
{
    public Item[] items;
    public List<Vector3> positions;
    public Queue<string> messageQueue;  // 직렬화를 위해 List로 변환 필요
}
반응형