데중애설 2장 <데이터 모델과 질의 언어>
지난주부터 데이터 중심 애플리케이션 설계 (어플리케이션이 아닌 애플리케이션 왜와이) 를 읽기 시작했다. 오늘은 2장을 다 마치게 되어 글을 적는다.
소개
이번 장의 핵심은 어느 데이터 모델을 사용해서 데이터 관리 문제를 해결할 것인가이다. 작가는 초반부터 역할에 따라 생각해야 하는 계층이 다를 것이라고 말한다.
예를 들어 애플리케이션 개발자는 객체나 데이터 구조 혹은 이러한 데이터 구조를 다루는 API 등을 모델링하고 데이터베이스 소프트웨어 개발자들은 데이터를 메모리나 디스크 또는 네트워크 상의 바이트 단위로 표현하는 방법을 결정하는 등 다양한 계층이 있다는 것을 알려준다.
역사
본격적으로 오늘날 기술들에 대해서 다루기 전에 저자와 같이 역사를 배우는 시간이 있다. 요약하자면 옛날에는 관계형 모델 (오늘날 SQL) 이 일어났는데 처음에는 네트워크 모델이나 계층 모델 등이 반격을 시도했다가 실패했다는 요지다. 사실 이 외에도 XML 이나 객체 데이터베이스 등과 같이 다른 모델들도 있었지만 이들은 빛을 받지 못했다.
2010년에 NoSQL 이 어떻게 탄생했는지도 알려주는데 트위터에서 비관계형 데이터베이스 모임을 위한 #NoSQL 이 배경이라고 한다. 사실 나도 이전에는 NoSQL 의 의미가 "Not Only SQL" 인지 "No SQL" 인지 헷갈렸는데 여기에서는 역사의 시작이 "No SQL" 에 근접하고 최근 들어 "Not Only SQL" 로 재해석된다는 글을 읽고 TMI 이지만 나름 흥미로웠다.
NoSQL 의 탄생 이유
기술들은 그냥 이유없이 탄생하지 않는다고 생각한다. 만든 사람의 목적이 있지 않은 이상 굳이 노력해서 만들까? 세상에 태어나지 않는다는 것이 내 개인적인 의견이다.
NoSQL 도 마찬가지인듯하다. 책에서는 4가지의 이유로 탄생했다고 하는데 요약본으로 적자면 다음과 같다:
- 확장성 - 대규모 데이터셋을 쓰기 처리할 때 필요
- 무료 오픈소스 소프트웨어 증가
- 관계형에서 못하는 질의 동작
- 정적인 관계형 스키마에 대한 불만과 동적 스키마에 대한 요구
물론 태어난 이유는 여러가지이겠지만 정말 어느 세계이든 변화는 피할 수 없어 보인다;;
Impedence Mismatch
사실 이 부분은 이미 ORM 을 공부할 때 이미 접했던 개념이다. Impedence Mismatch... 한국어로는 객체 관계형 불일치로 쉽게 말해 관계형 데이터베이스와 어플리케이션 코드 간 통역이 100% 안된다는 뜻이다. 무슨 말이냐면 관계형 데이터베이스에서는 나름의 수학적 근거로 데이터베이스가 설계되었고 테이블 간 관계, 스키마 등 작동하는 방식이 있는데 이걸 그냥 파이썬 코드로 조회하는 것은 쉽지 않다는 거다. 이 차이를 ORM 들이 최대한 채우기 위해 노력을 한다지만... 결국에는 체계가 다르기 때문에 어느정도의 불일치는 불가피하다.
그렇다고 NoSQL 에서 존재하는 JSON 형식이나 몽고DB 와 같이 문서형 데이터베이스가 어플리케이션 코드와 완벽하게 작동한다도 아니다. 이러한 기술들도 사실 결국에는 차이가 조금씩 날 수 밖에 없다. 다만 관계형 데이터베이스와 동일한 차이는 아닐 뿐이다.
Schema-on-Read vs Schema-on-Write
관계형과 비관계형의 다른 차이 중 하나는 스키마다. 사전에 체계화된 스키마에서 모든 것이 돌아가야 하는 관계형 데이터베이스에서는 데이터를 쓸 때, 즉 새로 추가할 때 데이터의 형식을 신경써야 한다. 데이터 타입이 다르거나 기대하는 형식이 아니거나 등 이러면 삽입할 수가 없다는 뜻이다.
반면에 NoSQL 에서는 읽기 시점에서 스키마를 중요시한다. 즉, 데이터를 삽입할 때에는 그냥 막 넣어도 되지만 읽어올 때 원하는 데이터를 정리해야 한다. 따라서 사실 NoSQL 을 스키마가 없는 Schemaless 라고 부르기에는 조금 그렇다;; 심지어 예전에 몽고DB 썼을 때에도 원하는 데이터를 막 넣을 수 있어서 신났지만 데이터를 불러왔을 때 곤란했던 기억이 나기도 한다...
다대일 & 다대다
흔히들 많이 생각해야 하는 문제는 Many-to-Many, One-to-Many 이다. 어떻게 관계를 작성할 지 생각을 많이 해야하고 이를 효율적으로 저장하고 쓰기 오버헤드와 불일치 문제가 발생하지 않도록 주의하고 싶다면 신경써야 하는 부분이다.
책에서는 빌 게이츠의 링크드인 프로필을 어떻게 저장할 것인가를 두고 예시를 보여줬는데 한 사람의 프로필을 보여주기 위해서 뒷단에는 얼마나 많은 노력이 들어가고 테이블들, 관계들 설정이 있어야 하는지 보여주는 예시였다.
저자가 준 팁을 정리하자면 "여러 곳에서 사용될 데이터는 아이디값을 통해 따로 조회할 수 있게 하라" 이다. 코드를 짤 때에도 물론 마찬가지인 것처럼 동일한 값을 여러 변수에 선언하게 되면 관리가 힘드니까 최소한으로 줄이고 참조로 묶어준다는 뜻이다.
데이터 모델
계층 모델과 네트워크 모델
위에서 실패했다던 모델들 중에서 그나마 컸던 것들은 다음과 같다:
- 계층 모델: IBM 의 정보 관리 시스템 (Information Management System [IMS])
- 네트워크 모델: 코다실 (Conference on Data Systems Languages [CODASYL])
쉽게 말해 IMS 는 JSON 과 비슷하고 CODASYL 은 계층 모델의 일반화이다 (계층 모델에서 트리 구조에서 모든 레코드는 하나의 부모가 있음)
관계형 모델
관계형 모델은 질의 최적화기 (query optimizer) 라는 것이 있는데 쉽게 말해서 동일한 SQL 쿼리를 작성하더라도 이를 수행하는 순서나 방법 등을 변경하면 효율이 변한다이다.
이는 상당히 큰 메리트이다. 즉, 일반적으로 질의 언어를 작성하는 것과 별개로 따로 데이터베이스 엔진이 어떻게 돌아갈지 정할 수 있다는 것이다. 이렇게 할 수 있는 이유는 애초에 SQL 은 선언형 언어이기 때문이다.
문서 데이터베이스
문서 데이터베이스라고 해서 아이디나 고유값이 없는 것은 아니다 무시 멈춰!. 문서들 간에 참조할 수 있는 식별자가 따로 부여된다. 실제로 이는 매우 유용하고 나중에 가서 책에 나오겠지만 성능에도 영향을 미친다. 또한 이러한 부분을 이용해 서로가 참조할 수 있는데 이런 현상을 document reference 라고 부른다.
문서 데이터베이스도 중요한 것은 중첩이 심하지 않아야 한다. 적당히 중첩해야 읽기도 사용하기도 편하다. 그렇지 않으면 지옥??.
애플리케이션 코드를 간단하게 하는 데이터 모델
저자가 알려주는 해답은... 당연히 케바케이다... 역시 답이 없는 세상...
하지만 완전히 답이 없다고 보기는 힘들다. 케바케이지만 각 케이스에서 어떤 상황과 어떤 어플리케이션에서 어떤 데이터 모델이 어울리는지, 적합한지 판별할 수 있는 것이 중요하다. 책에서는 단일 해답은 없기 때문에 서로가 보완해 줄 수 있는 데이터 모델을 섞어서 사용하는 것도 해답이라고 한다.
예를 들어 다대다가 힘든 문서형 데이터베이스를 관계형으로 보완해줄 수 있고 지역성이나 유연성이 떨어지는 관계형을 문서형 데이터베이스가 보완해주는 것처럼 말이다.
데이터 지역성
간단하게 데이터 지역성에 대해서 짚고 넘어가자면 문서형 데이터베이스와 같은 경우에는 데이터가 하나의 문서에 집합되어 있다. 즉, 조인을 할 필요가 없다는 것이다. 하나만 조회하면 끝이기 때문에 그만큼 더 편리하고 어떤 상황에서는 효율적이다.
여기에 현혹되어서 문서 하나에 온갖 정보를 넣으려고 하면 문제가 발생한다. 특히 문서의 크기가 너무 크게 되어버리면 부담이 된다. 또한 다른 문서를 조회해야 하는 상황에 직면하면 효율과 성능은 문 밖을 걸어나가고 있을 수도 있다.
그러니 애초에 문서형 데이터베이스를 잘 사용하거나 설계를 나름 잘해야 하고 장점보다는 단점을 보면 진행해야 할 필요도 있다.
질의
맵리듀스 질의
맵리듀스 (MapReduce) 는 병렬 처리에서 많이 사용되는 기술로 컴퓨터 자원이 많은 때 더 빛을 보인다. 특히 대량의 데이터 Big Data 처리에 더 유용하다. 작동 방식은 크게 봐서는 말 그대로 "Map" 과 "Reduce" 순이다.
함수형 프로그래밍에 기반하기 때문에 각 함수 "Map" 이나 "Reduce" 는 순수 함수이어야 한다는 것을 기억해야 한다.
순수함수란 side effects 가 없는 주어진 input 으로만 작업할 수 있어야 하는 함수를 가리킨다.
이번 장에서는 다양한 데이터 모델과 해당 모델들의 질의 방법도 살펴보기 때문에 맵리듀스도 나온 것 같다.
인상 깊었던 것은 몽고DB 2.2 는 집계 파이프라인 (aggregation pipeline) 이 있었다는 것이다. 왜 몰랐지? 그렇기 때문에 문서들을 가지고 맵리듀스와 비슷하게 한번에 대량의 데이터를 다룰 수 있게 된다.
그래프형 데이터 모델
마지막은 그래프형 데이터 모델인데 핵심은 정점 (vertex/node/entity) 와 간선 (edge/relation/arc) 으로 이루어졌다는 것이다. 여기에는 크게 두 가지로 종류를 나누는데 바로 속성 그래프와 트리플 그래프이다.
여기에 관해서는 정리하자면 속성 그래프는 하나의 정점에 JSON 처럼 여러가지 키-값 쌍을 저장하고 연결된 간선들 정보 등을 저장한다는 것이고 트리플 그래프와 같은 경우에는 3 개의 단어로 구성된다는 것이다.
3개의 단어란 주어 - 서술어 - 목적어이다.
참고할 수 있는 자료 목록
- The Property Graph Database Model: ceur-ws.org/Vol-2100/paper26.pdf