자기참조관계로 계층형 데이터를 설계하는 방법

자기참조관계의 통합형·복합형 모델과 관계 유형, 재귀 쿼리 및 계층형 데이터 성능 최적화 방안을 정리한다.

2026-08-14 · 최초 발행 2025-08-10

같은 엔티티 안에서 부모와 자식을 연결하는 모델

자기참조관계(Self-Referencing Relationship)는 하나의 엔티티 타입 안에서 인스턴스가 다른 인스턴스를 참조하는 데이터베이스 모델링 방식이다. 부모-자식 연결을 통해 트리 형태의 데이터를 표현하며, 하나의 테이블로 복잡한 계층을 다룰 수 있다.

조직도, 제품 카테고리, 댓글과 대댓글처럼 레벨 제한 없이 확장되는 구조가 대표적인 대상이다. 엔티티가 자신을 참조한다는 점에서 재귀적 관계이기도 하다.

BOM으로 보는 계층 구조

제조업의 BOM(Bill of Materials)은 완성 제품과 구성 부품, 하위 부품의 연결을 표현하는 전형적인 사례다.

완성 제품부품 1부품 2하위 부품 1-1하위 부품 1-2하위 부품 2-1

테이블 안에 둘 것인가, 관계를 분리할 것인가

통합형(Integrated Type)은 엔티티가 자기 자신을 직접 참조하는 방식이다. 가장 일반적인 형태이며, 직원 테이블의 manager_id가 같은 테이블의 employee_id를 가리키는 구성이 이에 해당한다.

reports toEMPLOYEEintemployee_idPKstringnameintmanager_idFK
CREATE TABLE employee (
    employee_id INT PRIMARY KEY,
    name VARCHAR(100),
    manager_id INT,
    FOREIGN KEY (manager_id) REFERENCES employee(employee_id)
);

복합형(Composite Type)은 동일한 주키(PK)를 가진 테이블을 별도로 분리해 관계를 보관한다. 특정 계층 구조를 명확히 구분해야 할 때 사용할 수 있다.

parentchildCATEGORYintcategory_idPKstringnameCATEGORY_HIERARCHYintparent_category_idFKintchild_category_idFK
CREATE TABLE category (
    category_id INT PRIMARY KEY,
    name VARCHAR(100)
);

CREATE TABLE category_hierarchy (
    parent_category_id INT,
    child_category_id INT,
    PRIMARY KEY (parent_category_id, child_category_id),
    FOREIGN KEY (parent_category_id) REFERENCES category(category_id),
    FOREIGN KEY (child_category_id) REFERENCES category(category_id)
);

참조 방향에 따라 달라지는 관계

한 인스턴스가 하나만 참조하는 경우

1:1 자기참조관계에서는 한 인스턴스가 다른 하나의 인스턴스만 참조한다. 부부 관계나 1:1 매칭 구조에 적용할 수 있다.

married toPERSONintperson_idPKstringnameintspouse_idFK

상위 하나에 여러 하위 항목이 연결되는 경우

1:M(일대다) 자기참조관계는 하나의 상위 인스턴스 아래 여러 인스턴스를 둘 수 있고, 각 인스턴스는 하나의 상위 인스턴스만 참조하는 구조다. 조직도와 댓글-대댓글 구조에서 흔히 사용된다.

repliesCOMMENTintcomment_idPKstringcontentintparent_comment_idFK

서로 여러 항목을 연결하는 경우

M:N(다대다) 자기참조관계에서는 인스턴스들이 서로 여러 개의 인스턴스를 참조할 수 있다. 소셜 네트워크의 친구 관계나 상호 참조 시스템이 해당한다.

friends withfriends withUSERintuser_idPKstringusernameFRIENDSHIPintuser_id1FKintuser_id2FK

조회와 변경 비용을 함께 고려해야 한다

자기참조관계에서는 연결 속성(FK)에 인덱스를 설정해야 한다. 계층 구조를 조회할 때 성능에 직접 영향을 준다.

CREATE INDEX idx_employee_manager ON employee(manager_id);

계층을 조회하려면 연결된 데이터를 함께 가져올 SQL이 필요하다. Oracle에서는 계층적 쿼리를 사용할 수 있다.

SELECT * FROM ev_group
START WITH group_code = '5503'
CONNECT BY PRIOR parent_group_code = group_code;

MySQL에서는 재귀 CTE(Common Table Expression)로 경로를 따라갈 수 있다.

WITH RECURSIVE category_path AS (
  SELECT category_id, name, 0 AS level
  FROM category
  WHERE parent_id IS NULL

  UNION ALL

  SELECT c.category_id, c.name, cp.level + 1
  FROM category c
  JOIN category_path cp ON c.parent_id = cp.category_id
)
SELECT * FROM category_path ORDER BY level, category_id;

복합형은 관계를 추가할 때 새로운 테이블 생성이 필요할 수 있고, 기존 SQL 수정도 불가피하다. 관계 유지와 관리가 복잡해지며 조인 연산 증가로 성능이 저하될 가능성도 있다.

조직도, 카테고리, 댓글에 적용하는 형태

조직도에서는 직원과 관리자의 계층을 같은 테이블에서 표현할 수 있다.

CREATE TABLE employee (
    emp_id INT PRIMARY KEY,
    name VARCHAR(100),
    position VARCHAR(50),
    manager_id INT,
    FOREIGN KEY (manager_id) REFERENCES employee(emp_id)
);

INSERT INTO employee VALUES (1, '김사장', 'CEO', NULL);
INSERT INTO employee VALUES (2, '이부장', '부장', 1);
INSERT INTO employee VALUES (3, '박대리', '대리', 2);

쇼핑몰이나 콘텐츠 플랫폼의 카테고리도 상위 카테고리 키를 통해 계층을 만든다.

CREATE TABLE category (
    category_id INT PRIMARY KEY,
    name VARCHAR(100),
    parent_category_id INT,
    FOREIGN KEY (parent_category_id) REFERENCES category(category_id)
);

INSERT INTO category VALUES (1, '전자제품', NULL);
INSERT INTO category VALUES (2, '컴퓨터', 1);
INSERT INTO category VALUES (3, '노트북', 2);

댓글 시스템에서는 상위 댓글 키가 대댓글 구조를 만든다.

CREATE TABLE comment (
    comment_id INT PRIMARY KEY,
    content TEXT,
    user_id INT,
    post_id INT,
    parent_comment_id INT,
    FOREIGN KEY (parent_comment_id) REFERENCES comment(comment_id)
);

깊은 계층을 다룰 때의 선택지

참조 키 인덱스 외에도 재귀 쿼리 대신 접근 경로를 저장하는 Materialized Path를 고려할 수 있다. 계층 탐색에는 중첩 집합 모델(Nested Set Model)도 대안이 되며, 자주 사용하는 계층 구조는 캐싱으로 DB 부하를 줄일 수 있다.

-- Materialized Path 예시
CREATE TABLE category (
    category_id INT PRIMARY KEY,
    name VARCHAR(100),
    parent_id INT,
    path VARCHAR(255),
    FOREIGN KEY (parent_id) REFERENCES category(category_id)
);

-- 경로를 저장 (예: "1.2.3.")
INSERT INTO category VALUES (1, '전자제품', NULL, '1.');
INSERT INTO category VALUES (2, '컴퓨터', 1, '1.2.');
INSERT INTO category VALUES (3, '노트북', 2, '1.2.3.');

자기참조관계는 계층형 데이터를 표현하는 기본 모델링 패턴이다. 통합형과 복합형, 1:1·1:M·M:N 관계 유형을 데이터 특성에 맞게 선택해야 하며, 인덱스와 계층 조회 SQL, 성능 최적화 방식까지 함께 설계해야 한다.

자기참조관계데이터베이스 모델링계층형 데이터재귀 쿼리BOM