-
내일배움캠프 15일차 TIL - 팀 프로젝트 마무리TIL/C# 2024. 5. 3. 20:30
[학습목표]
저장/불러오기 기능을 구현하고, 클래스 파일들을 정리하거나 버그를 수정하는 등의 작업을 통해 프로젝트를 마무리한다.
[학습내용]
오늘은 우선 저장 기능을 구현했다. 개인 과제에서 진행했던 부분이라 어렵지 않게 끝낼 수 있을 거 같았다. 그런데 막상 해보니 계속 에러가 발생했다. 3가지 객체를 저장하려고 했는데, 3가지 객체 모두에서 각자의 에러가 떴다. 여러 에러가 동시에 나오니까 직렬화가 문제인지 역직렬화가 문제인지조차 알기 힘들었다. 구글에 검색해도 나와 비슷한 경우를 찾을 수 없어서 꽤 시간이 오래 걸렸다.
! 문제 발생 1
Inventory 객체가 모종의 이유로 역직렬화가 되지 않는다.
시도
우선 직렬화가 정상적으로 되었는지 저장 파일을 열어보았다. 그 곳에서는 이상을 찾을 수 없었다. 그래서 어떤 에러가 발생하는지 디버그 창에 에러 로그를 찍어보았다. System.InvalidOperationException이었다. 이름만으로 이유가 추측되지 않아서 구글에 검색해보았으나, 해답을 알 수 없었다.
생성자에 [JsonConstuctor]도 추가해보고, 프로퍼티에 get만 설정되어있는 곳이 있어서 set도 추가해주었다. item 클래스의 enum이 문제인가 싶어서 enum 직렬화에 관련해 검색해보았으나, 그것이 문제인 것 같지는 않았다. 그래서 생성자의 인자 수가 문제인가 인자 수도 억지로 맞춰보았으나, 되지 않았다.
해결
답은 생각보다 쉬운 곳에 있었다. 바로 inventory 필드변수 중에 List<Item>이 있었는데, 이 Item 클래스 에 있는프로퍼티의 타입은 float형이었는데, 생성자 인자의 타입이 int형이었던 것이다. 자동 형변환이 가능하다보니 빨간 줄이 그어지지 않아 둘이 다른지 몰랐다. 결국 하나하나 훑어보다가 뒤늦게서야 깨달았다.
학습
아무래도 여러 사람이 협업을 하다 보니, 이런 사소한 곳에서 올바르지 못하게 작성된 부분이 있었던 것 같다. 언제나 변수 타입을 잘 확인해야겠다.
! 문제 발생 2
인벤토리를 역직렬화를 해결하자, 이번에는 퀘스트 역직렬화가 터졌다.
시도
인벤토리 문제를 해결했던 경험을 바탕으로, 프로퍼티와 생성자를 점검했다. 그런데 변수형도 다 일치하고 안 될 이유가 없었다. 이것도 시간을 꽤 잡아먹었다.
해결
알고보니까 생성자에서 변수명 오타 문제(...)였다. QuestObjectiveCount 이런 변수인데, 이름이 길다보니 QuestObjcetiveCount 이런 식으로 오타가 나있어도 몰랐던 것이다. e와 c의 위치가 바껴 있었다. 그래서 역직렬화 할 때 QuestObjectiveCount를 찾지 못해서 일어난 일이었다. 자동완성기능을 쓰다보니 다른 곳에서도 순서가 바뀌어있어서 빨간 줄이 그어지지 않았다.
학습
역직렬화를 할 때 생성자를 활용하는 것 같다. 여기에서 변수명이 다르면 안 된다. 변수명이 길 땐 오타가 났는지 잘 확인하자..
! 문제 발생 3
시도
이번에는 Character에서 역직렬화가 되지 않았다.
해결
위의 두 문제를 해결하고 나니까 살짝 정신이 나가서 변수명부터 확인했다. 그런데 이번엔 구글신이 해결해줬다. 바로 역직렬화 하려는 객체의 클래스가 추상클래스로 구현되어있기 때문이라는 글이 있었다. Character가 추상클래스로 선언되어있기는 하나, 그 활용을 의미있게 하고 있지 않아서 abstract를 지워줬다. 그러자 말끔하게 해결됐다.
학습
추상 클래스는 역직렬화가 되지 않는다.
아래는 이렇게 여러 억까들을 이겨내고 구현한 SaveManager 코드다.
using System.Diagnostics; using System.Text.Json; using OceanStory.Characters; namespace OceanStory { internal class SaveManager { public void Save(string fileName) { string directory = ".\\..\\..\\..\\sav"; string filePath = directory + "\\" + fileName; string saveInfo; saveInfo = JsonSerializer.Serialize(Program.Character); saveInfo += ("\n" + JsonSerializer.Serialize(Program.Inventory)); saveInfo += ("\n" + JsonSerializer.Serialize(Program.QuestManager)); try { DirectoryInfo di = new DirectoryInfo(directory); if (!di.Exists) di.Create(); FileInfo fi = new FileInfo(filePath); if (fi.Exists) { fi.Delete(); StreamWriter sw = new StreamWriter(filePath); sw.WriteLine(saveInfo); sw.Close(); Program.SystemMessage.SetMessage("동일한 이름의 저장 파일이 있어 덮어쓰기 하였습니다."); } else { StreamWriter sw = new StreamWriter(filePath); sw.WriteLine(saveInfo); sw.Close(); Program.SystemMessage.SetMessage("저장했습니다."); } } catch (Exception e) { Program.SystemMessage.SetMessage("저장에 실패했습니다. " + e.Message); } } public bool Load(string fileName) { string directory = ".\\..\\..\\..\\sav"; string filePath = directory + "\\" + fileName; string characterInfo, inventoryInfo, questInfo; DirectoryInfo di = new DirectoryInfo(directory); FileInfo fi = new FileInfo(filePath); try { if (!(di.Exists && fi.Exists)) { Program.SystemMessage.SetMessage("그런 이름의 저장 파일이 존재하지 않습니다."); return false; } else { StreamReader sr = new StreamReader(filePath); characterInfo = sr.ReadLine(); inventoryInfo = sr.ReadLine(); questInfo = sr.ReadLine(); sr.Close(); Program.Character = JsonSerializer.Deserialize<Character>(characterInfo); Program.Inventory = JsonSerializer.Deserialize<Inventory>(inventoryInfo); Program.QuestManager = JsonSerializer.Deserialize<QuestManager>(questInfo); Program.SystemMessage.SetMessage($"{fileName} 파일 불러오기에 성공했습니다."); return true; } } catch (Exception e) { Program.SystemMessage.SetMessage("불러오기에 실패했습니다. " + e.Message); Debug.WriteLine(e.Message); return false; } } } }
여기까지 구현하고, 팀원분이 스킬 구현에 성공하셔서 그것도 합쳤다. 그리고 슬슬 프로젝트 마무리를 시작해야 했다. 주석을 달고, ReadMe.md를 작성하고, 불필요한 using문을 제거해 주는 등의 작업을 했다.
아래는 지금까지 구현한 구현 목록이다.
[필수 요구사항]
- 게임 시작 화면
- 상태 보기
- 전투 시작
[선택 요구사항]
- 캐릭터 생성
- 직업 선택
- 치명타
- 회피
- 레벨업
- 전투 보상
- 퀘스트
- 콘솔 꾸미기
- 아이템
- 회복
- 스테이지
- 저장/불러오기
- 스킬
[추가 구현]
- 로그인
[결과물]
https://github.com/Gambling7l7l7JackPot/OceanStory
[회고]
이번 주는 이걸로 마치고, 다음주 화요일 2시에 발표가 있다. 이번 주 주말이 어린이날이 껴있어서 3일 연휴지만 시간을 조금 내서 발표준비와 프로젝트 리팩토링에 조금 더 신경 써야할 거 같다.
'TIL > C#' 카테고리의 다른 글
내일배움캠프 16일차 TIL - 프로젝트 발표 (0) 2024.05.07 내일배움캠프 14일차 TIL - 퀘스트 구현 (1) 2024.05.02 내일배움캠프 13일차 TIL - 전투 구현 마무리 (1) 2024.05.01 내일배움캠프 12일차 TIL - 팀 프로젝트 전투 기능 관련 (0) 2024.04.30 내일배움캠프 11일차 TIL - 텍스트 기반 RPG 제작 팀 프로젝트 기초 (1) 2024.04.29