금번 프로젝트에서 사용했던 Amazon DynamoDB 및 NoSQL에 대한 리뷰가 되겠다.


근간에 잘 나가는 소위 Amazon Serverless Architecture - Amazon API Gateway / AWS Lambda / Amazon DynamoDB 기반으로 프로젝트를 진행하다보니 자연스럽게 마주하게 된 경과라능.

일단 알려진 특징 먼저 간단히 나열한다.

  • NoSQL - document store database
    SON 데이터를 통으로 저장하며, 각 JSON record가 동일한 scheme을 가질 필요가 없다(schema-free. 다만 Hash/Range Key는 필수). 또한, 1 depth에 국한되기는 하지만 JSON document의 각 attribute를 column으로 하여 JSON parsing 없이 direct 접근이 가능하다.

  • Hash / Range Key
    각 JSON record를 구분 짓는 Key는 Hash Key와 Range Key로 나뉘는데, 이들 둘이 합쳐져 각 record의 식별자가 된다. 이들 Key는 JSON record 내 attribute 중에 지정하며, Hash Key는 Partition 결정에 사용되어 필수이고, Range Key는 optional이다. 당연하게도 Hash Key에 대한 연산은 equality 비교만 가능하며, Range Key는 크기/string 등 여러 연산이 가능하다.

  • LSI(Local Secondary Index) / GSI(Global Secondary Index)
    query를 통한 모든 검색은 table Key 또는 LSI / GSI에 설정된 key - index를 통해서만 이루어진다. LSI는 해당 table의 Range Key만 다른 것을 뜻하고, GSI는 Hash, Range Key 모두가 다른 index를 뜻한다.

  • Scalability
    대부분의 NoSQL 주요 특징인 scaling out을 지원한다. data replication을 위해 partition은 3개의 site(AZ)에 분산 저장된다.

  • eventually / strongly consistent read
    scalability를 지원하면 당연한 이야기인데, data replication 도중에 reading이 발생할 경우 update 전 데이터를 보내줄 것인지(eventually - 하지만 결국에는 update된 데이터를 전달), 무조건 update된 데이터를 전달할 것인지(strongly)를 선택 가능하다. 물론 후자는 부가적인 비용을 요구한다.

  • RCU(Read Capacity Unit) / WCU(Write Capacity Unit)
    PaaS 솔루션 특징인 과금 모델 - provisioning 전략으로 초당 read / write 성능 지표를 뜻한다. 더 높은 성능을 위해서는 해당 값이 더 크도록 설정해야하고, 물론 크면 클 수록 비용이 더 든다.

  • query / scan 분리
    read 연산은 두 가지로 query / scan 두 가지로 나뉘는데, 전자는 index 또는 key를 사용한 조건 검색을, scan은 해당 table 또는 GSI 전체에 대한 조회를 뜻한다. 당연하게도 scan은 불필요한 data까지 조회하게 될 경우가 많기에 query를 우선적으로 사용해야 한다. 조회한 만큼 RCU를 소모하므로 성능 / 비용 측면에서도 query가 유리하다.

아래부터는 NoSQL 및 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를 기본 언어로 사용했는데 이 덕분에 현재 골머리 중.

결론

어쩌다보니 소감이 아니라 NoSQL / DynamoDB에 대한 불평불만인 듯한 글이 되어버렸는데, 객관/절대적인 평가가 아닌 매우 주관적인 감상이 본질이다. 명시적으로 언급은 안했지만 사실 상 RDB를 염두해두고 비교한 측면이 큰데, 설계 관점이 주로서 운영 및 성능 관점은 거의 빠졌다는 점을 잊어서는 안된다. 예컨데, auto scaling은 차치하더라도 scalability는 보통의 RDB가 감당하지 못하는 대표적인 장점이거니와, case by case이기는 하겠지만 성능 부문에서도 많은 장점을 가지는 것이 사실이다. 또한, 설계 관점에서도 RDB가 훨씬 더 익숙한 상황에서 기술되었다는 점을 감안해야 한다.

첨언

지난 포스트에 이어 얼마 되지도 않아 바로 이렇게 포스팅한 이유는, 역시나 애드센스 땜시 ㅎㅎㅎ. 애드센스가 블로그 평가를 할 때 최근 2~3개를 중점으로 본다는 소문에 1000자를 넘기는 노력의 일환이다. 추가로, 하루 2000회 방문에 월 1000달러 번다는 이야기는 일반적인 사항은 아닌 듯 하다. CTR(Click Through Ratio), CPC(Cost Per Click) 등, 영향을 미치는 요소가 좀 있는 듯. 용어에서도 보듯이 좀 신경써서 볼 필요가 있네. 역시... 세상엔 공짜가 없어.

저작자 표시 비영리 변경 금지
신고
Posted by 어쨌건간에

얼래벌래 포스팅 공백이 2년이 되어가는 이 시점에, 갑작스럽게 포스팅을 하게 된 계기라면,

구글 애드센스

하루 2000여 방문으로도 월 1000 달러를 번다는 소식에, 바로 이 블로그를 확인. 근간 대강 하루 평균 500여 방문이 이루어지는 듯 보이는데, 아니 그것만으로도 수입이 어디인가.

블로그 한 지가 얼마나 오래되었는데, 아직까지 그걸 몰랐을까 하는 후회와 함께 바로 애드센스를 설치했더니만, '컨텐츠 불충분'이란 google로부터의 회신이었다.. '내 블로그만큼이나 컨텐츠가 unique하고 충실한 블로그가 또 어디 있냐'하며 황당해하며 구글링해보니, 최근의 몇 개 포스팅을 검토한단다. 일단 1000자가 넘어가야 한다고. 마침 최근 포스팅 딱 2개가 상당히나 짧았지. 사실 주절주절 쓸 것을 핵심만 요약한건데 이런 문제가 있을 줄이야.

해서 본 포스팅을 하게 되었다는, 쫌 길다면 긴 서문. 이런 식으로 1000자 넘어가는 거야 일도 아니지 ㅎㅎ

2여년 간 블로그 공백 정리

낭중에 하나씩 포스팅으로 풀어갈 것들이지만, 일단 간단히 요약 정도만. 먼저 개발 건 부터 풀어간다.

그간의 포스팅도 그랬지만 꽤 오랜 시간 개발 이야기가 없었는데, 개발 안하고 산 게 아니라(밥벌이라 그렇게 살 수도 없고), 그냥 어쩌다보니 개발 포스팅이 없었다는 정도.

  1. http://anyflow.github.io/lannister/ : 개인 프로젝트로 만든 MQTT broker. 한참이나 IoT가 화두에 마침 유사 기능을 갖는 대용량 Push Notification Server 개발도 했던 찰나, 오픈 소스로 나와있는 MQTT broker가 다덜 하나씩 이빨 빠져있어 아예 만들게 된 물건. 
    이 역시 (당연스럽게) 대용량 session handling이 one of 목표였는데, 주요 feature set 전체 구현/테스트에 문서까지 maven documentation 기반으로 이쁘장하게 꾸며놓았더만, 성능 테스트에서 덜컹 삑사리. version 0.9.8로 눈물을 머금고 (지금은) 개발을 중단했다. 성능 이슈는 클러스터링을 위해 사용한 hazelcast에 있었다는. 이 땜시 가슴 미어지던 작년 말의 아련한 추억(?)이...

  2. https://github.com/anyflow/lannister-admin : 근간에 한참이나 잘나가는 React 기반으로 만든, 위 Lannister의 admin site에 해당하는 물건. 이 역시 주요 기능은 거반 만들어놨는데, Lannister가 뽀까닥하는 바람에 이넘도 함께 뽀까닥. 만든 목적 중 하나는 frontend 트랜드 스터디였는데, 이 거 하나 건진 셈. React.. 꽤나 흥미로운 물건이라능. 사실 React 자체보다도, nodeJS, ES6, webpack, immutable.JS, redux, Visual Studio Code 등, 이 주위의 여러 frontend 기술 익히는 것이 더욱 의미있었다고나 해야 할까나. 추가로 봐둘 것은 React Native(Mobile App용. 무려 native compiling을 지원한단다).

  3. Serverless / AWS PaaS : 이건 지금 한참이나 사내 업무로 사용 중인 넘으로, 대강 Lambda Function + AWS API Gateway + DynamoDB (+ AWS etc.)가 핵심. 이들은 각기 따로 포스팅이 필요한 넘들이기에 여기서는 패스. 여담으로, Serverless Framework란 이름의 app lifecycle 지원 도구를 잠시 검토했었는데, 구조적인, 그리고 critical한 이슈 몇 개 때문에 직접 해당 도구를 만들어 썼다는게 하고픈 말. 이 역시 오픈소스화를 노려볼만한 물건이지만, 사내 소스 오픈 이슈를 포함하여 당장에 쉽지 않은 난관 여러 개가 생각나네.
아래부터는 그간 연습했고, 하는 중인 연주곡들.
  1. Fugue in G minor, BWV 578 : 무려 2년 내내 연습 중인 Bach의 Little Fugue. YouTube에서 이를 연주하는 사람들 보며 어쩜 저리 잘 칠까 하며 부러워하던 모습이 '아니, 전공자가 그렇게 밖에 못치나'하는 맘으로 변해가고 있다는 깔때기 먼저 ㅎㅎ. 지금 연습 중인 악보는 I. Philipp + Hanozix 두 가지 버전을 짬뽕한 버전. I. Philipp 버전이 많이들 사용하고 먼가 정통파스럽지만, 오른손 trill이 이어지는 부분이 심심하게 편곡되었다는 점이 거시기. 해서 그 부분을 포함한 몇 부분만 Hanozix 버전으로 대체 연습 중. 금년 말  정도면 Recording(?) 들어갈 수준이 나오리라는 예상.

  2. Toccata & Fugue BWV 565 : 들어보면 다 알만한 Bach의 organ 곡으로, 이 곡을 언젠가는 치리라... 맘먹은지 15여년이 되어간다. 당시 샀던 악보는 지금봐도 너무 어려운데, piano에서 organ의 웅장함을 살리기 위해 온갖 꾸밈이 들어가서 그랬다는 것이 함정. 편곡자 이름은 나름 유명해보이는 Buzoni. 물론 지금은 original 버전을 살짝 piano 버전으로 살짝 바꾼 수준의 Federico Casal의 것으로 연습 중. 그럼 웅장함은 무얼로 매꾸느냐? 물론 organ 음색으로 바꿔서 치는 것이지. 난이도는 BWV 578에 비하면 피식(?) 할 수준.

  3. Game of Thrones - Light of the Seven : 왕좌의 게임 에피소드6의 마지막 편 배경음악.. 한참이나 잔잔히 깔리다가 신전 대참사로 끝나는 장면의 그 것. Kyle Landry란 놀라운 편곡자가 만든 piano 버전인데, 악보 만들어지길 기다리느라 목 좀 뺐다. 이 아저씨의 편곡은 이외에도 Inception, Interstellar 등 상당한데, 한마디로 아주 쌈박하다. 아니나다를까 팬들도 수두룩. 이 곡... 그간 못봐왔던 테크닉을 상당히 요하는지라, 지금 같아서는 little fugue를 처음 접할 때의 맘 수준?
일단 이번 포스트는 대강 요기까지. 1000자야 우습게 넘겼겠지. ㅎㅎ

포스트 정리는 그간 little fugue 연습의 reference가 되어준 Dario Ronchi란 이름의 피아니스트의 것. 댓글에 달린 말마따나 태풍의 눈을 연상케 한다. 그러면서도 표정이나 액션은 무뚝뚝. 이게 아주 맘에 드는 것이 클래식 연주자 상당수가 보이는 오만 똥폼 및 표정이 그간 눈에 거슬려왔기 때문.


저작자 표시 비영리 변경 금지
신고
Posted by 어쨌건간에