개발독서/데이터

[고투런1기] 데이터 중심 애플리케이션 설계 (2장 데이터 모델과 질의 언어)

보리시스템 2024. 5. 11.
<더 생각해보기>
- 관계형 DB에서 다대다 관계를 표현할 때 어려움을 겪은 적이 있었는지?
=> Node.js에서 다대다 관계를 표현하기 위해 ORM을 사용할 때 TypeORM의 경우 테이블 간 가상의 연결 테이블을 만들어 주지만, Sequelize에서는 실제로 연결 테이블을 만들어줘야 하는 불편함이 있음

 


 

[1부 데이터 시스템의 기초]
2장 데이터 모델과 질의 언어

1. 관계형 모델과 문서 모델

1.1 NoSQL의 탄생
1.2 객체 관계형 불일치
1.3 다대일과 다대다 관계
1.4 문서 데이터베이스는 역사를 반복하고 있나?
1.5 관계형 데이터베이스와 오늘날의 문서 데이터베이스

2. 데이터를 위한 질의 언어
2.1 웹에서의 선언형 질의
2.2 맵리듀스 질의

3. 그래프형 데이터 모델
3.1 속성 그래프
3.2 사이퍼 질의 언어
3.3 SQL의 그래프 질의
3.4 트리플 저장소와 스파클
3.5 초석: 데이터로그

 

[정리: 데이터 중심 애플리케이션 설계를 뒷받침하는 근본 개념을 설명]

1.역사적으로 데이터를 하나의 큰 트리(계층 모델)로 표현하려고 노력했지만 다대다 관계를 표현하기에 적합하지 않았기에 '관계형 모델'이 고안 됨
- 관계형 모델에도 적합하지 않은 애플리케이션이 있어 NoSQL이라는 비관계형 데이터 저장소가 등장함

2. NoSQL는 2가지 주요 갈래가 있음
- 문서 DB는 데이터가 문서 자체에 포함돼 있으면서 하나의 문서와 다른 문서 간 관계가 거의 없는 사용 사례를 대상으로 함
- 그래프 DB는 문서 DB와 정반대로 모든 것이 잠재적으로 관련 있다는 사용 사례를 대상으로 함

=> 문서, 그래프 DB의 공통점은 일반적으로 저장할 데이터를 위한 스키마를 강제하지 않아 변화하는 요구사항에 맞춰 애플리케이션을 쉽게 변경할 수 있다는 점임
=> 하지만 애플리케이션은 데이터가 특정 구조를 갖는다고 가정할 가능성이 높음
=> 스키마가 명시적인지(쓰기에 강요됨) 암시적인지(읽이에 다뤄짐)의 문제일 뿐임

3. 관계형, 문서, 그래프 모델은 적재적소에 따라 사용됨

 


 

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

- 대부분의 애플리케이션은 하나의 데이터 모델을 다른 데이터 모델 위에 계층을 둬서 만듦
=> 각 계층의 핵심적인 문제는 다음 하위 계층 관점에서 데이터 모델을 표현하는 방법임

 

1. 관계형 모델과 문서 모델

- 오늘날 가장 잘 알려진 데이터 모델은 1970년 에드가 코드(Edgar Codd)가 제안한 '관계형 모델을 기반으로 한 SQL'
=> 데이터는 관계(relations, SQL에서는 table)로 구성되고 각 관계는 순서 없는 튜플(tuple, SQL에서는 row) 모음

- 관계형 데이터베이스의 근원은 1960, 1970년대 메임프레임 컴퓨터에서 수행된 '비즈니스 데이터 처리'
=> 사용 사례로는 트랙잭션 처리, 일괄 처리 등이 있음
=> 다른 DB 사용하는 개발자는 DB 내부 데이터 표현에 대해 고민해야 했지만, 관계형 모델의 목표는 정리된 인터페이스 뒤로 구현 세부 사항을 숨기는 것이었음

- 1980년대 중반 이론적 제안이었던 관계형 모델은 정규화된 구조로 데이터를 저장하고 질의하여 쓰려는 사람들에게 많이 사용됨=> RDBMS(관계형 데이터베이스 관리 시스템), SQL


- 데이터 모델의 역사
1) 1970년대, 1980년대 초반에는 '네트워크 모델', '계층 모델'을 주로 사용했지만 결국 '관계형 모델'이 우위를 차지함
2) 1980년대 후반, 1990년 초반에 '객체 데이터 베이스'가 등장했지만 사라짐
3) 2000년대 초반 'XML 데이터베이스'가 등장했지만 매우 적게 사용됨

 


 

1.1 NoSQL의 탄생

NoSQL?

- 2009년 오픈소스, 분산 환경, 비관계형 데이터베이스 밋업용 인기 트위터 해시태그였음
- Not Only SQL로 재해석 됨
- 2010년대 관계형 모델의 우위를 뒤집으려는 시도로 NoSQL이 등장
=> 채택 이유
1) 대규모 데이터셋, 매우 높은 쓰기 처리량 달성을 관계형 DB보다 쉽게 할 수 있는 뛰어난 확장성의 필요
2) 상용 DB 제품보다 무료 오픈소스 SW에 대한 선호도 확산
3) 관계형 모델에서 지원하지 않는 특수 질의 동작
4) 관계형 스키마의 제한에 대한 불만과 더욱 동적이고 표현력이 풍부한 데이터 모델에 대한 필요

- 이후에는 관계형 DB가 폭넓은 다양함을 가진 비관계형 데이터스토어와 함께 사용될 것임
=> 다중 저장소 지속성(polyglot persistence)

 



1.2 객체 관계형 불일치(Impedance Mismatch)

객체 관계형 불일치?

모델 사이의 분리

 

- 데이터를 관계형 테이블에 저장하려면 애플리케이션 코드와 DB 모델 객체(테이블, 로우, 칼럼) 사이에 전환 계층이 필요함
=> ORM(객체 관계형 매핑) 프레임워크를 통해 그 전환 계층에 필요한 상용구 코드(boilerplate code)의 양을 줄일 수 있지만 두 모델 간의 차이를 완벽히 숨길 수는 없음

 



1.3 다대일(many-to-one)과 다대다(many-to-many) 관계

- 중복된 데이터를 정규화하려면 다대일 관계가 필요
=> 그러나 다대일 관계는 문서 모델에 적합하지 않음
=> 관게형 DB에서는 조인이 쉽기 때문에 ID로 다른 테이블의 로우를 참조하는 방식이 일반적

 



1.4 문서 데이터베이스는 역사를 반복하고 있나?

  • 계층 모델
- 1970년대 비즈니스 데이터 처리를 위해 가장 많이 사용한 DB는 IBM의 IMS였음
=> IMS(정보 관리 시스템, Information Management System)
=> 원래는 아폴로 우주 프로그램에서 재고 관리를 위해 개발 됨
=> 1968년에 상업적으로 출시 됨

- IMS의 설계는 계층 모델을 사용함
=> 문서 DB에서 사용하는 JSON 모델과 비슷함
=> 모든 데이터를 레코드 내 중첩된 레코드 트리로 표현함

- IMS는 일대다 관계에서는 잘 동작하지만, 다대다 관계 표현에 어려움이 있고 조인을 지원하지 않음
=> 개발자는 비정규화된 데이터로 중복할지 한 레코드와 다른 레코드의 참조를 수동으로 해결해야 할지 결정해야 했음

- 이러한 계층 모델의 한계를 해결하기 위해 2가지 해결책이 나옴
=> '네트워크 모델'과 '관계형 모델'임 

 

  • 네트워크(코다실) 모델
- 코다실(CODASYL, Conference on Data Sytems Languages)이라는 위원회에서 표준화함
=> 계층 모델을 일반화해 계층 모델의 트리구조에서 모든 레코드는 정확히 하나의 부모가 있지만
=> 네트워크 모델에서 레코드는 다중 부모가 있을 수 있음

- 네트워크 모델에서 레코드 간 연결 방법은 '접근 경로'임
=> 접근 경로는 최상위 레코드(root record)에서부터 연속된 연결 경로를 따르는 방법
=> 외래 키보다는 프로그래밍 언어의 포인터와 더 비슷하다고 할 수 있음

- 목록의 맨 앞에서 시작해 원하는 레코드를 찾을 때까지 한 번에 하나의 레코드를 보는 방식
=> 하지만 다대다 관계에서는 다양한 다른 경로가 같은 레코드로 이어질 수 있어 경로의 맨 앞에서 이런 다양한 접근 경로를 계속 추적해야 함
=> 코다실 위원회도 이 방식이 n차원 데이터 공간을 항해하는 것 같다고 인정함
=> 수동 접근 경로 선택은 1970년대에는 제한된 HW 성능을 가장 효율적으로 사용할 수 있었지만 DB 질의, 갱신 코드가 복잡하고 유연하지 못한 문제가 있었음

- 초기에는 많은 신봉자들이 있었지만 결국 잊혀짐

 

  • 관계형 모델
- 관계(테이블)는 단순히 튜플(로우)의 컬렉션이 전부임
=> 중첩 구조와 데이터를 보고 싶을 때 따라가야 할 복잡한 접근 경로가 없음
=> 임의 조건과 일치하는 테이블의 일부나 모든 로우를 선택해 읽을 수 있고, 일부 칼럼을 키로 지정해 칼럼과 일치하는 특정 로우를 읽을 수 있음
=> 다른 테이블과의 외래 키 관계에 대해 신경 쓰지 않고 임의 테이블에 새 로우를 삽이할 수 있음

- 관계형 DB에서 질의 최적화기(query optimizer)는 질의의 어느 부분을 어떤 순서로 실행할지 결정하고 사용할 색인을 자동으로 결정함
=> 이 선택이 '접근 경로'임
=> 하지만 네트워크 모델에서의 접근 경로와의 차이는 질의 최적화기가 자동으로 만들어 준다는 것임

 

  • 문서 DB와의 비교
- 다대일, 다대다 관계 표현 시 관계형 DB와 근본적으로 차이는 없음
=> 관련 항목은 고유한 식별자로 참조함
=> 관계형 모델에서는 '외래 키', 문서 모델에서는 '문서 참조(document reference)'라고 부름
=> 이 식별자는 조인, 후속 질의를 사용해 읽기 시점을 확인함
=> 문서 DB는 코다실의 전철을 밟지 않고 있다고 할 수 있음

 



1.5 관계형 데이터베이스와 오늘날의 문서 데이터베이스

- 문서 데이터 모델을 선호하는 주요 이유는
=> 스키마 유연성, 지역성에 기인한 더 나은 성능
=> 일부 애플리케이션의 경우 애플리케이션에서 사용하는 데이터 구조와 더 가깝기 때문임

- 관계형 모델은
=> 조인, 다대일, 다대다 관계를 더 잘 지원

 

  • 어떤 데이터 모델이 애플리케이션 코드를 더 간단하게 할까?
- 데이터 항목 간에 존재하는 관계 유형에 따라 이 질문의 답은 달라짐
=> 애플리케이션에서 데이터가 문서와 비슷한 구조라면? 문서 모델
=> 상호 연결이 많은 데이터의 경우? 그래프 모델 (관계형 모델도 무난하긴 함)

 

  • 문서 모델에서의 스키마 유연성
- 문서 DB, 관계형 DB에서 지원하는 JSON은 문서의 데이터에 어떤 스키마를 강요하지 않음
=> 임의의 키, 값을 문서에 추가할 수 있음
=> 읽을 때 클라이언트는 문서에 포함된 필드의 존재 여부를 보장하지 않음

- 문서 DB는 스키마리스(schemaless)로 불리지만 오해의 소지가 있음
=> 데이터를 읽는 코드는 보통 구조의 유형을 어느 정도 가정함
=> 암묵적인 스키마가 있지만 DB는 이를 강요하지 않음

- 이를 쓰기 스키마, 읽기 스키마라고 함
1) 쓰기 스키마(schema-on-write)
=> 관계형 DB의 전통적인 접근 방식으로 스키마는 명시적이고 DB는 쓰여진 모든 데이터가 스키마를 따르고 있음을 보장함
=> 정적(컴파일 타임) 타입 확인과 비슷함

2) 읽기 스키마(schema-on-read)
=> 데이터 구조는 암묵적이고 데이터를 읽을 때만 해석됨
=> 동적(런타임) 타입 확인과 비슷함

 

  • 질의를 위한 데이터 지역성
- 애플리케이션이 자주 전체 문서에 접근해야 할 때 '저장소 지역성(storage locality)'을 활용하는 것이 좋음
=> 지역성의 이점은 한 번에 해당 문서의 많은 부분을 필요로 하는 경우에만 적용됨
=> 일반적으로 문서를 아주 작게 유지하면서 문서의 크기가 증가하는 쓰기를 피하라고 권장함

- 이러한 성능 제한 때문에 문서 DB가 유용한 경우가 적음

 

  • 문서 데이터베이스와 관계형 데이터베이스의 통합
- 문서/관계형 DB는 시간이 지날수록 더 비슷해지고 있음
=> 문서 DB는 리싱크DB의 경우 질의 언어에서 관계형 조인을 지원하고, 몽고DB 드라이버는 자동으로 DB 참조를 확인함 
=> 관계형 DB는 MySQL을 제외하고 2000년대 중반 이후부터는 XML을 지원함

- 각 데이터 모델이 서로 부족한 부분을 보완해 간다는 것으로 문서/관계형의 혼합 모델은 미래 DB가 가야 할 올바른 방향임

 


 

2. 데이터를 위한 질의 언어

- 관계형 모델이 등장했을 때 데이터를 질의하는 새로운 방법도 함께 나타남
=> IMS와 코다실은 명령형 언어, SQL은 선언형 질의 언어

- 명령형 언어
=> 특정 순서로 특정 연산을 수행하게끔 지시함

- 선언형 질의 언어
=> 알고자 하는 데이터의 패턴, 즉 결과가 충족해야 하는 조건과 데이터를 어떻게 변환할지를 지정하기만 하면 됨
=> 명령형 언어보다 더 간결하고 쉽게 작업할 수 있음
1) DB 엔진의 상세 구현이 숨겨져 있어 질의를 변경하지 않고도 DB 시스템의 성능을 향상시킬 수 있음
2) 기능적으로 더 제한적이지만 이는 곧 DB에게 자동으로 최적화할 수 있는 여지를 더 많이 준다는 의미임
3) 병렬 실행에 적합함. 결과를 결정하기 위한 알고리즘을 지정하는 것이 아닌 결과의 패턴만 지정하기 때문에 병렬 실행으로 더 빨라질 가능성이 큼

 


 

2.1 웹에서의 선언형 질의 

- 선언형 질의 언어의 장점은 DB에만 국한되지 않음
=> 웹 브라우저에서 선언형 CSS 스타일을 사용하는 것이 JavaScript에서 명령형으로 스타일을 다루는 것보다 훨씬 좋기도 함

 


 

2.2 맵리듀스 질의

맵리듀스(MapReduce)?
- 많은 컴퓨터에서 대량의 데이터를 처리하기 위한 프로그래밍 모델
- 여러 함수형 프로그래밍 언어에 있는 map(collect)과 reduce(fold, inject) 함수를 기반으로 함

=> 몽고DB, 카우치DB 등 일부 NoSQL 데이터 저장소에서 제한된 형태의 맵리듀스를 지원함
=> 많은 문서를 대상으로 읽기 전용(read-only) 질의를 수행할 때 사용함

 

- 맵리듀스는 선언형 질의 언어도 명령형 언어도 아닌 그 중간 정도에 있음

- 몽고DB의 map, reduce 함수는 수행 시 순수(pure) 함수여야 한다는 제약 사항이 있음
1) 입력으로 전달된 데이터만 사용하고 추가적인 DB 질의를 수행할 수 없어야 함
2) 부수 효과(side effect)가 없어야 함

- 이러한 제약 사항 때문에 DB가 임의 순서로 어디서나 이 함수를 실행할 수 있고, 장애가 발생해도 함수를 재실행할 수 있음
=> 하지만 map, reduce 함수는 문자열 파싱, 라이브러리 함수 호출/계산 등의 작업을 할 수 있다는 장점이 있음

- 맵리듀스의 사용성 문제는 연계된 자바스크립트 함수 2개를 신중하게 작성해야 한다는 점임
=> 종종 하나의 질의를 작성하는 것보다 어려움
=> 몽고DB 2.2는 집계 파이프라인(aggregation pipeline)이라는 선언형 질의 언어 지원을 추가함

 


 

3. 그래프형 데이터 모델 

- 다대다 관계가 많다면?
=> 그래프 모델을 사용하는 것이 좋음

- 그래프는 두 유형의 객체로 이뤄짐
1) 정점(vertex): 노드, 엔티티라고도 함
2) 간선(edge): 관계, 호(arc)라고도 함

- 그래프에서 데이터를 구조화하고 질의하는 방법으로는 '속성 그래프 모델', '트리플 저장소 모델' 등이 있음
- 그래프용 선언형 질의 언어로는 '사이퍼', '스파클', '데이터로그' 등이 있음

 


 

3.1 속성 그래프

  • 속성 그래프 모델에서 정점과 간선의 구성 요소
정점 간선
고유한 식별자 고유한 식별자
유출(outgoing) 간선 집합 간선이 시작하는 정점 (꼬리 정점)
유입(incoming) 간선 집합 간선이 끝나는 정점 (머리 정점)
속성 컬렉션(키-값 쌍) 두 정점 간 관계 유형을 설명하는 레이블
  속성 컬렉션(키-값 쌍)

 

- 그래프는 발전성이 좋아서 애플리케이션에 기능을 추가하는 경우 애플리케이션의 데이터 구조 변경을 수용하게끔 그래프를 쉽게 확장할 수 있음

 


 

3.2 사이퍼 질의 언어

사이퍼(Cypher)?

속성 그래프를 위한 선언형 질의 언어로 네오포제이 그래프 DB용으로 만들어짐

 


 

3.3 SQL의 그래프 질의

- 그래프 데이터를 관계형 구조로 넣어도 SQL을 사용해 질의할 수 있을까?
=> 가능은 하지만 약간 어려움
=> 관계형 DB에서는 보통 질의에 필요한 조인을 미리 알고 잇음
=> 그래프 질의에서는 찾고자 하는 정점을 찾기 전에 가변적인 여러 간선을 순회해야 함. 즉 미리 조인 수를 고정할 수 없음

- 동일한 질의를 어떤 질의 언어는 4줄로만 작성하는데 29줄로 작성해야 하는 질의 언어도 있음
=> 애플리케이션에 적합한 데이터 모델을 선택하는 작업은 중요함

 


 

3.4 트리플 저장소와 스파클

- 트리플 저장소에서는 모든 정보를 세 부분 구문 형식으로 저장함

 

  • 시맨틱 웹
- 트리플 저장소 데이터 모델과 시맨틱 웹은 완전 다르지만 많은 사람들이 매우 밀접한 관계가 있다고 생각함

- 시맨틱 웹
=> 웹 사이트가 아미 사람이 읽을 수 있는 텍스트와 그림으로 정보를 게시하고 있으니 컴퓨터가 읽을 수 있을게 기계 판독 가능한 데이터로도 정보를 게시하자는 개념임
=> RDF(자원 기술 프레임워크, Resource Description Framework)는 서로 다른 웹 사이트가 일관된 형식으로 데이터를 게시하기 위한 방법을 제안함
=> 2000년대 초반에 과대평가돼 지금까지 현실에서 실현된 흔적은 많이 없음
=> 이렇게 RDF 데이터를 게시하지 않는다 해도 애플리케이션의 훌륭한 내부 데이터 모델이 될 수도 있음

 

  • RDF 데이터 모델
- 터틀 언어는 RDF 데이터를 사람이 읽을 수 있는 형식으로 표현함
=> 때로는 XML 형식을 쓰기도 하지만 내용을 너무 장황하게 만들기 때문에 한눈에 보기 위해 터틀/N3을 보통 사용함
=> 아파치 제나(Jena) 같은 도구가 필요한 경우 서로 다른 RDF 형식으로 자동 변환할 수 있음

 

  • 스파클 질의 언어
- 스파클(SPARQL)은 RDF 데이터 모델을 사용한 트리플 저장소 질의 언어임
=> SPARQL Protocol and RDF Query Language
=> 사이퍼의 패턴 매칭은 스파클에서 차용한 것임

 


 

3.5 초석: 데이터로그

- 데이터로그(Datalog)는 스파클, 사이퍼보다 훨씬 오래된 언어로 1980년대 광범위하게 연구됨
=> 질의 언어의 기반이 되는 초석을 제공함
=> 주어, 서술어, 목적어로 트리플을 작성하는 대신 서술어(주어, 목적어)로 작성함
=> 사이퍼와 스파클은 SELECT로 바로 질의하지만 데이터로그는 단계를 나눠 한 번에 조금씩 질의함
=> 간단한 일회성 질의에 사용하기에 편리하지 않지만, 데이터가 복잡한 경우 효과적으로 사용될 수 있음