김선영
한세대학교 22학번 컴퓨터공학과
한세대학교 22학번 컴퓨터공학과
게임을 만들다 보면 아이템, 퀘스트, 스킬 등 수많은 데이터를 관리해야 합니다. “아이템 이름은 무엇인지”, “공격력은 얼마인지” 같은 고정 데이터와 “유저가 이 아이템을 가졌는지”, “퀘스트를 깼는지” 같은 변동 데이터를 어떻게 나누고 저장해야 할까요?
오늘은 유니티 개발의 정석이라 불리는 ScriptableObject(SO)와 JSON + AES 암호화 저장 구조를 알아보겠습니다.
가장 먼저 이해해야 할 것은 원본 데이터와 세이브 데이터를 분리하는 것입니다.
많은 입문자가 리스트를 스크립트에 직접 하드코딩하거나 엑셀만 고집하곤 합니다. 하지만 SO를 쓰면 다음과 같은 강력한 장점이 있습니다.
결론부터 말씀드리면 “아니오”입니다. PlayerPrefs는 간단한 설정값 저장용이지, 복잡한 인벤토리나 퀘스트 데이터를 담기엔 부적합합니다.
그래서 우리는 JSON 형식을 사용합니다. JSON은 객체 구조를 문자열로 바꿔주기 때문에 복잡한 리스트도 한 번에 저장할 수 있습니다.
로컬 파일(.json)로 저장하면 유저가 메모장으로 열어 내용을 수정할 위험이 있습니다. 이를 방지하기 위해 AES(Advanced Encryption Standard) 양방향 암호화를 사용합니다.
이렇게 하면 유저가 파일을 열어도 암호화된 외계어만 보이게 되어 데이터 조작을 원천 봉쇄할 수 있습니다.
// 원본 데이터 (ScriptableObject)
public class QuestData : ScriptableObject {
public int QuestID;
public string Title;
public int TargetCount;
}
// 유저 저장 데이터 (일반 Class)
[Serializable]
public class UserQuestState {
public int QuestID;
public int CurrentCount;
public bool IsCompleted;
}
System.Security.Cryptography를 사용하여 데이터를 안전하게 보호합니다.
public static class SaveSystem {
private static readonly string Key = "MySecretKey1234567890123456789012"; // 32바이트
public static void Save(SaveData data) {
string json = JsonUtility.ToJson(data);
string encrypted = Encrypt(json); // AES 암호화 함수
File.WriteAllText(Path.Combine(Application.persistentDataPath, "save.dat"), encrypted);
}
}
ScriptableObject 리스트로 관리하여 메모리를 아끼고 에디터 편의성을 높이세요.persistentDataPath에 저장하는 것이 가장 안전하고 대중적인 방법입니다.