해당 게시글은 [데이터 중심 애플리케이션] 책을 읽고 스터디하며 정리한 글입니다.
서론
소프트웨어 개발에서 가장 중요한 부분인 데이터 모델에 대해 이야기한 챕터. 데이터 모델은 문제를 어떻게 생각해야하는지에 대해서도 큰 영향을 미치기 때문에 매우 중요하다고 기술하고 있다.
각 애플리케이션은 하나의 데이터 모델을 다른 데이터 모델 위에 계층을 두어 만드는데, 이때 각 계층의 핵심 문제는 다음 하위 계층 관점에서의 데이터 모델을 표현하는 방법이다.
따라서 명확한 데이터 모델을 제공하면 하위 계층의 복잡성을 숨길 수 있어 다른 그룹의 사람들이 효율적으로 일할 수 있도록 함. (ex. API)
해당 장에서는 데이터 저장과 질의를 위한 다양한 범용 데이터 모델을 살펴 볼 것임
1. 관계형 모델과 문서 모델
관계형 모델을 기반으로 한 SQL이 오늘 날 가장 잘 알려짐. RDB에서 데이터는 관계(relation)로 구성되고, 각 관계(relation)은 순서 없는 튜플(tuple) 모음이다.
RDBMS와 SQL는 정규화된 구조로 데이터를 저장하고 질의를 수행할 필요가 있는 사람들이 대부분 선택하는 도구가 되었는데, 트랜잭션 처리나 일괄 처리 같은 비지니스 데이터 처리에 근원을 두고 있다.
NoSQL의 탄생
NoSQL 데이터베이스를 채택하는 데에는 여러가지 이유가 있다
- 대규모 데이터셋 or 매우 높은 쓰기 처리량 달성을 RDB보다 쉽게 할 수 있을만큼의 뛰어난 확장성
- 무료 오픈소스 선호도 확산
- 관계형 모델에서는 지원하지 않는 특수 질의
- 동적이고 풍부한 데이터 모델에 대한 바람
애플리케이션은 저마다 요구사항이 달라 하나의 선택이 전체의 최적은 아니게 된다. 따라서 가까운 미래에는 RDBMS가 다양한 데이터 스토어와 함께 사용될 것! 이런 개념을 다중 저장소 지속성(polyglot persistence) 이라고 한다
객체 관계형 불일치
오늘날의 객체 지향 프로그래밍으로 개발 된 객체들과 데이터 베이스 모델 사이에 거추장 스러운 전환계층이 필요하다. 이런 모델의 분리를 임피던드 불일치(impedance mismatch)라고 부른다
하이버네이트나 액티브레코드 같은 객체 관계형 맵핑(ORM) 프레임워크는 전환 계층에 필요한 코드의 양을 줄이지만 두 모델간 차이를 완벽히 숨길 수 없다
예를들어, 관계형 스키마에서 이력서를 표현할 경우를 생각해보자. 대부분의 사람은 학력 기간과 연락처 정보등 하나이상의 데이터를 담아야한다. 사용자와 이들 항목은 일대다(one-to-many)관계이며 이는 아래와 같은 다양한 방법으로 나타 낼 수 있다.
- 전통적인 SQL모델에서는 각 학력과 연락처등 정보를 개별 테이블에 넣고 외래키로 참조한다
- 이후 SQL마지막 버전에서는 구조화된 데이터 타입과 XML데이터에 대한 지원도 되었다.
- 마지막으로는, 직업 학력 연락처 정보를 JSON등으로 부호화해 텍스트 칼럼에 저장하여 애플리케이션이 해석하도록 하는 방식이다. -> but, 부호화된 칼럼의 값을 질의하는 DB는 사용할 수 없다.
위의 예인 이력서 같은 구조는 모든 내용을 갖추고 있는 문서라 JSON 표현에 매우 적합하다. 몽고DB, 리싱크DB, 카우치DB, 에스프레소 같은 문서 지향 DB는 JSON데이터 모델을 지원한다. 일부 개발자들은 JSON 모델이 임피던스 불일치를 줄인다고 생각하는데, 사실 JSON 자체가 가진 문제도 있다(이후 4장에서 설명). JSON식의 표현은 다중 테이블 스키마 보다 더 나은 지역성(locality)를 갖는다. 복잡한 조인이 필요없다!
사실 이력서 상의 데이터들은 TREE구조와 같은데, 이는 JSON 표현에서 명시적으로 드러나게 된다.
다대일과 다대다 관계
앞선 예제에서 지역과 업계는 직접 입력받는 것이 아닌 region_id 와 industry_id를 사용했는데, 이렇게 표준 목록으로 드롭다운 리스트 형식으로 만든데에는 여러 장점이있다.
- 일관된 스타일의 철자 & 모호함 회피
- 갱신의 편의성
- 더 나은 검색
ID를 사용하느냐 또는 입력받은 텍스트를 저장햐느냐는 중복의 문제라고 할 수 있다. 중복된 데이터를 정규화 하려면 다대일 관계가 필요하지만, 문서 모델에서 다대일 관계는 적합하지 않다. 따라서 데이터 베이스에 대한 다중 질의를 만들어서 애프리케이션 코드에서 조인을 흉내내야 하기에 어렵다.
문서 데이터베이스는 역사를 반복하고 있나??
RDBMS는 일상적으로 다대다 관계와 조인을 사용하지만, 문서형 DB와 NOSQL은 DB에서 다대다 관계 표현의 가장 좋은 방법에 대한 논쟁을 펼치고 있다.
1970년대 비지니스 데이터 처리를 위해 IBM의 정보 관리 시스템을 데이터베이스로 가장 많이 사용했는데, 이는 계층 모델이라 부르는 상당히 간단한 모델을 사용했다. 계층 모델은 오늘날 사용하는 JSON 모델과 놀랍도록 비슷하며, 모든 데이터를 레코드 내에 중첩된 레코드 트리로 표현한다.
하지만 계층 모델 역시 다대다 관계 표현이 어려워 오늘날과 똑같은 고민했고, 이런 계층 모델의 한계를 해결하기 위해 관계형 모델과 네트워크 모델이 나타나게 되었다.
네트워크 모델
코다실 모델이라고 부르기도한다. 계층 모델을 일반화한 모델로, 계층 모델의 트리 구조에서는 모든 레코드는 정확하게 하나의 부모가 존재하는데, 네트워크 모델에서는 다중 부모가 존재가능하다. 레코드에 접근하는 유일한 방법은 최상위 레코드에서부터 연속된 연결 경로를 따르는 방법으로, 이를 접근 경로 라고 하며, 외래키 보다는 포인터와 더 비슷하다.
만약 레코드가 다중 부모를 가진다면 애플리케이션 코드는 다양한 관계를 모두 추적해야하며, 이런 수동 접근 경로 선택은 데이터베이스 질의와 갱신을 위한 코드가 복잡하고 유연하지 못하다. 접근 경로를 수정할 수 있지만 많은 수작업 질의코드를 살펴봐야하고 재작성 하는 등 매우 어려운 일이다.
관계형 모델
대조적으로 관계형 모델이 하는 일은 알려준 모든 데이터를 배치하는 것으로, 단순히 튜플의 컬렉션이 전부이다. 다른 테이블과의 관계를 신경쓰지 않고 새 로우를 삽입할 수 도 있다. 이런 RDB에서 query optimizer는 질의의 어느 부분을 어떤 순서로 실행할지 결정하고 사용할 색인을 자동 결정한다. 이 선택이 바로 실제 “접근 경로”인 것. 하지만 개발자가 아니라 query optimizer기가 자동으로 만드므로 개발자가 고려할 필요가 없다.
문서 데이터베이스와의 비교
문서 데이터베이스는 상위 레코드 내에 중첩된 레코드를 저장한다는 측면에서 계층 모델로 되돌아갔다. 하지만 다대일과 다대다를 표현할때 RDB와 근본적으로 다르지 않았으며, 관계형 모델에서 외래키가 문서 모델에서의 문서 참조(document reference)와 같다.
관계형 데이터베이스와 오늘날의 문서 데이터베이스
- 관계형 선호 : 조인, 다대다, 다대일 관계 지원
- 문서 데이터 모델 선호 : 스키마 유연성, 지역성
어떤 데이터 모델이 애플리케이션 코드를 더 간단하게 할까?
애플리케이션 데이터가 문서와 비슷한 구조라면 문서 모델을 사용하는 것이 좋다. 관계형 모델은 문서와 비슷한 구조를 여러 테이블로 나누어 찢기(shredding) 때문에 복잡한 애플리케이션 코드를 발생시킨다.
But, 문서 모델은 중첩항목을 바로 참조할 수 없고, 미흡한 조인 지원은 때떄로 문제가 된다(때로는 아닐 수 있음). 다대다 관계를 사용하면 문서 모델의 매력은 떨어지는것이 대표적인 문제다.
결론 : 일반적으로 어떤 데이터 모델이 코드를 더 간단하게 만드는지 말할수 없음. (데이터 유형에 따라 다름!)
발표하신 스터디원 분께서 몽고DB같은게 로그 검색에 유의미한 이유를 알게 된것 같았다, 라고 했는데. 듣고보니 오 .. 그렇구나 싶었다. 생각해보면 로그 데이터는 애초에 조인이 필요하지 않는 그저 쌓이는 문서지만 필요할때 찾아보면 좋을 데이터이기 때문이다!
문서모델에서의 스키마 유연성
문서 데이터베이스는 종종 스키마리스(schemaless)로 불리지만, 이는 오해의 소지가 있는 표현이며, 데이터를 읽는 코드는 보통 구조의 유형을 어느정도 가정한다. 즉 쓰기 스키마말고 읽기 스키마 인것이다.
쓰기 스키마와 읽기 스키마
- 쓰기 스키마(schema-on-write) : RDB의 전통적인 접근 방식으로 스키마는 명시적으로 DB는 쓰여진 모든 데이터가 스키마를 따르고 있음을 보장한다
- 정적 타임 확인과 유사하다
- 읽기 스키마(schema-on-read) : 데이터 주고는 암묵적으로 읽을때만 해석이 된다.
- 프로그래밍 언어에서 동작 타입 확인과 유사하다
예를들어 현재의 이름을 성과 이름 필드로 분리할 경우, “동적 타입”에서는 예전 문서를 읽은 경우를 처리하는 코드만 있으면 되는데, “정적 타입”의 경우 마이그레이션 작업이 필요하다
스키마 변경에 대한 평판은 매우 나쁘지만, 사실 대부분의 RDBMS에서 ALTER TABLE 문은 수 밀리초 안에 수행한다. 하지만 MYSQL의 경우 전체 테이블을 복사하여 수분에서 수초까지 중단 시간이 발생한다.
UPDATE 문을 실행하면 모든 로우가 재작성 될 수 있기에 오래걸릴 수 있다.
읽기 스키마 접근 방식은 컬렉션 안의 항목이 모두 동일한 구조가 아닐때 유리하다. 왜냐면
- 각 유형의 오브젝트 별로 자체 테이블에 넣는 방법은 실용적이지 않다.
- 언제나 변경 가능한 외부 시스템에 의해 데이터 구조가 결정되기 때문
스키마는 득보다 싫이 많지만, 모든 레코드가 동일한 구조라 예상 가능하다면 스키마는 문서화와 구조를 강제하기 위한 아주 좋은 메커니즘이다.
질의를 위한 데이터 지역성
문서는 보통 JSON이나 부호화된 단일 연속 문자열(몽고DB 같은)로 저장된다. 애플리케이션이 자주 전체 문서에 접근해야할 때 저장소 지역성(storage locality)를 활용하면 성능상의 이점이 있다.
지역성의 이점은 해당 문서의 많은 부분을 필요로 하는 경우에 적용된다. 따라서 일반적으로 문서를 아주 작게 유지하면서 문서의 크기가 증가하는 쓰기를 피하라고 권장한다.
지역성은 문서모델에만 국한되지 않는데, 오라클은 다중 테이블 색인 클러스터 테이블(multi-table index cluster table)기능을 사용해 지역적 특성을 제공한다
문서 데이터베이스와 관계형 데이터베이스의 통합
RDB랑 문서DB는 시간이 지남에 따라 점점 더 비슷해지고 있으며, 서로 부족한 부분은 보완해 나가고 있다. 이 두 DB의 혼합 모델은 미래 데이터베이스들이 가야할 올바른 길이라고 이야기한다.
2. 데이터를 위한 질의 언어
관계형 모델이 등장했을 때 데이터를 질의하는 새로운 방법로 함께 나타났음. SQL이나 관계 대수 같은 선언형 질의 언어에서는 목표를 달성하기 위한 방법이 아니라 결과가 충족해야하는 조건과 데이터를 어떻게 변환 할지 지정하기만 하면된다. 나머지는 쿼리 최적화기가 할 일.
선언형 질의 언어는 데이터베이스 엔진의 상세 구현이 숨겨져 있어 질의를 변경하지 않고도 성능을 향상 시킬 수 있음.또한 종종 병렬 실행에 적합하다. 결과를 결정하기 위한 알고리즘이 아니라 패턴만 지정하기 때문에 병렬 실행하여 더 빨라질 가능성이 크다.
웹에서의 선언형 질의
선언형 질의 언어의 장점은 DB에만 국한되지 않는다. 예를들어 CSS를 사용하여 선택자에 특정 디자인(패턴)을 일괄 적용할 수 있으며 이는 선언형 방식이다.
명령형 접근 방식의 경우 JS에서 DOM API를 사용하여 구현할 수 있다. 이경우 이해하기 어려울 뿐만 아니라 몇가지 문제사항이 있다.
- 새로운 API의 장점을 취하고 싶으면 코드를 재작성 해야한다. (CSS의 경우 호환성을 깨뜨리지 않음)
- 특정 작업이 수행되면 전체 페이지가 로딩될때까지 유지된다. (반면에 CSS는 자동으로 감지해서 삭제되자마자 같이 삭제한다)
웹에서도 DOM API보다 CSS를 더 추천하는 것처럼, DB에서도 선언형 질의언어가 더욱 추천된다.
맵리듀스 질의
맵리듀스(MapReduce)는 많은 컴퓨터에서 대량의 데이터를 처리하기 위한 프로그래밍 모델로 구글에 의해 널리 알려졌다. 몽고DB를 포함한 일부 NOSQL 데이터 저장소는 제한된 형태인 맵리듀스를 지원한다. 이 매커니즘은 많은 문서를 대상으로 읽기 전용(read-only)질의를 수행할 때 사용된다.
현 챕터에서는 몽고DB의 모델 사용에 대해 간단히 살펴 볼것이다.
맵리듀스는 선언형 질의도 완전한 명령형 질의API도 아닌 그 중간이다. 맵리듀스는 여러 함수형 프로그래밍 언어에 있는 map과 reduce 함수를 기반으로 한다.
예시로, 상어과에 속하는 1)종만 보이도록 관측치를 필터링 한 다음, 2)관측치가 발생한 달력의 월로 그룹화 하고, 3)해당 달의 모든 관측치에 보여진 동물 수 합치는 경우를 생각해보자
- 상어 종만 거르기 위한 필터를 지정하고
- map함수가 연도와 월로 구성된 값을 방출하는데,
- 방출한 키-값 쌍은 키로 그룹화 되어, 같은 키(연도-월)을 갖는 모든 키-값 쌍은 reduce 함수를 한번 호출한다.
- reduce는 특정 월의 모든 관측치에서 동물수를 합치고 최종출력이된다.
맵리듀스의 사용성 문제는 연계된 자바스크립트 함수 두개를 신중하게 작성해야 한다는 점인데 이는 어렵다. 또한 선언형 질의 언어는 질의 최적화기가 질의 성능을 높일 수 있는 기회를 제공하는데, 이런 이유로 몽고DB는 집계 파이프라인(aggregation pipeline)이라 부르는 선언형 질의 언어 지원을 추가했다! 이는 SQL의 부분집합과 유사하지만 JSON기반 구문을 사용한다
3. 그래프형 데이터 모델
앞서 다대다 관계가 다양한 데이터 모델을 구별하는 중요한 기능임을 이야기 했는데, 애플리케이션이 주로 일대다 관계(트리 구조)이거나 레코드 간 관계가 없다면 문서 모델이 적합하다.
다대다 관계가 일반적일 경우, 또 데이터 간 연결이 더 복잡해지면 그래프로 데이터를 모델링 하기 시작하는 편이 더 자연스럽다
그래프는 정점(vertax)과 간선(edge)로 이루어지는데, 동종 데이터에 국한 되지 않는다
- ex) 페이스북의 정점은 사람, 장소, 체크인, 코멘트 등 여러가지가 될 수 있음
그래프에서 데이터를 구조화하고 질의하는 몇가지 방법과 언어를 설명할 것
속성 그래프
속성 그래프 모델의 정점의 구성요소
- 고유한 식별자 / 유출 간선 집합 / 유입 간선 집합 / 속성 컬렉션(키-값 쌍)
속석 그래프 모델의 간선의 구성요소
- 고유한 식별자 / 간선이 시작하는 정점 / 간선이 끝나는 정점 / 두 정점 간의 관계 유형을 설명하는 레이블 / 속성 컬렉션(키-쌍 값)
이 모델의 몇가지 중요한 면은 다음과 같다
- 정점은 다른 정점과 간선으로 연결된다. 특정 유형과 관련 여부를 제한하는 스키마는 없다
- 정점이 주어지면, 정점의 유입과 유출 간선을 효율적으로 찾을 수 있으며, 그래프 순회가 가능하다.
- 다른 유형의 관계에 서로 다른 레이블을 사용하면, 단일 그래프에 다른 유형의 정보를 저장하면서도 모델을 깔끔히 유지할 수 있다
이런 기능들을 통해 그래프는 데이터 모델링을 위한 많은 유연성을 제공한다. 그래프는 발전성이 좋아 애플리케이션에 기능을 추가하는 경우 애플리케이션 데이터 구조 변경을 수용하게끔 그래프를 쉽게 확장할 수 있다.
사이퍼 질의 언어
사이퍼(Cypher)는 속성 그래프를 위한 선언형 질의 언어로 네오포제이 그래프 디비용으로 만들어 졌다.
똑같은 질의를 실행하는데에도 여러가지 방법이 있는데, 보통 선언형 질의 언어는 질의를 작성할때 수행에 대해 자세히 지정할 필요가 없다! 질의 최적화기가 가장 효율적이라고 예측한 전략을 자동으로 선택하기 때문이다.
SQL의 그래프 질의 언어
그래프를 관계형 구조로 넣어도 SQL을 사용하여 질의할 수 있을까? 대답은 예지만 어렵다.
그 이유는 그래프 질의에서는 찾고자 하는 정점을 찾기 전 가변적인 간선을 순회해야 하여 미리 조인 수를 고정할 수 없기 때문이다. 반면에 사이퍼에서는 매우 간결히 표시 가능하다.
SQL:1999 이후로 가변 순회 경로에 대한 질의 개념은 재귀 공통 테이블 식(recursive common table expression)을 사용해서 표현 가능하지만, 문법이 사이퍼에 비해 어렵다.
트리플 저장소와 스파클
트리플 저장소 모델은 속성 그래프 모델과 거의 동등한데, 트리플 저장소에서는 모든 정보를 주어, 서술어, 목적어 처럼 매우 간단한 세부분의 구문 형식으로 저장한다.
시맨틱 웹
트리플 저장소 데이터 모델은 시맨틱 웹과 완전 독립적이지만, 많은 사람들이 이 둘은 밀접한 관계가 있다고 생각한다. 시맨틱 웹은 웹 사이트는 사람이 이미 읽을 수 있는 정보를 게시하고 있으니, 컴퓨터가 읽게끔 기계가 판독 가능한 데이터로도 정보를 게시하자는 생각이다. 하지만 현실에 실현된 흔적이 없으며, 부정적 견해를 보이는 사람이 많다
RDF 데이터 모델
RDF는 인터넷 전체의 데이터 교환을 위해 설계한 데이터인데, 때로는 데이터모델로 RDF를 채택하기도 한다.
스파클 질의 언어
스파클(SPARQL)은 RDF 데이터 모델을 사용한 트리플 저장소 질의 언어로, 사이퍼보다 스파클을 사용하면 때로 질의문이 더 간결해진다.
그래프 데이터베이스와 네트워크 모델의 비교
1. 코다실 DB에는 다른 레코드 타입과 중첩 가능한 레코드 타입을 지정하는 스키마가 있다. -> 근데 그래프에는 제한이 없음, 즉, 유연성이 더 크다 (그래프가)
2. 코다실에서는 레코드 접근 경로중 하나를 탐색해야만 특정 레코드에 도달할 수 있음. -> 그래프는 고유 ID를 가져 직접 참조 가능하다
3. 코다실에서 레코드 하위 항목은 정렬된 집합 -> 그래프는 정점과 간선을 정렬하지 않는다
4. 코다실은 명령혈 질의 언어 사용 -> 대부분 그래프에서는 고수준 선언형 질의를 사용한다
초석: 데이터로그
데이터로그는 스파클이나 사이퍼보다 훨씬 오래된 언어로 이후의 질의 언어의 기반이 되는 초석을 제공하기에 중요하다. 데이터로그의 데이터 모델은 트리플 저장소 모델과 유사하지만, 조금 더 일반화 됐다. (주어, 서술어, 목적어)로 트리플을 작성하는 대신 서술어(주어, 목적어)로 작성한다.
정리
해당 장에서는 다양한 종류의 모델을 간략하게 살펴봤다.
역사적으로 데이터를 하나의 큰 트리로 표현하고자 했지만, 다대다 관계를 표한기에 트리 구조는 적절하지 않았고 이 문제를 해결하기 위해 관계형 모델이 고안됐다. 하지만 최근들어 관계형 모델에도 적합하지 않는 유형을 발견했고, “NoSQL”이 새로운 등장했으며 아래 두가지 갈래로 나뉜다.
- 문서 데이터베이스
- 그래프 데이터베이스
세가지 모델 모두 현재 널리 사용하고 있으며 각기 목적에 맞는 다양한 시스템에 사용하고 있다.
문서 및 그래프 데이터베이스가 가진 공통점 중 하나는 저장할 데이터를 위한 스키마를 강제하지 않는다. 하지만 대게의 애플리케이션은 데이터가 특정 구조를 갖는다고 가정할 가능성이 높다.
각 데이터 모델은 고유한 질의 언어랑 프레임워크를 제공한다.
'Reading > 데이터 중심 어플리케이션 설계' 카테고리의 다른 글
[데이터 중심 애플리케이션 설계] 1장 : 신뢰할 수 있고 확장가능하며 유지보수하기 쉬운 애플리케이션 (0) | 2022.12.28 |
---|