예제로 쉽게 배우는 SQL JOIN (Inner, Left, Right, Full)
작은 테이블 두 개, 명확한 쿼리, 정확한 결과로 INNER, LEFT, RIGHT, FULL, CROSS, SELF JOIN을 배웁니다.
- INNER JOIN: 두 테이블 모두에서 일치하는 행만 반환합니다.
- LEFT JOIN: 왼쪽의 모든 행과 일치하는 행(없으면 NULL)을 반환합니다.
- RIGHT JOIN: 오른쪽의 모든 행과 일치하는 행을 반환합니다.
- FULL JOIN: 두 테이블의 모든 행을 가능한 한 짝지어 반환합니다.
- 키로 조인하고, 테이블 별칭을 사용하며, 조인 컬럼에 인덱스를 만드세요.
실제 데이터베이스는 모든 것을 하나의 테이블에 담지 않습니다. 고객은 한 테이블에, 주문은 다른 테이블에 있습니다. “이번 달에 주문한 고객은 누구인가?”에 답하려면 둘을 결합해야 하며, 이것이 SQL JOIN의 역할입니다.
이 가이드는 실습 중심입니다. 같은 두 테이블도 조인 유형에 따라 결과가 달라서 초보자는 JOIN을 헷갈립니다. 작고 구체적인 데이터로 보면 쉬워집니다.
SQL JOIN 설명: 샘플 테이블
customers
| id | name |
|---|---|
| 1 | Asha |
| 2 | Ben |
| 3 | Chitra |
orders
| id | customer_id | total |
|---|---|---|
| 101 | 1 | 250 |
| 102 | 1 | 120 |
| 103 | 2 | 90 |
| 104 | 9 | 40 |
Chitra는 주문이 없고, 주문 104는 존재하지 않는 고객(9)을 가리킵니다. 이 두 가지 경계 사례가 조인 유형의 차이를 보여 줍니다.
INNER JOIN
INNER JOIN은 조건이 두 테이블 모두에서 참인 행만 반환합니다. 짝이 없는 행은 제외됩니다.
SELECT c.name, o.id AS order_id, o.total
FROM customers c
INNER JOIN orders o ON o.customer_id = c.id;
결과: Asha(101), Asha(102), Ben(103). Chitra와 주문 104는 빠집니다. 고객 정보가 포함된 주문처럼 관련된 데이터만 필요할 때 사용하세요. JOIN만 쓰면 INNER JOIN을 뜻합니다.
LEFT JOIN
LEFT JOIN은 왼쪽 테이블의 모든 행을 유지하고 오른쪽의 일치하는 행을 붙입니다. 일치하는 행이 없으면 오른쪽 컬럼은 NULL이 됩니다.
SELECT c.name, o.id AS order_id, o.total
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id;
결과: Asha(101), Asha(102), Ben(103), Chitra(NULL, NULL). 이제 Chitra가 나타납니다.
빠른 팁: 한 번도 주문하지 않은 고객을 찾으려면 오른쪽의 NULL로 필터링하세요. WHERE o.id IS NULL은 Chitra를 반환합니다. 테스터는 이를 이용해 고아 레코드나 누락된 레코드를 찾습니다.
RIGHT JOIN과 FULL JOIN
RIGHT JOIN은 LEFT JOIN의 거울상으로, 오른쪽 테이블의 모든 행을 유지합니다. 대부분은 읽기 편한 LEFT JOIN을 쓰기 위해 테이블 순서를 바꿉니다.
SELECT c.name, o.id AS order_id
FROM customers c
RIGHT JOIN orders o ON o.customer_id = c.id;
결과에는 고객 이름이 NULL인 주문 104가 포함됩니다. FULL (OUTER) JOIN은 두 테이블의 모든 행을 반환합니다. 주문이 없는 Chitra와 고객이 없는 주문 104가 모두 나옵니다.
SELECT c.name, o.id AS order_id
FROM customers c
FULL OUTER JOIN orders o ON o.customer_id = c.id;
PostgreSQL과 SQL Server는 지원합니다. MySQL은 지원하지 않으므로 LEFT JOIN과 RIGHT JOIN을 UNION으로 결합하세요. 더 알고 싶다면 PostgreSQL 매뉴얼의 명확한 조인 튜토리얼을 참고하세요.
| 조인 | 왼쪽에만 있는 행 | 오른쪽에만 있는 행 | 일치하는 행 |
|---|---|---|---|
| INNER | 아니요 | 아니요 | 예 |
| LEFT | 예 | 아니요 | 예 |
| RIGHT | 아니요 | 예 | 예 |
| FULL | 예 | 예 | 예 |
CROSS JOIN과 SELF JOIN
CROSS JOIN은 한 테이블의 모든 행을 다른 테이블의 모든 행과 짝짓습니다. 고객 3명과 주문 4건이면 12행이 됩니다. 자주 쓰이진 않지만 모든 사이즈와 색상별 테스트 데이터처럼 조합을 만들 때 유용합니다.
SELECT c.name, o.id
FROM customers c
CROSS JOIN orders o;
SELF JOIN은 별칭을 사용해 테이블을 자기 자신과 조인합니다. 예를 들어 각 직원의 상사를 찾을 때 씁니다.
SELECT e.name AS employee, m.name AS manager
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;
SQL JOIN: 흔한 실수와 성능 팁
- ON 절 누락은 의도치 않게 CROSS JOIN을 만들어 행 수가 폭발합니다.
- LEFT JOIN 후 WHERE에서 오른쪽 테이블을 필터링하면 INNER JOIN이 되어 버립니다. 조건은 ON에 두세요.
- 모호한 컬럼 이름: 컬럼 앞에 테이블 별칭을 붙이세요.
- 유일하지 않은 컬럼으로 조인하면 행이 불어나고 합계가 부풀려집니다.
- 조인 컬럼에 인덱스를 만들고, 필요한 컬럼만 선택하며, 느린 쿼리는
EXPLAIN으로 분석하세요.
테스터에게 조인이 중요한 이유
QA 엔지니어는 UI나 API로 생성한 데이터가 데이터베이스에 올바르게 들어갔는지 확인하고 고아 레코드를 찾기 위해 조인을 사용합니다. Postman으로 하는 API 테스트 가이드(영어)와 함께 읽어 보세요. 기초는 초보자를 위한 SQL 튜토리얼(영어), 새로운 데이터 저장소는 벡터 데이터베이스(영어)를 참고하세요. 데이터베이스를 로컬에서 실행하려면 Docker 튜토리얼(영어)을 확인하세요.
마무리
SQL JOIN을 한 줄로: INNER는 일치하는 것만, LEFT는 왼쪽 전부, RIGHT는 오른쪽 전부, FULL은 모두 유지합니다. 쿼리를 실행하기 전에 결과를 예측할 수 있을 때까지 작은 테이블 두 개로 연습하세요. 그다음 테이블 세 개를 조인하고 조인과 GROUP BY를 함께 사용해 보세요.
자주 묻는 질문
INNER JOIN과 LEFT JOIN의 차이는 무엇인가요?
INNER JOIN은 두 테이블에서 일치하는 행만 반환합니다. LEFT JOIN은 왼쪽 테이블의 모든 행을 반환하고, 일치하지 않는 오른쪽 컬럼은 NULL로 채웁니다.
가장 빠른 SQL JOIN은 무엇인가요?
항상 가장 빠른 유형은 없습니다. 성능은 인덱스, 테이블 크기, 실행 계획에 따라 달라집니다. 조인 컬럼에 인덱스를 만들고 실행 계획을 확인하세요.
MySQL은 FULL OUTER JOIN을 지원하나요?
아니요. MySQL에서는 LEFT JOIN과 RIGHT JOIN을 UNION으로 결합하면 같은 결과를 얻을 수 있습니다.
SELF JOIN은 어디에 쓰나요?
SELF JOIN은 같은 테이블의 행을 비교합니다. 예를 들어 하나의 employees 테이블에서 각 직원의 상사를 찾을 때 사용합니다.
조인 결과에 중복 행이 나오는 이유는 무엇인가요?
조인 컬럼이 어느 한 테이블에서 유일하지 않을 때 중복이 생깁니다. 키를 확인하거나 조인 전에 데이터를 집계하세요.
계속 배우기 (영어 문서)
테스트, WordPress, SEO에 도움이 필요하신가요?
팀이 더 좋은 소프트웨어를 출시하고 사이트를 성장시키도록 돕습니다. 어떤 작업을 하고 계신지 알려 주시면 다음 단계를 제안해 드립니다.
추가 가이드 테스트, AI 및 최신 개발
이 기사가 마음에 드셨나요? 주제를 선택하고 최신 튜토리얼로 바로 이동하세요.
