title: "**Amazon DynamoDB 소감**"
description: "Amazon DynamoDB 특징 및 사용 소감"
cleanUrl: /sw-engineer/dynamodb
ogImage: "<https://oopy.lazyrockets.com/api/v2/notion/image?src=https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F7570d2fc-66b1-4e23-bb3c-ff7b56842b0d%2Fb70ddf70-ed79-435e-b9b0-274794f4515a%2FUntitled.png&blockId=46609b07-3ee8-409f-ba17-9bcf216275a4>"
floatFirstTOC: right
금번 프로젝트에서 사용했던 Amazon DynamoDB 및 NoSQL에 대한 리뷰가 되겠다.
근간에 잘 나가는 소위 Amazon Serverless Architecture - Amazon API Gateway / AWS Lambda / Amazon DynamoDB 기반으로 프로젝트를 진행하다보니 자연스럽게 마주하게 된 경과.
사실 상 본격적으로 사용한 최초 NoSQL Lannister에 적용했던 Hazelcast 역시 NoSQL로 분류하기도 하던데, Hazelcast는 그들이 In-Memory DataGrid라고 부르기도 하거니와, NoSQL로 칭하기에는 나의 use case 및 일반적으로 알려진 특성 상 좀 거시기하고, CQL로 애를 먹었던 Cassandra는 어디까지나 간단한 리뷰 정도라서리.
이는 그 뒤에서부터 이어질 이야기에 삑사리가 있을 수도 있다는 디펜스이자 독자로의 사전 주의(?).
Query-first approach 난감 NoSQL 설계 특징 중 하나가 소위 'Query-first approach', 즉, scheme 이후 query 고려가 아닌 query를 먼저 고려하는 설계인데, 이게 말이 Query first 이지 결국에는 scheme 설계 이후 query를 만들 일이 비일비재하다. 예컨데, 초기 요구 구현, 즉 scheme 설계 확정 이후 추가 요구가 들어왔다고 하자. 이 경우 기 설계된 scheme를 바탕으로 query를 만들어야 할 터인데, 이러한 흔한 상황 자체가 query first가 불가한 조건이다.여기서 DynamoDB에 '거참...'하게 만드는 기능 중 하나가 LSI(Local Secondary Index)인데, LSI는 table 생성되고 나면 추가할 수 없기 때문. 'GSI가 있는데 뭔 불만이냐' 할 수도 있는데, GSI는 사실 상 table 추가하는 것과 사실 상 동일하거니와(LSI와는 달리 table 과는 별도로 과금됨), LSI를 애용(?)하라는 Amazon의 guide 사실 상 따르기가 어렵다(이번 프로젝트에서는 LSI를 그렇게나 사용하려 노력했음에도 적용된 곳이 없다. 좀 더 정확히 말하자면, 적용할 구석을 찾을 수 없었다).
쉽지 않은 사용법 NoSQL 특징 중 하나로 쉬운 사용법을 거론하고는 하는데 '결국에는' 공감이 안된다. query의 경우, SQL 대신에 JSON 기반의 자체 query를 사용하는데, 간단하게 line 수만 보더라도 SQL에 비해 훨씬 더 많다. 어찌보면 당연한 게 SQL 자체가 query에 특화된 언어인데 이를 능가하는 것이 만무하다. Cassandra의 CQL이나, Hadoop - Hive의 HiveQL 등 여타 비 RDB 시스템에서 SQL을 지원하려는 노력만 봐도 이해가 될 만한 사항.NoSQL이라 당연하기는 하지만, join 연산이 불가능하다보니 RDMS가 제공하는 폭넓은 검색은 꿈도 못꾼다. 단일 table 내에서도 특정 table attribute를 조건으로 검색하는 것도 index를 통해서만 가능한데, index 생성도 위의 LSI/GSI에서도 보았듯이 관리가 쉽지 않다는 것이 함정. 물론 filtering을 통해서도 검색 효과를 볼 수 있지만, filtering은 이름에서도 (작게나마) 감잡을 수 있듯이, data fetching 이후 filtering하는 것이라 성능이 안나오는 것은 물론이고, RCU 감소 효과도 볼 수 없다. 이 외에도, RDB의 수많은 SQL function에 비해 query function이 몇 개 없다는 점과 효율적인 resource 사용을 위해 특정 partition에 hit이 몰리지 않게 hash key 설계하는 것도 유의 할 점이다(resource - W/RCU는 각 partition에 일괄로 나뉘어 할당된다).
WCU / RCU 설정 부담 더 많은 WCU / RCU을 할당할 수록 성능은 좋아지겠지만 그 만큼 더 많은 돈이 나가는지라, 적정선의 값을 할당해야만 하는데, 이게 만만하지 않다. WCU / RCU 조율을 위해 한동안 cloud watch를 항시 모니터링했고, 여전히 하고 있다. 조만간 autoscaling을 지원한다는데, 얼마나 이 부담을 덜어줄 지는 나와봐야 알 일.
Transaction 부재 유감(NoSQL이니 당연하다만) NoSQL에서 transaction을 찾는 것도 이상한 일이다만, 어쨌건 transaction에 대한 요구는 일반적이다. 두 개 이상의 table으로 변경을 이루는 단일 action은 매우 흔한 일인데, 이에 대한 Atomic 연산이 DB 차원에서는 불가하다는 이야기. 이는 DB가 아닌 client library에서 지원을 하는 듯 보이는데, java에만 해당한다는 점이 함정(2017/05/30 기준). 금번 프로젝트는 nodeJS를 기본 언어로 사용했는데 이 덕분에 현재 골머리 중.