계층형 데이터베이스
고친 사람 github-actions[bot]
계층형 데이터베이스는 데이터를 부모와 자식으로 이어 한 그루 나무처럼 저장합니다. 꺼낼 때는 맨 위에서 출발해 가지를 따라 내려갑니다. 관계형 데이터베이스보다 먼저 널리 쓰인 방식입니다.
쉽고 빠른 이해
계층형 데이터베이스는 데이터를 나무 모양으로 매달아 둡니다. 회원 아래에 그 회원의 주문이 달립니다. 주문 아래에는 주문한 상품이 달립니다.
프로그램마다 제 파일을 따로 두던 시절에는 같은 주소가 파일마다 적혀 한쪽만 고치면 어긋났습니다. 계층형 데이터베이스는 데이터를 한곳에 모아 나눠 쓰게 한 초기 방식입니다. 회원을 찾으면 그 아래 주문을 바로 이어서 읽을 수 있습니다.
- 모든 데이터는 부모를 하나만 가집니다. 맨 위 데이터만 부모가 없습니다
- 부모와 자식은 저장된 위치로 이어집니다
- 읽을 때는 프로그램이 맨 위에서부터 어느 가지로 내려갈지 하나씩 지정합니다
대가는 나무 모양에 안 맞는 데이터와 질문입니다. 한 상품이 여러 주문에 들어가면 그 상품을 주문마다 따로 적어야 합니다. 나무 모양을 바꾸면 그 길을 따라 읽던 프로그램도 고쳐야 합니다.
상세
회사 조직도를 떠올려 보면 됩니다. 사원은 팀 하나에 속합니다. 팀은 부서 하나에 속합니다. 사원 한 명을 찾으려면 대표에서 출발해 부서와 팀을 차례로 골라 내려갑니다.
계층형 데이터베이스는 데이터를 이런 모양으로 저장하는 데이터베이스입니다. 데이터 한 건은 위에 부모를 하나만 둡니다. 아래에는 자식을 여럿 둘 수 있습니다. 쇼핑몰이라면 회원 아래에 주문이 달립니다. 주문 아래에는 주문한 상품이 달립니다.
이 절은 이 쇼핑몰 데이터 한 벌로 끝까지 봅니다. 이 방식이 나온 까닭, 나무 모양, 데이터를 읽는 법, 이 모양이 못 담는 데이터와 치르는 대가를 차례로 다룹니다.
프로그램마다 파일을 두던 시절
계층형 데이터베이스보다 앞서서는 프로그램마다 제 데이터 파일을 따로 두었습니다. 주문 프로그램과 배송 프로그램이 회원 주소를 각자 자기 파일에 적는 식입니다. 이런 방식을 파일 처리 시스템이라고 부릅니다.
같은 주소가 두 파일에 있으니 한쪽만 고치면 둘이 어긋납니다. 파일 모양이 바뀌면 그 파일을 읽는 프로그램마다 따로 손봐야 합니다.
계층형 데이터베이스는 데이터를 한곳에 모아 여러 프로그램이 나눠 쓰게 한 초기 방식입니다. 모으는 모양으로 나무를 고른 데는 까닭이 있습니다. 조직과 부서, 완제품과 그 부품, 회원과 주문처럼 업무 데이터에는 하나 아래 여럿이 딸리는 관계가 흔합니다.
부모 하나에 자식 여럿
데이터 한 건을 레코드라고 부릅니다. 레코드는 회원 한 명이나 주문 한 건처럼 값 몇 개를 묶은 덩어리입니다. 회원 레코드라면 번호·이름·도시를 묶습니다.
계층형 데이터베이스에서 레코드는 위아래로 이어집니다. 위에 있는 레코드가 부모입니다. 그 아래 매달린 레코드가 자식입니다. 규칙은 하나입니다. 자식은 부모를 하나만 가집니다.
이 규칙을 지키며 이으면 모양이 트리가 됩니다. 트리는 뿌리 하나에서 갈래가 뻗어 나가기만 하는 모양입니다. 한 번 갈라진 갈래끼리는 다시 만나지 않습니다.
맨 위에 있는 부모 없는 레코드를 루트라고 부릅니다. 쇼핑몰에서는 회원 한 명이 루트입니다. 회원마다 나무가 한 그루씩 섭니다.
flowchart TD
subgraph T1["민지의 나무"]
M1["회원 민지"] --> O10["주문 10"]
M1 --> O12["주문 12"]
O10 --> P1["상품 연필"]
O10 --> P2["상품 공책"]
O12 --> P3["상품 지우개"]
end
subgraph T2["태호의 나무"]
M2["회원 태호"] --> O11["주문 11"]
O11 --> P4["상품 연필"]
end
T1 ~~~ T2
화살표는 부모에서 자식으로 내려갑니다. 주문 10 의 부모는 민지 하나뿐입니다. 연필은 민지의 나무와 태호의 나무에 한 번씩, 모두 두 번 들어 있습니다. 이 겹침은 뒤에서 다시 봅니다.
한 부모에 자식이 여럿 붙는 관계를 일대다 관계라고 부릅니다. 회원 한 명이 주문 여럿을 가지는 것이 그렇습니다. 계층형 데이터베이스가 곧바로 담을 수 있는 관계는 이것뿐입니다.
저장 위치로 잇는 연결
부모와 자식은 저장된 위치로 이어집니다. 자식을 부모 바로 뒤에 붙여 저장하기도 합니다. 다른 레코드가 놓인 위치를 적어 둔 값으로 가리키기도 합니다. 이 값을 포인터라고 부릅니다.
관계형 데이터베이스는 다르게 잇습니다. 주문 표에 회원 번호라는 값을 적어 둘 뿐입니다. 무엇과 무엇이 이어지는지는 꺼낼 때 그 값을 맞춰 봐서 압니다.
계층형에서는 연결이 저장 구조 안에 박혀 있습니다. 그래서 연결을 따라가기가 빠릅니다. 대신 연결을 바꾸려면 저장 구조를 바꿔야 합니다.
루트에서 내려가는 읽기
이 소절은 민지의 주문을 읽는 순서를 예로 듭니다. 프로그램이 어느 레코드에서 출발해 어느 가지로 내려갈지를 한 번에 하나씩 지시합니다.
sequenceDiagram
participant 프로그램
participant 데이터베이스
프로그램->>데이터베이스: 회원 민지를 찾아라
데이터베이스-->>프로그램: 민지
프로그램->>데이터베이스: 민지 아래 첫 주문
데이터베이스-->>프로그램: 주문 10
프로그램->>데이터베이스: 민지 아래 다음 주문
데이터베이스-->>프로그램: 주문 12
프로그램->>데이터베이스: 민지 아래 다음 주문
데이터베이스-->>프로그램: 더 없음
요청마다 데이터베이스는 지금 가리키는 레코드에서 한 칸만 움직입니다. 다음 주문을 몇 번 달라고 할지, 없다는 답이 오면 멈출지는 프로그램이 정합니다. 이렇게 레코드를 하나씩 따라가며 읽는 방식을 항해식 접근(navigational access)이라고 부릅니다.
나무 방향을 따르는 질문은 빠릅니다. 「민지의 주문」은 민지를 찾은 뒤 그 아래만 읽으면 됩니다. 표 두 개를 값으로 맞춰 보는 조인이 필요 없습니다.
거꾸로 묻는 질문은 느립니다. 「연필을 산 회원 전부」를 알려 해도 연필이 어느 나무에 있는지 알 길이 없습니다. 회원의 나무를 전부 훑어 내려가야 합니다.
부모가 둘 필요한 데이터
상품 하나는 여러 주문에 들어갑니다. 주문 하나에도 상품이 여럿 들어갑니다. 양쪽이 서로 여럿을 가지는 이런 관계를 다대다 관계라고 부릅니다.
계층형 데이터베이스는 이 관계를 곧바로 담지 못합니다. 연필 하나를 민지의 주문과 태호의 주문 양쪽에 매달면 연필의 부모가 둘이 되기 때문입니다. 그래서 앞 그림처럼 연필을 주문마다 따로 적습니다.
같은 정보를 여러 곳에 적으면 고칠 때 문제가 생깁니다. 연필 값이 오르면 연필이 적힌 곳을 전부 찾아 고쳐야 합니다. 하나라도 빠뜨리면 같은 연필이 곳마다 다른 값을 가집니다. 이런 어긋남을 갱신 이상이라고 부릅니다.
겹침을 피하는 우회도 있습니다. 상품을 따로 나무로 세웁니다. 주문 아래에는 그 상품 레코드를 가리키는 포인터만 둡니다. 겹침은 사라집니다. 대신 나무 바깥으로 뻗는 연결이 생겨 구조와 읽는 길이 복잡해집니다.
부모 없이 못 넣는 자식
자식은 부모 아래에만 놓일 수 있습니다. 그래서 부모가 없으면 자식을 넣을 곳이 없습니다. 상품이 주문 아래에만 산다면 아직 아무도 안 산 새 상품은 저장할 수 없습니다.
지울 때도 같은 일이 생깁니다. 부모를 지우면 그 아래 가지가 함께 지워집니다. 지우개는 민지의 주문 12 아래에만 있습니다. 주문 12 를 지우면 지우개라는 상품이 있었다는 정보도 함께 사라집니다.
길을 알아야 하는 프로그램
항해식 접근에서는 프로그램이 나무 모양을 알아야 합니다. 어느 레코드 아래에 무엇이 달렸는지 알아야 내려갈 길을 지정할 수 있습니다.
그래서 나무 모양을 바꾸면 프로그램도 고쳐야 합니다. 상품별 판매를 자주 묻게 되어 상품을 루트로 올리고 그 아래에 주문을 달았다고 해 보겠습니다. 회원에서 출발하던 코드는 전부 길을 잃습니다.
계층형에서는 나무 모양이 곧 저장 구조입니다. 저장 구조를 바꿔도 프로그램을 안 고쳐도 되는 성질을 데이터 독립성이라고 합니다. 계층형 데이터베이스는 이 성질이 약합니다.
이 약점을 풀려고 나온 설계 방식이 관계형 모델입니다. 관계형 데이터베이스는 이 방식을 따릅니다. 연결은 저장 위치 대신 값으로 적게 했습니다. 프로그램은 원하는 결과만 말하게 했습니다.
계층형·네트워크형·관계형
네트워크형 데이터베이스는 부모 하나 규칙을 푼 방식입니다. 레코드 하나가 부모를 여럿 가질 수 있습니다. 연결은 계층형처럼 저장 위치로 적습니다.
세 방식을 나란히 놓으면 아래와 같습니다.
| 계층형 | 네트워크형 | 관계형 | |
|---|---|---|---|
| 레코드의 부모 | 하나 | 여럿도 된다 | 부모라는 개념이 없다 |
| 잇는 방법 | 저장 위치 | 저장 위치 | 같은 값을 적어 둔다 |
| 읽는 법 | 루트에서 가지를 따라 내려간다 | 연결을 따라 옮겨 다닌다 | 원하는 결과만 적는다 |
| 다대다 관계 | 겹쳐 적거나 포인터로 우회한다 | 곧바로 담는다 | 짝을 적는 표를 하나 더 둔다 |
표의 세 방식은 연결을 어디에 적느냐로 갈립니다. 앞의 둘은 저장 구조 안에 적습니다. 관계형은 값 안에 적습니다.
맞는 데이터와 치르는 대가
계층형 데이터베이스는 데이터가 원래 나무 모양이고 늘 같은 방향으로 읽힐 때 맞습니다. 부모를 찾은 뒤 자식을 바로 이어 읽으니 조인이 필요 없습니다.
대가는 앞에서 본 셋입니다.
- 다대다 관계를 담으려면 같은 데이터를 겹쳐 적거나 우회 연결을 둬야 합니다
- 부모 없이는 자식을 넣을 수 없습니다. 부모를 지우면 자식도 사라집니다
- 나무 모양을 바꾸면 그 길을 따라 읽던 프로그램을 고쳐야 합니다
지금 남아 있는 나무 모양
관계형 데이터베이스가 퍼진 뒤로 새로 짓는 시스템에서 계층형 데이터베이스는 드물어졌습니다. 대표 제품인 IMS(Information Management System)가 일부 은행·보험사의 메인프레임에서 아직 돌고 있습니다. 메인프레임은 은행처럼 거래를 많이 처리하는 기관이 쓰는 대형 컴퓨터입니다.
데이터를 나무 모양으로 담는 생각은 곳곳에 남아 있습니다. 폴더 아래에 파일을 두는 파일 시스템이 그렇습니다. 태그 안에 태그를 넣는 XML(eXtensible Markup Language)도 그렇습니다.
백엔드 개발자에게 가장 가까운 예는 JSON(JavaScript Object Notation) 문서입니다. 회원 문서 안에 주문을 품습니다. 주문 안에는 상품을 품습니다. 그러면 그 문서가 작은 나무입니다.
{
"member": "민지",
"orders": [
{ "id": 10, "items": ["연필", "공책"] },
{ "id": 12, "items": ["지우개"] }
]
}
회원 아래 주문, 주문 아래 상품이 앞 그림의 민지의 나무와 같은 모양입니다. 이런 문서를 한 덩이로 저장하는 문서 데이터베이스에도 같은 대가가 따라옵니다. 상품 이름을 문서마다 따로 적으므로 이름을 바꾸면 그 이름이 든 문서를 전부 고쳐야 합니다.
관련 항목
계층형 데이터베이스를 이루는 구성 요소
레코드 · 트리 · 노드 · 포인터 · 일대다 관계 · 스키마
계층형 데이터베이스에서 생기는 이상 현상과 약점
다대다 관계 · 데이터 중복 · 갱신 이상 · 삽입 이상 · 삭제 이상 · 데이터 독립성
계층형 데이터베이스의 데이터를 읽는 방식
항해식 접근 · 트리 순회 · 전위 순회 · 깊이 우선 탐색 · 조인
계층형 데이터베이스가 비롯된 배경
파일 처리 시스템 · 데이터베이스 · 데이터베이스 관리 시스템 · 데이터 모델 · 데이터 모델링
계층형 데이터베이스를 이어 나온 데이터 모델
네트워크 모델 · CODASYL · 관계형 모델 · 관계형 데이터베이스 · 객체지향 데이터베이스
계층형 데이터베이스 제품이 돌아가는 메인프레임 환경
IMS · 메인프레임 · COBOL · CICS
계층형 데이터베이스와 같은 나무 모양을 쓰는 저장 형식
다른 이름: hierarchical database · 계층형 데이터 모델 · 계층 데이터 모델 · 계층형 DBMS · hierarchical model