요즘 포트폴리오 작업을 하면서 정신없이 보내고 있는데요
포트폴리오를 만들면서 기획 데이터 부분을 어떤 식으로 설계하면 좋을까 고민했습니다.
고민한 이유는 기획자가 없는 포트폴리오 작업이기 때문이죠..
뭔가 간편하게 csv 파일로 게임 데이터 작업을 하면서 이것 그대로 로드 해오는게 좋을지,
아니면 json 형식으로 변환하는게 좋을지 고민하다가 csv 파일을 json파일로 변환해서 쓰자! 라고 마음 먹었는데..
안그래도 포트폴리오 하고 싶은 것들이 너무 많은데 할게 더 추가됐습니다.
욕심만 그득..
게임 회사에서 일할 때, 주로 게임 데이터(즉, 기획자가 만들어둔 데이터)를 어떻게 받아오느냐의 차이가 있습니다.
각 회사의 프로젝트마다 이 특성이 달라요!!..
하지만, 이번 포트폴리오에선 json 형식으로 쓰려고 이름하여 CsvToJsonConverter!!!
CSV TO JSON
일단 가볍게 기획데이터를 만들어줬습니다.
이름하여 Stat Data!! (추후에 수정 예정이긴 합니다..ㅠ)
public class Stat : ICsvConvertible
{
public int Level { get; set; }
public int MaxHp { get; set; }
public int MaxMp { get; set; }
public int Attack { get; set; }
public int TotalExp { get; set; }
public void FromCsv(string[] values)
{
Level = int.Parse(values[0]);
MaxHp = int.Parse(values[1]);
MaxMp = int.Parse(values[2]);
Attack = int.Parse(values[3]);
TotalExp = int.Parse(values[4]);
}
}
일단 Main 쪽을 한번 볼게요.
public class Program
{
public static void Main(string[] args)
{
var folderPath = Path.Combine("../../../", "GameData");
string[] files = Directory.GetFiles(folderPath, "*.csv");
var saveForlderPath = Path.Combine("../../../../Common/", "GameData");
CsvToJsonConverter.ConvertCsvToJson(files, saveForlderPath);
Console.WriteLine(files);
}
}
너무나도 뭐가 없는.. 그저 CsvToJsonConverter 에다가 csv 파일이 있는 경로를 입력해주고, json 파일을 세이브 하는 폴더를 입력해줍니다. ^_^
마지막은 로그로 마무리.. 이렇게 심플하게 만들었습니다.
내부적으로 보면
public static void ConvertCsvToJson(string[] csvPaths, string saveFolderPath)
{
// 현재 어셈블리에서 모든 ICsvConvertible 구현 클래스를 찾는다.
var convertibleTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => typeof(ICsvConvertible).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract)
.ToList();
foreach (var csvPath in csvPaths)
{
var fileName = Path.GetFileNameWithoutExtension(csvPath).ToLower();
var targetType = convertibleTypes.FirstOrDefault(t => t.Name.ToLower() == fileName);
if (targetType == null)
{
Console.WriteLine($"Unsupported file type: {fileName}");
continue;
}
var method = typeof(CsvToJsonConverter)
.GetMethod("LoadCsv")
.MakeGenericMethod(targetType); // 해당 타입에 맞는 LoadCsv 호출
var save = Path.Combine(saveFolderPath, $"{targetType.Name}.json");
var data = method.Invoke(null, new object[] { csvPath });
var jsonData = JsonConvert.SerializeObject(data, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(save, jsonData);
}
}
일단 ICsvConvertible 인터페이스를 상속 받고 있는 구현 클래스들을 reflection으로 찾아줍니다.
그 다음에 파일명들을 소문자들로 바꿔주는데요.
이렇게 한 이유는 파일들이 소문자나 대문자가 섞여서 잘못되었을 수도 있기 때문에 미연에 방지하고자 해놨습니다.
그리고 각 타입에 맞는 LoadScv를 해서 가져온 파일을 save 해주는 것으로 알 수 있습니다. ^_^
그렇다면 LoadScv는 무엇이냐?!
제가 만든 매서드 입니다. ( C++ 에서는 주로 Function이라고 이야기했었는데, C# 에서는 Method 라고 설명하더라구요.)
public static List<T> LoadCsv<T>(string filePath) where T : ICsvConvertible, new()
{
var result = new List<T>();
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var encoding = Encoding.GetEncoding("euc-kr");
var lines = File.ReadAllLines(filePath, encoding)
.Where(line => !string.IsNullOrWhiteSpace(line))
.ToArray();
foreach (var line in lines.Skip(1)) // 첫번째 줄은 건너뛴다.
{
var values = line.Split(','); // 한줄씩 가져온다.
T item = new T();
item.FromCsv(values);
result.Add(item);
}
return result;
}
여기서 테스트 해본 결과, 한글이 깨지는 현상이 발생했어서 encoding 으로 해주었습니다.
원래 기본적으로 게임 데이터에서는 string 파일을 따로 만들어서 각 언어별로 연결 시켜주는 부분이 존재하지만,
저는 개인 포트폴리오 작업을 진행하고 있기 때문에 그냥 Name 에다가 한국어 때려박는걸로 ^_^..
각 line들을 불러오는데요. 여기서 하나씩 읽어다가 데이터를 파싱해줍니다.
그러면 그것대로 끝나는거죠.
여담
너무나도 간단한거지만 생각보다 귀찮은 작업이고 프로젝트 내에서도 처음 만들고 나서 추후에 변경할 일이 적기 때문에
이런 작업을 할 일이 별로 없긴 합니다.
포트폴리오를 만들면서 좋은 점은 이렇게 자주 해보지 않은 작업들을 직접 한땀한땀 해야하기 때문에 재미 있는 것 같아요.
그리고 회사마다 다르겠지만 오래된 곳은 하나하나 뭔가 수동적으로 해야하는 곳도 있는데요.
신입 시절에 보통 막내 포지션으로 잡다한 업무를 하기 때문에 그러한 잡다한 것들을 어떻게 하면 자동화할 수 있을까 라는 생각이 스치게 됩니다. ( 아마도..? )
저는 업무하면서 완전 초창기에는 그런 생각도 못했었는데, 어느 순간부터 귀찮은 수동적인 작업들을 자동화 하려고 합니다. (왜냐하면 수동적으로 귀찮은 업무들은 막내에게 오기 때문이죠..)
그러면서 삽질도 하고 그러면서 잡다한 기술이 늘어가는 느낌..
'C#' 카테고리의 다른 글
[C#] Lock Free 하게 써보기 (Concurrent, Interlocked 활용) (0) | 2024.12.04 |
---|---|
[C#] 인터페이스와 추상 클래스 (1) | 2024.11.18 |
[C#] Unity에서 ProtoBuf 사용하는 방법 (1) | 2024.11.04 |
[C#] NLog 라이브러리를 사용하는데 로그가 안 찍히는 해결 방법 (0) | 2024.10.28 |
[C#] Parse() 와 TryParse()는 무슨 차이점이 있을까? (0) | 2024.08.02 |