코스 9: Eight Advanced - 종합 프로젝트
코스 개요
이 코스는 지금까지 배운 모든 개념을 통합하는 종합 프로젝트로 구성됩니다. 학생들은 실제로 플레이 가능한 완성된 게임을 만들면서, 여러 시스템이 어떻게 함께 동작하는지 경험합니다. 이 과정에서 소프트웨어 설계, 디버깅, 최적화의 실제적인 도전을 경험합니다.
예상 소요 시간: 20~40시간
소요 시간은 학생의 학년, 사전 경험, 학습 속도에 따라 크게 달라집니다. 또한 기본 개념만 익히고 넘어가는 경우와 추가 실습 문제나 창의적 프로젝트를 더 진행하는 경우에 따라서도 차이가 납니다. 위 시간은 평균적인 범위이며, 자녀의 페이스에 맞추어 유연하게 진행하시기 바랍니다.
어떤 능력을 키우게 되나요?
여러 데이터 시스템을 통합하여 하나의 완성된 시스템을 만드는 능력을 훈련합니다. 현대의 서비스는 사용자 데이터, 상품 데이터, 결제 데이터, 분석 데이터 등 여러 데이터 시스템이 연결되어 동작합니다. 이 통합 설계 능력이 소프트웨어 아키텍트, 데이터 엔지니어의 핵심 역량입니다.
어떤 원리를 배우나요?
- (데이터 흐름 설계) 플레이어 → 무기 → 적 → 점수 → UI로 이어지는 데이터의 흐름을 설계합니다. 실제 서비스도 주문 → 결제 → 배송 → 알림의 데이터 흐름으로 구성됩니다.
- (데이터 기반 디버깅) "데이터가 어디서 잘못되었는가?"를 추적하며 데이터의 상태를 확인하고 문제를 해결합니다. 이것이 실제 개발자가 버그를 찾는 방법입니다.
AI 시대 사고력: 컴퓨팅 (문제해결) | 데이터 기반 | 확률적 사고력
컴퓨팅 사고력 (Computational Thinking)
| 스킬 | 설명 | 활동 예시 |
|---|---|---|
| 🧩 분할 정복 | 큰 문제를 작은 문제로 분해 | FPS = 입력 + 물리 + 렌더링 + UI |
| 🔗 시스템 통합 | 독립 모듈을 연결 | 플레이어 ↔ 인벤토리 ↔ UI 연동 |
| 🐛 체계적 디버깅 | 오류 원인 추적 및 수정 | 이진 탐색으로 버그 위치 찾기 |
| 📊 프로젝트 관리 | 우선순위와 단계별 진행 | MVP 먼저, 기능 추가는 나중에 |
수학적 연결고리
| 수학 개념 | 프로그래밍 적용 | 학습 효과 |
|---|---|---|
| 분할 정복 | 복잡한 문제 → 작은 하위 문제 | 재귀적 문제 해결 |
| 그래프/네트워크 | 시스템 간 연결 관계 | 의존성 파악 |
| 논리적 추론 | 버그 원인 추적 | 가설-검증 과정 |
| 최적화 | 효율적인 코드 작성 | 시간/공간 복잡도 |
분할 정복 전략 (Divide & Conquer)
flowchart TD
A["🎯 큰 문제<br/>완전한 FPS 게임 만들기"] --> B["👤 1. 플레이어"]
A --> C["🔫 2. 무기"]
A --> D["👾 3. 적"]
A --> E["📊 4. UI"]
B --> B1[이동]
B --> B2[시점 조절]
B --> B3[체력 관리]
C --> C1[총 발사]
C --> C2[재장전]
C --> C3[데미지 계산]
D --> D1[AI 이동]
D --> D2[공격]
D --> D3[스폰]
E --> E1[체력바]
E --> E2[점수]
E --> E3[미니맵]
핵심: 각각 독립적으로 개발 → 통합 → 테스트
디버깅 = 과학적 방법
| 단계 | 과학적 방법 | 디버깅 적용 |
|---|---|---|
| 1. 관찰 | 현상 관찰 | 버그 증상 확인 |
| 2. 가설 | 원인 추측 | "이 변수가 문제일 것이다" |
| 3. 실험 | 가설 테스트 | print()로 값 확인 |
| 4. 결론 | 결과 분석 | 원인 확정 또는 새 가설 |
| 5. 검증 | 해결 확인 | 수정 후 테스트 |
프로젝트 관리 - 애자일 방식
반복 1: 핵심 기능 (MVP)
├── 플레이어가 움직인다 ✓
├── 총을 쏠 수 있다 ✓
└── 적이 나타난다 ✓
반복 2: 게임 로직
├── 적을 맞추면 점수 ✓
├── 적에게 맞으면 데미지 ✓
└── 게임 오버 조건 ✓
반복 3: 개선
├── UI 추가
├── 사운드 효과
└── 난이도 조절
"완벽한 계획보다 동작하는 버전이 먼저"
MVC 패턴 - 관심사 분리
| 구성요소 | 역할 | 예시 |
|---|---|---|
| Model | 데이터 | 인벤토리 배열, 아이템 정보 |
| View | 화면 표시 | UI 버튼, 아이템 아이콘 |
| Controller | 로직 처리 | 클릭 시 아이템 사용 |
💻 코드 예시 & 시각화
예시 1: 모듈화된 게임 구조
# ==================== player.py ====================
class Player:
def __init__(self):
self.health = 100
self.position = (0, 0, 0)
self.inventory = []
def move(self, direction):
# 이동 로직
pass
def take_damage(self, amount):
self.health -= amount
# ==================== enemy.py ====================
class Enemy:
def __init__(self, position):
self.health = 50
self.position = position
def update(self, player_pos):
# AI 로직: 플레이어 추적
pass
# ==================== weapon.py ====================
class Weapon:
def __init__(self, name, damage):
self.name = name
self.damage = damage
def fire(self):
# 발사 로직
pass
# ==================== main.py ====================
from player import Player
from enemy import Enemy
from weapon import Weapon
player = Player()
enemies = [Enemy((5, 0, 0)), Enemy((10, 0, 0))]
gun = Weapon("권총", 25)
모듈 구조:
game_project/
│
├── main.py ← 메인 진입점
│
├── player.py ← Player 클래스
│ └── class Player
│ ├── move()
│ └── take_damage()
│
├── enemy.py ← Enemy 클래스
│ └── class Enemy
│ └── update()
│
└── weapon.py ← Weapon 클래스
└── class Weapon
└── fire()
각 파일이 독립적 → 테스트 쉬움!
예시 2: FPS 게임 시스템 통합
from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController
app = Ursina()
# ===== 시스템 1: 플레이어 =====
player = FirstPersonController()
player.health = 100
# ===== 시스템 2: 무기 =====
class Gun(Entity):
def __init__(self):
super().__init__(
model='cube',
color=color.gray,
scale=(0.1, 0.1, 0.5),
parent=camera,
position=(0.5, -0.3, 0.5)
)
self.damage = 25
def shoot(self):
# 레이캐스트로 충돌 검사
hit_info = raycast(camera.position, camera.forward, distance=100)
if hit_info.hit:
if hasattr(hit_info.entity, 'take_damage'):
hit_info.entity.take_damage(self.damage)
gun = Gun()
# ===== 시스템 3: 적 =====
class Enemy(Entity):
def __init__(self, position):
super().__init__(
model='cube',
color=color.red,
position=position,
collider='box'
)
self.health = 50
def take_damage(self, amount):
self.health -= amount
if self.health <= 0:
destroy(self)
update_score(10)
enemies = [Enemy((5, 1, 10)), Enemy((-5, 1, 15))]
# ===== 시스템 4: UI =====
score = 0
score_text = Text(text=f'Score: {score}', position=(-0.85, 0.45))
health_bar = Entity(model='quad', color=color.red,
scale=(0.5, 0.03), position=(-0.6, 0.4))
def update_score(points):
global score
score += points
score_text.text = f'Score: {score}'
# ===== 시스템 통합: 입력 처리 =====
def input(key):
if key == 'left mouse down':
gun.shoot()
app.run()
시스템 통합 다이어그램:
flowchart TD
subgraph FPS["🎮 FPS 게임"]
direction TB
P["👤 Player System"] -->|소유| G["🔫 Gun System"]
G -->|공격| E["👾 Enemy System"]
P --> UI["📊 UI System"]
G --> UI
E --> S["🏆 Score System"]
S --> UI
end
예시 3: 디버깅 과정
# 버그가 있는 코드
def calculate_damage(base_damage, multiplier, defense):
# 버그: defense를 빼야 하는데 더하고 있음!
damage = base_damage * multiplier + defense
return damage
# 디버깅 과정
def calculate_damage_debug(base_damage, multiplier, defense):
print(f"[DEBUG] base_damage: {base_damage}")
print(f"[DEBUG] multiplier: {multiplier}")
print(f"[DEBUG] defense: {defense}")
damage = base_damage * multiplier + defense # ← 문제 발견!
print(f"[DEBUG] calculated damage: {damage}")
# 수정: + → -
damage = base_damage * multiplier - defense
print(f"[DEBUG] corrected damage: {damage}")
return max(0, damage) # 음수 방지도 추가
디버깅 플로우:
flowchart TD
A["🐛 1. 버그 발견<br/>데미지가 너무 높음!"] --> B["🤔 2. 가설 설정<br/>데미지 계산 문제?"]
B --> C["🔍 3. print 로 확인<br/>base=10, mult=2, def=5<br/>결과: 25 ← 예상: 15"]
C --> D["💡 4. 원인 발견<br/>+ 가 아니라 - 여야 함!"]
D --> E["✅ 5. 수정 및 검증<br/>damage = base×mult - def<br/>결과: 15 ✓"]
예시 4: MVC 패턴 - 인벤토리 시스템
# ===== Model (데이터) =====
class InventoryModel:
def __init__(self, rows, cols):
self.grid = [[None for _ in range(cols)] for _ in range(rows)]
def add_item(self, row, col, item):
if self.grid[row][col] is None:
self.grid[row][col] = item
return True
return False
def remove_item(self, row, col):
item = self.grid[row][col]
self.grid[row][col] = None
return item
# ===== View (화면 표시) =====
class InventoryView:
def __init__(self, model):
self.model = model
self.buttons = []
def create_ui(self):
for row in range(len(self.model.grid)):
for col in range(len(self.model.grid[0])):
btn = Button(
position=(col * 0.1 - 0.2, -row * 0.1 + 0.2),
scale=0.08
)
self.buttons.append(btn)
def update_display(self):
for row in range(len(self.model.grid)):
for col in range(len(self.model.grid[0])):
item = self.model.grid[row][col]
idx = row * len(self.model.grid[0]) + col
if item:
self.buttons[idx].text = item.name[0]
else:
self.buttons[idx].text = ""
# ===== Controller (로직) =====
class InventoryController:
def __init__(self, model, view):
self.model = model
self.view = view
self.selected = None
def on_slot_click(self, row, col):
if self.selected is None:
# 아이템 선택
self.selected = (row, col)
else:
# 아이템 이동
self.swap_items(self.selected, (row, col))
self.selected = None
self.view.update_display()
MVC 구조 다이어그램:
flowchart TD
U["🖱️ 사용자 입력<br/>(클릭)"] --> C["🎛️ Controller<br/>로직 처리"]
C --> M["📦 Model<br/>데이터"]
C --> V["🖥️ View<br/>화면"]
M <-->|동기화| V
V --> R["✨ 화면 업데이트"]
핵심: Model 변경 → View 자동 업데이트
예시 5: 프로젝트 진행 단계
"""
FPS 게임 개발 로드맵
=== Phase 1: MVP (핵심 기능) ===
[x] 플레이어 이동
[x] 마우스로 시점 조절
[x] 총 발사 (클릭)
[x] 적 생성
=== Phase 2: 게임 로직 ===
[x] 적 체력 시스템
[x] 적 처치 시 점수 획득
[x] 플레이어 체력 시스템
[ ] 게임 오버 조건
=== Phase 3: 개선 ===
[ ] 적 AI (플레이어 추적)
[ ] 사운드 효과
[ ] 파티클 이펙트
[ ] 난이도 시스템
=== Phase 4: 폴리싱 ===
[ ] 메인 메뉴
[ ] 설정 화면
[ ] 저장/불러오기
"""
# 현재 Phase 2 진행 중...
개발 진행도 시각화:
왜 종합 프로젝트가 중요한가요?
교육적 가치
개별 개념을 배우는 것과 통합하여 적용하는 것은 다른 능력입니다:
| 개별 학습 | 종합 프로젝트 |
|---|---|
| 조건문 이해 | 적절한 상황에 조건문 선택 |
| 리스트 사용법 | 게임에서 리스트가 필요한 곳 판단 |
| 클래스 정의 | 어떤 것을 클래스로 만들지 설계 |
| 개념 암기 | 문제 해결에 개념 적용 |
종합 프로젝트는 "알고 있다"에서 "할 수 있다"로의 전환입니다.
프로젝트 1: FPS Complete - FPS 게임 완성본
| 항목 | 내용 |
|---|---|
| 무엇을 배우나요? | 1인칭 슈팅 게임 전체 구현 |
| 통합 개념 | 입력, 물리, 충돌, 클래스, 이벤트 |
완전한 FPS 게임을 처음부터 끝까지 구현합니다. 플레이어 이동, 시점 조절, 총 발사, 적 AI, 체력 시스템, 점수 시스템이 모두 통합됩니다. 학생들은 각 시스템이 서로 어떻게 연결되는지 이해합니다. 버그가 발생하면 어디서 문제가 생겼는지 추적하는 디버깅 능력을 기릅니다. 완성된 게임은 친구들과 공유하며 성취감을 느낍니다.
시스템 통합의 도전
| 항목 | 내용 |
|---|---|
| 무엇을 배우나요? | 복잡한 시스템 관리하기 |
| 핵심 개념 | 모듈화, 디버깅, 테스트 |
여러 시스템이 동시에 동작하면 예상치 못한 상호작용이 발생할 수 있습니다. "총을 쏘면서 점프하면 버그가 생긴다" 같은 엣지 케이스를 발견하고 수정합니다. 학생들은 코드를 모듈(기능 단위)로 나누어 관리하는 중요성을 배웁니다. 각 모듈을 독립적으로 테스트하고 통합하는 방법도 익힙니다. 이것은 실제 소프트웨어 개발의 표준 방식입니다.
프로젝트 2: Inventory Complete - 인벤토리 시스템 완성
| 항목 | 내용 |
|---|---|
| 무엇을 배우나요? | 완전한 아이템 관리 시스템 |
| 통합 개념 | 2D 배열, 클래스, UI, 이벤트 |
아이템 획득, 사용, 장착, 버리기가 가능한 완전한 인벤토리입니다. 아이템 클래스(무기, 방어구, 소비품)의 상속 구조를 설계합니다. 드래그 앤 드롭으로 아이템을 이동하는 UI를 구현합니다. 학생들은 데이터 모델과 UI의 분리라는 중요한 설계 원칙을 경험합니다. 이 시스템은 대부분의 RPG 게임에서 핵심 기능입니다.
데이터와 UI의 분리
| 항목 | 내용 |
|---|---|
| 무엇을 배우나요? | 좋은 소프트웨어 설계 |
| 핵심 개념 | MVC 패턴, 관심사 분리 |
데이터(어떤 아이템이 어디에 있는지)와 UI(화면에 어떻게 보이는지)를 분리합니다. 데이터가 변경되면 UI가 자동으로 업데이트되도록 설계합니다. 이 패턴은 MVC(Model-View-Controller)라 불리며, 전문 개발에서 표준입니다. 학생들은 코드를 유지보수하기 쉽게 구조화하는 방법을 배웁니다. 나중에 웹 개발, 앱 개발에서 동일한 원리를 적용합니다.
프로젝트 3: Minecraft with Items - 마인크래프트 + 아이템
| 항목 | 내용 |
|---|---|
| 무엇을 배우나요? | 블록 세계와 아이템 시스템 통합 |
| 통합 개념 | 2D 배열, 클래스, 인벤토리, 물리 |
마인크래프트 스타일 세계에 아이템 시스템을 추가합니다. 블록을 캐면 인벤토리에 추가되고, 인벤토리에서 선택하면 설치할 수 있습니다. 다양한 블록 타입(흙, 돌, 나무)은 클래스 상속으로 구현합니다. 학생들은 여러 큰 시스템을 통합하는 경험을 합니다. 이 프로젝트는 커리큘럼의 최종 도전이자 종합 평가입니다.
프로젝트 관리 경험
| 항목 | 내용 |
|---|---|
| 무엇을 배우나요? | 큰 프로젝트 진행하기 |
| 핵심 개념 | 계획, 우선순위, 반복 개발 |
큰 프로젝트는 한 번에 완성되지 않습니다. 학생들은 기능을 우선순위에 따라 나누고, 단계적으로 구현합니다. 먼저 핵심 기능(블록 설치/제거)을 만들고 점차 추가 기능을 더합니다. 이것은 실제 소프트웨어 개발의 애자일(Agile) 방법론과 유사합니다. 완벽을 추구하다 완성 못하는 것보다 동작하는 버전을 먼저 만드는 것이 중요합니다.
종합 프로젝트의 의미
학습 완성
종합 프로젝트를 마치면 학생들은:
- 자신감: "나도 게임을 만들 수 있다"는 확신
- 포트폴리오: 보여줄 수 있는 실제 작품
- 문제 해결 경험: 실제 어려움을 극복한 경험
- 설계 능력: 큰 문제를 작은 부분으로 나누는 능력
- 완주 경험: 끝까지 해낸 성취감
이 경험은 프로그래밍뿐 아니라 모든 분야의 프로젝트에 적용됩니다.
이 코스를 마치면...
학습 성과
학생들은 다음 능력을 갖추게 됩니다:
- 여러 시스템을 통합하여 완전한 게임을 만들 수 있음
- 큰 프로젝트를 계획하고 단계적으로 진행할 수 있음
- 버그를 추적하고 수정하는 디버깅 능력
- 코드를 모듈화하고 구조화하는 설계 능력
- 실제 게임을 완성해본 경험
- 더 복잡한 프로젝트나 다른 분야로 확장할 준비