(금)2024.10.04 자 회고...
저번 주 금요일 당일 전날 밤을 새서 너무 피로한 나머지 TIL을 작성하지 못하고 기절하여 버렸다. 그래서 지금이라도 그날의 배운점을 작성하겠다.
목요일 저녁에 zep에 들어와서 상점 기능과 인벤토리, 아이템 사용(장비 장착), 스테이지, 레벨업을 구현했다.
잠깐이면 될 줄 알았는데, 개발을 하다보니 어느새 아침이 되어 있었다.
여기서 내가 오래 걸린 부분은 아이템 관리 부분이었다.
일단 나는 며칠전 본 객체지향 블로그의 영향을 받아 프로그래밍을 어떻게든 객체지향적으로 작성하여 코드를 객체객체하게 만들고 싶었다.
근데 이제 팀원분이 퀘스트와 리워드 구조를 만들며 만들어 놓으신 아이템 클래스가 있었고, 간단하게 설명해주시면서 내가 구조를 바꿔서 사용해도 된다고 하셨다.
나는 들뜬 마음으로 아이템 클래스를 마개조를 해서 객체객체하게 만들어 놓겠다 다짐했지만, 생각보다 쉽지 않았다.
사실 작성한 아이템 코드 자체는 어렵지 않았다. 그런데 아이템 리스트가 switch case문에 작성이 되어있었다.
ItemStruct tempData = ItemData;
switch (itemName)
{
case "수련자 갑옷":
tempData.Name = new StringBuilder(itemName);
tempData.Description = new StringBuilder("수련에 도움을 주는 갑옷입니다. ");
tempData.ItemCategory = ItemCategory.ARMOR;
tempData.Stat = 5;
tempData.Price = 1000;
break;
case "무쇠 갑옷":
tempData.Name = new StringBuilder(itemName);
tempData.Description = new StringBuilder("무쇠로 만들어져 튼튼한 갑옷입니다. ");
tempData.ItemCategory = ItemCategory.ARMOR;
tempData.Stat = 9;
tempData.Price = 2000;
break;
case "스파르타의 갑옷":
tempData.Name = new StringBuilder(itemName);
tempData.Description = new StringBuilder("스파르타의 전사들이 사용했다는 전설의 갑옷입니다.");
tempData.ItemCategory = ItemCategory.ARMOR;
tempData.Stat = 15;
tempData.Price = 3500;
break;
case "낡은 검":
tempData.Name = new StringBuilder(itemName);
tempData.Description = new StringBuilder("쉽게 볼 수 있는 낡은 검 입니다. ");
tempData.ItemCategory = ItemCategory.WEAPON;
tempData.Stat = 2;
tempData.Price = 600;
break;
case "청동 도끼":
tempData.Name = new StringBuilder(itemName);
tempData.Description = new StringBuilder("어디선가 사용됐던거 같은 도끼입니다. ");
tempData.ItemCategory = ItemCategory.WEAPON;
tempData.Stat = 5;
tempData.Price = 1500;
break;
case "스파르타의 창":
tempData.Name = new StringBuilder(itemName);
tempData.Description = new StringBuilder("스파르타의 전사들이 사용했다는 전설의 창입니다. ");
tempData.ItemCategory = ItemCategory.WEAPON;
tempData.Stat = 7;
tempData.Price = 3000;
break;
case "취업의 돌":
tempData.Name = new StringBuilder(itemName);
tempData.Description = new StringBuilder("소유한자를 취업시켜준다는 취업의 돌...열심히 하자");
tempData.ItemCategory = ItemCategory.WEAPON;
tempData.Stat = 100;
tempData.Price = 9999;
break;
}
ItemData = tempData;
여기선, 아이템 생성자에 아이템의 이름을 string으로 넘겨주면, 그 아이템의 데이터들을 struct형식으로 모아서 ItemData라는 Item클래스의 struct에 넣어 아이템을 만들어주는 방식을 취했다.
사실 미니멀한 프로젝트에서는 이렇게 사용해도 문제없을 것이다. 하지만, 아이템이 조금만 많아져서 수십 개에서 백 개만 되어도 관리하기가 어려워질 것이고, 더욱더 많아진다면, 아이템을 생성할 때 비교하는 string 개수와 값이 꽤나 많아서 성능에도 많은 영향을 끼칠 것이다.
나는 아이템 클래스를 만들어서 아이템을 만들 때마다 아이템 클래스를 상속받는 아이템을 만들고, 아이템의 공통된 기능들(사고, 팔고 등등)을 아이템 클래스에서 구현하여 새로운 아이템을 만들 때, 아이템 클래스를 상속하여 그 아이템의 기능만 오버라이딩해서 특정한 아이템이 되도록 만들고 싶었다.
사실 바꾸는 건 그렇게 어렵지 않다.
Item클래스를 새로 생성해서 기능들을 붙여주고, struct형식으로 주고받는 데이터를 Item클래스의 필드로 그냥 만들어 주고 아이템들의 데이터를 각 class에서 생성될 때, 집어넣어 주면 된다.(struct형식이 꼭 필요할까? 나중에 혹시 아이템에 스킬 같은 것이 부여된다면, struct값으로 아이템을 표현하기 어려워질 것이다.)
만약, 장비 아이템과 포션같은 사용 아이템이 나뉜다면, 또 그 클래스를 중간에 끼워 넣으면 될 것이다.
아무튼, 머리 아프게 생각해서 마개조는 어렵지 않다 판단했으나, 큰 문제가 있었다.
이미 이 아이템 클래스를 이용해 퀘스트와 리워드 시스템을 만들어 놓은 것이다.
내가 아이템 클래스를 변경하더라도, 그곳에서 사용하는 형식에 맞춰서 만들어 놓긴 해야 코드가 작동을 하는 것이다.
이때 딱 느꼈다. 아, 이게 객체지향의 필요성이구나!
물론, 코드를 만들어 주신 K님께 이 부분을 고쳐서 싶은데 이렇게 해서 이런식으로 동작하는 Item클래스로 만들어도 될까요? 라고 물어본다면 흔쾌히 부탁을 들어주실 것이다. (사실 생각보다 아이템을 많이 쓰진 않은 것 같았다.)
하지만, 이미 하루밖에 남은 시간도 없고, 이미 깊은 밤이고, K님도 언제 자러가실 지 모르는 상황에 내 부탁 때문에 원래 있을 것보다 더 있게 하고 싶진 않았다.(우린 이미 필수구현과제는 완료했고, 사실 쉬는 날이고, 굳이 더 안해도 되긴 하니까?)
어쨌든 이런 여러가지 이유와 얼마 남지 않은 시간 때문에 나는 Item 클래스의 마개조를 포기하고 나머지 기능들을 구현하였다.
만들어진 Item으로 상점과 인벤토리, 아이템 사용을 구현을 하였는데, 구현 과정에 있어서 뭔가 내가 생각한 아이템 구조와 좀 달라서 아이템을 다루는 데에 조금 어려움이 있었다.
원하는 아이템을 생성할 때는 string을 넣어서 생성해줘야 하고, struct형태로 데이터를 관리하고...(struct가 꼭 필요한가? 라는 생각이 드는데 아직 모르는 게 많아서 좋은지 나쁜지는 모르겠다. 근데 class내부가 struct랑 비슷한 형태니까 굳이 필요하진 않지 않을까? 라는 나의 생각이 싫지 않은 내가 싫지 않은 그런 느낌.)
아무튼, 조금 하드코딩이 되었던 부분도 있었던 것 같다. (하루밖에 남지 않았는데 객체지향 설계 생각할 시간이 어딨어 일단 만들고 봐!)
K님도 사실 굉장히 자기계발을 열심히 하시고 코드도 잘 짜는 고수신데 이번 프로젝트 과제가 굉장히 미니멀한 프로젝트라 가볍게 코드를 작성하셨다고 한다.
아무튼 사소한 해프닝이었지만, 만약 큰 프로젝트에서 객체객체하지 않은 코드를 마주한다면 너무 두려울 것 같단 생각이 들었다. 굉장한 양의 하드하드코딩..! 무서워!
아무아무튼 오늘의 결론, 객체객체한 코드를 작성하려고 노력하자.
이상 2024.10.07 자에 회고하는 2024.10.04 자 TIL 전달 끝!