앵커 및 재귀 구성원
재귀 CTE의 두 부분 구조와 종료가 작동하는 방식을 알아봅니다.
앵커 및 재귀 구성원은(는) CoddyKit의 무료 SQL Interview Prep 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 SQL Interview Prep 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. SQL Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.
재귀 CTE가 등장하는 이유
면접관이 조직도, 자재 명세서 또는 범주 트리를 제시하고 모든 하위 항목을 찾으라고 한다면, 재귀 CTE를 활용할 수 있는지 확인하려는 것입니다. 일반 조인으로는 고정된 수의 계층만 탐색할 수 있지만 재귀를 사용하면 깊이에 제한 없이 탐색할 수 있습니다.
문제에서 단서가 되는 표현은 “어떤 깊이까지든” 또는 “끝까지 모두”입니다. 이것이 바로 재귀를 사용하라는 신호입니다. 이 레슨에서는 모든 재귀 CTE가 공유하는 두 부분 구조인 앵커와 재귀 멤버를 배웁니다.
두 부분으로 이루어진 뼈대
재귀 CTE에는 항상 WITH RECURSIVE 키워드가 포함됩니다(PostgreSQL, SQLite, MySQL 8 이상에서는 사용하며 SQL 서버에서는 RECURSIVE를 생략합니다). 본문은 UNION ALL로 결합된 두 쿼리로 구성됩니다.
- 앵커 멤버 — 시작 행이며 한 번 실행됩니다.
- 재귀 멤버 — CTE 이름 자체를 참조하며 반복해서 실행됩니다.
이 뼈대를 외워 두십시오. 면접관은 처음부터 직접 작성해 보라고 자주 요청합니다.
WITH RECURSIVE cte AS (
-- anchor member
SELECT ...
UNION ALL
-- recursive member
SELECT ... FROM cte JOIN ...
)
SELECT * FROM cte;앵커의 역할
앵커 멤버는 CTE를 참조하지 않는 일반 쿼리입니다. 이 멤버는 씨앗 행, 즉 레벨 0의 시작점을 만듭니다. 조직도에서는 보통 CEO입니다(관리자가 NULL인 행). 숫자 수열에서는 첫 번째 숫자입니다.
앵커는 정확히 한 번 실행됩니다. 앵커의 출력은 재귀 단계에 입력되는 첫 번째 행 묶음이 됩니다.
-- Anchor: the top of the hierarchy
SELECT id, name, manager_id, 1 AS depth
FROM employees
WHERE manager_id IS NULL재귀 멤버의 역할
재귀 멤버는 이름으로 CTE를 참조합니다. 각 반복에서 이전 반복이 만든 행을 기본 테이블과 조인하여 다음 계층을 찾습니다.
재귀 멤버는 지금까지의 전체 CTE를 보는 것이 아니라 바로 직전 단계에서 추가된 행만 봅니다. 이것이 면접관이 확인하는 핵심적인 사고 모델입니다.
-- Recursive: children of the rows found so far
SELECT e.id, e.name, e.manager_id, c.depth + 1
FROM employees e
JOIN cte c ON e.manager_id = c.id하나로 결합하기
앵커 멤버와 재귀 멤버를 UNION ALL로 결합하면 엔진이 자동으로 반복 실행합니다. 각 실행은 다음 계층을 추가하며, 재귀 멤버가 행을 0개 반환할 때까지 계속됩니다. 행이 0개가 되면 재귀가 중지됩니다.
다음은 depth도 추적하는 완전하고 실행 가능한 조직도 탐색 쿼리입니다.
WITH RECURSIVE org AS (
SELECT id, name, manager_id, 1 AS depth
FROM employees
WHERE manager_id IS NULL
UNION ALL
SELECT e.id, e.name, e.manager_id, o.depth + 1
FROM employees e
JOIN org o ON e.manager_id = o.id
)
SELECT id, name, depth FROM org ORDER BY depth, id;종료가 작동하는 방식
재귀 멤버가 새 행을 전혀 만들지 않으면 재귀가 중지됩니다. 명시적인 반복 횟수 카운터는 필요하지 않습니다. 트리의 말단에 도달하면 조인이 자연스럽게 더 이상 결과를 만들지 않기 때문입니다.
조직도 예시에서 직속 부하 직원이 없는 직원에 도달하면 다음 반복의 조인에서 자식 행을 찾지 못하고 빈 결과를 반환하므로 엔진이 중지됩니다. 이러한 자체 종료 동작을 이해하는 것은 대표적인 추가 질문에 대비하는 데 도움이 됩니다.
UNION ALL과 UNION 비교
면접관은 왜 UNION ALL을 사용하고 UNION은 사용하지 않는지 자주 질문합니다. 이유는 두 가지입니다.
- 성능 —
UNION은 매 반복마다 중복을 제거하므로 비용이 많이 듭니다. - 정확성 — 트리에서는 일반적으로 중복 행이 발생할 수 없으므로 중복 제거가 불필요한 작업입니다.
구조가 그래프이고 반복되는 노드를 의도적으로 하나로 합치려는 경우에만 UNION을 사용하십시오. 다만 순환을 안전하게 처리하려면 명시적인 방어 조건을 사용하는 편이 더 좋습니다(뒤에서 다룹니다).
깊이와 경로 추적하기
두 개의 열을 추가하면 재귀 결과가 훨씬 유용해지며, 면접에서도 자주 요청됩니다.
- 깊이 — 앵커에서 1로 시작하고 재귀 멤버에서 1씩 더합니다.
- 경로 — 루트에서 노드까지의 이동 경로를 볼 수 있도록 식별자나 이름의 연결을 누적합니다.
path를 문자열로 만들면 나중에 순환을 감지하는 도구로도 사용할 수 있습니다.
WITH RECURSIVE org AS (
SELECT id, name, manager_id, 1 AS depth,
CAST(name AS VARCHAR(1000)) AS path
FROM employees WHERE manager_id IS NULL
UNION ALL
SELECT e.id, e.name, e.manager_id, o.depth + 1,
o.path || ' > ' || e.name
FROM employees e JOIN org o ON e.manager_id = o.id
)
SELECT name, depth, path FROM org;열 유형은 일치해야 합니다
주의해야 할 미묘한 함정이 있습니다. 앵커 멤버와 재귀 멤버는 열의 개수가 같아야 하며 호환되는 유형을 반환해야 합니다. path 문자열을 만들 때는 앵커의 초기 값을 충분히 넓은 유형(예: VARCHAR(1000))으로 변환해야 합니다. 그렇지 않으면 이후 반복에서 엔진이 값을 잘라 내거나 유형 불일치 오류를 발생시킬 수 있습니다.
이는 재귀 CTE를 실제로 실행해 보았는지, 아니면 읽어 보기만 했는지 확인하기 위해 면접관이 제시하는 대표적인 세부 사항입니다.
자재 명세서 예시
같은 뼈대가 자재 명세서에도 적용됩니다. 어떤 부품이 주어졌을 때 깊이에 제한 없이 모든 하위 부품을 나열하는 문제입니다. 앵커는 최상위 조립품을 선택하고, 재귀 멤버는 parent_part에서 child_part로 이어지는 연결을 따라갑니다.
구조가 조직도와 완전히 같고 열 이름만 다르다는 점에 주목하십시오. 하나의 뼈대가 여러 문제에 적용된다는 사실을 알아보는 것이 진정한 면접 기술입니다.
WITH RECURSIVE bom AS (
SELECT child_part, parent_part, 1 AS lvl
FROM parts WHERE parent_part = 'ENGINE'
UNION ALL
SELECT p.child_part, p.parent_part, b.lvl + 1
FROM parts p JOIN bom b ON p.parent_part = b.child_part
)
SELECT child_part, lvl FROM bom;방언별 참고 사항
면접관이 높이 평가하는 간단한 SQL 방언별 요약은 다음과 같습니다.
- PostgreSQL, SQLite, MySQL 8 이상:
WITH RECURSIVE name AS (...)을 사용합니다. - SQL 서버:
WITH name AS (...)만 사용합니다.RECURSIVE키워드는 암시적으로 적용되며 기본MAXRECURSION은 100입니다. - 오라클: 재귀 CTE와 이전 방식인
CONNECT BY구문을 모두 지원합니다.
“SQL 서버에서는 RECURSIVE라는 단어를 사용하지 않습니다”라고 말하면 폭넓은 지식을 보여 줄 수 있습니다.
빠른 확인
두 부분 구조를 제대로 이해했는지 확인해 보십시오.
복습
이제 재귀 CTE의 뼈대를 익혔습니다.
- WITH RECURSIVE + 앵커 +
UNION ALL+ 재귀 멤버 - 앵커는 레벨 0의 씨앗을 만들고 한 번 실행됩니다.
- 재귀 멤버는 이전 반복의 결과를 기본 테이블과 조인하며 행을 반환하지 않을 때까지 실행됩니다.
UNION ALL을 사용하고depth와path를 추적하며 열 유형이 호환되도록 유지합니다.
다음에는 이 뼈대를 실제 조직도를 위아래로 탐색하는 데 적용합니다.
자주 묻는 질문
“앵커 및 재귀 구성원” 강의는 무료인가요?
네 — “앵커 및 재귀 구성원” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 SQL Interview Prep 강의 전체를 잠금 해제할 수 있습니다. SQL Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.
“앵커 및 재귀 구성원”에서 뭘 배우나요?
재귀 CTE의 두 부분 구조와 종료가 작동하는 방식을 알아봅니다. 브라우저에서 직접 실행하는 실습 코드로 SQL Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
SQL Interview Prep을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 SQL Interview Prep은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“앵커 및 재귀 구성원” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 SQL Interview Prep 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 SQL Interview Prep 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 앵커 및 재귀 구성원
- 조직도 순회하기
- 숫자 및 날짜 계열 생성하기
- 무한 재귀 방지하기