선형대수 이야기: 행렬은 공간을 바꾸는 동사다

피그마에서 사각형 하나를 잡고 회전시킨다. 크게 늘이고, 비스듬히 기울인다. CSS로 쓰면 transform: rotate(30deg) scale(1.4) skewX(20deg) 같은 한 줄이다. 이 모든 변형 뒤에는 똑같은 물건 하나가 돌아간다. 행렬(matrix)이다.

학교에서 행렬을 숫자를 네모나게 늘어놓은 표로 배웠다면, 그건 절반만 본 거다. 표는 행렬의 겉모습일 뿐이고, 진짜 정체는 따로 있다. 행렬은 공간을 통째로 바꾸는 동사다. 이 글은 그 이야기 하나로 선형대수의 기본을 꿰어보려 한다.

벡터는 화살표이자 좌표

시작은 벡터(vector)다. 벡터는 원점에서 뻗어 나간 화살표다. 2차원이라면 화살표 끝의 위치를 (x, y) 두 숫자로 적는다. 디자인으로 옮기면 점의 위치이자, 얼마만큼 움직이라는 이동량이기도 하다. (2, 1)은 오른쪽으로 2칸, 위로 1칸 간 자리다.

좌표는 두 기준 화살표의 조합

그런데 (2, 1)이라는 좌표에는 숨은 뜻이 하나 더 있다. 이건 기준이 되는 화살표 두 개를 얼마씩 섞었나를 적은 레시피다. 오른쪽으로 한 칸 가는 단위 화살표를 î, 위로 한 칸 가는 단위 화살표를 ĵ라고 하자. 그러면 (2, 1)은 î를 두 번, ĵ를 한 번 쌓은 것이다.

îĵv
모든 점은 기저 î와 ĵ를 얼마씩 쌓았는지로 적힌다. v = 2î + 1ĵ.

이 두 기준 화살표 î와 ĵ를 기저(basis)라고 부른다. 좌표란 언제나 이 기저를 얼마씩 쌓았느냐는 말이다. (2, 1)2î + 1ĵ의 다른 표기일 뿐이다. 사소해 보이는 이 관점이 다음 장에서 행렬의 정체를 여는 열쇠가 된다.

행렬은 기저가 어디로 가는지를 적은 것

이제 공간을 변형한다고 하자. 변형이란 결국 모든 점을 새 자리로 옮기는 일이다. 점이 무한히 많으니 막막해 보인다. 그런데 여기 결정적인 사실이 있다. 모든 점은 î와 ĵ의 조합이고, 우리가 다루는 변형(선형 변환)은 그 조합 관계를 그대로 지킨다. 2î + 1ĵ였던 점은 변형 뒤에도 여전히 새 î의 두 배에 새 ĵ의 한 배다.

그러니 î와 ĵ 딱 둘이 어디로 가는지만 정하면, 나머지 무한한 점의 행선지가 저절로 따라온다. 2×2 행렬은 바로 그 새 î와 새 ĵ의 위치를 세로줄(열)로 나란히 적어둔 것이다. 첫 열이 î의 도착지, 둘째 열이 ĵ의 도착지다.

예를 들어 î는 제자리에 두고 ĵ만 오른쪽으로 눕혀 (1, 1)로 보내는 변형을 생각해보자. 이걸 기울이기(shear)라고 한다. 행렬로 적으면 이렇다.

[ 1  1 ]   첫 열 (1,0) = 새 î,  둘째 열 (1,1) = 새 ĵ
[ 0  1 ]

이 변형을 공간 전체에 적용하면 격자가 통째로 기울어 평행사변형이 된다. 그리고 아까 그 점 v는, 여전히 새 기저로 2î + 1ĵ이므로 그 기운 격자를 따라 새 자리로 옮겨간다.

îĵ'v
행렬은 î와 ĵ를 어디로 보낼지만 정한다. 격자가 통째로 기울고, v는 여전히 2î + 1ĵ로 따라간다.

행렬을 숫자표로만 보면 [[1,1],[0,1]]은 그냥 네 개의 수다. 하지만 동사로 보면 이건 î는 그대로 두고 ĵ를 오른쪽으로 눕혀라라는 하나의 명령이다. 그게 행렬의 진짜 뜻이다.

곱셈은 그 규칙을 좌표에 적용하는 것

행렬에 벡터를 곱한다는 건 뭘 하는 걸까. 방금 이야기 그대로다. 좌표가 (x, y)인 점은 x·(새 î) + y·(새 ĵ)로 간다. 곧 x만큼 첫 열을, y만큼 둘째 열을 쌓는 것이다. 위 기울이기 행렬로 점 (2, 1)을 옮겨보자.

[ 1  1 ] [ 2 ]   = 2 × (1,0) + 1 × (1,1)
[ 0  1 ] [ 1 ]   = (2,0) + (1,1)
                 = (3, 1)

(2, 1)(3, 1)로 갔다. 공식을 외울 필요가 없다. 각 좌표만큼 새 기저를 쌓아라, 이 한 문장이 행렬 곱셈의 전부다.

익숙한 변형들이 다 행렬이다

이렇게 보면 디자인 툴의 변형이 전부 행렬로 읽힌다. 기저를 어디로 보내느냐만 다를 뿐이다.

확대 (2배)      회전 (90도)      기울이기
[ 2  0 ]        [ 0 -1 ]         [ 1  1 ]
[ 0  2 ]        [ 1  0 ]         [ 0  1 ]
î,ĵ를 늘림       î→(0,1)          ĵ를 눕힘
                ĵ→(-1,0)

CSS의 transform: matrix(a, b, c, d, tx, ty)가 정확히 이 2×2 행렬(에 이동을 더한 것)이다. 앞의 네 숫자 a, b, c, d가 바로 새 î와 새 ĵ의 좌표다. 피그마에서 변형 핸들을 잡아 돌리고 늘일 때도, 툴은 내부에서 이 숫자들을 고쳐 쓰고 있다.

행렬 곱은 변형을 이어 붙이는 것

변형을 하나 하고, 그 위에 또 하나를 하면 어떻게 될까. 두 행렬을 곱한다. 행렬 곱 AB는 B를 먼저 적용하고 그 결과에 A를 적용하라는 뜻이다. 변형을 순서대로 이어 붙이는 게 곱셈이다.

여기서 중요한 성질이 나온다. 순서를 바꾸면 결과가 달라진다. 먼저 회전하고 늘이는 것과, 먼저 늘이고 회전하는 것은 일반적으로 다른 그림이 된다. 그래서 행렬 곱은 교환법칙이 성립하지 않는다. ABBA가 다르다. CSS transform에서 함수의 순서를 바꾸면 결과가 달라지는 이유가 정확히 이것이다. rotate(30deg) scale(1.5, 1)scale(1.5, 1) rotate(30deg)는 다른 변형이다. 툴이 까다롭게 구는 게 아니라, 변형을 이어 붙이는 순서 자체가 원래 결과를 바꾼다.

덤: 행렬식은 넓이가 몇 배인지

변형이 넓이를 얼마나 키우거나 줄이는지를 한 숫자로 요약한 게 행렬식(determinant)이다. î와 ĵ가 이루던 단위 정사각형이 변형 뒤에 평행사변형이 되는데, 그 평행사변형의 넓이가 곧 행렬식이다. 2배 확대는 가로세로가 다 2배라 넓이가 4배, 그래서 행렬식이 4다. 앞의 기울이기는 격자가 비스듬해져도 넓이는 그대로라 행렬식이 1이다. 값이 음수면 공간이 뒤집힌 것(거울상), 0이면 공간이 납작하게 눌려 넓이가 사라진 것이다. 넓이가 0으로 눌리면 정보가 뭉개져서 되돌릴 수 없다. 역변환이 없다는 말과 같다.

정리

행렬은 숫자표가 아니라 공간을 바꾸는 동사다. 벡터가 점이라는 명사라면, 행렬은 그 점 전체에 작용하는 변형이다. 행렬의 열은 기저 î와 ĵ가 도착한 자리이고, 행렬 곱셈은 좌표만큼 새 기저를 쌓는 일이며, 행렬끼리의 곱은 변형을 순서대로 이어 붙이는 일이다. 다음에 피그마에서 오브젝트를 기울이거나 CSS transform을 쓸 때, 뒤에서 도는 그 숫자 네 개가 사실은 î와 ĵ의 새 주소라는 걸 떠올리면 된다. 그 순간 행렬은 외워야 할 표에서, 눈에 보이는 동작으로 바뀐다.

곱을 덧셈으로 눕히는 로그 이야기는 앞 글에서 다뤘다.

이 글, 어떠셨어요?