카테시안 곱은 두 집합의 모든 가능한 쌍을 만드는 연산이다.
집합 A에서 하나 고르고, 집합 B에서 하나 골라서 (a, b) 형태의 순서 쌍을 모두 생성한다.
예시:
그럼 A × B는 다음과 같다:
(1, a), (1, b), (1, c),
(2, a), (2, b), (2, c)
즉, |A| × |B| 만큼의 조합이 만들어지는 셈이다.
우리가 흔히 알고 있는 경우의 수 계산이랑도 사실 거의 똑같은 개념이다.
SQL에서는 CROSS JOIN이 바로 카테시안 곱이다.
SELECT *
FROM A CROSS JOIN B;
이렇게 쓰면 A 테이블의 모든 행과 B 테이블의 모든 행을 전부 짝지어서 결과를 반환한다.
예를 들어,
가 있다면, CROSS JOIN은 100 × 200 = 20,000행을 반환한다.
그래서 조인 조건을 잘못 걸면 갑자기 결과가 폭발적으로 증가하는 이유가 바로 카테시안 곱이 암묵적으로 발생했기 때문이다.
백엔드 개발자는 보통 ORM(JPA, QueryDSL 등)을 통해 SQL을 간접적으로 작성한다.
이때 조인 조건을 깜빡하면, 내부적으로 CROSS JOIN이 발생해서 트래픽을 몰아먹거나 장애가 날 수 있다.
예시 (JPA):
select a, b
from A a
join B b -- ON 조건이 없음 → 카테시안 곱 발생
이건 A × B 조합만큼 레코드가 나오기 때문에 실수 하나로 DB에 큰 부담을 줄 수 있다.
쇼핑몰/추천 시스템/재고 시스템 등에서
"모든 상품 × 모든 카테고리" 같은 조합을 임시로 만들어야 할 때 CROSS JOIN을 명시적으로 쓰기도 한다.
예:
상품 옵션 조합 생성
(S, M, L) × (Red, Black, White)
예를 들어, "지난 7일 동안 모든 사용자에 대해 빈 KPI 레코드까지 포함해 매핑" 같은 상황에서도 카테시안 곱이 자연스럽게 등장한다.
조인 조건 하나만 빠져도 결과가 n배로 폭증한다.
백엔드에서 가장 흔하게 발생하는 퍼포먼스 사고 중 하나가 바로 이 “암묵적 카테시안 곱 문제”.
JPA/QueryDSL도 결국 SQL을 만든다.
코드를 작성하는 개발자가 카테시안 곱 개념을 모르면
무심코 작성한 코드가 “조인 조건 없는 CROSS JOIN”이 되어버릴 수 있다.
조합 생성, 파생 데이터 생성 등에서 CROSS JOIN이 필요할 때가 꽤 많다.
그때 개념을 모르면 “왜 이 쿼리가 이렇게 많이 나오지?” 하고 당황하게 된다.