AWS 기술 블로그

AWS Glue와 Amazon Athena를 활용한 MongoDB 데이터 분석 방법 비교하기

IoT 디바이스 또는 웹/앱 애플리케이션에서 발생되는 데이터는 JSON 다큐먼트 형태로 주로 저장되고 있으며, 이 데이터에 대한 분석 요구가 증대됨에 따라 MongoDB와 같은 다큐먼트 지향 데이터베이스 사용도 늘어나고 있습니다. AWS에서 제공되는 분석 서비스는 완전관리형 또는 서버리스 형태로 제공되어 사용자의 분석패턴에 따라 다양한 서비스를 활용할 수 있습니다. 이번 게시글에서는 여러 분석 서비스 중 Amazon Athena를 활용하여 ad-hoc 쿼리로 손쉽게 데이터를 분석할 수 있는 방법을 소개합니다. Amazon Athena는 서버리스 대화형 분석 서비스로 SQL 또는 Apache Spark 기반 분석Publish to Live을 프로비저닝이나 구성 작업 없이 페타바이트 규모의 데이터를 쉽고 유연하게 분석하게 해주는 서비스입니다. 최근에 공개된 Athena Provisioned Capacity를 활용하면, 다수의 동시 쿼리 실행으로 인한 지연없이 전용 쿼리 처리 용량 (Dedicated Query Processing Capacity)을 이용하여 빠르게 SQL 쿼리를 수행할 수 있습니다.

솔루션 개요

MongoDB의 데이터를 Amazon Athena로 조회하는 방법은 2가지가 있습니다. 첫째, AWS Glue crawler
실행 후, Amazon Athena에서 쿼리하는 방법입니다. AWS Glue crawler로 MongoDB를 호스팅하는 서버에 접근하여 크롤링하고, AWS Glue ETL Job으로 데이터 레이크인 Amazon Simple Storage Service (Amazon S3)에 데이터를 저장합니다. 이후, S3에 저장된 데이터를 Amazon Athena로 분석할 수 있습니다. 둘째, Amazon Athena에서 Data source를 설정하고 Athena Federated Query를 통해 직접 쿼리하는 방법입니다. 이 방법은 데이터 레이크에 데이터를 저장하지 않기 때문에, 소스에서 발생되는 데이터를 거의 실시간으로 분석할 수 있는 방법입니다.

[그림1] AWS Glue crawler 실행 후, Amazon Athena에서 쿼리하는 방법

[그림1] AWS Glue crawler 실행 후, Amazon Athena에서 쿼리하는 방법

[그림2] Amazon Athena에서 Data source를 설정하고 Athena Federated Query를 통해 직접 쿼리하는 방법

[그림2] Amazon Athena에서 Data source를 설정하고 Athena Federated Query를 통해 직접 쿼리하는 방법

단계 요약

위에서 소개한 2가지 방법을 구현하기 위해 아래와 같은 순서로 단계별로 설명합니다.
[방법 1] AWS Glue crawler 실행 후, Amazon Athena에서 쿼리

  • 단계 1 : MongoDB on EC2 생성
  • 단계 2 : Dummy Data 생성
  • 단계 3 : AWS Glue Connection 및 crawler 설정
  • 단계 4 : AWS Glue ETL Job 생성 및 실행
  • 단계 5 : Amazon Athena에서 데이터 조회

[방법 2] Amazon Athena에서 Data source를 설정하고 Athena Federated Query를 통해 직접 쿼리

  • 단계 6 : Amazon Athena에서 Data source 생성
  • 단계 7 : Amazon Athena Federated Query 실행

사전 준비사항

솔루션을 배포하기 위해서는 아래와 같은 사항을 준비해야 합니다.

  • AWS 계정
  • AWS CLI(Command Line Interface)
  • MongoDB on EC2
    • 운영중인 환경이 있다면 단계 2 : Dummy Data 생성 수행
    • 운영중인 환경이 없다면 단계 1 : MongoDB on EC2 생성 수행

단계 1: MongoDB on EC2 생성

  1. AWS console에서 EC2를 검색하고 AWS EC2 console에 접근한 후에 ‘Launch Instance’를
    클릭합니다.
  2. Name을 입력하고 Amazon Machine Image (AMI)는 ‘Amazon :inux 2 AMI (HVM) – Kernel 5.10, SSD Volume Type’를 선택합니다.
  3. [그림3]을 참조하여 Instance type과 Key pair를 설정합니다.
  4. Subnet은 Private subnet으로 설정합니다.
  5. Security Group은 Self-referencing하는 Security Group을 선택합니다. (아래 [그림4] 참조)

[그림3] 인스턴스 생성

[그림3] 인스턴스 생성

[그림4] Security Group 설정

[그림4] Security Group 설정

      6. UserData에 아래 스크립트를 복사하여 붙여넣고 ‘Launch Instance’를 클릭합니다.

#!/bin/bash
echo “downloading mongondb-org 4.0 packages from https://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/4.0/x86_64/RPMS/ ...” >>/tmp/mongosetup.log
wget https://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/4.0/x86_64/RPMS/mongodb-org-4.0.21-1.amzn1.x86_64.rpm
wget https://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/4.0/x86_64/RPMS/mongodb-org-server-4.0.21-1.amzn1.x86_64.rpm
wget https://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/4.0/x86_64/RPMS/mongodb-org-shell-4.0.21-1.amzn1.x86_64.rpm
wget https://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/4.0/x86_64/RPMS/mongodb-org-mongos-4.0.21-1.amzn1.x86_64.rpm
wget https://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/4.0/x86_64/RPMS/mongodb-org-tools-4.0.21-1.amzn1.x86_64.rpm
echo “running rpm for mongodb-org installation...” >>/tmp/mongosetup.log
rpm -Uvh mongodb-org-tools-4.0.21-1.amzn1.x86_64.rpm >>/tmp/mongosetup.log
rpm -Uvh mongodb-org-mongos-4.0.21-1.amzn1.x86_64.rpm >>/tmp/mongosetup.log
rpm -Uvh mongodb-org-server-4.0.21-1.amzn1.x86_64.rpm >>/tmp/mongosetup.log
rpm -Uvh mongodb-org-shell-4.0.21-1.amzn1.x86_64.rpm >>/tmp/mongosetup.log
rpm -Uvh mongodb-org-4.0.21-1.amzn1.x86_64.rpm >>/tmp/mongosetup.log
echo “starting mongo service... ” >>/tmp/mongosetup.log
service mongod start >>/tmp/mongosetup.log
echo “install telnet service... ” >>/tmp/mongosetup.log
yum install telnet -y >>/tmp/mongosetup.log
chkconfig mongod on >>/tmp/mongosetup.log
#python 설치
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python3 get-pip.py
pip3 install boto3
pip3 install pymongo

7. 인스턴스가 생성되면 선호하는 방법으로 접속합니다. 여기서는 EC2 Instance Connect Endpoint를 사용하였습니다. (EC2 Instance Connect Endpoint가 없는 경우는 필수 조건 페이지를 참고해서 생성)

8. Mongo, pip3 가 설치됐는지 확인합니다.

단계 2 : Dummy Data생성

[MongoDB on EC2 추가 설정]

Mongo를 입력하여 mongoDB shell에 접속하고 아래와 같은 순서로 입력합니다.

1. ‘labdb’ 데이터베이스 생성

use labdb

2. user 생성

db.createUser({ user: "admin", pwd: "1234", roles: [{ role: "readWrite", db: "labdb"}]})

3. ‘customers’ collection 생성

db.createCollection("customers");

4. ctrl+D로 mongoDB shell에서 나옵니다.

MongoDB에 접속할 수 있도록 /etc/mongod.conf를 아래와 같이 변경합니다. (sudo로 접근합니다.)

    • 여기서는 bindIP를 0.0.0.0으로 설정하였으나, bindIp: localhost,10.8.0.10,192.168.4.24와 같은 구조로 세부 설정할 수도 있습니다.
    • authorization은 enabled로 설정해줍니다. (authorization은 2번, ‘enabled’는 1번 띄어쓰기 합니다.) 띄어쓰기가 맞지 않을 경우, mongo restart시, 이슈가 발생합니다.

sudo service mongod restart를 입력하여 변경된 설정으로 재시작합니다.

아래와 같이 입력하여 labdb에 접속되는 것을 확인합니다. mongo mongodb://admin:1234@<EC2 private IP>:27017/labdb

[Dummy Data 생성]

Dummy Data 생성을 위해 아래 코드로 mongo.py를 생성합니다. 이때 ‘mongoIP’의 <<privateip>>는 EC2 private IP로 대체합니다.

import json
import boto3
import random
import os
import datetime
from datetime import timedelta
import time
import pymongo
#MongoIP = os.getenv('MONGOIP')
MongoIP = '<<EC2 private IP>>'
#Login = os.getenv('LOGIN')
Login = 'admin:1234'
connection = 'mongodb://'+Login+'@'+MongoIP+'/labdb'
client = pymongo.MongoClient(connection, directConnection=True)
db = client.labdb
def getReferrer():
  x = random.randint(1,2)
  x = x*10
  y = x+50
  data = {}
  product = random.randint(1,250)
  data['custid'] = random.randint(x,y)
  data['trafficfrom'] = random.choice(['amazon.com', 'facebook.com', 'twitter.com'])
  data['url'] = random.choice(['beer_vitrine_nav','beer_product_detail','bee'])
  data['device'] = random.choice(['app_mobile','app_tablet','browser'])
  data['touchproduct'] = 0
  now = datetime.datetime.now()
  time.sleep(.5)
  str_now = now.isoformat()
  data['trans_timestamp'] = str_now
  if data['url'] != 'beer_vitrine_nav':
    data['touchproduct'] = product
  return data
begining = datetime.datetime.now()
newtime = begining
print(connection)
print(db)
#for doc in db.customers.find():
# print(doc)
while (newtime - begining).total_seconds()<55:
  #data = json.dumps(getReferrer())
  #print(data)
  result=db.customers.insert_one(getReferrer())
  print(result)
  newtime = datetime.datetime
print ('Cleaned end execution.')

python3 mongo.py를 입력하여 아래와 같이 Dummy Data가 생성되는 것을 확인합니다.

생성이 완료되면 mongouse labdb db.auth("admin", "1234")로 인증을 합니다.

아래 명령어로 샘플 데이터를 확인합니다.

db.customers.findOne()

단계 3 : AWS Glue Connection 및 crawler 설정

[Connection 생성]

AWS Glue의 좌측 메뉴에서 ‘Connections’를 클릭하고 ‘Create connection’을 클릭합니다.

Connection Name을 입력하고 Connection type은 ‘MongoDB’를 클릭합니다. (예, Mongo-EC2)

아래와 같이 Connection access를 설정합니다.

  • MongoDB URL 형식 : mongodb://<EC2 Private IP>:27017/labdb
  • Usename과 Password를 입력: admin과 1234
  • Network options: EC2정보와 동일한 VPC, Subnet, Security groups선택

위 설정을 완료한 후, ‘Create connection’을 클릭합니다.

[Glue crawler 생성]

AWS Glue의 좌측 메뉴에서 ‘Crawlers’를 클릭하고 ‘Create crawler’를 클릭합니다.

Name을 입력하고 ‘Next’를 클릭합니다. 예) mongo-source-crawler

Data source의 ‘Add a data source’를 클릭하고 아래와 같이 설정한 후, ‘Add a DocumentDB/MongoDB data source’를 클릭합니다.

  • Data source: DocumentDB/MongoDB 선택
  • Connection: 생성한 Connection 선택
  • Include path: labdb/customers 입력

Data source에 추가된 것을 확인한 후, ‘Next’를 클릭합니다.

다음 화면에서 IAM role을 선택한 후, Next’를 클릭합니다.

  • 여기서 Glue_Admin은 AmazonS3FullAccess, AWSGlueServiceRole을 포함하는 역할입니다.
  • IAM role이 없다면 아래 ‘Create new IAM role’을 클릭하여 신규 생성합니다.
  • 운영 환경의 경우, 보안 정책에 따른 최소한의 권한만 가진 역할을 지정합니다.

이어서 Target database를 지정합니다.

  • Glue crawler에서 생성되는 테이블을 위한 데이터베이스를 지정합니다. (예, mongo-ec2)
  • 데이터베이스가 없다면, ‘Add database’ 버튼을 눌러 새로 생성합니다.

‘Next’를 클릭하고 이어서 ‘Create crawler’를 클릭합니다.

crawler 생성 후, 우측 상단의 ‘Run crawler’를 클릭하고 Status가 ‘Completed’인지 확인합니다.

crawler가 정상적으로 완료되면, Glue Table에서 생성된 테이블과 Schema를 확인할 수 있습니다.

단계 4 : AWS Glue ETL Job 생성

단계 3에서 생성된 Data Catalog를 기반으로 ETL job을 수행하여 MongoDB 데이터를 S3에 저장합니다.

  1. AWS Glue console의 좌측 메뉴에서 ‘Visual ETL’를 클릭합니다.
  2. Source와 Target을 아래와 같이 지정하고 우측 상단의 ‘Create’를 클릭합니다.

보이는 Visual을 클릭하여 순차적으로 설정합니다. Data source와 Data target 사이에 있는 Transform은 별도의 설정을 하지 않습니다.

먼저 Data Catalog table을 클릭하고 아래와 같이 Database와 Table을 선택해줍니다.

S3 bucket은 아래와 같이 설정합니다.

  • Format은 parquet을 선택합니다.
  • S3 Target Location의 경우, s3://<bucketname>/mongo/와 같이 입력합니다.
  • ‘Job details’ 탭으로 이동하여, Job 이름을 ‘mongo’로, IAM Role은 위 단계에서 사용한 role을 설정합니다.

Script 탭으로 이동하여 ‘Edit script’를 클릭하고, # Script generated for node Data Catalog table 부분을 아래와 같이 변경합니다.

# Script generated for node Data Catalog table
DataCatalogtable_node1 = glueContext.create_dynamic_frame.from_catalog(
    database="mongo-ec2",
    table_name="labdb_customers",
    additional_options = {"database":"labdb","collection":"customers"},
    transformation_ctx="DataCatalogtable_node1",
)

‘Save’를 누르고 ‘Run’을 클릭합니다.

‘Runs’ 탭에서 Run status가 Success가 되면 S3 bucket의 mongo/에서 파일을 확인합니다.

참고: S3 console에서 해당 버킷과 폴더로 이동하고 객체를 선택한 후에 Actions의 ‘Query with S3 Select’를 통해 결과를 확인할 수 있습니다.

단계 5: Amazon Athena에서 데이터 조회

이번 단계에서는 정제된 데이터 (Transformed Data)에 대해 다시 한번 크롤링합니다. 이를 통해 생성된 table은 Amazon Athena에서 바로 query할 수 있습니다.

AWS Glue console에서 ‘Crawlers’와 ‘Create crwaler’를 클릭하고 아래와 같이 진행합니다.

  1. Name 입력 후, ‘Next’를 클릭 (예, mongo-transformed-crawler)
  2. ‘Add a data source’ 클릭하여 아래와 같이 설정하고 ‘Add an S3 data source’를 클릭하고 이어 ‘Next’를 클릭
    1. Data source: S3
    2. S3 경로: Transformed Data가 있는 s3://<버킷이름>/<폴더명>/ (예, s3://<버킷이름>/mongo/)
  3. IAM role: 단계 3에서 선택한 role과 동일한 것(예, Glue_Admin)을 선택한 후, ‘Next’를 클릭
  4. Target Database (예, mongo-ec2)를 선택한 후, ‘Next’를 클릭
  5. ‘Create crawler’를 클릭
  6. ‘Run crawler’를 클릭하여 결과 확인
  7. 생성이 완료되면 Amazon Athena로 이동합니다.

그림과 같이 좌측 Tables가 추가된 것을 확인하고 이를 활용하여 쿼리할 수 있습니다.

지금까지 MongoDB의 데이터를 Glue Connection을 통해 크롤링하고, 데이터 레이크에 저장하여 Amazon Athena를 통해 조회하는 방법을 알아보았습니다.

지금부터는 MongoDB의 데이터를 데이터 레이크에 저장하지 않고, Athena Federated Query를 통해 직접 데이터소스에 연결하고, 조회하는 방법에 대해 알아보겠습니다.

단계 6 : Amazon Athena에서 Data Source 생성

이번 단계에서는 MongoDB를 위한 Data Source를 Amazon Athena에서 생성합니다.

[Amazon Athena Console -> Data sources -> Create data source]에서 데이터소스를 생성합니다. Amazon Athena에서 연결할 수 있는 데이터소스로 30개 이상을 제공하고 있습니다. 여기서는 MongoDB에 연결하기 위해 ‘Amazon DocumentDB’를 선택하고 ‘Next’를 클릭합니다.

Data source details에서 Data source name에 임의의 이름을 지정합니다. (예, mongodb)

Connection details에서 “Create Lambda function” 버튼을 클릭하여 데이터소스 연결을 위한 Lambda 함수를 생성합니다. AWS Lambda Application 화면의 Application settings 부분에서 아래와 같이 입력합니다.

이름
Application name AthenaMongoDBConnector
SecretNameOrPrefix mongodb-*
SpillBucket

현재 계정에서 소유한 임의의 S3 버킷명

(예, amazon-athena-query-results-xxx)

AthenaCatalogName mongodb
DocDBConnectionString mongodb://admin:1234@<EC2 Private IP>:27017/labdb
SecurityGroupIds MongoDB EC2에 지정된 Security Group
SubnetIds MongoDB EC2에 지정된 SubnetID

LambdaMemory와 LambdaTimeout 값은 사용자 요구사항에 맞게 변경할 수 있습니다.

위와 같이 값을 입력한 후, ‘Deploy’ 버튼을 눌러 Lambda Application을 생성합니다.

Deploy가 완료된 후, 이전 화면인 “Create data sources”에서 새로고침 버튼을 누르면, 이전에 생성된 Lambda 함수를 선택할 수 있습니다. ‘Next’를 클릭합니다.

마지막 단계에서 “Create data source” 버튼을 눌러 데이터소스를 생성합니다. 데이터소스가 성공적으로 생성되면, 아래 그림과 같이 Lambda 함수가 MongoDB의 데이터베이스 “labdb”에 연결됩니다.

단계 7 : Amazon Athena Federated Query 실행

이제 Amazon Athena Query Editor에서 <Data source>.<Database>.<Table> 구문으로 MongoDB 데이터소스를 직접 조회할 수 있습니다.

리소스 정리하기

  1. MongoDB를 설치한 EC2를 선택하고 ‘Terminate’합니다.
  2. AWS Glue에서 생성한 ‘Crawlers’, ‘Connections’, ‘Visual ETL’, ‘Databases’를 삭제합니다.
  3. Amazon Athena에서 생성한 ‘Data sources’를 삭제합니다.
  4. 실습에 사용한 Amazon S3 혹은 특정 접두사를 삭제합니다.

결론

지금까지 MongoDB의 데이터를 분석하기 위한 방법으로 1. AWS Glue를 통해 데이터 레이크 (Amazon S3)에 저장한 후에 분석하는 방법과 2. Amazon Athena Federated Query를 통해 데이터 레이크에 저장하지 않고 즉시 조회하는 방법에 대해 소개했습니다. 이 두가지 방법은 아래와 같이 비교 항목에서 차이가 있으므로, 여러분의 데이터 분석 패턴에 따라 알맞은 방법을 선택하여 비즈니스 요구사항에 맞게 AWS 분석 서비스를 활용할 수 있습니다.

항목 AWS Glue ETL을 통한 분석 Amazon Athena Federated Query를 통한 분석
데이터 조회 시간 ETL에 따른 시간 지연 즉시 조회
데이터 저장 S3에 데이터 저장 별도 데이터 저장 불필요
소요 비용 Glue 비용, S3 저장 비용, Athena 스캔 비용 Athena 스캔 비용, Lambda 호출 비용
분석 패턴 배치 분석 실시간 분석
활용 사례

소스 데이터의 원본 저장이 필요한 경우

소스 테이터의 복잡한 변환이 필요한 경우

소스 데이터의 변환없이 다른 데이터와 즉시 조인이 필요한 경우

TaeHoon Kyeong

TaeHoon Kyeong

Kyeong Tae-Hoon (Nick) is a solutions architect at AWS responsible for optimizing architecture for media and entertainment customers to achieve their desired business results. 경태훈(Nick) 솔루션즈 아키텍트는 미디어 및 엔터테인먼트 고객이 원하는 비즈니스 결과를 얻을 수 있도록 아키텍처를 최적화하는 역할을 담당하고 있습니다.

Incheol Roh

Incheol Roh

Incheol Roh is a Solutions Architect based in Seoul. With database and data analytics experience in various industries, he has been working with his customers to build efficient architectures to help them achieve data-driven business outcomes. 노인철 솔루션즈 아키텍트는 다양한 산업 군에서 데이터베이스와 데이터 분석 경험을 바탕으로 고객이 데이터 기반의 비즈니스 성과를 달성할 수 있도록 고객과 함께 효율적인 아키텍처를 구성하는 역할을 수행하고 있습니다.