4차시: 방향이 있는 숫자 - vector()로 2D·3D 움직임 제어하기¶
🧠 핵심 개념 1: vector 객체와 연산¶
숫자 하나가 아닌 방향+크기를 동시에 담는 그릇, vector(x, y, z)의 덧셈·뺄셈·스칼라곱을 익힙니다.
🧠 핵심 개념 2: mag와 norm¶
벡터에서 크기만 뽑는 mag와 방향만 뽑는 norm — 물리 시뮬레이션의 핵심 도구를 배웁니다.
💻 따라하기 실습¶
arrow 객체로 벡터를 눈으로 확인하고, 3차시 애니메이션을 벡터 방식으로 리팩토링합니다.
📝 평가¶
벡터 연산 퀴즈 + 대각선 이동 코딩 도전으로 오늘 배운 내용을 점검합니다.
⏱️ 수업 흐름¶
🔥 도입 — 숫자 하나로는 부족해! (5분)¶
3차시에서 pos.x만 바꿨던 한계를 떠올리며, "방향이 있는 숫자"의 필요성을 체감합니다.
📖 개념 탐구 — vector 객체와 벡터 연산 (12분)¶
vector(x, y, z) 생성, 덧셈·뺄셈·스칼라곱을 코드로 실습하며 개념을 잡습니다.
🛠️ 실습 1 — arrow로 벡터를 눈에 보이게! (10분)¶
arrow 객체를 사용하여 벡터를 3D 공간에 직접 그려보고, 연산 결과를 시각적으로 확인합니다.
📖 개념 탐구 — mag와 norm 함수 (10분)¶
벡터의 크기(mag)와 단위벡터(norm)를 분리하는 방법을 배우고, 왜 이것이 중요한지 이해합니다.
🚀 실습 2 — 3차시 코드를 벡터로 리팩토링 + 평가 (13분)¶
3차시 애니메이션을 벡터 방식으로 업그레이드하고, 형성 평가로 마무리합니다.
🔥 도입 — 숫자 하나로는 부족해! (5분)¶
3차시에서 우리가 했던 것¶
3차시에서 공을 오른쪽으로 움직일 때, 이렇게 코드를 작성했습니다:
x만 바꿨으니 공은 오른쪽으로만 이동했죠. 그런데 만약 공을 대각선으로 움직이고 싶다면요?
세 줄을 써야 합니다. 물체가 10개라면? 30줄이요! 😱
일상 속 "방향이 있는 숫자"¶
내비게이션을 떠올려 보세요:
| 안내 방식 | 충분한가요? |
|---|---|
| "300m 이동하세요" | ❌ 어느 방향으로요? |
| "북쪽으로 300m" | ⭕ 방향 + 거리 = 도착! |
"북쪽으로 300m" 처럼, 방향과 크기(거리)를 한 덩어리로 담는 것이 바로 벡터(vector) 입니다. 오늘은 이 벡터를 VPython에서 어떻게 쓰는지 배워봅니다.
📖 핵심 개념 1: vector 객체와 벡터 연산 (12분)¶
🎯 비유로 시작: 택배 배달 주소¶
택배 기사님에게 "3층으로 올라가세요"라고만 하면 어떤 건물인지 모릅니다. "동쪽 2블록, 북쪽 3블록, 3층"이라고 해야 정확히 찾아갈 수 있죠.
VPython의 vector(x, y, z)가 바로 이 역할을 합니다:
| 성분 | VPython 축 | 의미 |
|---|---|---|
| x | 오른쪽(+) / 왼쪽(−) | 좌우 방향 |
| y | 위(+) / 아래(−) | 상하 방향 |
| z | 화면 밖(+) / 안(−) | 앞뒤(깊이) 방향 |
🔎 정의: vector란?¶
vector(x, y, z) 는 3D 공간에서 방향과 크기를 동시에 표현하는 VPython의 특별한 객체입니다. 파이썬 리스트
[x, y, z]와 달리, 수학 연산(+, −, ×)을 바로 할 수 있습니다.
v1: vector 만들어보기 (기본)¶
실행 환경: VPython 3.2 (Web VPython 또는 로컬 설치)
from vpython import *
# 벡터 만들기 — 오른쪽 2, 위로 3, 앞으로 0
v = vector(2, 3, 0)
# 벡터의 각 성분 확인
print(v) # 전체 출력
print(v.x) # x 성분만
print(v.y) # y 성분만
print(v.z) # z 성분만
예상 출력:
위 코드의 3번째 줄 v = vector(2, 3, 0)이 바로 벡터 객체 생성입니다. 숫자 세 개를 넣으면, 3D 공간에서의 방향과 크기를 하나의 변수에 담을 수 있습니다.
📊 리스트 vs vector — 뭐가 다를까?¶
"파이썬 리스트 [2, 3, 0]이랑 뭐가 다른데요?"라고 궁금하시죠? 핵심 차이를 볼게요:
from vpython import *
# 파이썬 리스트로 시도
list_a = [2, 3, 0]
list_b = [1, 1, 0]
# list_a + list_b → [2, 3, 0, 1, 1, 0] ← 이어붙이기! 😢
# VPython vector로 시도
vec_a = vector(2, 3, 0)
vec_b = vector(1, 1, 0)
print(vec_a + vec_b) # <- 여기가 벡터 덧셈!
예상 출력:
| 연산 | 리스트 [2,3,0] + [1,1,0] |
vector vector(2,3,0) + vector(1,1,0) |
|---|---|---|
| 결과 | [2, 3, 0, 1, 1, 0] (이어붙이기) |
<3, 4, 0> (성분별 더하기) ✅ |
| 의미 | 프로그래밍적 연결 | 수학적 벡터 덧셈 |
리스트는 그냥 숫자를 담는 가방이고, vector는 수학을 이해하는 똑똑한 가방인 셈이죠! 🎒
v2: 벡터 연산 — 덧셈, 뺄셈, 스칼라곱¶
이제 벡터끼리의 연산을 해봅시다. 이전 v1 코드에 연산을 추가합니다:
from vpython import *
a = vector(2, 3, 0)
b = vector(1, -1, 0)
# 벡터 덧셈: 성분끼리 더하기
print("a + b =", a + b) # <- 여기가 벡터 덧셈
# 벡터 뺄셈: 성분끼리 빼기
print("a - b =", a - b) # <- 여기가 벡터 뺄셈
# 스칼라곱: 모든 성분에 같은 수를 곱하기
print("3 * a =", 3 * a) # <- 여기가 스칼라곱
print("0.5 * b =", 0.5 * b)
예상 출력:
개념-코드 매핑:
- 7번째 줄
a + b— 벡터 덧셈: 각 성분끼리 더합니다. (2+1, 3+(-1), 0+0) = (3, 2, 0) - 10번째 줄
a - b— 벡터 뺄셈: 각 성분끼리 뺍니다. (2−1, 3−(−1), 0−0) = (1, 4, 0) - 13번째 줄
3 * a— 스칼라곱: 숫자(스칼라) × 벡터 = 모든 성분에 곱합니다. (3×2, 3×3, 3×0) = (6, 9, 0)
벡터 연산을 한눈에 정리하면:
🚨 에러 경험: vector끼리 곱하면?¶
아래 코드를 실행하면 어떤 에러가 날까요?
from vpython import *
a = vector(2, 3, 0)
b = vector(1, -1, 0)
# vector끼리 * 연산을 시도!
result = a * b
print(result)
에러 메시지:
원인 분석: * 연산자는 숫자 × 벡터 (스칼라곱)에만 사용할 수 있습니다. 벡터끼리 곱하려면 dot(a, b) (내적)이나 cross(a, b) (외적)이라는 별도 함수를 사용해야 합니다. 이 내용은 물리 시뮬레이션 심화에서 다루므로, 지금은 "벡터끼리는 * 안 됨!" 만 기억하세요.
수정 코드 — 스칼라곱으로 바꾸기:
예상 출력:
💡 핵심 정리: 벡터 연산 규칙¶
| 연산 | 코드 | 가능 여부 | 결과 |
|---|---|---|---|
| 벡터 + 벡터 | a + b |
✅ | 성분별 덧셈 |
| 벡터 − 벡터 | a - b |
✅ | 성분별 뺄셈 |
| 숫자 × 벡터 | 3 * a |
✅ | 모든 성분에 곱 |
| 벡터 × 벡터 | a * b |
❌ | TypeError 에러! |
| 벡터 / 숫자 | a / 2 |
✅ | 모든 성분을 나눔 |
🛠️ 실습 1 — arrow로 벡터를 눈에 보이게! (10분)¶
벡터를 숫자로만 보면 감이 안 잡힙니다. VPython의 arrow 객체를 사용해서 벡터를 3D 공간에 직접 그려봅시다!
v1: 화살표 하나 그리기¶
from vpython import *
# 3D 캔버스 생성
scene = canvas(title="벡터 시각화", width=600, height=400)
# 벡터를 화살표로 표현
# pos: 화살표 시작점, axis: 화살표 방향과 길이(= 벡터!)
my_arrow = arrow(
pos=vector(0, 0, 0), # 원점에서 시작
axis=vector(3, 2, 0), # <- 여기가 우리가 표현할 벡터!
color=color.yellow,
shaftwidth=0.1 # 화살표 굵기
)
실행 결과: 원점 (0,0,0)에서 (3,2,0) 방향으로 노란색 화살표가 그려집니다.
위 코드의 10번째 줄 axis=vector(3, 2, 0)이 바로 화살표가 나타내는 벡터입니다. axis는 "화살표가 가리키는 방향과 길이"를 의미해요.
v2: 두 벡터의 덧셈을 눈으로 확인¶
이전 코드에서 두 번째 벡터와 합 벡터를 추가합니다:
from vpython import *
scene = canvas(title="벡터 덧셈 시각화", width=600, height=400)
# 벡터 a (빨간색)
a = vector(3, 1, 0)
arrow_a = arrow(pos=vector(0, 0, 0), axis=a,
color=color.red, shaftwidth=0.1)
# 벡터 b (파란색) — a의 끝점에서 시작!
b = vector(1, 2, 0)
arrow_b = arrow(pos=a, axis=b, # <- pos가 a! (이어 그리기)
color=color.blue, shaftwidth=0.1)
# 벡터 a+b (초록색) — 원점에서 최종 도착점까지
result = a + b # <- 벡터 덧셈!
arrow_sum = arrow(pos=vector(0, 0, 0), axis=result,
color=color.green, shaftwidth=0.15)
# 라벨로 표시
label(pos=a/2, text="a", color=color.red)
label(pos=a + b/2, text="b", color=color.blue)
label(pos=result/2 + vector(0, -0.3, 0), text="a+b", color=color.green)
실행 결과: 빨간 화살표(a) 끝에 파란 화살표(b)가 이어지고, 초록 화살표(a+b)가 원점에서 최종 도착점까지 한 번에 연결됩니다.
개념-코드 매핑:
- 12번째 줄
pos=a— 벡터 b의 시작점을 a의 끝점에 놓아서 이어 그리기(tip-to-tail) 를 구현합니다. - 16번째 줄
result = a + b— 벡터 덧셈의 결과를 계산합니다. 이것이 합벡터입니다. - 17번째 줄의 초록 화살표가 "원점에서 최종 도착점까지의 지름길" — 바로 벡터 덧셈의 기하학적 의미입니다!
v3: pos 이동에 벡터 활용하기¶
이제 핵심입니다! 벡터를 물체의 위치 변경에 사용해봅시다. 3차시에서 pos.x만 바꾸던 것을, 벡터 한 줄로 깔끔하게 바꿉니다:
from vpython import *
scene = canvas(title="벡터로 위치 이동", width=600, height=400)
ball = sphere(pos=vector(0, 0, 0), radius=0.3, color=color.cyan)
# 이동할 방향과 거리를 벡터 하나로!
displacement = vector(2, 1.5, 0) # <- 이동 벡터 (변위)
# 위치 업데이트: 현재 위치 + 이동 벡터 = 새 위치
ball.pos = ball.pos + displacement # <- 벡터 덧셈으로 위치 변경!
print("공의 새 위치:", ball.pos)
예상 출력:
이전 방식(3차시)과 비교해볼까요?
| 3차시 방식 (성분별) | 4차시 방식 (벡터) |
|---|---|
ball.pos.x = ball.pos.x + 2 |
ball.pos = ball.pos + vector(2, 1.5, 0) |
ball.pos.y = ball.pos.y + 1.5 |
(한 줄이면 끝!) |
| 2줄 필요, z도 바꾸면 3줄 | 1줄로 3D 이동 완료 ✅ |
11번째 줄 ball.pos = ball.pos + displacement가 바로 벡터를 활용한 위치 업데이트입니다. 이 패턴이 앞으로 속도, 가속도를 배울 때 계속 반복됩니다!
📖 핵심 개념 2: mag와 norm 함수 (10분)¶
🎯 비유로 시작: 레시피의 "방향"과 "양"¶
카레를 만들 때 "물 500ml"라고 하면: - 방향: 물 (다른 재료가 아님) - 크기: 500ml (양)
벡터도 마찬가지입니다. vector(3, 4, 0)에는:
- 방향: 오른쪽으로 약간, 위로 조금 더 (3:4 비율)
- 크기: 이 벡터의 총 길이
이 둘을 분리해서 다룰 수 있으면 매우 강력합니다! 🔧
🔎 정의: mag와 norm¶
mag(v)또는v.mag: 벡터 v의 크기(magnitude) 를 반환합니다. 피타고라스 정리로 계산됩니다: √(x² + y² + z²)norm(v)또는hat(v)또는v.hat: 벡터 v와 같은 방향이지만 크기가 1인 벡터(단위벡터)를 반환합니다.
v1: mag 사용해보기¶
from vpython import *
v = vector(3, 4, 0)
# 벡터의 크기(길이) 구하기
length = mag(v) # <- 여기가 mag (크기 구하기)
print("벡터:", v)
print("크기:", length)
# 수학적으로 확인: sqrt(3² + 4²) = sqrt(9+16) = sqrt(25) = 5
print("검증:", (3**2 + 4**2)**0.5)
예상 출력: