벡터와 행렬로 데이터를 공간에 놓기
데이터는 표 안에만 있지 않다
이전 장에서 우리는 숫자를 그래프로 바꾸는 순간, 데이터가 눈에 보이는 모양을 갖는다는 사실을 살펴보았다. 매출은 선 그래프 위에서 오르내리고, 사용자 행동은 막대그래프에서 비교되며, 두 변수의 관계는 산점도 위의 점들로 나타난다.
이번 장에서는 그 생각을 한 단계 더 밀고 나간다. 데이터는 그래프 위의 점이 될 수 있을 뿐 아니라, 더 넓은 공간 안의 위치가 될 수 있다. 사용자는 하나의 점이 되고, 상품도 하나의 점이 된다. 문서, 이미지, 검색어, 음악, 영화, 코드 조각까지 모두 숫자로 이루어진 공간 어딘가에 놓을 수 있다.
처음 들으면 조금 낯설다. "사용자가 공간에 놓인다고?" 하지만 개발 실무에서는 이미 이런 방식이 널리 쓰인다. 추천 시스템은 사용자의 취향과 상품의 특징을 같은 공간에 놓고 가까운 것을 찾는다. 검색 엔진은 검색어와 문서를 숫자 공간에 배치한 뒤 방향이 비슷한 문서를 우선 보여 준다. AI 모델은 문장과 이미지를 벡터라는 숫자 묶음으로 바꾼 뒤, 그 위치와 관계를 계산한다. 그래픽스에서는 물체의 위치, 방향, 회전, 크기를 벡터와 행렬로 다룬다.
이 장의 목표는 복잡한 선형대수 공식을 외우는 것이 아니다. 핵심은 단순하다.
데이터를 숫자의 목록으로만 보지 말고, 공간 안의 점과 방향으로 보는 감각을 얻는 것이다.

벡터는 여러 숫자를 한 덩어리로 묶은 데이터다
벡터를 처음 배울 때 흔히 화살표 그림이 나온다. 원점에서 시작해 어떤 방향으로 뻗어 나가는 화살표 말이다. 이 그림은 매우 중요하지만, 개발자에게는 조금 더 친숙한 설명이 필요하다.
벡터는 여러 숫자를 순서 있게 묶은 값이다.
예를 들어 어떤 상품을 다음과 같은 숫자로 표현한다고 해 보자.
상품 A = [가격 점수, 평점, 리뷰 수, 할인율]
= [0.7, 0.9, 0.4, 0.2]이 숫자 묶음 하나가 벡터다. 여기서 첫 번째 값은 가격과 관련된 점수, 두 번째 값은 평점, 세 번째 값은 리뷰 수, 네 번째 값은 할인율을 나타낸다. 상품 A는 이제 단순히 데이터베이스의 한 행이 아니라, 네 개의 축을 가진 공간 안의 한 점이 된다.
사용자도 벡터로 표현할 수 있다.
사용자 U = [저가 선호도, 고평점 선호도, 인기 상품 선호도, 할인 민감도]
= [0.8, 0.6, 0.3, 0.9]이 벡터는 사용자가 어떤 성향을 가졌는지 숫자로 나타낸다. 저가 상품을 좋아하고, 할인에 민감하며, 평점도 어느 정도 본다는 식이다. 추천 시스템은 이런 사용자 벡터와 상품 벡터를 비교해 "이 사용자에게 이 상품이 잘 맞을까?"를 계산한다.
여기서 중요한 점은 벡터가 꼭 물리적인 위치만 뜻하지 않는다는 것이다. 벡터는 속성들의 묶음이다. 그리고 속성이 여러 개 모이면 데이터는 공간 안의 위치처럼 해석될 수 있다.
차원은 속성의 개수다
2차원 좌표는 익숙하다. 화면에서 어떤 버튼의 위치를 나타낼 때 x와 y를 사용한다.
버튼 위치 = [x, y] = [120, 40]3차원도 크게 어렵지 않다. 게임이나 3D 그래픽스에서 물체의 위치는 x, y, z로 표현된다.
캐릭터 위치 = [x, y, z] = [10, 0, 25]그렇다면 4차원, 10차원, 100차원은 무엇일까? SF 영화에 나오는 이상한 공간을 상상할 필요는 없다. 개발자 관점에서는 차원이 곧 속성의 개수라고 생각하면 된다.
상품을 가격, 평점, 리뷰 수, 할인율이라는 네 개의 속성으로 표현하면 4차원 벡터다. 문서를 1,000개의 단어 중요도로 표현하면 1,000차원 벡터다. 이미지를 픽셀 값들의 묶음으로 표현하면 수천, 수만 차원의 벡터가 될 수 있다. AI 모델에서 자주 등장하는 임베딩 벡터는 보통 수십 차원에서 수천 차원까지 다양하다.
예를 들어 문서를 다음처럼 표현할 수 있다.
문서 D = ["수학" 점수, "개발" 점수, "AI" 점수, "보안" 점수]
= [0.8, 0.9, 0.7, 0.1]이 문서는 수학, 개발, AI와는 관련이 높고 보안과는 관련이 낮다. 다른 문서가 다음과 같다면 어떨까?
문서 E = [0.7, 0.8, 0.6, 0.2]두 문서는 꽤 비슷해 보인다. 숫자들이 비슷하기 때문이다. 즉, 두 문서는 이 4차원 공간에서 가까운 곳에 놓여 있을 가능성이 높다.
물론 현실의 데이터는 이렇게 깔끔하지 않다. 어떤 속성은 0에서 1 사이이고, 어떤 속성은 수백만 단위일 수 있다. 예를 들어 상품 가격이 1,000,000이고 평점이 4.8이라면, 계산할 때 가격이 다른 속성을 압도할 수 있다. 그래서 벡터를 만들 때는 값을 적절히 정규화한다. 정규화는 서로 다른 단위의 숫자들을 비교 가능한 범위로 맞추는 작업이다.
벡터를 잘 만든다는 것은 결국 질문을 잘 정의한다는 뜻이다. "이 데이터를 어떤 속성으로 설명할 것인가?" "각 속성은 얼마나 중요하게 볼 것인가?" "서로 다른 단위는 어떻게 맞출 것인가?" 이런 질문에 답해야 비로소 숫자 묶음이 의미 있는 공간이 된다.
벡터는 점이면서 방향이다
벡터는 두 가지 방식으로 볼 수 있다. 하나는 공간 안의 점이고, 다른 하나는 방향과 크기를 가진 화살표다.
사용자 벡터를 점으로 보면 "이 사용자는 취향 공간의 어디쯤 있는가?"를 묻는 것이다. 사용자 A와 사용자 B가 가까운 위치에 있다면 두 사용자는 비슷한 취향을 가졌다고 볼 수 있다.
반대로 벡터를 방향으로 보면 "이 데이터는 어떤 쪽을 향하고 있는가?"를 묻는다. 예를 들어 어떤 문서 벡터가 개발, 수학, AI 축 방향으로 강하게 뻗어 있다면 그 문서는 그 주제들과 관련이 깊다고 볼 수 있다.
벡터에는 크기도 있다. 2차원 벡터 [3, 4]의 크기는 5다. 피타고라스 정리를 떠올리면 된다.
크기([3, 4]) = sqrt(3*3 + 4*4) = 5차원이 늘어나도 원리는 같다.
크기([a, b, c]) = sqrt(a*a + b*b + c*c)크기는 데이터의 강도나 양을 나타낼 수 있다. 문서 벡터에서 크기가 크다는 것은 특정 단어들이 많이 등장했거나, 여러 특징이 강하게 나타난다는 뜻일 수 있다. 하지만 검색이나 추천에서는 크기보다 방향이 더 중요할 때가 많다. 같은 주제를 다룬 짧은 글과 긴 글은 단어 수가 다르므로 벡터의 크기는 다를 수 있지만, 바라보는 방향은 비슷할 수 있다.
이 차이가 뒤에서 볼 코사인 유사도의 핵심이다.
벡터 덧셈은 의미를 섞는 연산이다
벡터 덧셈은 같은 위치의 숫자끼리 더하는 연산이다.
[1, 2, 3] + [4, 5, 6] = [5, 7, 9]공식은 단순하지만 의미는 꽤 강력하다. 벡터를 방향으로 보면, 덧셈은 두 방향의 움직임을 합치는 것이다. 게임에서 캐릭터가 오른쪽으로 움직이는 속도와 위쪽으로 움직이는 속도를 더하면 최종 이동 방향이 나온다.
오른쪽 이동 = [1, 0]
위쪽 이동 = [0, 1]
최종 이동 = [1, 1]추천 시스템에서도 비슷한 생각을 할 수 있다. 사용자가 최근 본 상품들의 벡터를 더하면 사용자의 최근 관심사가 만들어진다.
최근 본 상품 1 = [0.9, 0.1, 0.2]
최근 본 상품 2 = [0.8, 0.2, 0.1]
최근 본 상품 3 = [0.7, 0.3, 0.2]
합계 = [2.4, 0.6, 0.5]이 합계 벡터는 사용자의 관심이 첫 번째 속성 쪽으로 강하게 기울어 있음을 보여 준다. 다만 본 상품 개수가 많아질수록 값이 커지므로, 보통은 평균을 낸다.
평균 관심 벡터 = [2.4, 0.6, 0.5] / 3
= [0.8, 0.2, 0.166...]이 평균 벡터는 "이 사용자는 대체로 어떤 방향의 상품을 좋아하는가?"를 나타낸다. 클러스터링이나 추천에서 자주 등장하는 중심점이라는 개념도 이와 비슷하다. 여러 데이터 포인트의 평균을 구하면 그 그룹을 대표하는 위치를 얻을 수 있다.
벡터 덧셈을 단순 계산으로만 보지 말자. 개발 실무에서는 여러 신호를 합쳐 하나의 판단을 만드는 일이 많다. 최근 클릭, 장바구니 추가, 구매, 검색어, 체류 시간은 모두 사용자의 의도를 나타내는 작은 방향들이다. 이 방향들을 어떻게 더하느냐에 따라 시스템이 사용자를 이해하는 방식이 달라진다.
스칼라 곱은 중요도를 조절하는 손잡이다
스칼라는 하나의 숫자다. 벡터에 스칼라를 곱하면 벡터의 각 값에 같은 숫자를 곱한다.
3 * [1, 2, 4] = [3, 6, 12]기하학적으로 보면 방향은 그대로 두고 크기만 키우거나 줄이는 연산이다. 0.5를 곱하면 절반만큼 약해지고, 2를 곱하면 두 배로 강해진다. 음수를 곱하면 방향이 반대로 뒤집힌다.
개발 관점에서는 스칼라 곱을 가중치 조정으로 이해하면 좋다. 모든 신호가 같은 중요도를 갖지는 않는다. 사용자가 상품을 단순히 조회한 것보다 장바구니에 넣은 것이 더 강한 관심 신호일 수 있다. 구매는 그보다 더 강한 신호일 수 있다.
조회한 상품 벡터 * 1
장바구니 상품 벡터 * 3
구매한 상품 벡터 * 5이렇게 가중치를 곱한 뒤 더하면 사용자의 취향 벡터를 만들 수 있다. 단순히 최근 본 상품을 모두 더하는 것보다 훨씬 현실적인 모델이 된다.
사용자 취향 = 1 * 조회 벡터 + 3 * 장바구니 벡터 + 5 * 구매 벡터AI 모델의 학습에서도 비슷한 일이 일어난다. 모델은 입력 신호마다 가중치를 곱하고, 그 결과를 합쳐 예측을 만든다. 어떤 특징은 크게 반영하고, 어떤 특징은 작게 반영한다. 스칼라 곱은 그 크기를 조절하는 가장 기본적인 도구다.
프론트엔드 애니메이션에서도 같은 감각이 쓰인다. 방향 벡터에 속도라는 스칼라를 곱하면 실제 이동량이 된다.
이동량 = 방향 * 속도방향과 크기를 분리해서 생각할 수 있으면 움직임, 추천, 모델 학습, 점수 계산을 훨씬 깔끔하게 이해할 수 있다.
거리와 유사도는 비슷하지만 같은 말이 아니다
데이터를 공간에 놓으면 자연스럽게 이런 질문이 생긴다.
"두 데이터는 얼마나 가까운가?"
가장 직관적인 방법은 거리다. 2차원 평면에서 두 점 사이의 거리를 구하듯이, 벡터 사이의 거리도 구할 수 있다.
A = [1, 2]
B = [4, 6]
거리(A, B) = sqrt((4-1)^2 + (6-2)^2)
= sqrt(3^2 + 4^2)
= 5차원이 늘어나도 같은 방식으로 계산한다. 각 차원의 차이를 구하고, 제곱해서 더한 뒤, 제곱근을 취한다. 이것을 유클리드 거리라고 부른다.
거리는 실제 위치 차이가 중요할 때 유용하다. 예를 들어 지도 좌표에서 두 장소가 얼마나 떨어져 있는지, 이미지 색상 값이 얼마나 다른지, 센서 데이터가 정상 범위에서 얼마나 벗어났는지 볼 때 사용할 수 있다.
하지만 모든 문제에서 거리가 최선은 아니다. 검색에서는 문서의 길이가 문제가 된다. 같은 주제를 다룬 짧은 글과 긴 글은 방향은 비슷하지만, 단어 수가 많아지면서 벡터 크기가 커질 수 있다. 이때 단순 거리만 보면 두 문서가 멀다고 판단할 수 있다.
추천에서도 비슷하다. 어떤 사용자는 많은 상품을 평가했고, 어떤 사용자는 적은 상품만 평가했을 수 있다. 활동량의 차이가 취향의 차이처럼 보이면 곤란하다. 그래서 유사도를 계산할 때는 "얼마나 가까운가?"뿐 아니라 "얼마나 같은 방향을 바라보는가?"도 중요하게 본다.
그때 등장하는 것이 내적과 코사인 유사도다.
내적은 같은 방향을 얼마나 바라보는지 재는 도구다
내적은 두 벡터의 같은 위치 값끼리 곱한 뒤 모두 더하는 연산이다.
A = [1, 2, 3]
B = [4, 5, 6]
내적(A, B) = 1*4 + 2*5 + 3*6
= 4 + 10 + 18
= 32계산 자체는 어렵지 않다. 그런데 이 단순한 연산이 왜 중요할까?
내적은 두 벡터가 얼마나 같은 방향을 향하는지 알려 준다. 같은 위치의 값이 함께 클수록 내적은 커진다. 한쪽에서 큰 값이 다른 쪽에서도 크면 "두 벡터는 비슷한 특징을 강하게 공유한다"고 볼 수 있다.
검색 예시를 보자. 검색어를 벡터로 만들고 문서도 벡터로 만든다.
축 = [수학, 개발, 요리]
검색어 Q = [1.0, 0.9, 0.0]
문서 A = [0.8, 0.7, 0.1]
문서 B = [0.1, 0.2, 0.9]검색어 Q는 수학과 개발에 관심이 있고 요리와는 관련이 없다. 문서 A도 수학과 개발 쪽 점수가 높다. 문서 B는 요리 쪽 점수가 높다.
내적을 계산하면 다음과 같다.
내적(Q, A) = 1.0*0.8 + 0.9*0.7 + 0.0*0.1
= 0.8 + 0.63 + 0
= 1.43
내적(Q, B) = 1.0*0.1 + 0.9*0.2 + 0.0*0.9
= 0.1 + 0.18 + 0
= 0.28문서 A의 점수가 훨씬 높다. 검색어와 같은 방향을 더 많이 바라보고 있기 때문이다.
추천에서도 같은 방식이 가능하다. 사용자 벡터와 상품 벡터의 내적이 크면, 사용자가 중요하게 여기는 속성과 상품이 가진 속성이 잘 맞는다고 볼 수 있다.
사용자 U = [저가 선호, 품질 선호, 할인 선호]
= [0.9, 0.6, 0.8]
상품 P = [저가 점수, 품질 점수, 할인 점수]
= [0.8, 0.7, 0.9]
내적(U, P) = 0.9*0.8 + 0.6*0.7 + 0.8*0.9
= 0.72 + 0.42 + 0.72
= 1.86이 값은 추천 점수처럼 사용할 수 있다. 물론 실제 추천 시스템은 훨씬 복잡하지만, 기본 아이디어는 여기서 크게 벗어나지 않는다. 사용자와 상품을 같은 공간에 놓고, 서로 얼마나 잘 맞는지 계산한다.
내적을 직관적으로 해석하면 다음과 같다.
두 벡터가 비슷한 방향이면 내적은 커진다.
두 벡터가 서로 관련 없는 방향이면 내적은 0에 가까워진다.
두 벡터가 반대 방향이면 내적은 음수가 될 수 있다.
이 세 가지 감각만 있어도 검색, 추천, 임베딩 모델의 많은 설명이 훨씬 덜 낯설어진다.
코사인 유사도는 크기를 빼고 방향만 비교한다
내적은 유용하지만 한 가지 문제가 있다. 벡터의 크기가 클수록 내적도 커지기 쉽다. 예를 들어 어떤 문서가 단지 길다는 이유만으로 많은 단어 점수를 갖고 있다면, 검색어와 정말 잘 맞지 않아도 내적이 커질 수 있다.
이 문제를 줄이기 위해 코사인 유사도를 사용한다. 코사인 유사도는 두 벡터의 내적을 각 벡터의 크기로 나눈 값이다.
코사인 유사도(A, B) = 내적(A, B) / (크기(A) * 크기(B))이렇게 나누면 벡터의 크기 효과가 줄어들고, 두 벡터가 이루는 방향의 유사성이 더 잘 드러난다.
예를 들어 다음 두 문서를 보자.
문서 A = [1, 1, 0]
문서 B = [10, 10, 0]문서 B는 문서 A보다 값이 10배 크다. 하지만 방향은 같다. 둘 다 첫 번째와 두 번째 주제에 같은 비율로 관련되어 있고, 세 번째 주제와는 관련이 없다. 코사인 유사도는 이런 두 벡터를 매우 비슷하다고 판단한다.
반대로 다음 문서는 다르다.
문서 C = [0, 0, 10]문서 C는 세 번째 주제만 강하다. 문서 A와 문서 C는 크기만 보면 둘 다 값이 있지만, 바라보는 방향이 다르다. 코사인 유사도는 이 둘을 비슷하지 않다고 본다.
검색 엔진, 추천 시스템, 문서 분류, 이미지 검색, 문장 임베딩 비교에서는 이런 방향 비교가 매우 중요하다. 특히 텍스트 데이터에서는 길이가 제각각이기 때문에, 단순한 내적이나 거리보다 코사인 유사도가 더 자연스러운 경우가 많다.
간단한 의사 코드로 보면 다음과 같다.
function cosineSimilarity(a, b):
dot = 0
normA = 0
normB = 0
for i from 0 to length(a)-1:
dot += a[i] * b[i]
normA += a[i] * a[i]
normB += b[i] * b[i]
return dot / (sqrt(normA) * sqrt(normB))여기서 dot은 같은 방향으로 겹치는 정도이고, normA와 normB는 각 벡터의 크기다. 결국 코사인 유사도는 "두 데이터가 얼마나 같은 방향을 향하는가?"라는 질문에 답한다.
임베딩은 의미를 좌표로 바꾸는 기술이다
지금까지는 사람이 직접 축을 정하는 예시를 많이 보았다. 상품 벡터의 축을 가격, 평점, 리뷰 수, 할인율로 정하거나, 문서 벡터의 축을 수학, 개발, 요리 같은 주제로 정했다.
하지만 AI에서는 사람이 축 하나하나의 의미를 직접 정하지 않는 경우가 많다. 모델이 데이터를 학습하면서 적절한 좌표를 스스로 만든다. 이렇게 만들어진 벡터 표현을 임베딩이라고 부른다.
임베딩은 데이터를 숫자 공간에 심어 놓는 방법이다. 문장을 임베딩하면 의미가 비슷한 문장들이 가까운 위치나 비슷한 방향에 놓인다. 상품을 임베딩하면 함께 구매되거나 비슷한 취향을 가진 사용자가 좋아하는 상품들이 가까워질 수 있다. 이미지를 임베딩하면 시각적으로 비슷하거나 같은 개념을 담은 이미지들이 가까운 위치에 놓일 수 있다.
예를 들어 검색어가 "입문자를 위한 파이썬 수학"이라고 해 보자. 전통적인 검색은 문서에 같은 단어가 있는지 많이 본다. 물론 이것도 중요하다. 하지만 임베딩 기반 검색은 문장의 의미를 벡터로 바꾼 뒤, 의미적으로 가까운 문서를 찾을 수 있다. 문서 제목에 "초보 개발자를 위한 알고리즘 기초"라고 되어 있어도, 내용이 비슷하면 검색 결과에 올라올 가능성이 생긴다.
추천에서도 마찬가지다. 사용자가 본 상품의 이름이 정확히 같지 않아도, 임베딩 공간에서 가까운 상품을 찾으면 "비슷한 취향의 다른 상품"을 추천할 수 있다. 음악 추천에서는 장르, 분위기, 청취 패턴이 섞이고, 쇼핑 추천에서는 카테고리, 가격대, 브랜드, 사용자의 행동 기록이 함께 반영된다.
임베딩을 이해할 때 중요한 것은 축의 이름을 몰라도 된다는 점이다. 어떤 차원이 정확히 "가격"이고 어떤 차원이 정확히 "분위기"인지 사람이 해석하기 어려울 수 있다. 그래도 벡터 공간 안에서 가까움과 방향은 계산할 수 있다. AI 시스템은 바로 이 계산 가능한 관계를 활용한다.
행렬은 벡터를 여러 개 쌓아 놓은 표다
벡터 하나가 데이터 한 건이라면, 행렬은 그런 벡터 여러 개를 모아 놓은 것이다.
사용자 1 = [0.9, 0.6, 0.8]
사용자 2 = [0.2, 0.9, 0.1]
사용자 3 = [0.7, 0.4, 0.6]이 사용자 벡터들을 행으로 쌓으면 행렬이 된다.
사용자 행렬 U = [
[0.9, 0.6, 0.8],
[0.2, 0.9, 0.1],
[0.7, 0.4, 0.6]
]행렬은 2차원 배열처럼 생겼다. 그래서 개발자에게 비교적 친숙하다. 하지만 행렬은 단순한 표가 아니다. 행과 열에 수학적 의미가 들어간다.
보통 데이터 분석과 머신러닝에서는 행 하나가 데이터 한 건이고, 열 하나가 속성 하나인 경우가 많다.
행: 사용자, 상품, 문서, 이미지 같은 개별 데이터
열: 나이, 가격, 클릭 수, 단어 점수, 픽셀 값 같은 특징예를 들어 다음 행렬은 세 개의 문서를 네 개의 주제 점수로 표현한 것이다.
문서 행렬 D = [
[0.8, 0.9, 0.7, 0.1],
[0.1, 0.2, 0.0, 0.9],
[0.7, 0.8, 0.6, 0.2]
]첫 번째 문서는 첫 번째, 두 번째, 세 번째 주제와 관련이 높고, 두 번째 문서는 네 번째 주제와 관련이 높다. 세 번째 문서는 첫 번째 문서와 비슷해 보인다.
이미지도 행렬로 볼 수 있다. 흑백 이미지는 각 픽셀의 밝기 값을 담은 2차원 행렬이다. 컬러 이미지는 빨강, 초록, 파랑 값을 따로 가지므로 여러 개의 행렬이 겹친 구조로 볼 수 있다.
추천 시스템에서는 사용자와 상품의 관계를 행렬로 나타낼 수 있다.
평점 행렬 R = [
[5, 4, ?, 1],
[?, 5, 4, 1],
[1, ?, 5, 4]
]행은 사용자, 열은 상품이다. 물음표는 아직 평가하지 않은 상품이다. 추천 시스템은 이런 빈칸을 예측하려고 한다. "이 사용자가 아직 보지 않은 상품에 몇 점을 줄까?"라는 질문을 행렬 위의 문제로 바꾸는 것이다.
행렬 곱셈은 여러 내적을 한 번에 계산한다
행렬 곱셈은 처음 보면 이상하다. 왜 같은 위치끼리 곱하지 않고, 행과 열을 복잡하게 곱하는지 의문이 든다. 하지만 벡터의 내적을 이해했다면 행렬 곱셈도 훨씬 쉬워진다.
행렬 곱셈은 행 벡터와 열 벡터의 내적을 여러 번 계산하는 연산이다.
예를 들어 사용자 두 명과 상품 세 개가 있다고 하자. 사용자는 세 가지 취향 속성으로 표현된다.
사용자 행렬 U = [
[0.9, 0.6, 0.8],
[0.2, 0.9, 0.1]
]상품도 같은 세 가지 속성으로 표현할 수 있다. 그런데 행렬 곱셈을 하려면 상품 벡터를 열 방향으로 배치하면 편하다.
상품 행렬 P = [
[0.8, 0.1, 0.7],
[0.7, 0.9, 0.4],
[0.9, 0.2, 0.6]
]여기서 P의 첫 번째 열은 상품 1, 두 번째 열은 상품 2, 세 번째 열은 상품 3이라고 생각하자.
상품 1 = [0.8, 0.7, 0.9]
상품 2 = [0.1, 0.9, 0.2]
상품 3 = [0.7, 0.4, 0.6]이제 U와 P를 곱하면 각 사용자와 각 상품의 추천 점수가 한 번에 나온다.
점수 행렬 S = U * P결과 행렬 S의 첫 번째 행, 첫 번째 열은 사용자 1과 상품 1의 내적이다.
S[1,1] = 0.9*0.8 + 0.6*0.7 + 0.8*0.9
= 0.72 + 0.42 + 0.72
= 1.86첫 번째 행, 두 번째 열은 사용자 1과 상품 2의 내적이다.
S[1,2] = 0.9*0.1 + 0.6*0.9 + 0.8*0.2
= 0.09 + 0.54 + 0.16
= 0.79이런 식으로 모든 사용자-상품 조합의 점수를 계산한다. 사용자 2에 대해서도 같은 계산이 이어진다. 행렬 곱셈은 이 많은 내적을 하나의 연산으로 묶는다.
개발자의 눈으로 보면 행렬 곱셈은 반복문을 압축한 표현이다.
for user in users:
for item in items:
score[user][item] = dot(userVector[user], itemVector[item])이중 반복문으로 모든 사용자와 모든 상품의 점수를 계산하는 일을, 수학에서는 행렬 곱셈 하나로 표현한다. 그래서 머신러닝 프레임워크와 GPU가 행렬 곱셈을 매우 중요하게 다룬다. 대량의 예측, 변환, 학습이 결국 거대한 행렬 곱셈의 반복으로 바뀌기 때문이다.
행렬 곱셈에서 모양을 보는 법
행렬 곱셈을 이해할 때 가장 먼저 확인해야 하는 것은 모양이다. 보통 행렬의 크기를 "행 개수 x 열 개수"로 쓴다.
A의 크기 = 2 x 3
B의 크기 = 3 x 4A와 B를 곱할 수 있는 이유는 A의 열 개수 3과 B의 행 개수 3이 같기 때문이다.
(2 x 3) * (3 x 4) = (2 x 4)가운데 숫자 3은 서로 맞아야 하고, 결과의 크기는 바깥 숫자인 2 x 4가 된다.
이 규칙은 단순 암기처럼 보이지만 의미가 있다. A의 한 행은 길이가 3인 벡터다. B의 한 열도 길이가 3인 벡터다. 내적을 하려면 두 벡터의 길이가 같아야 한다. 그래서 가운데 차원이 맞아야 한다.
결과가 2 x 4인 이유도 자연스럽다. A에는 행이 2개 있고, B에는 열이 4개 있다. A의 각 행과 B의 각 열을 하나씩 짝지어 내적하면 2 곱하기 4개의 결과가 나온다.
행렬 곱셈을 볼 때는 다음 세 가지를 확인하면 된다.
안쪽 차원이 같은가? 그래야 곱할 수 있다.
결과의 크기는 바깥 차원으로 정해진다.
결과의 각 칸은 왼쪽 행과 오른쪽 열의 내적이다.
이 감각은 디버깅에도 도움이 된다. 머신러닝 코드를 작성하다 보면 shape mismatch, dimension error 같은 오류를 자주 만난다. 대부분은 "벡터 길이가 맞지 않는데 내적하려고 했다"거나 "행렬의 안쪽 차원이 맞지 않는데 곱하려고 했다"는 뜻이다. 에러 메시지를 수학이 아니라 데이터 모양의 문제로 보면 훨씬 덜 무섭다.
행렬은 데이터를 변환하는 기계다
행렬은 벡터를 모아 놓은 표이기도 하지만, 동시에 벡터를 다른 벡터로 바꾸는 변환 기계이기도 하다.
예를 들어 어떤 사용자 벡터가 세 개의 속성을 갖는다고 하자.
사용자 U = [가격 민감도, 품질 선호도, 브랜드 선호도]
= [0.8, 0.6, 0.3]우리는 이 사용자를 두 개의 추천 카테고리 점수로 바꾸고 싶다.
추천 카테고리 = [가성비 상품 점수, 프리미엄 상품 점수]이때 3차원 사용자 벡터를 2차원 카테고리 점수로 바꾸는 행렬을 만들 수 있다.
변환 행렬 W = [
[0.9, 0.2],
[0.5, 0.8],
[0.1, 0.9]
]U의 크기는 1 x 3이고, W의 크기는 3 x 2다. 곱하면 결과는 1 x 2가 된다.
U * W = [가성비 점수, 프리미엄 점수]계산해 보면 다음과 같다.
가성비 점수 = 0.8*0.9 + 0.6*0.5 + 0.3*0.1
= 0.72 + 0.30 + 0.03
= 1.05
프리미엄 점수 = 0.8*0.2 + 0.6*0.8 + 0.3*0.9
= 0.16 + 0.48 + 0.27
= 0.91결과를 보면 이 사용자는 프리미엄 상품보다 가성비 상품에 조금 더 잘 맞는다. 이 예시에서 행렬 W는 각 사용자 속성을 추천 카테고리 점수로 바꾸는 규칙이다.
머신러닝 모델의 많은 부분이 이런 방식으로 동작한다. 입력 벡터에 가중치 행렬을 곱해 새로운 벡터를 만든다. 그다음 다시 다른 행렬을 곱해 또 다른 벡터로 바꾼다. 복잡한 모델도 안쪽을 들여다보면 "벡터를 행렬로 변환하고, 그 결과를 다시 변환하는 과정"이 반복된다.
그래픽스에서도 행렬은 변환 기계다. 2D나 3D 공간의 점에 행렬을 곱하면 회전, 확대, 축소, 기울이기 같은 변환을 적용할 수 있다. 다음 장에서 더 깊게 보겠지만, 물체의 위치와 방향을 다루는 많은 계산이 행렬 곱셈으로 표현된다.
검색과 추천을 하나의 그림으로 보기
이제 검색과 추천을 벡터 공간의 관점에서 다시 그려 보자.
검색에서는 검색어와 문서가 같은 공간에 놓인다. 사용자가 검색어를 입력하면 시스템은 검색어를 벡터로 바꾼다. 문서들도 미리 벡터로 만들어져 있다. 그런 다음 검색어 벡터와 문서 벡터의 유사도를 계산한다. 방향이 비슷한 문서일수록 상위에 노출된다.
추천에서는 사용자와 상품이 같은 공간에 놓인다. 사용자의 행동 기록을 바탕으로 사용자 벡터를 만들고, 상품의 속성이나 구매 패턴을 바탕으로 상품 벡터를 만든다. 사용자 벡터와 상품 벡터의 내적이나 코사인 유사도를 계산하면 추천 점수를 만들 수 있다.
이 과정을 아주 단순하게 표현하면 다음과 같다.
검색 점수 = similarity(검색어 벡터, 문서 벡터)
추천 점수 = similarity(사용자 벡터, 상품 벡터)여기서 similarity는 문제에 따라 내적일 수도 있고, 코사인 유사도일 수도 있고, 거리 기반 점수일 수도 있다. 중요한 것은 검색어, 문서, 사용자, 상품을 모두 벡터로 바꾼 뒤 같은 공간에서 비교한다는 점이다.
이 관점이 생기면 많은 실무 문제가 비슷한 모양으로 보인다.
비슷한 문서 찾기는 문서 벡터끼리 가까운 것을 찾는 문제다.
비슷한 상품 추천은 상품 벡터끼리 가까운 것을 찾는 문제다.
사용자 개인화는 사용자 벡터와 후보 콘텐츠 벡터의 궁합을 계산하는 문제다.
이미지 검색은 이미지 벡터와 검색 벡터의 유사도를 비교하는 문제다.
이상 탐지는 정상 데이터들이 모인 공간에서 멀리 떨어진 점을 찾는 문제다.
서로 다른 기능처럼 보이지만, 수학적으로는 "공간에 놓고 관계를 계산한다"는 같은 구조를 갖는다.
벡터로 만들었다고 의미가 생기는 것은 아니다
벡터와 행렬은 강력하지만, 숫자로 바꿨다고 자동으로 좋은 시스템이 되는 것은 아니다. 데이터 공간은 사람이 설계하거나 모델이 학습한 결과다. 잘못 만든 공간에서는 가까워야 할 데이터가 멀어지고, 멀어야 할 데이터가 가까워질 수 있다.
예를 들어 상품 추천에서 가격 단위를 그대로 사용하면 비싼 상품의 숫자가 너무 커져 다른 속성을 압도할 수 있다. 문서 검색에서 흔한 단어를 너무 중요하게 보면 모든 문서가 비슷해 보일 수 있다. 사용자 행동 데이터에서 클릭만 보고 구매를 보지 않으면, 실제 선호가 아니라 호기심을 추천하게 될 수 있다.
그래서 벡터를 다룰 때는 다음 질문을 계속 던져야 한다.
이 벡터의 각 차원은 무엇을 의미하는가?
서로 다른 차원의 스케일은 적절히 맞춰져 있는가?
가까움이나 방향이 실제 비즈니스 의미와 연결되는가?
빠진 데이터나 편향된 데이터가 결과를 왜곡하지 않는가?
유사도가 높다는 것이 정말 좋은 추천이나 좋은 검색 결과를 뜻하는가?
수학은 계산을 정확하게 해 주지만, 무엇을 계산할지는 개발자와 팀이 정해야 한다. 벡터 공간은 현실의 축소판이다. 축소판을 잘 만들면 복잡한 현실을 빠르게 계산할 수 있지만, 잘못 만들면 그럴듯한 숫자로 잘못된 결론을 내릴 수 있다.
개발자가 가져야 할 벡터와 행렬 감각
이 장에서 다룬 내용은 앞으로 AI, 그래픽스, 최적화, 추천, 검색을 이해하는 기반이 된다. 모든 공식을 완벽히 외울 필요는 없다. 대신 다음 감각은 꼭 가져가자.
벡터는 여러 속성을 가진 데이터 한 건이다. 사용자의 취향, 상품의 특징, 문서의 주제, 이미지의 픽셀, 문장의 의미를 숫자 묶음으로 표현할 수 있다.
차원은 속성의 개수다. 2차원과 3차원은 눈에 보이지만, 100차원과 1,000차원도 원리는 같다. 다만 차원이 많아질수록 사람이 직접 상상하기 어려워질 뿐이다.
벡터 덧셈은 여러 신호를 합치는 연산이고, 스칼라 곱은 신호의 강도를 조절하는 연산이다. 조회, 클릭, 구매 같은 행동을 서로 다른 가중치로 반영할 때 이 감각이 쓰인다.
내적은 두 벡터가 얼마나 같은 방향을 바라보는지 재는 기본 도구다. 사용자와 상품, 검색어와 문서, 이미지와 이미지의 궁합을 점수화할 수 있다.
코사인 유사도는 크기의 영향을 줄이고 방향의 비슷함을 본다. 문서 길이나 활동량처럼 크기 차이가 큰 데이터에서 특히 유용하다.
행렬은 벡터 여러 개를 모아 놓은 구조이자, 벡터를 다른 벡터로 바꾸는 변환 기계다. 행렬 곱셈은 많은 내적을 한 번에 계산하고, 여러 데이터를 한꺼번에 변환한다.
이제 데이터는 단순한 행과 열의 묶음이 아니다. 공간 안에 놓인 점이고, 방향이며, 서로의 거리를 잴 수 있는 대상이다. 이 관점이 생기면 AI 모델의 임베딩, 추천 시스템의 유사도, 검색 랭킹의 점수, 그래픽스의 변환이 하나의 언어로 연결된다.
다음 장에서는 이 언어를 조금 더 깊게 파고든다. 벡터와 행렬이 단순히 데이터를 담는 그릇을 넘어, 공간을 회전시키고 확대하고 압축하는 도구가 되는 과정을 살펴볼 것이다. 선형대수는 AI와 그래픽스가 공유하는 공통 언어다. 지금 배운 벡터와 행렬 감각이 그 문을 여는 열쇠가 된다.
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.
