CS/데이터 중심 애플리케이션 설계 요약

2장 - 데이터 모델과 질의 언어

Junuuu 2022. 11. 16. 00:01

데이터 모델

데이터 모델은 아마도 소프트웨어 개발에서 가장 중요한 부분일 것입니다.

데이터 모델을 통해 해결하려는 문제를 어떻게 생각해야 하는지에 대해 큰 영향을 미치기 때문입니다.

 

대부분의 애플리케이션은 하나의 데이터 모델을 다른 데이터 모델 위에 계층을 두어 만듭니다.

각 계층의 핵심적인 문제는 다음 하위 계층 관점에서 데이터 모델을 표현하는 방법입니다.

 

예를 들어 각 계층별로 데이터를 표현하는 방법입니다.

- 애플리케이션 개발자는 현실을 보고 객체나 데이터 구조를 다루는 API를 모델링합니다.

- 데이터 구조를 저장할 때는 JSON, XML, RDB, NoSQL 등으로 표현합니다.

- DB 소프트웨어를 개발자는 JSON, XML, RDB, NoSQL 데이터를 메모리나 디스크 또는 네트워크 상의 바이트 단위로 표현하는 방법을 결정짓고 다양한 방법으로 데이터를 질의, 탐색, 조작, 처리할 수 있게 합니다.

- 더 낮은 계층의 하드웨어 엔지니어는 전료, 빛의 파동, 자기장 등의 관점에서 바이트를 표현하는 방법을 알아냅니다.

 

복잡한 어플리케이션에도 이런 추상화를 통하여 각 계층을 두어 하위 계층의 복잡성을 숨깁니다.

 

다양한 유형의 데이터 모델이 존재하고 이런 차이점들이 있습니다.

-  A는 어떤 기능의 사용법은 쉽지만 어떤 동작은 지원하지 않는다.

-  A의 어떤 연산은 빠르지만 어떤 연산은 매우 느리다.

-  A의 어떤 데이터 변환은 자연스럽지만 어떤 데이터 변환은 부자연스럽다.

 

특히 RDB, 문서 모델, 그래프 기반 데이터 모델들이 존재하며 이런 데이터 모델을 살펴보겠습니다.


관계형 모델과 문서 모델

관계형 모델에서 데이터는 테이블이라 불리는 관계로 구성되고 각 관계는 순서 없는 튜블(row) 모음입니다.

관계형 데이터베이스의 근원은 비즈니스 데이터 처리에 있습니다.

보통 트랜잭션 처리(은행 거래, 항공 예약)와 일괄 처리로 오늘날의 관점에서는 일상적으로 수행되는 일입니다.

 

이외에 네트워크 모델, 계층 모델, XML 데이터베이스 등이 등장하였지만 여전히 관계형 데이터베이스를 이길 순 없었습니다.

 

NoSQL의 탄생

관계형 모델의 우위를 뒤집으려는 가장 최신 시도입니다.

NoSQL은 Not Only SQL로 해석됩니다.

즉, SQL 뿐만 아니라 다른 기능도 제공함을 의미합니다.

 

NoSQL의 등장배경

- 대규모 데이터셋이나 매우 높은 쓰기 처리량 달성을 RDB보다 쉽게 할 수 있는 뛰어난 확장성 필요

- 상용 DB보다 무료 오픈소스에 대한 선호도 확산

- RDB에서 지원하지 않는 특수 질의 동작

 

애플리케이션마다 요구사항은 다르고 가까운 미래에는 RDB와 NoSQL이 함께 사용될 것입니다.

*실제로 요구사항에 따라 MySQL, Redis, MongoDB 등 RDB와 NoSQL이 함께 사용되고 있습니다.

 

객체 관계형 불일치

JPA를 다루어보았다면 조금 익숙한 주제입니다.

오늘날 대부분의 애플리케이션은 객체지향 프로그래밍 언어로 개발합니다.

데이터를 RDB에 저장하려면 애플리케이션 코드와 DB 모델 객체 사이에 거추장스러운 전한 계층이 필요합니다.

하이버네이트와 같은 ORM이 등장하며 전환 계층에 필요한 보일러 플레이트 코드의 양을 줄이지만 두 모델 간의 차이를 완벽히 숨길 순 업습니다.

 

이력서 데이터와 RDB와 NoSQL

이력서를 user_id로 식별하여 RDB로 나타낼 수 있지만 이런 데이터 구조는 모든 내용을 갖추고 있는 문서라서 JSON 표현에 매우 적합합니다.

 

몽고 DB, 리싱크 DB, 카우치 DB, 에스프레소와 같은 문서 지향 DB는 JSON 데이터 모델을 지원합니다.

일부 개발자는 JSON 모델이 계층 간 불일치를 줄인다고 생각하지만 데이터 부호화 형식으로서 JSON이 가진 문제도 있다고 합니다(4장에서 설명)

 

JSON 표현의 또 다른 장점은 지역성을 갖습니다.

RDB에서 프로필을 가져오려면 user_id로 다중 질의를 수행하거나 다중 조인을 수행해야 합니다.

하지만 JSON 표현에서는 모든 관련 정보가 한 곳에 있어 질의 하나로 충분합니다.

 

하지만 중복된 데이터를 정규화하려면 RDB의 다대일 관계가 필요한데 안타깝게도 다대일 관계는 문서 모델이 적합하지 않습니다.

RDB는 조인이 쉽기 때문에 ID로 다른 테이블의 로우를 참조하는 방식이 일반적입니다.

하지만 문서 DB에서는 조인에 대한 지원이 보통 약합니다.

 

즉, DB가 조인을 지원하지 않으면 DB에 대한 다중 질의를 만들어 애플리케이션 코드에서 조인을 흉내 내야 합니다.

 

문서 DB는 역사를 반복하고 있나?

1970년대에 가장 많이 사용한 DB는 IBM의 정보 관리 시스템으로 우주 프로그램에서 재고 관리를 위해 개발되었습니다.

이때 계층 모델이라 불리는 간단한 데이터 모델을 사용했으며 이는 JSON 모델과 유사합니다.

이 또한 1:N 관계는 잘 표현하였으나 N:1 관계의 표현을 어려웠습니다.

지금 고민하는 문제와 유사하며 이 문제를 해결하기 위해서 RDB가 등장하게 되었습니다.

 

RDB vs 문서 DB

RDB와 문서 DB를 비교하는 경우 내결함성과 동시성 처리, 데이터 구조를 포함해 고려해야 할 차이점이 많이 있습니다.

문서 DB를 선호하는 이유는 스키마 유연성, 지역성에 기인한 더 나은 성능입니다.

반면 RDB는 조인, 다대일, 다대다 관계를 더 잘 지원합니다.

 

RDB와 문서 DB의 통합

대부분의 RDB는 2000년대 중반 이후로 XML을 지원합니다.

이를 통해 문서 DB와 비슷한 모델을 사용할 수 있습니다.

postgresql 9.3, mysql 5.7부터 JSON 문서에 대해 비슷한 수준의 지원 기능을 제공합니다.

또한 문서 DB에서도 리싱크 DB는 질의 언어에서 관계형 조인을 지원하고 몽고 DB 드라이버는 자동으로 데이터베이스 참조를 확인합니다.

 

즉, 시간이 지남에 따라 서로 부족한 부분을 보완해 나가고 있고 이런 혼합은 미래 데이터베이스들이 가야 할 올바른 길입니다.

 

 

데이터를 위한 질의

RDB는 일반적인 절차적인 코드와 다르게 SQL이라는 선언형 질의를 사용합니다.

 

이를 통해 가독성이 매우 높아지고 내부적으로 DB가 최적화를 수행할 수 있습니다.

 

또한 절차적인 코드에서는 특정 순서가 중요하지만 SQL은 특정 순서를 보장하지 않을 수 있기 때문에 DB에게 최적화할 수 있는 여지를 더 많이 줄 수 있습니다.

 

유사하게 절차적인에서는 순서가 중요하기 때문에 병렬 처리가 매우 어렵지만 순서가 중요하지 않은 SQL은 병렬 구현을 마음껏 사용할 수 있습니다.

 

 

맵리듀스 질의

맵리듀스는 많은 컴퓨팅에서 대량의 데이터를 처리하기 위한 프로그래밍 모델로 구글에 의해 널리 알려졌습니다.

여러 함수형 프로그래밍에 있는 map과 reduce 함수를 기반으로 합니다.

 

예를 들어 몽고 DB의 맵리듀스 기능입니다.

db.observations.mapReduce(
    function map(){
    	var year = this.observationTimestamp.getFullYear();
        var month = this.observationTimestamp.getMonth() + 1;
        emit(year + "-" + month, this.numAnimals);
    },
    function reduce(key, values){
    	return Array.sum(values)    
    },
    {
    	query: {family: "Sharks"},
        out: "monthlyShartReport"
    }
);

이때 map과 reducs는 순수 함수여야 하며 부수효과가 없어야 합니다.

이런 제약을 통해 DB가 임의 순서로 어디에서나 이 함수를 실행할 수 있고 장애가 발생해도 함수를 재 실행할 수 있습니다.

개인적으로 아직 몽고 DB를 사용해보지 않아 조금 어색하게 느껴집니다.

 


그래프형 데이터 모델

애플리케이션이 일대다 관계, 관계가 없다면 문서 모델이 적합합니다.

하지만 데이터에서 다대다 관계가 매우 일반적인 경우에서 RDB는 이런 문제를 해결할 수 있지만 더 복잡해지는 경우에는 그래프로 데이터를 모델링하는 편이 더 자연스럽습니다.

 

정점과 간선으로 이루어져 있으면 일반적으로 다음과 같은 데이터들이 그래프로 모델링 됩니다.

- 소셜 그래프

- 웹 그래프

- 도로, 철도 네트워크

 

그래프에서 데이터를 구조화하고 질의하는 다른 방법들이 있지만 여기서는 속성 그래프 모델과 트리플 저장소 모델을 알아보고 그래프용 선언형 질의 언어 사이퍼, 스파클, 데이터 로그를 알아보겠습니다.

 

속성 그래프

각 정점은 다음과 같은 요소로 구성됩니다.

- 고유한 식별자

- 유출 간선 집합

- 유입 간선 집합

- 속성 컬렉션(키-값 쌍)

 

각 간선은 다음과 같은 요소로 구성됩니다.

-  고유한 식별자

- 간선이 시작하는 정점

- 간선이 끝나는 정점

- 두 정점 간 관계 유형을 설명하는 레이블

- 속성 컬렉션(키-값 쌍)

 

RDB에서도 다음과 같이 그래프 저장소를 구성할 수 있습니다.

CREATE TABLE vertices(
    vertex_id integer PRIMARY KEY,
    properties json
);

CREATE TABLE edges (
    edge_id integer PRIMARY KEY,
    tail_vertex integer REFERENCES vertices (vertex_id),
    head_vertex integer REFERENCES vertices (vertex_id),
    label       text,
    properties  json

)

CREATE INDEX edges_tails ON edges(tail_vertex);
CREATE INDEX edges_heads ON edges(head_vertex);

 

그래프 모델 몇 가지 중요한 점들이 있습니다.

- 정점은 다른 정점과 간선으로 연결되며 특정 유형과 관련 여부를 제한하는 스키마가 없다. 

- 정점이 주어지면 정점의 유입 유출 간선을 효율적으로 찾아 그래프를 순회할 수 있다(index를 생성하는 이유)

- 다른 유형의 관계에서 서로 다른 레이블을 사용하면 단일 그래프에 다른 유형의 정보를 저장하면서도 데이터 모델을 깔끔하게 유지할 수 있다.

 

전통적인 RDB에서 표현하기 힘든 예시들이 있습니다.

- 국가마다 지역 구조가 다름(프랑스에서는 주와도를 사용하지만 미국에서는 군과 주를 사용)

 

그래프 모델은 발전성이 좋아 애플리케이션에 기능을 추가하는 경우 데이터 구조 변경을 수용하게끔 그래프를 쉽게 확장할 수 있습니다.

 

 

사이퍼 질의 언어

속성 그래프를 위한 선언형 질의 언어입니다.

책에서 사이퍼 질의 언어의 예시가 나오는데 아직 사용해본 경험도 없고 흥미롭게 생각하진 않아 이 부분은 눈으로만 읽고 넘어갔습니다.

 

 

SQL의 그래프 질의

그래프 데이터를 RDB에 넣어도 SQL을 사용해 질의할 수 있습니다. (약간 어려움)

 

사이퍼 질의 언어에서 :WITH*0..는 간결하게 표현되지만 "0회 이상 WITH 간선을 따라가라"는 의미로 정규 표현식의 * 연산자와 동일합니다.

 

SQL에서도 WITH RECURSIVE를 사용하여 표현할 수 있습니다.

 

하지만 동일한 질의를 사이퍼에서는 4줄로 작성할 수 있고 SQL에서는 29줄로 작성해야 합니다.

 

 

트리플 저장소와 스파클

트리플 저장소 모델은 속성 그래프 모델과 거의 동등합니다.

트리플 저장소에서는 모든 정보를 주어, 서술어, 목적어처럼 매우 간단한 세 부분 구문으로 나눕니다.

 

스파클은 RDF 데이터 모델을 사용한 트리플 저장소 질의 언어입니다.

사이퍼보다 먼저 만들어졌으며 사이퍼의 패턴 매칭을 스파클에서 차용했기 때문에 둘을 유사해 보입니다.

 

데이터 로그

1980년대에 연구되었으며 스파클이나 사이퍼보다 훨씬 오래된 언어입니다.

다양한 질의 언어의 기반이 되는 초석을 제공합니다.

트리플 저장소 모델과 유사하지만 조금 더 일반화되어있습니다.

(주어, 목적어)로 작성됩니다.


정리

데이터 모델을 광범위한 주제이며 애플리케이션의 요구사항에 가장 적합한 모델을 찾는 것이 제일 중요합니다.

역사적으로 데이터를 하나의 큰 트리로 표현하려고 했지만 다대다 관계를 표현하기에 트리 구조는 적절하지 않았습니다.

따라서 관계형 모델이 고안되었습니다.

 

하지만 최근에 관계형 모델에도 적합하지 않은 애플리케이션에 새롭게 등장한 NoSQL을 사용합니다.

- 문서 데이터베이스

- 그래프 데이터베이스

 

세 가지 모델(문서, 관계형, 그래프) 모두 널리 사용하고 있으며 각 모델은 각자의 영역에서 훌륭합니다.

한 모델을 다른 모델로 흉내 낼 수 있지만 그 결과는 대부분 엉망입니다.

따라서 단일 만능 솔루션이 아닌 각기 목적에 맞는 다양한 시스템을 보유해야 합니다.