본문 바로가기

Develop/Backend 가이드

[Spring] RDB 에서 계층적인 데이터 구조 관리 전략 - Adjacency list

반응형

Adjacency List
Adjacency List

관계형 데이터베이스에서 계층적인 데이터 구조 관리

관계형 데이터베이스 (RDB) 는 계층적인 데이터 구조를 표현하기에 적합하지 않은 관계형 모델을 기초로 설계되어 있습니다. 반면에 관계형 데이터베이스를 활용하는 서버는 주로 객체지향 언어로 작성되며 내부적으로 이진트리와 같은 계층적인 데이터 구조를 자주 활용합니다. 따라서 서버에서 그래프 구조의 데이터를 계층적인 데이터 구조 관리에 적합하지 않은 관계형 데이터베이스에 어떻게든 저장하려면 아래와 같은 전략이 필요합니다.

관계형 데이터베이스에 그래프를 표현하는 전략 4 가지

계층적인 데이터 구조를 관계형 데이터베이스에 저장하게 되면 서버가 데이터베이스의 무결성을 책임져야 합니다. 관계형 데이터베이스는 그래프 구조의 데이터의 무결성을 체크하는 기능이 없기 때문에 의도치 않게 데이터가 오염되는 사태를 맞이하게 될 수도 있으니 주의해야 합니다.

Adjacency list

Adjacency list 는 관계형 데이터베이스에 계층적인 데이터 구조를 저장하려고 하면 직관적으로 떠오르는 전략으로, 테이블의 컬럼 하나를 부모 레코드의 기본키를 가지도록 하는 전략입니다.

Adjacency list 는 단순한 전략이라 적용하고 활용하기 어렵지 않습니다. 하지만 데이터베이스 성능 면에서는 다른 전략보다 비효율적인 전략입니다.

예제 테이블
-- 'parent' 가 adjacency list 전략의 핵심입니다.
CREATE TABLE IF NOT EXISTS `family` (
  `id` smallint(5) NOT NULL AUTO_INCREMENT,
  `parent` smallint(5) DEFAULT NULL,
  `role` varchar(30) NOT NULL,
  PRIMARY KEY (`id`)
);
예제 데이터
-- 부모
INSERT INTO family (id, parent, role) VALUES (NULL, NULL, 'parents');
SET @PARENTS_ID = LAST_INSERT_ID();

-- 딸
INSERT INTO family (id, parent, role) VALUES (NULL, @PARENTS_ID, 'daughter');
SET @DAUGHTER_ID = LAST_INSERT_ID();

-- 아들
INSERT INTO family (id, parent, role) VALUES (NULL, @PARENTS_ID, 'son');
SET @D_SON_ID = LAST_INSERT_ID();

-- 손자
INSERT INTO family (id, parent, role) VALUES (NULL, @DAUGHTER_ID, 'son');
SET @D_SON1_ID = LAST_INSERT_ID();
INSERT INTO family (id, parent, role) VALUES (NULL, @DAUGHTER_ID, 'son');
SET @D_SON2_ID = LAST_INSERT_ID();
INSERT INTO family (id, parent, role) VALUES (NULL, @D_SON_ID, 'son');
SET @D_SON3_ID = LAST_INSERT_ID();
INSERT INTO family (id, parent, role) VALUES (NULL, @D_SON_ID, 'daughter');
SET @D_DAUGHTER_ID = LAST_INSERT_ID();

-- 증손자
INSERT INTO family (id, parent, role) VALUES (NULL, @D_SON2_ID, 'daughter');
INSERT INTO family (id, parent, role) VALUES (NULL, @D_SON2_ID, 'son');

INSERT INTO family (id, parent, role) VALUES (NULL, @D_SON1_ID, 'daughter');
INSERT INTO family (id, parent, role) VALUES (NULL, @D_SON1_ID, 'son');

INSERT INTO family (id, parent, role) VALUES (NULL, @D_DAUGHTER_ID, 'daughter');
INSERT INTO family (id, parent, role) VALUES (NULL, @D_DAUGHTER_ID, 'daughter');
INSERT INTO family (id, parent, role) VALUES (NULL, @D_DAUGHTER_ID, 'daughter');

Adjacency list 에서 데이터를 검색하는 방법

Adjacency list 는 아래와 같은 SQL 구문으로 모든 데이터를 검색할 수 있을 정도로 단순한 구조를 가지고 있는게 장점입니다.

SELECT * FROM family ORDER BY parent ASC;

하지만 Adjacency list 는 SQL 구문으로 특정 데이터를 검색하기 어렵다는 단점이 있습니다. 따라서 코드로 SQL 구문으로 표현하지 못하는 부분을 커버해야만 합니다. 따라서 데이터 검색을 위해 SQL 구문을 자주 호출해야 합니다.

Adjacency list 에서 데이터를 조작하는 방법

Adjacency list 는 구조가 단순해서 데이터를 추가하는 방법도 아래와 같이 단순합니다.

INSERT INTO family (id, parent, role) VALUES (NULL, 73, 'daughter');

Adjacency list 에서 데이터를 삭제하는 건 parent 컬럼을 외래키로 설정한 뒤 CASCADE 옵션을 설정하면 쉽게 해결할 수 있습니다.

반응형