게임 캐릭터 진화 시스템 백엔드 구현: 4단계 시스템 설계
게임 캐릭터 진화 시스템 백엔드 구현! 4단계 시스템 설계로 포인트 상점, 인벤토리 연동 복잡성을 해결한 개발 회고.
미니홈 서비스에 캐릭터 세트 진화 시스템을 구현해야 했다. 기존에는 캐릭터 성장이나 새로운 외형 획득 기능이 아예 없었거든. 이걸 어떻게든 만들어야 사용자 경험이 좀 더 풍부해질 것 같았다.
시도와 함정
처음에는 단순히 포인트 상점에 진화 아이템을 추가하고, 그걸 사용하면 캐릭터 외형이 바뀌는 식으로 간단하게 생각했다. 하지만 인벤토리 시스템과 연동하는 과정에서 생각보다 복잡한 문제에 부딪혔다.
캐릭터의 현재 레벨, 보유 아이템, 그리고 진화 단계까지 모두 고려해야 했는데, 이걸 어떻게 데이터로 관리하고 API로 전달할지가 막막했다. 특히 이미 존재하는 포인트 상점과 인벤토리 시스템에 영향을 주지 않으면서 자연스럽게 통합하는 게 어려웠다.
원인
가장 큰 문제는 각 시스템 간의 데이터 연동 방식이 명확하지 않았다는 점이었다. 포인트 상점에서는 아이템 구매 기록만 관리하고, 인벤토리에서는 보유 아이템 목록만 관리하는 식이었다. 캐릭터 진화라는 새로운 상태 값을 어디에, 어떻게 저장하고 조회할지에 대한 설계가 부족했다.
해결
결국 포인트 상점, 인벤토리 시스템과 연동하여 4단계의 캐릭터 진화 시스템을 구현했다. 각 진화 단계마다 필요한 아이템과 포인트를 정의하고, 이를 통해 캐릭터의 외형과 능력치를 업데이트하는 로직을 만들었다.
# 캐릭터 진화 로직 예시 (간소화)class CharacterEvolutionService: def init(self, user_id): self.user_id = user_id self.inventory_service = InventoryService(user_id) self.point_shop_service = PointShopService(user_id) self.character_data = self.load_character_data(user_id) # 현재 캐릭터 데이터 로드
def load_character_data(self, user_id): # 실제로는 DB에서 사용자 ID로 캐릭터 데이터를 조회 # 예시: {"level": 1, "evolution_stage": 0, "skin_id": "default_skin"} return {"level": 1, "evolution_stage": 0, "skin_id": "default_skin"} def can_evolve(self, target_stage): # 현재 진화 단계와 필요한 아이템, 포인트를 확인 required_items = self.get_evolution_requirements(target_stage) if not self.inventory_service.has_items(required_items): return False required_points = self.get_evolution_points(target_stage) if self.point_shop_service.get_current_points() < required_points: return False return True def evolve_character(self, target_stage): if not self.can_evolve(target_stage): raise ValueError("진화 조건이 충족되지 않았습니다.") # 필요한 아이템 제거 required_items = self.get_evolution_requirements(target_stage) self.inventory_service.remove_items(required_items) # 포인트 차감 required_points = self.get_evolution_points(target_stage) self.point_shop_service.deduct_points(required_points) # 캐릭터 데이터 업데이트 self.character_data["evolution_stage"] = target_stage self.character_data["skin_id"] = self.get_skin_id_for_stage(target_stage) self.save_character_data(self.user_id, self.character_data) return True def get_evolution_requirements(self, stage): # 실제로는 설정 파일이나 DB에서 조회 requirements = { 1: {"item_id": "evolution_stone_1", "quantity": 1}, 2: {"item_id": "evolution_stone_2", "quantity": 2}, 3: {"item_id": "evolution_stone_3", "quantity": 3}, 4: {"item_id": "evolution_stone_4", "quantity": 4} } return requirements.get(stage, {}) def get_evolution_points(self, stage): # 실제로는 설정 파일이나 DB에서 조회 points = {1: 100, 2: 200, 3: 300, 4: 400} return points.get(stage, 0) def get_skin_id_for_stage(self, stage): # 실제로는 설정 파일이나 DB에서 조회 skins = {1: "stage1_skin", 2: "stage2_skin", 3: "stage3_skin", 4: "stage4_skin"} return skins.get(stage, "default_skin") def save_character_data(self, user_id, data): # 실제로는 DB에 사용자 ID로 캐릭터 데이터 저장 print(f"캐릭터 데이터 저장: {user_id}, {data}")--- Mock Services (실제 환경에서는 실제 서비스 호출) ---
class InventoryService: def init(self, user_id): self.user_id = user_id self.items = {"evolution_stone_1": 2, "evolution_stone_2": 1} # 예시 보유 아이템
def has_items(self, required_items): if not required_items: return True item_id = required_items["item_id"] quantity = required_items["quantity"] return self.items.get(item_id, 0) >= quantity def remove_items(self, required_items): if not required_items: return item_id = required_items["item_id"] quantity = required_items["quantity"] if self.has_items(required_items): self.items[item_id] -= quantity print(f"{item_id} {quantity}개 제거. 남은 개수: {self.items[item_id]}") else: raise ValueError("아이템이 부족합니다.")class PointShopService: def init(self, user_id): self.user_id = user_id self.current_points = 500 # 예시 보유 포인트
def get_current_points(self): return self.current_points def deduct_points(self, amount): if self.current_points >= amount: self.current_points -= amount print(f"{amount} 포인트 차감. 남은 포인트: {self.current_points}") else: raise ValueError("포인트가 부족합니다.")--- 사용 예시 ---
user_id = "test_user_123"
evo_service = CharacterEvolutionService(user_id)
try:
print(f"현재 진화 단계: {evo_service.character_data['evolution_stage']}")
if evo_service.can_evolve(1):
print("1단계 진화 가능")
evo_service.evolve_character(1)
print(f"진화 후 단계: {evo_service.character_data['evolution_stage']}, 스킨: {evo_service.character_data['skin_id']}")
else:
print("1단계 진화 불가")
except ValueError as e:
print(f"오류 발생: {e}")
이 코드는 사용자의 인벤토리와 포인트 정보를 확인하고, 조건을 만족하면 캐릭터의 진화 단계를 업데이트하고 외형을 변경한다. 각 진화 단계별로 필요한 아이템과 포인트, 그리고 적용될 스킨 ID를 명확하게 관리하도록 설계했다.
결과
- 사용자는 이제 게임 내에서 캐릭터를 성장시키고 새로운 외형을 획득할 수 있게 되었다.
- 기존 포인트 상점 및 인벤토리 시스템과의 연동이 자연스럽게 이루어졌다.
- 4단계의 체계적인 진화 시스템을 통해 사용자에게 더 깊이 있는 플레이 경험을 제공할 수 있게 되었다.
정리 — 같은 함정 안 빠지려면
- [ ] 새로운 기능을 구현할 때, 기존 시스템과의 데이터 연동 방식을 미리 명확히 설계하자.
- [ ] 캐릭터의 상태 값(진화 단계, 외형 등)을 저장하고 관리할 데이터 구조를 신중하게 결정하자.
- [ ] API 호출 시 필요한 모든 파라미터와 반환 값을 정확하게 정의하자.
- [ ] 각 시스템 간의 의존성을 최소화하면서 유연하게 확장할 수 있는 구조를 고민하자.
태그