- 이 글은 마틴 클레프만의 데이터 중심 애플리케이션 설계를 기반으로 작성되었습니다.
- 개요
데이터 모델은 S/W 가 어떻게 작성되었는지와 문제를 어떻게 생각해야하는지에 대해서도 영향을 미친다. 대부분의 애플리케이션에서는 각 계층마다 데이터 모델에 대한 관점이 다르다.
- App. 개발자는 현실을 보고 객체, 데이터 구조, API를 모델링 한다.
- 데이터 구조를 저장할 때는 JSON, XML, RDB 테이블, 그래프와 같은 모델로 표현한다.
- DB S/W 엔지니어는 데이터를 메모리나 디스크에 표현하는 방법을 결정한다. 그리고 이 표현은 질의, 탐색, 조작, 처리할 수 있게 한다.
각 계층에서 명확한 데이터 모델을 제공하면 하위 계층에 대한 복잡성을 숨길 수 있다.
- 관계형 모델
관계형 모델이라는 단어가 어색할 수 있지만 우리가 가장많이 사용하는 SQL 이 관계형 모델이며, 데이터 모델중 가장 유명하다. 데이터는 관계로 구성되고, 각 관계는 순서없는 튜플(Row)가 된다. 네트워크 모델과 계층 모델이 잠시 주요 대안으로 떠오르기도 했지만 결국 관계형 모델이 우위를 차지했다.
- NoSQL
Not Only SQL 로 관계형 모델의 우위를 뒤집으려는 시도로 등장했다. NoSQL 이 채택되거나 등장하게된 배경에는 아래와 같은 원동력이 있다.
- 대규모 데이터 Set, 높은 쓰기 처리량 달성
- 관계형 모델에서 지원하지 않는 특수 질의
- 관계형 스키마의 제한에 대한 불만과 표현력이 풍부한 데이터 모델 요구
- 객체-관계형 불일치
많은 App. 들은 객체지향 언어로 개발되고 데이터는 관계형 모델로 저장된다. 관계형 데이터 모델을 App. 으로 불러올때에 전환계층이 필요한데 이런 모델 사이의 분리를 '임피던스 불일치' 라고 한다. ORM 이 boilerplate 코드를 줄여주긴하지만 완벽한 개념이라고 볼 수는 없다.
관계형 스키마에서 링크드인의 이력서 데이터를 표현한다고 가정해보자. 이력서에는 회원 정보, 직위, 학력, 연락처등의 정보가 있을 것이다. 직위, 학력, 연락처등의 정보는 여러 건이 될 수 있어서 사용자와 이 항목들간의 관계는 1 : N 관계이다. 이런 1 : N 관계를 여러 가지 방법으로 표현할 수 있다.
- 전통적인 RDB 로 유저정보를 하나의 테이블로 두고 여러 건이 될 수 있는 각 항목을 테이블로 구성한 뒤 유저의 Key 를 참조
- SQL 표준에서 구조화된 데이터 타입과 XML 데이터 지원이 추가되어 단일 행에 다중값을 저장할 수 있고 문서 내 질의와 색인이 가능(단, DBMS 마다 지원 형태가 다르고, JSON 지원여부도 다름)
- 직업, 학력, 연락처 정보 JSON, XML 문서로 부호화하여 DB 텍스트 칼럼에 저장한다. 그리고 App. 에게 구조와 내용 해석을 위임한다.
이력서 같은 데이터 구조는 모든 내용을 갖추고 있는 문서라서 JSON 표현에 매우 적합하다. JSON 으로 표현하면 각 항목을 각 테이블의 스키마로 관리하는것보다 더 나은 지역성(locality) 갖는다. 지역성이 좋다는 말이 헷갈릴 수 있는데 간단한 최소한의 질의로 모든 정보를 조회할 수 있다는 뜻이 된다.
예를 들어 각 항목의 테이블로 이력서 정보를 불러오려면 사용자의 Key 값으로 여러 번 조회를 하여 App. 에서 결합하거나, 다중 테이블들을 사용자의 Key 로 조인을 해야 한다. 하지만 JSON 으로 표현하면 하나의 질의로 모든 정보를 불러올 수 있다.
- N : 1
이력서에서 근무하는 지역(region) 이 있다고 가정해보자. 이 지역명을 text 형 데이터로 저장하고 있어도 되지만 region_id 로 저장할 수도 있다. 만약 UI 에 지역명을 Text Field 로 입력할 수 있게 해놓았다면 text 형으로 데이터를 저장하는게 합리적이겠지만 드랍다운이나 자동완성기능으로 구현하면 몇 가지 이점이 있다.
- 프로필간 일관된 스타일
- 모호함 회피(이름이 같은 도시들)
- 갱신이 편리(메타정보만 변경하면 id 로 참조하는곳 모두 변경)
- 현지화 지원
- 고차원적인 검색(워싱턴 주 자선가 검색시 시애틀이 워싱턴에 있다는 사실을 이용한 검색 가능)
ID 는 식별정보를 변경해도 ID 가 유지되는 장점이 있다. 특수한 경우가 아니라면 ID 를 채번할때에는 규칙이 없는것이 좋다. 규칙성을 갖게 되면 변경해야하는 경우가 생길 수 있다. 만약 ID 참조가 아닌 Text 로 정보를 중복시키면 쓰기 오버헤드가 발생하며 일부만 갱신되는 불일치 문제가 발생할 수도 있다.
중복된 정보를 정규화 한다는 것은 N : 1 의 관계를 맺는다는 말과 같은데 안타깝게도 N : 1 관계는 문서 모델에는 적합하지 않다. RDB 에서는 조인이 일상적인 작업이지만 문서 모델은 조인지원이 강력하지는 않다.
만약 DB 에서 조인을 지원하지 않으면 App. 코드에서 이를 흉내내야 한다. App. 의 초기 설계에서는 문서 모델이 적합하다고 판단했더라도 시간이 지남에 따라 추후 데이터들이 연결될 가능성이 있다.
- 문서 DB의 역사
IBM의 IMS 라는 정보 관리시스템은 1970 년대 널리 사용된 DB 이다. 계층모델 설계로 JSON 과 상당히 유사하다. 이 DB는 문서 DB 와 유사하게 1 : N 에서 수월하게 동작했지만 M : N 은 동작이 수월하지 않았다. 이런 계층 모델의 한계를 해결하기 위해 관계형 모델(SQL) 과 네트워크 모델이 등장했다.
- 네트워크 모델
'코다실 모델' 이라고도 불리는 네트워크 모델은 계층모델을 일반화한것이다. 계층형 모델은 하나의 부모만을 가질 수 있지만 네트워크 모델은 다중 부모를 가질 수 있다. 그래서 N : 1과 M : N 이 가능하다.
레코드 접근시에는 root 레코드부터 시작해서 연결 경로를 항해하는데 이를 접근경로라고 한다. 그러나 문제점이 있는데 질의가 복잡해질 경우 n 차원을 항해하는것 같이 복잡해진다. 수동으로 접근경로를 선택하는 이점은 있으나 DB 질의와 갱신이 복잡하다.
- 관계형 모델
관계형 모델은 모든 데이터를 배치하는 것이다. 관계는 튜플(row)의 컬렉션이 전부이다. 임의 조건과 일치하는 데이터를 일부 선택하거나 전부 선택할 수 있다.
질의 최적화기(Query Optimizer) 가 질의의 순서와 사용할 인덱스를 선택한다. 이런 질의 순서와 인덱스 선택은 일종의 '접근 경로'라고 할 수 있는데 이 작업을 개발자가 수행하지 않는다.
- 문서 DB
문서 DB는 별도 테이블이 아닌 상위 레코드내의 중첩 레코드를 저장하므로 계층형 모델로 회귀했다고 할 수 있다. 하지만 N : 1 과 M : N 관계 표현시 RDB 와 문서 DB 는 근본적으로는 방식이 같은데 둘 다 관련 항목은 고유 식별자로 참조하기 때문이다. RDB 에서는 이를 '외래키'라고 부르며 문서 모델에서는 '문서 참조'라고 부른다.
- RDB vs 문서 DB
문서 모델은 스키마가 유연하고 지역성에 기인하여 좋은 성능을 낼 수 있다. 특히 일부 App. 의 경우 특화된 데이터 구조와 문서 모델의 사상이 잘 맞는 이점도 있다. 반면 RDB 는 조인을 지원하고 N : 1과 M : N 관계를 잘 지원한다.
- 데이터 모델과 App. 코드
데이터가 문서와 비슷한 구조의 1 : N 관계 트리라면 문서 모델이 적합할 수 있다. 만약 문서 구조에 적합한 데이터를 여러 개의 테이블로 구성하면 스키마를 다루기 힘들뿐더러 App. 코드도 복잡해진다.
반면 문서 모델을 사용할 경우 단점도 있다.
- 문서 내 중첩항목 직접 참조 불가(ex - 사용자 직위의 2번째 항목 참조)
- 조인 지원이 미흡
- M : N 관계에서 비정규화로 join을 줄일 수 있지만 데이터의 일관성을 유지하려면 추가 작업이 필요
정확한 정답은 없지만 대체적으로 상호 연결이 많은 데이터라면 관계형 모델이 무난하며, 그래프와 같은 모델은 문서 모델이 자연스럽다고 할 수 있다.
- 문서 모델의 스키마 유연성
JSON 은 스키마를 강요하지 않는다. 스키마가 없으므로 임의의 key, value 를 추가할 수 있지만 read 시 필드의 존재여부를 보장해주지 않는다. 문서 DB를 스키마리스라고 하지만 이는 약간의 오해가 있는 표현이다. 어떤 데이터를 읽는다는 것은 이미 구조를 어느정도 가정하고 있다는 얘기이기 때문이다. 따라서 쓰기 스키마가 아닌 읽기 스키마가 있다고 이해하는것이 보다 정확하다고 할 수 있다.
이런 접근방식의 차이가 확연히 드러나는 경우는 데이터 타입을 변경할 때 나타난다. 예를 들어 full name 을 이름과 성으로 분리할 때 문서 DB의 경우 이전 문서를 읽는 시점에 처리하면 된다. 하지만 정적타입의 경우 컬럼을 추가한 후 full name을 split 하여 마이그레이션을 해주어야 한다.
컬렉션 내의 항목이 모두 동일하지 않은 경우 읽기 스키마가 적합하다고 할 수 있다.
- 여러 종류의 오브젝트가 존재하며 각 유형별 오브젝트를 각각 자체 테이블에 넣는게 비 실용적인 경우
- 사용자가 제어할 수 없고 외부 시스템에 의해 데이터 구조가 결정되는 경우
- 질의를 위한 데이터 지역성
문서는 보통 JSON, XML 로 부호화된 단일 연속 문자열이나 이진 변형으로 저장된다. App. 이 자주 전체 문서에 접근해야할 때 저장소 지역성을 활용하면 성능이 향상된다. 이 말이 어려울 수 있는데 만약 데이터가 다중 테이블로 분기되어 있다면 Disk 를 탐색하는데 많은 시간이 들기 때문에 성능이 좋지 못하다는 얘기다.
지역성의 이점을 살리려면 한번에 해당 문서의 많은 부분이 필요한 경우만 적용해야 한다. 문서를 갱신하면 보통 전체 문서를 재작업하기 때문에 문서를 작게 유지하고 크기가 증가하는 쓰기를 회피하는것이 중요하다.
'지역성'이라는 단어는 한마디로 관련 데이터를 그룹화 하는 개념이라고 이해하면 된다. 이 말은 문서모델에만 국한되지 않는다. 오라클의 경우 다중 테이블 색인 클러스터 테이블을 지원한다.
- 문서 DB와 RDB 의 통합
MySQL 을 제외한 대부분 DB 는 XML 을 지원하며, XML 문서의 지역적 수정, 색인 질의 기능을 지원한다. PostgreSQL, MySQL, DB2 의 경우 JSON 에 대해 비슷한 기능을 지원한다. 문서 DB 의 리싱크 DB는 질의 언어에서 관계형 조인을 지원한다.
RDB 와 문서 DB 는 서로를 상호보완하는 식으로 단점을 보완해나가고 있다. 만약 DB가 데이터를 문서처럼 다룰 수 있고, 관계형 질의를 수행할 수 있다면 App. 은 필요에 따라 적합한 기능을 조합해 사용하면 된다.
'App 설계' 카테고리의 다른 글
DDIA - 그래프형 데이터 모델 (0) | 2021.11.21 |
---|---|
DDIA - 데이터를 위한 질의(query) 언어 (0) | 2021.10.31 |
DDIA - 신뢰성,확장성,유지보수성 - 유지보수성 (0) | 2021.10.25 |
DDIA - 신뢰성,확장성,유지보수성 - 확장성 (0) | 2021.10.19 |
DDIA - 신뢰성,확장성,유지보수성 - 신뢰성 (0) | 2021.10.17 |
댓글