Published on

[Database] DynamoDB 중요 개념

Authors
  • avatar
    Name
    유사공대생
    Twitter

개요

작년 1년 야심차게 시작했던 헬스케어 서비스를 마무리하게 되었다. 마무리라기보다, 이 서비스의 미래가 없어 보여 잠정개발중단되었다는 표현이 맞는 것 같다.

기술적으로 얻어갈 게 많았으면 했지만, 생각보다 얻은 건 없었고 배운 게 생각보다 없는 프로젝트였다. 실사용자를 모집해보지 못한 채 끝내서 그런가, 씁슬함이 있다. 전 프로젝트 ReFit 개발중단한 지금, 같은 팀원들과 나의 학부생 마지막 프로젝트를 시작했다.

기본적으로는 채팅 서비스여서 아키텍쳐에 대한 고민이 많았다. 기존에 내가 자주 사용하던 MySQL로 할건지, 아니면 채팅 서비스에서 잘 사용하는 NoSQL을 사용할건지 말이다.

결론적으로는 둘 다 섞기로 했다. 사용자 개인정보라던지, 기획 아이디어에 따라 변하지 않을 부분들은 Mysql에, 추후 기획에 따라 변동성이 많은 부분은 NoSQL에 저장하기로 했다. 관계형 데이터베이스는 내가 자주 사용하고, 익숙한 MySQL을 사용하면 된다. 하지만 NoSQL은 고민이 많았다.

MongoDB vs DynamoDB

결국 이 둘중에 하나를 선택해야 했다.

MongoDB를 사용한다면 두 가지 선택지가 있었다. AWS EC2 인스턴스에 MongoDB를 설치하여 사용하거나, AWS에서 제공하는 DocumentDB를 사용하는 것이었다.

하지만 백엔드를 혼자 개발하고 운영 관리할 계획이다 보니, 직접 인스턴스에 설치해서 관리하는 것은 쉽지 않을 것 같았다. 그리고 DocumentDB는 인스턴스 단위로 대여를 하는 것이여서 초기 비용이 너무 많이 나왔다.

따라서 AWS에서 제공하는 DynamoDB를 사용하게 되었다. 지금 인프라 세팅(데이터베이스 연결, CI/CD)은 끝났고, 이제 DynamoDB에 대해 공부하고 알아보려 한다.

DynamoDB란?

AWS에서 제공하는 서버리스, key value 기반 NoSQL 데이터베이스이다.

특징

NoSQL 데이터베이스에는 JOIN이 없다. 말 그대로 비관계형 데이터베이스이기 때문에 정규화도 불가능하다. 대신, NoSQL에서는 반정규화를 한다고 한다.

반정규화한?

데이터베이스 반정규화는 데이터베이스의 성능 향상을 위해서 데이터 중복을 허용하고, 조인을 줄이는 데이터베이스 성능 향상 방법이다.

일반적으로 정규화는 데이터 중복을 줄이고 데이터 무결성을 유지하기 위해 테이블을 분해하는 과정이다. 그러나 이로 인해 조인이 많이 발생하거나 쿼리의 성능이 저하될 수 있다.

반정규화는 조회(select) 속도를 향상시키지만 데이터 모델의 유연성은 낮아진다. 반정규화를 적용하면 데이터 무결성이 깨질 수 있는 위험이 있다.

DynamoDB 파티셔닝 원리

DB 파티셔닝 원리

DynamoDB 내에는 해쉬 함수가 존재한다. 여기서 파티션 키는 해쉬 함수를 거쳐서 데이터를 저장할 파티션을 결정한다. 동일한 파티션 키를 지닌 데이터는 물리적으로 가까운 위치에 저장된다. 이때 데이터를 구분하기 위해 정렬 키를 사용한다. 정렬 키를 사용하면 동일한 파티션에 저장된 데이터는 정렬 키를 기준으로 저장된다.

DynamoDB 구성요소

Key

DynamoDB 주요 개념

Primary Key (PK)

primary key를 표현할때는 PK라고 하지 않고 그냥 primary key라고 한다. partition key일 경우만 PK라고 부르는 경우가 많다.

DynamoDB에서의 Primary Key는 두개의 키로 이루어져 있다. Partition Key와 Sort Key이다.

파티션 키(Partition key = PK = Hash Key)

  • 물리적인 공간인 파티션을 구분하기 위한 키
  • 스케일이 아무리 커져도 주소를 알고 있어서 데이터를 빠르게 가져올 수 있다.
  • 파티션 키로는 일치하는 값만 가져올 수 있고, =, >, < 등의 범위지정 방식 검색은 지원하지 않는다.

정렬 키(Sort Key = SK = Range Key)

  • 파티션 안에서 데이터를 정렬하기 위한 키
  • DynamoDB에서는 Number, Binary, String 타입을 지원(String은 utf-8)
  • 단순 정렬이기 때문에 파티션 사이즈가 커져도 데이터를 빠르게 가져올 수 있다.
  • 파티션 키와 달리 범위지정 방식 검색 지원한다. 하지만 정렬 키만 가지고는 검색할 수 없다.

키 사용 방식

만약, 키 형태가 전역적으로 유일하다면(기존 mysql에서 pk와 같다면) Partition Key 하나만 사용해도 된다. 하지만 유일하지 않거나, 다른 값들과 함께 범위지정을 한 쿼리를 기반으로 사용하고 싶다면 Partition Key와 Sort Key를 같이 사용하면 된다.

이 외에도 다른 전략들이 있는데 참고만 하자.

  • Prefixes / Suffixes
  • composed partition keys
  • DynamoDB Accelerator(DAX)

GSI(Global Secondary Index)

만약에, 위 사진에 있는 테이블에서 OriginCountry가 USA인 사람을 리스트로 받아 보려면 어떻게 하면 될까?

단순히 생각했을 때는 테이블을 전부 조회하면서 USA와 같은 accountId를 불러오면 될 것이다. 하지만, 실제로 이런 방식으로 연산을 수행한다면 매우 비효율적이다. 만약 저 테이블에서 USA가 두개 밖에 없고, 테이블의 데이터 크기가 엄청 큰 경우만 봐도 알 수 있다.

그래서 GSI라는 것을 사용한다.

GSI 작동방식
  • GSI는 기본 테이블의 파티션 키와 정렬 키 외에 다른 속성을 기반으로 쿼리할 수 있는 보조 인덱스이다.
  • GSI를 생성하면 DynamoDB는 기본 테이블에 있는 각 항목에 대해 GSI의 파티션 키와 정렬 키의 값에 해당하는 항목을 GSI에 복제한다. 하지만 두 테이블은 동기화된 상태로 유지한다.
  • GSI를 통해 데이터를 조회할 때, GSI의 파티션 키와 정렬 키를 기반으로 쿼리할 수 있다.
  • 성능을 극대화하기 위해서는 데이터가 여러 파티션에 고르게 분산되어 있어야 한다.

LSI(Local Secondary Index)

  • LSI는 기본 테이블과 같은 파티션 키를 공유하며, 다른 정렬 키를 사용하여 쿼리할 수 있는 인덱스이다. 하지만 GSI와 달리 파티션 키를 변경할 수 없다.
  • LSI는 테이블 생성 시에만 정의할 수 있으며, 생성 후에는 변경할 수 없다.

DynamoDB에서 데이터를 핸들링하는 3가지 방식

Item-based Actions

DynamoDB에서 Item은 관계형데이터베이스의 Row에 해당한다.

Item-based Actions에는 Write, Delete, Update가 있다.

그리고 Primary Key를 통해 하나의 Item을 대상으로 처리한다. 다시 말해, 한번에 여러개를 처리 할 수 없다.(batch request 불가)

Query - Read-only Action

  • Query는 테이블 내의 항목을 검색할 때 사용한다.
  • 주로 파티션 키(Partition Key)를 기준으로 검색하며, 파티션 키는 테이블의 항목을 빠르게 식별할 수 있는 주요 키이다.
  • Query를 실행하려면 테이블의 파티션 키(Partition Key)를 지정하고, 선택적으로 정렬 키(Sort Key)와 함께 쿼리할 수 있다. 정렬 키는 파티션 내에서 항목을 정렬하는 데 사용된다.
  • Query는 효율적이며 특정 항목을 빠르게 찾을 수 있지만, 파티션 키(Partition Key)를 기준으로만 검색이 가능하다.

Scan

  • Scan은 테이블을 전체적으로 스캔하여 항목을 검색한다.
  • 특정 조건 없이 전체 테이블을 스캔하기 때문에 비용과 성능 측면에서 비효율적일 수 있다.
  • 하지만 파티션 키(Partition Key)나 정렬 키(Sort Key)와 상관없이 테이블의 모든 항목을 검색할 수 있다.
  • 특정 조건이나 필터를 적용하여 스캔 결과를 좁힐 수 있지만, 이 역시 비용과 성능에 영향을 줄 수 있다.

DynamoDB 모델링 방법

크게 세가지를 순서대로 하면 된다.

  1. Start with an ERD
  2. Define your access patterns
  3. Design your primary keys & secondary indexes

Start with an ERD

구현하고자 하는 서비스에서 필요한 Entity간의 관계를 표현해야 한다. 이 부분은 관계형 데이터베이스를 모델링 할때와 다르지 않다.

Define your access patterns

구현하고자 하는 서비스의 요구사항이 뭔지, 그리고 요구사항에 따라 어떤 데이터를 넣고 읽을것이지 작성해야 한다.

Design your primary keys & secondary indexes

앞서 본 두가지를 바탕으로 Write/Delete/Modify 가 가능하게 하고, Scan이 아는 Query로 데이터를 얻고, 필터링이 가능하게 key를 디자인해야 한다.

  • 참고자료

DynamoDB 제대로 알고 사용하기

Tables, Items, and Attributes AWS DynamoDB Guides 60분만에 이해하는 DynamoDB 모델링: DynamoDB Modeling