사전 객체지향 데이터베이스
개념

객체지향 데이터베이스

gabury1고친 사람 github-actions[bot]

객체지향 데이터베이스는 프로그램이 쓰던 객체를 표로 바꾸지 않고 객체 모양으로 저장합니다. 다시 꺼내면 객체끼리 서로 가리키던 연결까지 함께 돌아옵니다. 객체지향 언어로 짠 프로그램이 객체를 표로 쪼갰다가 다시 조립하는 수고를 없애려고 나온 방식입니다.

쉽고 빠른 이해

객체지향 데이터베이스는 프로그램 안의 객체를 모양을 바꾸지 않고 저장합니다. 회원 객체가 주문 목록을 들고 있으면 저장할 때도 꺼낼 때도 그 목록째입니다.

표에 저장하는 데이터베이스를 쓰면 객체를 표 여러 개로 쪼개 넣어야 합니다. 꺼낼 때는 다시 조립합니다. 이렇게 쪼개고 조립하는 코드를 번역 코드라 합니다.

번역 코드는 깁니다. 클래스가 바뀔 때마다 함께 고쳐야 합니다. 객체지향 데이터베이스는 이 번역을 없앱니다.

  1. 객체마다 값과 상관없는 고유 번호가 붙습니다
  2. 다른 객체를 가리키는 연결은 그 번호로 저장됩니다
  3. 꺼낼 때는 객체 하나를 찾은 뒤 연결을 따라 옆 객체로 넘어갑니다

그래서 객체끼리 촘촘히 얽혀 연결을 따라 읽는 일이 많은 데이터에 맞습니다.

대가는 묶임입니다. 저장된 데이터가 한 언어의 클래스 모양에 묶여 다른 언어나 도구에서 읽기 어렵습니다. 연결을 따라가지 않고 조건으로 걸러 세는 질문도 표 쪽보다 불편합니다.

상세

레고로 지은 성을 보관한다고 해 보겠습니다. 한 가지 방법은 성을 분해해 벽돌을 색깔별 서랍에 나눠 넣는 것입니다. 다시 보고 싶으면 설명서를 펴고 처음부터 조립합니다. 다른 방법은 다 지은 성을 모양 그대로 선반에 올려 두는 것입니다.

객체지향 데이터베이스는 뒤쪽 방법을 고른 데이터베이스입니다. 객체 지향 프로그래밍에서 프로그램은 데이터를 객체로 다룹니다. 객체는 값 몇 개와 다른 객체를 가리키는 연결을 함께 들고 있는 덩어리입니다. 이 데이터베이스는 그 객체를 쪼개지 않고 저장합니다.

이 절은 쇼핑몰 데이터 한 벌로 끝까지 봅니다. 회원 민지가 주문 10 과 주문 12 를 했습니다. 주문 10 에는 연필과 공책이, 주문 12 에는 지우개가 들어 있습니다. 이 데이터를 표로 옮길 때 생기는 어긋남, 객체를 저장하는 법과 꺼내는 법, 이 방식이 치르는 대가를 차례로 다룹니다.

객체 한 벌의 모양

자바로 적으면 회원·주문·상품은 아래 같은 클래스가 됩니다. 클래스는 객체를 찍어 내는 틀입니다.

Java
class Member {
    String name;
    List<Order> orders;
}
class Order {
    int id;
    List<Product> items;
}
class Product {
    String name;
    int price;
}

회원 객체는 주문 객체의 목록을 필드로 들고 있습니다. 주문 객체는 상품 객체의 목록을 들고 있습니다. 데이터가 표가 아니라 서로 가리키는 객체의 그물로 놓입니다. 객체 그래프는 이렇게 서로 가리키는 객체들의 그물입니다.

표로 옮길 때 생기는 어긋남

관계형 데이터베이스는 데이터를 표에 담습니다. 표의 칸 하나에는 값 하나만 들어갑니다. 목록을 칸에 넣을 수 없으니 회원 객체를 모양 그대로는 못 담습니다.

그래서 회원 표, 주문 표, 주문에 든 상품을 적는 표로 쪼갭니다. 객체끼리의 연결은 상대의 번호를 칸에 적는 것으로 바꿉니다.

꺼낼 때는 거꾸로 합니다. 표 셋을 번호로 맞춰 붙이는 조인을 합니다. 나온 행들은 다시 객체로 조립합니다.

flowchart TD
    A["회원 객체 민지"] --> B["표 셋으로 쪼갠다"]
    B --> C["회원 표"]
    B --> D["주문 표"]
    B --> E["주문 상품 표"]
    C --> F["조인으로 다시 붙인다"]
    D --> F
    E --> F
    F --> G["회원 객체로 다시 조립한다"]

그림의 위쪽 절반은 저장할 때, 아래쪽 절반은 꺼낼 때 하는 일입니다. 객체 하나를 넣고 빼는 데 쪼개기와 조립이 한 번씩 붙습니다.

객체와 표의 모양이 안 맞아 생기는 이 번거로움을 객체-관계 임피던스 불일치라고 부릅니다. 임피던스는 전기 회로에서 빌려 온 말입니다. 성질이 다른 두 쪽을 이을 때 생기는 손실을 빗댄 이름입니다.

이렇게 쪼개고 다시 조립하는 코드를 번역 코드라 부르겠습니다. 번역 코드는 클래스가 바뀔 때마다 깨집니다. 클래스에 필드 하나를 더하면 표 정의와 번역 코드도 함께 고쳐야 합니다.

객체지향 데이터베이스는 이 번역을 없애려고 나왔습니다. 프로그램이 객체로 생각한다면 저장도 객체로 하자는 생각입니다.

프로그램이 끝나도 남는 객체

보통 객체는 프로그램이 끝나면 메모리와 함께 사라집니다. 영속성은 프로그램이 끝난 뒤에도 데이터가 남아 있는 성질입니다.

객체지향 데이터베이스는 객체에 이 성질을 줍니다. 저장하라고 한 객체는 디스크에 남습니다. 다음에 프로그램을 켜면 같은 객체를 다시 받아 씁니다.

저장한 객체가 가리키던 객체도 함께 저장됩니다. 민지를 저장하면 민지의 주문과 그 안의 상품까지 따라 들어갑니다. 연결을 따라 닿는 객체를 모두 저장하는 이 방식을 도달 가능성에 의한 영속성(persistence by reachability)이라고 부릅니다.

값과 상관없는 객체 식별자

관계형 데이터베이스는 행을 가리킬 때 기본키 값을 씁니다. 회원 번호처럼 사람이 정해 넣은 값입니다.

객체지향 데이터베이스는 객체마다 객체 식별자(OID, Object Identifier)를 붙입니다. 데이터베이스가 만들어 붙이는 고유 번호입니다. 객체의 값이 바뀌어도 이 번호는 안 바뀝니다.

이름이 같은 회원이 둘이어도 식별자가 다르면 다른 객체입니다. 거꾸로 민지가 이름을 바꿔도 식별자가 같으면 같은 민지입니다. 값이 같은지와 같은 객체인지를 따로 따집니다.

객체 사이의 연결은 이 식별자로 저장됩니다. 주문 10 이 연필을 가리키면 주문 10 안에 연필의 식별자가 적힙니다. 다른 회원 태호도 주문 11 로 같은 연필을 샀습니다. 아래 그림은 두 회원의 데이터를 함께 그린 것입니다.

flowchart TD
    M1["회원 민지"] --> O10["주문 10"]
    M1 --> O12["주문 12"]
    M2["회원 태호"] --> O11["주문 11"]
    O10 --> P1["상품 연필"]
    O10 --> P2["상품 공책"]
    O12 --> P3["상품 지우개"]
    O11 --> P1

화살표 하나가 식별자 하나입니다. 연필 객체는 하나뿐이고 주문 10 과 주문 11 이 같은 연필을 가리킵니다. 연필 값이 오르면 연필 객체 하나만 고치면 됩니다.

다대다 관계는 양쪽이 서로 상대를 여럿 가질 수 있는 관계입니다. 상품 하나가 여러 주문에 들 수 있습니다. 주문 하나에도 상품이 여럿 듭니다.

관계형은 이 관계를 담으려고 주문과 상품의 짝을 적는 표를 하나 더 둡니다. 객체지향 데이터베이스는 식별자로 바로 가리키므로 표를 더 두지 않습니다.

계층형 데이터베이스는 데이터를 나무 모양으로 두는 방식입니다. 나무의 위 단계를 부모, 아래 단계를 자식이라 합니다. 자식마다 부모는 하나뿐입니다. 그래서 두 주문이 같은 연필을 가리킬 수 없어 연필을 주문마다 따로 적어야 했습니다.

연결을 따라가는 읽기

데이터베이스에서 꺼낸 민지 객체를 minji 라고 하겠습니다. 민지를 찾은 다음부터는 필드를 따라가면 됩니다. 메모리 안의 객체를 다루는 코드와 다를 게 없습니다.

Java
Order o = minji.orders.get(0);
o.id                  // 10
o.items.get(1).name   // "공책"

조인도, 행을 객체로 조립하는 코드도 없습니다. 필요한 객체는 대개 필드를 따라가는 순간에 데이터베이스가 디스크에서 불러옵니다.

이렇게 객체를 하나씩 따라가며 읽는 방식을 항해식 접근(navigational access)이라고 부릅니다. 계층형 데이터베이스도 이 방식으로 읽었습니다. 다른 점은 부모 하나 규칙이 없어 아무 객체나 가리킬 수 있다는 것입니다.

연결을 따라가는 질문은 빠릅니다. 식별자로 곧장 옆 객체로 넘어가기 때문입니다. 「민지의 첫 주문에 든 상품」이 그런 질문입니다.

연결을 따라가지 않는 질문은 불편합니다. 「천 원 넘는 상품을 산 회원이 몇 명인가」처럼 조건으로 걸러 모아 세는 질문입니다. 관계형에서는 SQL(Structured Query Language) 한 문장이면 됩니다. 객체지향 데이터베이스에서는 객체를 훑는 코드를 짜거나 따로 마련된 질의 언어를 써야 합니다.

그런 질의 언어로 OQL(Object Query Language)이 제안됐습니다. SQL 과 닮은 문법으로 객체를 고르는 언어입니다. 제품마다 지원하는 범위가 달라서 SQL 만큼 널리 퍼지지는 못했습니다.

클래스와 상속까지 아는 저장소

객체지향 데이터베이스는 클래스 구조도 함께 저장합니다. 스키마는 데이터가 어떤 모양이어야 하는지 적은 틀입니다. 이 데이터베이스에서 스키마는 표 정의가 아니라 클래스 정의입니다.

상속도 담습니다. 상품 클래스를 물려받은 책 클래스가 있으면 책 객체는 상품으로도 꺼낼 수 있습니다. 상품 전부를 고르면 책도 함께 나옵니다.

관계형·객체지향·객체관계형

객체관계형 데이터베이스는 관계형과 객체지향 사이에 선 방식입니다. 관계형 데이터베이스에 객체 쪽 기능을 더했습니다. 표와 SQL 은 지킵니다.

더한 기능의 하나가 사용자 정의 타입입니다. 주소처럼 여러 값을 묶은 타입을 만들어 칸 하나에 넣습니다. 그 타입끼리 상속을 두기도 합니다.

세 방식을 나란히 놓으면 아래와 같습니다.

관계형 객체지향 객체관계형
저장 단위 표의 행 객체 표의 행. 칸에 복잡한 값도 넣는다
하나를 가리키는 법 기본키 값 객체 식별자 기본키 값
둘을 잇는 법 상대 키를 적고 조인한다 식별자로 곧장 가리킨다 관계형과 같다
질의 SQL 연결 따라가기 · OQL SQL 을 넓힌 것
상속 없다 클래스 상속 타입 상속을 두기도 한다

위 표의 세 방식은 연결을 어떻게 적느냐로 먼저 갈립니다. 관계형과 객체관계형은 연결을 키 값으로 적습니다. 꺼낼 때 그 값을 맞춰 봅니다.

객체지향은 연결을 식별자로 적습니다. 꺼낼 때 그 식별자를 따라갑니다.

맞는 데이터와 치르는 대가

객체지향 데이터베이스는 객체끼리 촘촘히 얽히고 그 연결을 따라 읽는 일이 많은 데이터에 맞습니다. CAD(Computer-Aided Design, 컴퓨터 지원 설계)로 그린 설계도가 대표적입니다. 부품 안에 하위 부품이, 그 안에 또 부품이 듭니다. 이런 데이터를 표로 쪼개면 꺼낼 때마다 조인이 겹겹이 붙습니다.

첫째 대가는 언어에 묶인다는 것입니다. 저장된 데이터의 모양이 한 언어의 클래스 정의입니다. 다른 언어로 짠 프로그램이나 보고서 도구가 같은 데이터를 읽으려면 그 클래스를 알아야 합니다.

둘째 대가는 앞에서 본 질문의 불편입니다. 연결을 따라가지 않고 조건으로 걸러 모아 세는 질문은 관계형보다 손이 많이 갑니다.

셋째 대가는 클래스를 고칠 때 나옵니다. 클래스에 필드를 더해도 번역 코드를 고칠 일은 없습니다. 대신 디스크에 이미 쌓인 객체를 새 모양으로 옮기는 일이 남습니다.

스키마 진화는 이렇게 저장된 데이터를 바뀐 스키마에 맞춰 옮기는 일입니다. 클래스와 저장 구조가 하나라서 프로그램을 고치는 일이 곧 데이터를 고치는 일이 됩니다.

지금 남아 있는 흔적

업무 시스템에서는 관계형 데이터베이스가 계속 주류로 남았습니다. 객체지향 데이터베이스는 공학 설계처럼 객체 그물이 크고 깊은 분야에서 쓰입니다. ObjectStore, Versant 같은 제품이 이 갈래에 속합니다.

번역을 없애려던 문제는 다른 쪽에서 풀렸습니다. 프로그램 쪽에 번역기를 두는 ORM(Object-Relational Mapping, 객체-관계 매핑)입니다. 객체를 넘기면 ORM 이 표로 쪼개 저장합니다. 읽을 때는 다시 객체로 조립해 줍니다.

자바의 JPA(Java Persistence API)와 그 구현인 Hibernate가 그렇습니다. 엔티티 클래스에 애노테이션을 달아 저장하는 방식이 이것입니다. 데이터베이스는 표로 둡니다. 객체와 표 사이의 번역은 라이브러리가 맡습니다.

문서 데이터베이스는 같은 불편을 또 다른 쪽에서 풉니다. 회원 객체를 JSON(JavaScript Object Notation) 문서 하나로 저장합니다. 객체가 품은 목록까지 한 덩이로 넣으므로 쪼개고 붙이는 일이 줄어듭니다.

관련 항목

객체지향 데이터베이스를 이루는 구성 요소

객체 · 클래스 · 객체 식별자 · 참조 · 객체 그래프 · 영속성 · 스키마

객체지향 데이터베이스가 빌려 온 객체 지향 개념

객체 지향 프로그래밍 · 상속 · 캡슐화 · 다형성 · 메서드

객체지향 데이터베이스가 비롯된 배경

객체-관계 임피던스 불일치 · 관계형 데이터베이스 · 테이블 · 조인 · 데이터 모델 · 데이터 모델링

객체지향 데이터베이스에서 데이터를 읽는 방식

항해식 접근 · OQL · SQL · 지연 로딩 · 포인터 스위즐링

객체지향 데이터베이스와 견주는 데이터 모델

계층형 데이터베이스 · 네트워크 모델 · 관계형 모델 · 객체관계형 데이터베이스 · 문서 데이터베이스 · 그래프 데이터베이스

객체지향 데이터베이스를 대신할 수 있는 다른 수단

ORM · JPA · Hibernate · 액티브 레코드 · 직렬화

객체지향 데이터베이스가 치르는 대가와 약점

스키마 진화 · 다대다 관계 · 데이터 독립성 · 애드혹 질의

객체지향 데이터베이스를 구현한 제품

ObjectStore · Versant · GemStone · db4o · ObjectDB

다른 이름: object-oriented database · OODB · OODBMS · object database · 객체 데이터베이스 · 객체지향 DBMS