이 과정에서는 우리 주변의 세계를 보고 이를 코드로 영리하게 묘사하는 방법을 배웁니다. 우선 사과가 나무에서 떨어지고, 추가 공중에서 흔들리고, 지구가 태양을 중심으로 움직이는 현상 같은 기본적인 물리법칙부터 시작해 봅시다. 여기서 다루는 모든 내용에는 벡터(vector) 개념이 들어가 있습니다. 벡터는 사물의 움직임을 프로그래밍하기 위한 가장 기본적인 구성요소입니다. 지금부터 이야기를 시작해볼까요?
벡터라는 단어에는 많은 의미가 있습니다. 벡터는 1980년대 초반 캘리포니아의 새크라멘토에서 결성된 뉴웨이브 록 밴드의 이름입니다. 벡터는 캐나다 켈로그사에서 생산되는 시리얼의 이름이기도 합니다. 전염병학에서 벡터는 한 숙주로부터 다른 숙주로 감염시키는 유기체를 일컫는 말이기도 합니다. C++ 프로그래밍 언어에서 벡터(std::vector)는 유동적으로 크기 조절이 가능한 배열 자료 구조를 구현한 것입니다. 벡터의 다양한 정의는 모두 흥미롭지만 우리가 찾는 것은 아니에요. 우리가 원하는 것은 유클리디안 벡터(Euclidean vector)(그리스 수학자 유클리드의 이름을 따랐으며 기하학적 벡터(geometric vector) 로도 알려져 있음) 입니다. 이 과정에서 “벡터”라는 용어를 보면, 크기와 방향을 모두 가지는 어떤 양 으로 정의되는 유클리디안 벡터라고 생각하면 됩니다.
일반적으로 벡터는 화살표로 표현합니다. 화살표가 가리키는 쪽은 방향을 나타내며 화살표의 길이는 크기를 나타냅니다.
위 그림에서 벡터는 점 A와 점 B를 잇는 화살표로 나타내며 A에서 B로 이동하는 한 가지 방법을 나타내고 있습니다.

왜 벡터를 사용할까요?

벡터에 관해 좀 더 자세히 살펴보기 전에 기본적인 프로그램을 살펴보고 왜 벡터에 관심을 가져야 하는지 알아봅시다. 칸아카데미에서 JS 입문자 과정을 마쳤다면 아마도 간단한 탱탱볼 프로그램 만드는 법을 배웠을 것입니다.
위 예제는 매우 단순한 세계를 묘사해 놓았습니다. 이 세계에서는 공백인 배경 위로 원(“공”)이 돌아다니는 것이 전부입니다. 이 공은 코드에서 변수로 표현되는 몇 가지 속성을 갖습니다.
위치속도
x and yxspeed and yspeed
복잡한 프로그램에는 변수가 더 많이 있습니다.
가속도타겟 위치바람마찰력
xacceleration and yaccelerationxtarget and ytargetxwind and ywindxfriction and yfriction
이 세계는 2차원 세계이기 때문에 개념(바람, 위치, 가속도 등)마다 두 개의 변수가 필요합니다. 3차원 세계에서는 x, y, z, xspeed, yspeed, zspeed 등 변수 세 개가 필요할 것입니다.
코드를 단순화하고 좀 더 적은 수의 변수를 사용할 수 있다면 좋지 않을까요?
원래 변수는 아래와 같습니다.
var x = 5;
var y = 10;
var xspeed;
var yspeed;
위 변수를 두 개로 줄여서 각 변수가 2차원의 정보를 갖는, 벡터와 유사한 객체로 만들어 봅시다.
var location;
var speed;
벡터를 사용하는 위의 첫 번째 단계에는 새로운 것이 없습니다. 단지 변수로 벡터와 유사한 객체를 이용한다고 해서 프로그램이 저절로 물리법칙을 따라 작동하지는 않습니다. 그러나 이렇게 하면 코드를 단순화시킬 수 있습니다. 또한, 움직임을 프로그래밍하는 동안 반복적인 수학 연산을 할 때 편리한 함수 집합의 역할을 합니다.
지금은 벡터 개념을 막 배우는 단계이므로 2차원 세계에 있다고 가정할 것입니다. 여기 나오는 모든 예제는 3차원으로 간단하게 확장할 수 있습니다. (우리가 사용할 객체인 PVector는 3차원 벡터를 고려한 객체입니다) 하지만 2차원부터 시작하기가 더 쉽습니다.

PVector를 이용한 프로그래밍

벡터를 생각하는 한 가지 방법은 두 점 사이의 차이입니다. 한 점에서 다른 점으로 걸어가라는 지시에 대해 걸어가는 방법에 관해 생각해 보기 바랍니다.
다음은 여러 가지 벡터와 각 성분으로 나눈 것을 나타낸 그림입니다.
| (-15, 3) | 서쪽으로 15 걸음으로 걸어간 후 돌아서 북쪽으로 3 걸음 걸어갑니다. | | (3, 4) | 동쪽으로 3 걸음 걸어간 후 돌아서 북쪽으로 4 걸음 걸어갑니다. | | (2, -1) | 동쪽으로 2 걸음 걸어간 후 돌아서 남쪽으로 1 걸음 걸어갑니다. |
지금처럼 움직임을 프로그래밍하기 전에도 본 기억이 있을 겁니다. 애니메이션의 각 프레임(ProcessingJS의 draw() 반복문의 한 주기를 떠올리세요)마다 화면에 있는 객체는 특정 수 픽셀만큼 가로 및 세로로 움직이도록 프로그래밍 합니다.
각 프레임마다:
새로운 위치 = 현 지점에 적용된 속도
속도가 벡터(두 지점 사이의 거리차) 라면, 위치는 무엇일까요? 위치도 벡터일까요? 엄밀히 말하자면, 위치와 벡터는 같은 개념이 아니라는 주장도 맞습니다. 왜냐하면, 위치가 한 점에서 다른 점으로 움직이는 방법을 나타내는 것은 아니기 때문입니다. 위치는 단순히 공간 내 한 지점을 나타내는 개념입니다.
그렇지만 위치를 정의할 때 원점에서 일정한 경로로 움직여서 도달한 장소라고 말할 수도 있습니다. 그래서 위치는 위치와 원점 사이의 차이를 표현하는 벡터라고 할 수도 있습니다.
위치와 속도에 대한 기본 데이터를 검토해 보도록 하겠습니다. 공치기 예제에 다음이 존재합니다.
위치속도
x and yxspeed and yspeed
위치와 속도에 같은 데이터인 부동 소수점 수 xy를 저장한다는 점을 잘 봐두세요. 벡터 클래스를 처음부터 작성한다면 다음과 같은 기본적인 코드부터 시작할 것입니다:
var Vector = function(x, y) {
    this.x = x;
    this.y = y;
};
본질적으로 PVector는 두 개(3차원에서는 세 개)의 값을 저장하기에 편리한 방법입니다.
그래서 다음 코드는…
var x = 100;
var y = 100;
var xspeed = 1;
var yspeed = 3.3;
이렇게 됩니다…
var location = new PVector(100,100);
var velocity = new PVector(1,3.3);
이제 두 개의 벡터 객체(위치와 속도)를 만들었으므로, 움직임에 대한 알고리즘인 location = location + velocity를 구현할 수 있습니다. 예제 1.1에서 벡터가 쓰지 않고 다음과 같이 나타냈습니다.
x = x + xspeed;
y = y + yspeed;
위의 수식을 이상적으로 표현하면 다음과 같이 나타낼 수 있습니다.
location = location + velocity;
그러나 JavaScript에서 덧셈 연산자 +는 기본 값(숫자, 스트링)에만 쓸 수 있습니다. 일부 프로그래밍 언어에서 연산자가 "중복정의(overloaded)"될 수 있으나 JavaScript에서는 그렇지 않습니다. 다행히 PVector 객체는 add()와 같은 일반적인 수학 연산 메소드를 포함하고 있습니다.

벡터 덧셈

PVector객체와 add() 메소드를 살펴보기 전에 수학과 물리 교과서에 나오는 일반적인 표기법을 이용하여 벡터의 덧셈을 살펴봅시다.
일반적으로 벡터는 볼드체(굵은 글씨) 로 표시하거나 위에 화살표를 써서 나타냅니다. 여기에서는 벡터(vector)스칼라(scalar) (스칼라 는 정수나 부동 소숫점 수와 같은 단일 값입니다.)를 구분하기 위해, 화살표 표기법을 사용하겠습니다.
  • 벡터: u \vec{u}
  • 스칼라: x x
다음과 같이 어떤 두 벡터가 있다고 가정해 봅시다.
각 벡터에는 두 개의 성분 xy가 있습니다. 두 벡터를 더한다는 것은 단순히 x의 값과 y의 값을 더하는 것입니다. 
다른 말로 하면
w=u+v \vec{w} = \vec{u} + \vec{v}
위 식은 다음과 같이 나타낼 수 있습니다.
그런 다음 uv를 그림 1.6의 값으로 바꿉니다.
이를 간단하게 하면,
마지막으로 이 값을 벡터로 나타내면 다음과 같습니다.
w=(8,6) \vec{w} = (8, 6)
이제 두 벡터의 덧셈을 어떻게 하는지 이해했으므로, 덧셈을 PVector 객체에 어떻게 구현하는지를 살펴보겠습니다. 또 다른 PVector 객체를 인수로 입력받아 x와 y 성분을 단순히 더해주는 메소드 add()를 만들어 봅시다:
var Vector = function(x, y) {
    this.x = x;
    this.y = y;
};

Vector.prototype.add = function(v) {
  this.y = this.y + v.y;
  this.x = this.x + v.x;
};
이제 add()PVector의 내부에 어떻게 입력되었는지 살펴보았습니다. location + velocity 알고리즘을 갖는 공치기 예제로 돌아가서 벡터 덧셈을 구현해 봅시다.
location.add(velocity);
그리고 이제 PVector 객체를 이용하여 탱탱볼 예제를 다시 만들 준비가 되었습니다! 코드를 보고 이전 코드와의 차이점을 한 번 찾아보세요.
위에서 바꾼 코딩법에서 한 가지 알아야 할 중요한 부분이 있습니다. 두 개의 값—위치 x와 y 값 및 속도 x와 y 값—을 나타내기 위해 PVector 객체를 이용하더라도 앞으로 각 PVector의 x와 y 성분을 개별적으로 참조해야 할 일은 자주 있습니다. ProcessingJS에서 객체를 그릴 때는 다음과 같이 표현할 방법은 없습니다.
ellipse(location, 16, 16);
ellipse() 함수는 PVector를 인수로 허용하지 않습니다. 타원은 두 개의 스칼라 값인 x-좌표와 y-좌표로만 그릴 수 있습니다. 그래서 반드시 PVector 객체에 접근하여 객체지향적 점 표기법을 이용하여 x와 y 성분을 빼야 합니다.
ellipse(location.x, location.y, 16, 16);
원이 윈도우의 가장자리에 걸쳐있는 때에도 똑같은 문제가 발생합니다. 이 때도 두 벡터인 locationvelocity의 개별 성분에 접근해야 합니다.
if ((location.x > width) || (location.x < 0)) {
  velocity.x = velocity.x * -1;
}
지금 다소 실망스러울 수 있습니다. 결국, 벡터를 사용할 때 본문 방법처럼 다르게 응용하면 먼저 했던 방법보다 코드가 더 복잡해 보일 수도 있습니다. 어려워 보이는 것이 합리적이고 타당하지만, 지금까지 본 벡터는 아무것도 아닙니다. 프로그래밍에서 벡터로 가능한 일은 무궁무진하다는 것을 알아야 합니다. 단순한 공치기를 벡터 덧셈으로 구현하는 것은 그저 첫 단계일 뿐입니다. 다양한 객체와 다양한 힘(force)(곧 배울 내용입니다.)이 존재하는 복잡한 세계를 구현하다 보면 PVector의 장점을 확실하게 느낄 수 있습니다. 계속 나아가세요!

본 "내추럴 시뮬레이션" 과정은 다니엘 쉬프만(Daniel Shiffman)이 저술한 "The Nature of Code"의 내용을 차용한 것이며, 본 내용물의 저작권은 Creative Commons Attribution-NonCommercial 3.0 Unported License를 적용합니다.
로딩 중