Zayson
A to Zayson!
Zayson
전체 방문자
오늘
어제
  • 분류 전체보기 (132)
    • Computer Science (20)
      • Network (4)
      • DB (12)
      • OS (4)
    • Algorithm (32)
      • 완전탐색(Brute-Force) (3)
      • 그리디(Greedy) (6)
      • 투포인터(Two-Pointer) (1)
      • 그래프(Graph) (5)
      • BFS & DFS (9)
      • 구현, 시뮬레이션(Implementation) (5)
      • 다이나믹 프로그래밍(DP) (3)
    • Backend (51)
      • Spring Boot (19)
      • JPA (16)
      • Kafka (2)
      • Java (13)
      • Kotlin (1)
    • DevOps (1)
      • Jenkins (5)
      • Oracle Cloud Infrastructure (1)
      • Kubernetes & Docker (1)
    • Trouble Shooting (3)
      • JPA (1)
      • Spring Boot (2)
    • 회고 (5)
      • 엔빵 프로젝트 포스트 로드맵 (1)
      • 2022년 (4)
    • Kafka (7)
      • Kafka (5)
      • Kafka Connect (2)
    • 기술 서적 (6)
      • 데이터 중심 애플리케이션 설계 (3)
      • 개발자가 반드시 정복해야할 객체 지향과 디자인 패턴 (2)
      • 가상 면접 사례로 배우는 대규모 시스템 설계 기초 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

인기 글

태그

  • 프로그래머스
  • Java
  • kafka
  • BFS
  • 관계형 데이터베이스 실전 입문
  • CS
  • 나 혼자 스프링부트!
  • Kafka Connect
  • 백준
  • dfs
  • 그리디
  • Computer science
  • 구현
  • spring boot
  • 라이브스터디
  • SpringBoot
  • Backend
  • 완전탐색
  • 엔빵프로젝트
  • JPA

최근 글

티스토리

hELLO · Designed By 정상우.
Zayson

A to Zayson!

2장. 데이터 모델과 질의 언어
기술 서적/데이터 중심 애플리케이션 설계

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

2025. 1. 31. 23:46

개요


  • 데이터 저장과 질의를 위한 다양한 범용 데이터 모델을 알아보자.
  • 관계형 모델, 문서 모델, 그래프 기반 모델을 비교해보자.

관계형 모델과 문서 모델


  • 관계형 모델: 데이터가 관계(테이블)로 구성되고 각 관계는 순서 없는 튜플(Row)의 모음
  • 관계형 모델은 관계형 데이터베이스(RDBMS)로 발전했으며 정규화된 구조를 데이터를 저장하고 질의할 때 사용되었다.
  • 관계형 모델의 목표는 정리된 인터페이스 뒤로 구현 세부사항을 숨기는 것이다.

NoSQL의 탄생

  • NoSQL의 등장 배경은 다음과 같다.
    • 대규모 데이터셋이나 쓰기 연산에 대한 처리량을 관계형 데이터베이스보다 쉽게 도달할 수 있게하는 확장성의 필요도
    • 관계형 모델에서 지원하지 않는 특수 질의 동작
    • 제한적인 관계형 스키마에 비해 동적이고 표현력이 풍부한 데이터 모델에 대한 바람
  • 애플리케이션의 요구사항은 모두 다르기 때문에 관계형 데이터베이스와 NoSQL이 함께 사용될 것이다.
이를 다중 저장소 지속성(polyglot persistence)라고 한다.

객체 관계형 불일치

  • 객체 지향 프로그래밍에서 데이터를 관계형 테이블에 저장하기 위해선 애플리케이션 ↔ DB 모델 객체 사이의 전환 계층이 필요하다. (임피던스 불일치, impedence mismtach)
    • 전통적인 관계형 모델은 외래 키를 통한 참조, Join을 통해 표현이 가능하다.
  • JSON 모델은 다중 테이블 스키마보다 좋은 지역성을 갖는다.
    • JSON 모델에서는 관련된 데이터가 한 곳에 모여 있기 때문에 한번의 질의를 통해 데이터를 가져올 수 있다. (데이터 내에 일대다 관계가 녹여져 있다.)
  • 일대다 관계는 의미상 데이터 트리 구조와 동일하며, JSON 표현에서 명시적으로 드러난다.

다대일과 다대다 관계

  • 중복된 데이터를 정규화 하기 위해선 다대일 관계가 필요하다.
    • e.g) N (사람) → 1 (직장) / 사람 테이블에서 직장을 텍스트로 표현하면 중복이 많아지기 때문에 ID를 통해 표현할 수 있다.
  • 다대일 관계 (Many-to-One)는 문서 모델에 적합하지 않다.
    • 관계형 데이터베이스는 조인이 쉽기 때문에 ID로 다른 테이블 로우 참조가 간단하다.
    • 문서 데이터베이스는 조인에 대한 지원이 약하다. (일대다 관계에선 조인이 필요하지 않기 때문)
      • 애플리케이션 레벨에서 조인이 구현될 가능성이 높다. (Join-Free → Join required)

다양한 데이터 모델

  • 계층 모델: JSON 구조와 비슷하게 모든 데이터를 레코드 내에 중첩된 레코드 트리로 표현하는 모델
    • 다대다 관계 표현이 어렵고, 조인을 지원하지 않음
  • 네트워크 모델(코다실 모델)
    • 하나의 레코드가 다중 부모를 가질 수 있다. → 다대일 관계 가능
    • 레코드에 접근하기 위해선 최상위 레코드부터 연결된 경로를 따라가는 접근 경로 방식이다. (프로그래밍 언어의 포인터와 유사)
    • 다대다 관계에서는 하나의 레코드에 접근하는 경로가 여러 개이기 때문에 다양한 경로 추적이 필요하다.
    • 데이터 모델을 바꾸기 위해선모든 접근 경로를 파악해야하며 이는 데이터 모델을 바꾸는데 어려움이 생긴다.
    • 원하는 데이터에 대한 경로가 없는 경우 새로운 접근 경로를 다루기 위해 재작성 필요
  • 관계형 모델
    • 다른 테이블과의 외래 키 관계와 상관없이 편리하게 데이터를 저장할 수 있다.
    • 임의 조건과 일치하는 테이블, 로우를 선택해서 읽을 수 있다.
    • 관계형 데이터베이스에서 쿼리 옵티마이저는 데이터 접근 경로를 자동으로 만든다.
      • 쿼리 옵티마이저는 가장 최적의 인덱스를 사용한다.
  • 현재의 문서 데이터베이스는 관계형 데이터베이스의 외래 키처럼 문서 참조를 사용해 다대일, 다대다 관계를 해결하고 있다.

문서 데이터베이스, 관계형 데이터베이스 선택

  • 문서 데이터 모델: 스키마 유연성, 지역성에 기인한 좋은 성능 및 애플리케이션 데이터 구조와 유사
  • 관계형 모델: 조인, 다대일, 다대다 관계의 지원
  • 애플리케이션에서 데이터가 문서와 비슷한 구조인 경우 문서모델을 사용
  • 애플리케이션에서 다대다 관계를 사용하면 관계형 모델 사용
    • 애플리케이션 코드 상에서 비정규화된 데이터 일관성 유지하기 위한 코드 작업이 필요하기 때문이다.
    • DB 내에서 진행되는 조인 보다 애플리케이션 레벨 코드가 속도가 더 느리기 때문이다.

문서 모델의 스키마 유연성

  • JSON은 문서 데이터에 특정 스키마를 강요하지 않는다.
  • 문서 데이터베이스는 암묵적인 스키마가 있지만 데이터베이스는 이를 강요하지 않는다.
    • 쓰기 스키마: 스키마가 명시적이고 데이터베이스는 모든 데이터가 스키마를 따르고 있음을 보장 (컴파일 타입과 유사)
    • 읽기 스키마: 데이터 구조는 암묵적이고 데이터를 읽을 때만 해석된다. (동적 타입과 유사)
  • 애플리케이션이 데이터 타입을 변경하는 경우
    • 쓰기 스키마: 마이그레이션이 필요해 중단시간이 발생
    • 읽기 스키마: 과거 데이터를 읽는 경우를 예외처리만 해주면 되어 유연하다.
  • 읽기 스키마 접근 방식은 컬렉션 안의 항목이 모두 동일한 구조가 아닐 때 유리하다.
    • 다른 유형의 오브젝트가 있고 각 유형의 오브젝트별로 자체 테이블에 넣는 방법은 실용적이지 않다.
    • 외부 시스템에 의해 데이터 구조가 결정된다.

질의를 위한 데이터 지역성

  • 애플리케이션이 자주 전체 문서에 접근해야할 때 저장소 지역성을 활용하면 성능적으로 장점이 있다.
    • 대부분의 자업이 문서 단위이기 때문에 문서 크기에 상관 없이 전체 문서를 조회하거나 갱신해야 한다.
    • 문서를 작게 유지하고, 문서의 크기가 증가하는 쓰기를 피하자.
  • 지역성은 관계형 모델에서도 지원한다.
    • e.g) 구글 - 스패너, 오라클 - 다중 테이블 색인 클러스터 테이블

데이터를 위한 질의 언어


    • 명령형 언어
      • 특정 순서로 특정 연산을 수행하는 형식
      • 병렬 실행에 적합하지 않음
    • 선언형 언어
      • 데이터 패턴 (결과 충족 조건과 데이터 변환 방법)을 지정하는 방식
      • 실제 처리의 순서는 옵티마저이저가 수행
      • 병렬 실행에 적합
    • 맵리듀스
      • 많은 컴퓨터에서 대량의 데이터를 처리하기 위한 프로그래밍 모델
      • 많은 문서에 대해 읽기 전용 질의 수행시 주로 사용
// 몽고 DB 예시
db.observations.mapReduce( 
  // map
  function map() { 
	var year = this.observationTimestamp.getFullYear();
	var month = this.observationTimestamp.getMonth() + 1;
	emit(year + "-" + month, this.numAnimals)
  },
  // reduce
  function reduce(key, values) {
	return Array.sum(values);
  }, 
  {
	query: { family: "Sharks" },
	out: "monthlySharkReport"
  }
);
  •  
몽고DB map, reduce는 순수 함수여야 한다.

그래프형 데이터 모델


  • 다대다 관계가 일반적인 경우에는 그래프로 데이터를 모델링하는 것이 자연스럽다.
  • 그래프는 정점과 간선으로 구성된다.
    • e.g) 소셜 그래프 - 정점: 사람, 간선: 사람간 알고 있는 관계
    • e.g) 웹 그래프 - 정점: 웹 페이지, 간선: 다른 페이지에 대한 HTML 링크
  • 그래프에서 데이터를 구조화하고 질의하는 대표적인 방법
    • 속성 그래프 모델, 트리플 저장소 모델

속성 그래프

  • 정점의 구성
    • 고유한 식별자, 유출/유입 간선 집합, 속성 컬렉션 (Key/Value)
  • 간선의 구성
    • 고유한 식별자, 간선이 시작하는 정점(꼬리 정점), 간선이 끝나는 정점(머리 정점), 두 정점 간 관계 유형을 설명하는 레이블, 속성 컬렉션 (Key/Value)
CREATE TABLE vertices (
    vertex_id integer PRIMARY KEY,
    properties json
);

CREATE TABLE edges (
    edge_id integer PRIMARY KEY,
    tail_vertex integer REFERENCES vertices (vertex_id),
    head_vertex integer REFERENCES vertices (vertex_id),
    label text,
    properties json
);

CREATE INDEX edges_tails ON edges (tail_vertex);
CREATE INDEX edges_heads ON edges (head_vertex);    
  • 정점은 다른 정점과 간선으로 연결되며 특정 여부를 제한하는 스키마는 없다.
  • 정점이 주어지면 유입/유출 간선을 찾을 수 있고 정점 기준 앞/뒤로 그래프 순회가 가능하다.
  • 다른 유형의 관계에 서로 다른 레이블을 사용하면 단일 그래프에 다른 유형의 정보를 저장하면서도 데이터 모델을 깔끔하게 유지할 수 있다.
  • 그래프 모델은 발전성이 좋아 애플리케이션 기능 추가 시에 데이터 구조 변경이 되어도 그래프를 쉽게 확장할 수 있다.
# 사이퍼 질의 예시
MATCH
    (person) -[:BORN_IN ]-> () -[:WITHIN*0..]-> (us:Location {name:'United States'}),
    (person) -[:LIVES_IN ]-> () -[:WITHIN*0..]-> (us:Location {name:'Europe'}),
RETURN person.name    

그래프 데이터를 관계형 구조로 넣었을 때 SQL로 질의할 수 있지만 조인할 테이블 수를 고정하기 어렵기 때문에 질의가 어렵다.
WITH RECURSIVE 문을 사용해서 표현 가능

트리플 저장소

  • 모든 정보를 주어, 서술어, 목적어와 같이 세 부분의 구문으로 구성해 저장한다.
    • 주어: 그래프의 정점
    • 목적어
      • 문자열이나 숫자 같은 원시 데이터타입의 값 - 서술어의 목적어는 주어 정점에서 속성의 키, 값
        • e.g) (루시, 나이, 33) ⇒ {"age" : 33}
      • 그래프의 다른 정점 - 서술어 = 그래프 간선, 주어 = 꼬리 정점, 목적어 = 머리 정점
        • e.g) (루시, 결혼하다, 알랭) ⇒ 루시, 알랭 = 정점, 결혼하다 = 간선
# 스파클 wlfdml dPtl
PREFIX : <urn:example>

SELECT ?personName WHERE {
    ?person :name ?personName/
    ?person :bornIn / :within* / :name "United States".
    ?person :livesIn / :withIn /:name "Europe"
반응형
저작자표시 비영리 변경금지 (새창열림)

'기술 서적 > 데이터 중심 애플리케이션 설계' 카테고리의 다른 글

3장. 저장소와 검색  (0) 2025.03.02
1장. 신뢰할 수 있고 확장 가능하며 유지보수하기 쉬운 애플리케이션  (0) 2024.05.19
    '기술 서적/데이터 중심 애플리케이션 설계' 카테고리의 다른 글
    • 3장. 저장소와 검색
    • 1장. 신뢰할 수 있고 확장 가능하며 유지보수하기 쉬운 애플리케이션
    Zayson
    Zayson
    공부한 내용을 정리하는 공간

    티스토리툴바