🔍 오늘의 주제: 게임 코드 구조화의 필요성과 실전 적용
오늘은 코드 분리(모듈화)의 중요성과 실전 프로젝트 구조 예시를 중심으로 학습하고 정리했다.
초보 개발자일수록 모든 기능을 한 파일에 넣는 경향이 있는데, 이로 인해 발생하는 문제와 개선 방향을 집중적으로 분석했다.
🧠 학습 내용 요약
✅ 1. 왜 코드를 나눠야 하나?
- 유지보수의 어려움: Game.cs에 모든 기능을 때려박으면 1주일 후 본인도 못 읽는다.
- 협업의 충돌: 여러 사람이 하나의 파일을 수정하면 Merge Conflict의 지옥이 열린다.
- 버그 추적 난이도 상승: 전투 버그 수정하려고 인벤토리 코드까지 훑어야 한다.
- 의존성 얽힘: 전투 코드 수정했는데 상점에서 아이템이 사라진다? 나도 모르는 의존성 때문.
✅ 2. 코드 분리의 기본 원칙
- 클래스 하나 = 역할 하나
- ex) Player.cs는 플레이어만, BattleManager.cs는 전투만.
- 실생활 비유: 요리사가 손질, 조리, 설거지까지 다 하면 효율 떨어지는 것과 같음.
- UI vs 로직 분리: 계산 로직과 보여주는 로직은 분리해서 재활용과 유지보수를 쉽게.
✅ 3. 실제 프로젝트 코드 분석
기존에 우리 초보적인 팀원들이 함께 힘을 합쳐 진행한 텍스트RPG 프로젝트에서는 아래와 같이 기능이 분리되어 있음:
- Game.cs: 전체 흐름 컨트롤 (게임 루프, 상태 관리)
- Player.cs: 직업, 능력치, 장비, 인벤토리 초기화 포함
- Item.cs + ItemManager.cs: 아이템 정의 및 초기화/목록 관리
- Inventory.cs: 아이템 장착/해제 및 플레이어 능력치 반영
- Monster.cs: 적 행동 정의 및 전투중 공격 처리
- Shop.cs: 상점 UI 및 구매 흐름, 그리고 "육군 이등별" 특수 분기
- Music.cs: NAudio 기반 배경음악 재생
- Program.cs: Main 진입점
➡️ 이미 잘 분리된 구조라는 평가를 받았지만, 추가적으로 다음 리팩토링 고려 가능:
- BattleManager.cs: 전투 시스템을 Game.cs에서 분리
- UIManager.cs: 텍스트 출력, 애니메이션, 콘솔 색상 등을 따로 관리
- StateManager.cs: 현재 상태가 전투인지 상점인지 등 전체 상태 전환 관리
🧩 기존 코드 리팩토링 제안: 더 나은 구조를 위한 설계
현재까지 작성된 Game.cs, Battle.cs, Player.cs, Monster.cs, Shop.cs는 각각 기능이 집중되어 있지만 점차 비대해지고 있으며, 유지보수와 확장성 측면에서 다음과 같은 역할 분리 구조로 개선할 수 있다. 다음은. AI가 생각할때 기능은 유지하며 양이 방대해 질때, 분리할수있는 구조의 제안이다.
🎮 Game.cs → 게임 시스템 전체 분리
현재 Game.cs는 게임 루프, 초기화, 상태 전환, 텍스트 출력, 인스턴스 관리 등 너무 많은 책임을 지고 있다.
📂 제안 분리 구조:
| GameController | 게임 전체 상태 흐름(시작/종료, 상호작용 등) 제어 |
| GameLoop | 메인 루프 및 사용자 입력 처리 |
| GameInitializer | 플레이어 생성, 인벤토리 세팅, 첫 스토리 로딩 등 |
| StoryManager | 텍스트 스토리, 나레이션 처리 |
| PlayerCreator | 캐릭터 생성 전용 유틸리티 |
⚔️ Battle.cs → 전투 시스템 분리
현재 Battle.cs는 적 생성, 전투 UI, 턴 처리, 데미지 계산, 전투 종료까지 모두 책임진다.
📂 제안 분리 구조:
| BattleSystem | 전투의 전체 흐름을 담당하는 상위 관리자 |
| TurnManager | 턴 순서/상태/지속시간 관리 |
| ActionResolver | 공격, 스킬, 방어 등 실제 효과 계산 |
| BattleUI | 전투 중 텍스트, 선택지, 효과 등 출력 |
| BattleRewardManager | 전투 종료 후 보상 (골드, 경험치, 아이템 등) 지급 |
👤 Player.cs → 플레이어 시스템 분리
Player 클래스는 현재 스탯, 인벤토리, 장비, 레벨 등 모든 데이터를 가지고 있다.
📂 제안 분리 구조:
| Player | 이름, 직업 등 기본 정보와 참조 연결만 담당 |
| PlayerStats | 체력, 마나, 공격/방어, 회복 등 수치 관리 |
| PlayerSkills | 사용 가능한 스킬 목록과 효과 계산 |
| EquipmentManager | 무기/방어구 장착 및 능력치 반영 |
| PlayerProgressionSystem | 경험치, 레벨업, 성장 처리 로직 |
👹 Monster.cs → 몬스터 시스템 분리
몬스터는 단일 클래스로 AI와 행동 로직, 생성 모두 담당하고 있음.
📂 제안 분리 구조:
| MonsterBase | 이름, 스탯, 데미지 처리 등 기본 속성 |
| MonsterTypes | 몬스터 종족/직업/등급별 확장 |
| MonsterBehavior | 특수 행동 로직 (도주, 스킬 사용 등) |
| MonsterSpawner | 적 그룹 및 배치 결정, 생성 타이밍 |
| AIDecisionMaker | 턴마다 어떤 행동을 할지 결정 (AI 패턴) |
🛒 Shop.cs → 상점 시스템 분리
Shop.cs는 상점 UI, 상품 목록, 가격 계산, 구매 처리까지 모두 담고 있음.
📂 제안 분리 구조:
| ShopManager | 상점 메뉴/흐름 관리 |
| ShopInventory | 상품 목록 및 종류별 필터링 |
| PriceCalculator | 가격 계산 (직업, 난이도, 할인 등 반영) |
| ShopDialogue | 상점 주인 대사 관리 |
| TransactionProcessor | 구매, 판매, 실패 처리 등 트랜잭션 |
💡 정리 및 기대 효과
- 개발자 개인 기준: 클래스가 작고 단순해져 유지보수가 쉬워진다.
- 팀 협업 기준: 각 시스템이 분리되어 Git 충돌이 줄고, 병렬 개발이 가능해진다.
- 유지보수 기준: 버그 수정 시 영향을 미치는 범위를 예측할 수 있다.
- 확장 기준: 새로운 기능 추가(예: '스킬 시스템' 추가 시 PlayerSkills에만 영향)를 안정적으로 진행할 수 있다.
✅ 4. 얻은 인사이트
- 코드 구조화는 귀찮은 게 아니라, 시간을 아끼기 위한 장기적 투자다.
- 코드가 분리될수록, 디버깅이 쉬워지고 버그가 줄어든다.
- 나중에 다른 팀원이 참여하거나, 시간이 지나도 유지보수가 쉬워진다.
- 게임 개발에서 '전투', '상점', '스토리', 'UI'는 모두 개별 시스템이다.
🛠️ 느낀 점
- 처음부터 완벽하게 분리하려는 강박은 필요 없다. 기능 구현 후, 리팩토링하며 점진적으로 분리해도 충분하다.
- 이제 Game.cs 안에서 전투나 상점 코드를 보는 것만으로도 이건 "아니다"라는 느낌이 올 정도로 감각이 생겼다.
- 특히 Inventory.cs에서 Player를 참조하여 스탯을 조작하는 구조는 의존성 주입 개념을 알게 해줌.
✅ 정리 문장
코드를 나눈다는 건 머리로 감당할 수 있을 만큼 문제를 쪼갠다는 뜻이다.
'팀스파르타 코딩' 카테고리의 다른 글
| 📅 2025.06.06 /오늘의 코테(오전)! - 복습!! (1) | 2025.06.06 |
|---|---|
| 📝 [TIL] 2025-06-05 (목) - 다시 코딩테스트 (0) | 2025.06.05 |
| 📚 TIL - 2025년 4월 28일 (월) / 텍스트 RPG 발표 & 피드백 회고 (0) | 2025.04.28 |
| 📚 TIL - 2025년 4월 24일 (목) / C# 기초 개념 테스트 복기 (0) | 2025.04.24 |
| 📘오늘의 새로 배운 개념![C# 텍스트 타이핑 효과 구현] (0) | 2025.04.23 |