데이터 모델과 질의 언어
데이터 모델은 소프트웨어가 어떻게 작성됐는지 뿐만 아니라, 해결하려는 문제를 어떻게 생각해야 하는지 에 대해서도 지대한 영향을 미친다.
대부분의 애플리케이션은 하나의 데이터 모델을 다른 데이터 모델 위에 계층을 둬서 만든다. 각 계층은 다른 계층과 데이터 표현을 통해 소통한다. 예를 들면
- 애플리케이션은 클라이언트와 API 로 통신한다.
- 데이터 구조는 JSON, XML, 문서, RDB로 저장된다.
- 위의 데이터 구조들은 네트워크 바이트 단위로 저장되며, 이 바이트를 가지고 데이터를 질의, 탐색, 조작할 수 있다.
기본 개념은 다음과 같다.
각 계층은 명확한 데이터 모델을 제공해 하위 계층의 복잡성을 숨긴다.
이 장에서는 다양한 범용 데이터 모델을 살펴본다. 특히 관계형 모델, 문서 모델, 그래프 기반 데이터 모델을 비교한다.
관계형 모델과 문서 모델
관계형 데이터베이스의 근원은 1960년대와 70년대에 메인프레임 컴퓨터에서 수행된 비즈니스 데이터 처리에 있다. 보통 트렌젝션 처리와 배치 처리를 수행하였고, 오늘날에는 일반적인 데이터 처리 방식이다.
수 많은 모델들이 경쟁하였고, 1970년대에는 네트워크 모델과 계층 모델, 그리고 객체 데이터베이스, XML 데이터베이스가 나타났지만 관계형 데이터베이스는 위의 모델을 모두 무찌르고 현재 웹에서 볼 수 있는 대부분의 서비스에 사용되고 있다.
NoSQL 의 탄생
NoSQL 은 다음과 같은 특징이 있다.
- 대규모 데이터셋이나 매우 높은 쓰기 처리량 달성을 관계형 데이터베이스보다 쉽게 할 수 있다
- 상용 데이터베이스 제품보다 무료 오픈소스가 많다.
- 관계형 모델에서 지원하지 않는 특수 질의가 가능하다.
- 동적이고 표현력이 풍부한 데이터 모델을 사용할 수 있다.
애플리케이션이 저마다 요구사항이 다르므로, 가까운 미래에는 관계형 데이터베이스와 요구사항을 충족시킬 수 있는 NoSQL 을 같이 사용하게 될 것이다. 이런 개념을 종종 polyglot persistence 라 한다.
객체 관계형 불일치
오늘날 대부분의 애플리케이션은 객체지향 프로그래밍 언어인데 반해, SQL 데이터 모델은 그렇지 않다. 따라서 데이터를 저장할 때 전환 계층이 필요하다. 이를 해결하기 위해 액티브레코드나 하이버네이트같은 ORM 프레임워크를 사용하기도 하지만, 두 모델 간의 차이를 완벽히 숨길 수는 없다.
예를 들면 링크드인 프로필을 저장한다고 했을 때, RDBMS 는 여러 테이블을 설계하여 그 테이블 사이의 관계를 가지고 데이터를 표현하게 된다. 하지만, 이력서 같은 데이터 구조는 모든 내용을 갖추고 있는 문서 라서, JSON 표현에 매우 적합하다.
{
"user_id":251,
"first_name": "Bill",
"last_name": "Gates",
"summary": "Co-chair of the Bill & Melinda Gates... Active blogger.",
"region_id ": "us :91",
"industry_id": 131,
"photo_unl": "/p/7/000/253/05b/308dd6e.jpg",
"positions": [
{"job_title": "Co-chair ", "organization": " Bill & Melinda Gates Foundation"},
{"job_title": "Co-founder, Chairman", "organization": "Microsoft"}
],
"education": [
{"school_name": " Harvard University ", "start": 1973, "end": 1975},
{"school_name": "Lakeside School, Seattle", "start": null, "end": null}
],
"contact_info": {
"blog": "http://thegatesnotes .com",
"twitter": "http:/Itwitter.comlBillGates"
}
}JSON 표현은 RDBMS 의 다중 테이블 스키마보다 더 나은 지역성을 갖는다. 관계형 테이블에서는 프로필을 가져오려면 여러 쿼리를 날리던지, 난잡한 다중 조인을 수행하여야 한다. JSON 모델은 모든 관련 정보가 한 곳에 있어, 질의 하나로 충분하다. 또한 사용자 프로필에서 직위, 학력 기록, 연락처 정보는 의미상 1:N 관계이다. 즉, 사용자 251은 N개의 직업을 가졌고, N 개의 학력이 있는 것이다.
다대일과 다대다 관계
위의 예제에서 region_id 와 industry_id 는 평문이 아니라 id 로 주어졌다. 평문이 아니라 아이디로 저장하면 다음과 같은 이점이 있다.
- 프로필 간 일관된 스타일과 철자
- 모호함 회피
- 갱신의 편의성
- 현지화 지원
- 더 나은 검색
핵심적인 것은 중복의 문제이다. ID 를 사용하는 경우, 사람에게 의미 있는 정보는 한 곳에만 저장하고 그것을 참조하는 모든 것은 ID 를 사용한다. ID 는 아무 의미가 없기 때문에, 식별 정보를 변경하여도 ID 는 동일하게 유지할 수 있다. 만약 정보가 중복되어 있다면, 정보 갱신시에 모든 정보를 갱신하여야 한다. 이것은 쓰기 오버헤드와 불일치(일부 정보만 갱신됨) 를 불러일으킬 위험이 있다.
중복된 데이터를 정규화하려면 RDBMS 처럼 many-to-one 관계가 필요한데, 이는 문서 모델에는 적합하지 않다. 또한 애플리케이션에 점점 기능을 추가하면 할수록, 데이터 사이에 관계가 발생하게 된다.
- 추천서 : 한 사용자가 다른 사용자를 추천한다고 가정하자. 추천받은 사용자의 추천서에서는 추천인의 이름과 사진을 확인할 수 있다. 추천인이 자신의 사진을 갱신하면 모든 추천서에도 사진이 갱신되어야 한다. 즉, 추천서는 추천인의 프로필을 참조한다.
문서 데이터베이스는 역사를 반복하고 있나?
N대 M 관계를 표현하는 것은 역사적으로 한번 발생했던 일이다. 마찬가지로 M대 N 모델을 표현하기 위해서, 관계형 모델과 네트워크 모델이 대안으로 제시하였다. 이 모델을 간단하게 살펴보자
네트워크 모델
- 네트워크 모델에서 모든 레코드는 다수의 부모가 있다.
- 레코드 간 연결은 프로그래밍 언어의 포인터와 유사하다.
- 레코드에 접근하려면 root 부터 대상 데이터까지 경로를 따라 접근하여야 한다.
네트워크 모델에서 질의는 포인터를 움직이면서 노드를 순회하는 방식으로 이루어진다. 만약 레코드가 다중 부모를 가진다면, 애플리케이션 코드는 다양한 관계를 모두 추적하여야 한다. 이는 n차원 데이터 공간을 항해하는 것과 같다.
네트워크 모델은 1970년대 하드웨어를 잘 사용할 수 있다는 장점이 있지만, 데이터를 수정 / 질의하기 어렵다는 단점이 있었다.
관계형 모델
- 테이블은 로우의 컬렉션이다.
- 테이블의 일부 혹은 모든 로우를 읽을 수 있고, 일부 컬럼을 키로 설정하여 일부 로우를 읽을 수 있다.
- 외래 키 관계에 신경쓰지 않고 임의의 로우를 인서트 할 수 있다.
- SQL 을 통해 질의를 하면, 쿼리 옵티마이저가 어떻게 데이터를 질의할지, 어떤 인덱스를 사용할지 자동으로 결정한다. 새로운 방식으로 쿼리하고 싶다면, 인덱스를 새로 추가해주면 쿼리 옵티마이저가 자동으로 적당한 인덱스를 사용한다.
문서 데이터베이스와의 비교
- 문서 데이터베이스는 상위 레코드 내에 중첩된 테이블을 저장 : 이는 네트워크 모델과 동일
- 하지만 1:N 이나 M:N 관계를 표현할 때는 RDBMS 의 방법을 사용함 : 키를 저장하고 있다가 질의 시점에 외부 도큐먼트와 조인
관계형 데이터베이스와 오늘날의 문서 데이터베이스
- 문서 데이터베이스의 장점 : 스키마 유연성, 지역성에 기반한 더 나은 성능, 저장 모델이 애플리케이션에서 사용하는 데이터 모델과 흡사한 경우 있음
- 관계형 데이터베이스의 장점 : 조인, 1:N, M:N 관게를 더 잘 지원함
어떤 데이터 모델이 애플리케이션 코드를 더 간단하게 할까
애플리케이션에서 데이터가 문서와 흡사한 구조라면, 문서 모델을 사용하는 편이 좋다. 비슷한 구조의 테이블을 여러 개로 샤딩하여 배치하면 지역성이 낮아지기 때문에 스키마를 다루기 힘들고 불필요하게 애플리케이션 코드가 복잡해진다.
문서 모델에는 다음과 같은 제한이 있다.
- 바로 하나의 데이터에 접근할 수 없다. 예를 들면 빌 게이츠 > 학력 과 같은 식으로 데이터에 엑세스하여야 한다.
- 조인을 지원하는 게 미흡하다.
- 애플리케이션의 M:N 관게 지원이 미흡하다. 비정규화를 할 수 있지만, 데이터를 수정할 때 데이터의 일관성을 유지하기 위해 추가적인 작업을 하여야 한다. 애플리케이션에서 조인을 구현하는 것은 느릴 뿐만 아니라, 코드를 복잡하게 만든다.
문서 모델에서의 스키마 유연성
JSON 은 어떤 스키마를 강요하지 않는다. 이 말은, 문서에 임의의 키값을 추가할 수 있고 데이터를 읽을 때 클라이언트는 필드의 존재 여부를 보장하지 않는다는 의미이다. 다음의 예제로 확인해 보자
if (user && user.name && !user.first_name) {
user.First_name = user.name.split( " " ){@];
} 문서 데이터베이스는 위의 사례처럼 새로운 필드를 가진 문서를 생성하고, 애플리케이션 코드에서 위와 같이 처리해주면 된다. 반면에 RDBMS 는 데이터를 마이그레이션 하여야한다.
ALTER TABLE users ADD COLUMN first name text;
UPDATE users SET first_name = substring_index(name, " , 1);보통 다른 RDMBS 의 alter 는 수 밀리초 내에 수행되지만, MySQL 은 테이블 전체를 복사하기 때문에 큰 테이블을 변경할때는 수분에서 수십분간의 중단이 발생하게 된다.
첫 번째 예제로 미루어 볼 때, 문서 데이터베이스는 테이블 내의 구조가 모두 동일하지 않은 경우에 유용하다. 즉, 다음과 같은 조건 하에서 스키마를 강제하는 것은 단점이 된다.
- 다른 여러 유형의 오브젝트가 있고 각 유형의 오브젝트별로 각기 다른 테이블에 넣는 것은 실용적이지 않다.
- 사용자가 제어할 수 없고 언제나 변경할 수 있는 외부 시스템 구조에 의해 데이터 구조가 결정된다.
하지만 모든 레코드가 동일한 구조라면, 스키마를 강제하는 것이 문서화와 구조를 강제하기 위한 유용한 방법이 될 수 있다.
질의를 위한 데이터 지역성
한번에 많은 데이터를 가져올 때 스토리지 지역성을 사용하면 효율이 좋다. RDMBS 에서는 데이터가 다중 테이블로 나눠지게 되는데, 이 경우에는 코드가 복잡해지고 성능이 떨어지게 된다. 다만 지역성의 이점은 한번에 많은 데이터를 가져올 때만 유용하다. 문서 데이터베이스는 오히려 데이터를 변경하여 문서의 크기를 증가시키면, 전체 문서를 모두 업데이트해야 하여 쓰기 성능이 저하되는 경우가 있다.
지역성을 유지하는 개념은 RDBMS 에도 적용되는 경우가 많은데, 테이블 내에 테이블 데이터를 교차하여 입력할 수 있게 한다.
RDBMS 는 JSON 형테의 데이터를 컬럼에 추가할 수 있게 지원하기 시작했고, 문서 데이터베이스는 조인을 지원하거나 참조를 자동으로 확인할 수 있는 기능을 지원하게 되었다.
데이터를 위한 질의 언어
데이터를 질의하는 방법에는 선언형과 명령형이 있다. 이것은 무엇을 의미할까?
프로그래밍에서 일반적으로 많이 사용하는 것은 명령형이다. 코드로 보면 다음과 같다.
function getSharks() {
var sharks = [];
for (var i = 0; i < animals.length; i-H-) {
if (animals[i].Family === " Sharks ") {
sharks.push(animals[i]);
}
}
return sharks;
} 반면에 선언형 조회는 다음과 같다.
SELECT * FROM animals WHERE Family = 'Sharks'; 명령형 언어는 특정 순서로 특정 연산을 수행하게 지시한다. 즉, 로직의 내부를 디테일하게 지정해주는 것이다. 반면에 선언형 조회는 데이터를 질의할 때 목표를 달성하기 위한 방법이 아니라, 알고자 하는 데이터의 패턴, 즉 어떻게 데이터를 변환할지(정렬, 그룹화, 집계 등) 결정해주면 된다. 어떤 인덱스와 조인 함수를 사용할지는 데이터베이스에서 결정할 문제이다.
선언형 질의 언어는 데이터베이스의 상세 구현이 숨겨져 있기 때문에, 질의를 변경하지 않더라도 성능을 향상시킬 수 있다. 이는 주요한 장점이다.
마지막으로 선언형 언어는 병렬 프로그랭에 적합하다.
맵리듀스 질의
많은 컴퓨터에서 대용량 데이터를 처리하기 위한 기술이다. 여러 함수형 언어에 있는 map 과 reduce 를 기반으로 한다.
- 질의 로직은 처리 프레임워크가 반복적으로 호출하는 코드 조각으로 표현한다.
몽고DB의 다음 예제로 확인해 보자. 해양 생물학자가 되어 바다에서 동물을 볼 때마다 데이터베이스 관찰 기록을 추가하기로 한다. 프로스그래스큐엘에서는 다음과 같이 질의를 표현할 수 있다.
SELECT date_trunc('month', boservation_timestamp) AS observation_month,
sum(num_animals) AS total_animals
FROM observations
WHERE family = 'Sharks'
GROUP BY observation_month;이 질의는 상어과로 관측치를 필터링 한 후, 관측치가 발생한 달력의 월로 그룹핑하고 그 달의 모든 동물 수를 합친다. 같은 기능을 몽고DB의 맵리듀스로 표현하면 다음과 같다.
db.observations.mapReduce(
function map() { // 질의와 일치하는 모든 문서에 대해 한 번씩 호출, this 는 문서 객체
var year = this.observationTimestamp.getFullYear();
var month = this.observationTimestamp.getMonth() + 1
emit(year + "-" + month, this.numAnimals); // 모든 문서에 대해 해당 값을 방출한다.
},
function reduce(key, value) { // map 함수가 방출한 key, value 로 그룹화된다.
return Array.sum(values); // 특정 월의 관측치에서 모든 동물 수를 합친다.
},
{
query: {family: "Sharks"}, // 상어 종만 거르기 위한 필터
out : "monthlySharkReport"
}
)맵리듀스의 사용성 문제는 연계된 자바스크립트 함수 두 개를 신중하게 작성해야 한다는 점이다. 이는 종종 하나의 질의를 작성하는 것보다 어려운데, 이유는 두 함수는 입력으로 전달된 데이터만 사용하고 추가적인 데이터베이스 질의를 수행할 수 없어야 하기 때문이다. 이런 이유르 몽고DB 는 집계 파이프라인이라고 하는 선언형 질의 언어 지원을 추가했다.
db.observations.aggregate([
{ $match: {family: "Sharks"}},
{ $group: {
_id: {
year: { $year : "$boservationTimestamp"},
month : { $month : "$observationTimestamp"}
},
totalAnimals: {$sum: "$sumAnimals"}
}}
]);그래프형 데이터 모델
만약에 데이터에서 다대다 관계가 매우 일반적이라면 어떻게 해야 할까? 관계형 모델은 다대다 관계를 다룰 수 있지만, 데이터 간 연결이 더 복잡해지면 그래프로 데이터를 모델링하는 편이 더 자연스럽다.
그래프는 두 유영의 객체로 이루어진다. 정점(노드나 엔티티라고 한다)과 간선(관계나 호 라고도 한다)이다. 일반적으로 다음 관계를 그래프형 데이터 모델로 모델링 할 수 있다.
- 소셜 그래프
- 정점은 사람이고 간선은 사람들이 서로 알고 있음을 나타낸다.
- 웹 그래프
- 정점은 웹 페이지고 간선은 다른 페이지에 대한 HTML 링크를 나타낸다.
- 도로나 철도 그래프
- 정점은 교차로이고 간선은 교차로 간 도로나 철로 선을 나타낸다.
이와 같은 예제에서 잘 알려진 여러 알고리즘이 있다. 그러나, 그래프는 이런 데이터에만 국한된 데이터베이스가 아니다. 그래프 데이터베이스 단일 데이터 저장소에 완전히 다른 유형의 객체를 일관성 있게 저장할 수 있는 강력한 방법을 제공한다. 예를 들면 정점은 사람, 장소, 이벤트, 체크인, 사용자가 작성한 코멘트가 될 수 있고 간선은 어떤 사람이 서로 친구인지, 어떤 위치에서 체크인이 발생했는지, 어떤 포스트에 코맨트를 달았는지를 나타낼 수 있다. 예를 들면 다음과 같다.

정리
- 역사적으로 데이터를 하나의 큰 계층 모델로 표현하고자 노력하였으나, M:N 관계를 나타내기에는 트리 구조가 적합하지 않았다. 이를 해결하기 위해 관계형 모델이 등장했다.
- 관계형 모델이 적합하지 않은 애플리케이션을 위해 NoSQL 이 등장했다. 다음과 같은 두 가지 특징을 지닌다.
- 문서 데이터베이스 : 데이터가 문서 자체에 포함돼 있으면서 하나의 문서와 다른 문서 간 관계가 거의 없다
- 그래프 데이터베이스 : 문서 데이터베이스와 정반대로, 모든 것은 잠재적인 관계가 있다고 간주한다.
- 단일 만능 솔루션이 아닌 각기 목적에 맞는 다양한 시스템을 보유하여야 한다.