Comment on page
1.1 데이터 파이프라인
Data Infrastructure
이번 챕터에서는 데이터 파이프라인의 구성요소에 대해 이야기 합니다. 가상의 작은 회사 우동마켓을 가정하고, 우동마켓이 성장하면서 마주치는 문제들을 데이터 인프라 컴포넌트와 함께 하나씩 알아봅니다.
현실 세계에 존재하는 회사와는 관련이 없습니다.
가상의 스타트업 우동마켓은 글로벌한 우동 서비스를 제공하려는 야욕을 가지고 있습니다.
- 면과 토핑, 국물 및 송송썰린 파와 같은 재료의 직판매 부터 시작해서
- 수 많은 우동 매니아를 위한 Personalized 되고 Awesome 한 딥러닝 우동 추천 서비스와
- 비행기 입국장에서 사용자를 노려 국내 유수의 우동집을 홍보하는 실시간 타게팅까지를 목표로 하고 있습니다.
이른바 "우동 커머스" 를 제공하려는, AWS 를 사용하는 초기 단계의 우동 스타트업의 데이터 파이프라인이 어떨지 논의해 봅시다.
초기 단계의 스타트업에는 데이터 엔지니어가 필요 없을지 모릅니다.
- 아직은 기능을 만드는데 바빠 상품 검색은 MySQL 에서 LIKE 검색을
- 추천 상품은 단순히 판매건 기준으로 정렬해 Top 10 만 내보내고 있습니다
[그림] 우동마켓 초기 인프라 (AWS VPC 내 RDS, EC, EC2 정도)
이때 기획자로부터 첫 번째 데이터 요건이 들어옵 니다.
- 데이터를 보고 싶다. 실시간이면 좋겠다
- 개발자들은 기능 만드는데 바쁘니 쿼리보다는 UI 를 통해 이런저런 데이터를 보거나 가공할 수 있어야 한다
가장 쉬운 방법은 실제 서비스 DB 에 붙어 데이터를 보는것입니다. 물론 당연히 (...) 그러면 안됩니다. 따라서 AWS RDS 에 Read Replica 를 이용하면 (데이터가 적은 우동마켓의 경우에는) 아주 약간의 지연이 있을뿐, 실제 서비스 DB 를 실시간 / 비동기로 복제해 데이터를 확인할 수 있습니다.

AWS RDS 읽기 전용 복제본 (https://aws.amazon.com/ko/rds/features/read-replicas)
- AWS Aurora 는 최대 15개의 Read Replica 를 지원합니다.
- AWS RDS 는 최대 5개의 Read Replica 를 지원합니다.
Aurora 와 RDS 는 내부적인 구조가 다릅니다. 다음 그림을 통해 동작 방식이 어떻게 다를지 추론해볼 수 있습니다.
이렇게 추가된 읽기 전용 DB 에 우동마켓 내부 직원들이 사용하기 편리한 데이터 탐색 도구를 선정해 붙일 수 있습니다.
도구는 회사 내부 사용자들의 생산성을 결정하므로, 적절한 도구를 선택해 제공할 수 있습니다.
일반적으로는 여러 종류의 DB (RDB, NoSQL) 는 물론 구글 시트 등 다양한 시스템과 연동되고 다른 사람이 작성한 쿼리 / 대시보드 등을 쉽게 검색하고 재활용할 수 있으며 운영성으로 대용량 CSV 다운로드가 가능한 Redash 가 많이 쓰이는 편입니다.
필요하다면 여러 도구를 제공하는 것도 물론 가능합니다. 다만 늘 그렇듯이, 해당 시스템을 운영하는 엔지니어의 노동 비용 그리고 머신 값으로 지불해야 할 물리 비용, 사내 사용자들의 학습 부하 및 데이터 활용의 집중이 아니라 분산 (다양한 도구 사용시) 이 발생할 수 있으므로 적절한 한도 내에서 몇몇 도구를 사용할지 결정하면 됩니다.
여러분이 도입하는 모든 데이터 도구는, 데이터로 일하는 회사 구성원 전부의 생산성에 영향을 미칩니다. 따라서 단순히 '이 기능이 좋아' 보다는 다음 내용들을 고려하여 제공해야 합니다.
- 여러 시스템과의 연동
- 코드 수정 및 확장 가능성
- 다양한 활용처: 대용량 CSV 데이터 다운로드 / 데이터 탐색 / 대시보드 등

데이터 탐색 도구를 DB 에 붙이면 이제 준 실시간으로 (Read Replica 의 지연을 제외하면) 서비스의 데이터를 볼 수 있습니다. 그러나 몇 가지 제한점이 존재합니다.
- 우동마켓은 그 자그마한 서비스 규모에 걸맞지 않게, MSA 를 하느라 DB 를 여러개 사용합니다. DB 가 여러개이므로 DB 내에서 Join 이 불가능합니다.
- 우동마켓은 RDB 이외에도 Elasticache (AWS managed ElasticSearch) 와 AWS OpenSearch (AWS 관리형 ElasticSearch) 를 사용합니다.
- 우동마켓의 서비스 DB 인 RDB 는 사용할 수 있는 Query 문법이 별로 신통치 않습니다. MySQL 특정 버전 이후부터 With Clause Window Function, JSON Function, Spatial Function 이 지원됩니다. 다만 그정도이지, Unnest 등 다양한 패턴을 일관되고 사용성 높은 함수로 지원하지 못합니다. 게다가 문법이 다른 MySQL 이외의 DB 를 인수합병, 너와 내가 사이가 나빠 시작하는 MSA 등으로 도입하는 순간 쿼리 사용자는 지옥으로 가게됩니다.
따라서 다음의 요구사항을 충족하는 범용, 대규모 처리 쿼리 엔진이 필요합니다.
- 다양한 스토리지 (RDB, NoSQL) 를 지원하고 서로 다른 스토리지의 데이터를 Join 할 수 있습니다.
- 스토리지에 상관 없이 일관되고 사용성이 편리한 SQL 문법을 제공합니다.
- 대규모 데이터를 메모리에서 빠르게 처리할 수 있습니다.
Apache Presto 는 이런 용도를 위해 설계된 범용, 대규모 쿼리 엔진입니다. AWS 에서는 EMR 위에서 편리하게 사용할수 있습니다. 만약 직접 운영하지 않는다면 AWS Athena 와 같은 관리형 서비스를 사용할 수 있습니다. (Athena 는 Presto 를 기반으로 만들어졌습니다.)

Presto 를 이용하면 다양한 커넥터를 붙여 SQL 을 이용해 Join 하고 가공할 수 있습니다. 예를 들어, 아래의 Presto 쿼리는 RDB 로는 처리하기 힘든 대량의 데이터를 보관하는 Hive (엄밀히는 S3 또는 HDFS) 와 실제 서비스에 내보내는 RDB Replica 내의 메타값을 Join 해 집계하는, 서로 다른 두 저장소를 Presto 내에서 묶어 컴퓨팅하는 예제입니다.
SELECT AIRPORT.name as airport_name, count(*) as flight_count
FROM hive.flight_history.flights FLIGHT
JOIN mysql.flight_meta.airport AIRPORT
ON FLIGHT.code = AIRPORT.airport_code
GROUP BY AIRPORT.name
ORDER BY flight_count
LIMIT 100
Presto 는 JDBC / ODBC 를 통해 사용이 가능하며, HTTP API 로도 쿼리를 실행할 수 있습니다. 위 Presto 설명에 나온 사진과 같이 대부분의 오픈소스 / 상용 데이터 분석 도구는 전부 사용이 가능하며, 필요시 내부에서 JDBC / HTTP 등의 프로토콜을 이용해 직접 인하우스 분석 도구를 개발하는 것도 가능합니다.

이제 데이터를 '보는 것' 은 가능해 졌습니다. 원하는 스토리지에서 쿼리해 대시보드를 만들수도 있고, 마케팅이나 CS 대응과 같은 필요한 데이터도 CSV 로 추출하는것이 가능합니다.

Redash Query Parameter (https://redash.io/help/user-guide/querying/query-parameters)
그러나 여전히 몇 가지 문제가 있습니다.
- Read Replica 를 통해 (준) 실 시간으로 데이터를 확인하는건 좋은 일이지만, 컴퓨팅이 스토리지에 의존합니다. 다시 말해, Read Replica 사이즈에 따라 스캔 속도가 좌우됩니다.
- Presto 가 Predicate Push Down 지원하지 않는 스토리지거나, 특정 Presto SQL 구문의 경우에만 Push Down 이 동작하지 않을수도 있습니다. Push Down 을 이용하면, 필터링을 데이터를 가져온 이후에 메모리에서 수행하는 것이 아니라 데이터를 가져오는 시점부터 저장소가 제공하는 필터링을 사용할 수 있기 때문에 훨씬 효율적입니다.
- 스토리지 종류에 따라 당장 Read Replica 를 추가하기 어려운 경우도 있습니다. 관리형 서비스인 AWS RDS, Aurora, Elasticache (Redis, 모드에 따라) 는 읽기 전용 Endpoint 를 지원하지만 다른 저장소는 그렇지 않을수도 있습니다.
또한 RDB 의 데이터는 무한히 적재할 수 없습니다. 주문, 예약 등 비즈니스 크리티컬한 데이터가 아니라 단순 History 성 테이블의 경우에는 어느 순간에는 특정 시점을 기준으로 과거 데이터는 서비스 테이블에서 분리해 보존처리 해야할 수 있습니다.
이런 이유로 인해 '주기적으로' 데이터를 대량의 컴퓨팅을 수행할 수 있는 저장소로 옮겨오는 작업이 필요하게 됩니다.
- RDB, NoSQL (Redis, ElasticSearch 등) 에서 데이터를 읽어 AWS S3 / HDFS 등에 저장합니다.
- HDFS 는 별도로 Hadoop 을 운영해야 하므로 특정 상황이 아니라면 적은 규모에서는 S3 에 데이터를 적재합니다.
- AWS LB Acess Log / RDS Export 등 AWS 서비스는 S3 에 데이터를 저장하는 것을 지원합니다.
- AWS S3 는 데이터를 저장하고 데이터를 읽는 용도 이외에도 Storage Class 를 통해 사용이 덜 되는 데이터는 Tier 를 낮추어 비용을 절감하는 등의 다양한 기능을 제공합니다.
- 컬럼을 중심으로 데이터를 저장하는 Columnar Format 입니다. 대부분의 데이터 조회 및 가공시에는 전체 컬럼을 접근하지 않고 (
SELECT *
), 일부 컬럼만을 사용하므로 (SELECT airport_name, airport_code
) 데이터를 읽어오는 시점부터 필요한 컬럼만 읽어올 수 있습니다. - 컬럼 중심으로 데이터를 저장하므로 성별이나 도시 등의 ENUM 값처럼 Cardinality 가 비교적 낮은 값들의 데이터 사이즈를 많이 줄일 수 있습니다. (e.g, MALE = 1, FEMALE = 2 로 저장) 또한 File 자체에서 타입과 스키마를 지원하므로 파일을 읽는 시점부터 마치 RDB 와 같은 저장소처럼 데이터를 필터링해 가져올 수 있습니다.
- Snappy 등과 같은 압축 알고리즘과 같이 사용하면, 파일 사이즈를 굉장히 많이 줄일 수 있습니다.
다음 사진은 AWS RDS 또는 AWS Aurora 에서 S3 로 DB 스냅샷을 내보내는 걸 도식화 한 그림입니다.
한 가지 고민해보아야 할 점이 있습니다. AWS RDS / Aurora 를 S3 로 Snapshot 내보내는 AWS CLI API 를 살펴보면 어떤 인스턴스 내 DB / Table 를 뽑아낼지를 결정할 수 있습니다.
start-export-task
--export-task-identifier <value>
--source-arn <value>
--s3-bucket-name <value>
--iam-role-arn <value>
--kms-key-id <value>
[--s3-prefix <value>]
[--export-only <value>]
[--cli-input-json <value>]
[--generate-cli-skeleton <value>]
CLI 옵션을 살펴보면
- 1.어떤 Column 만 추출할지 결정할 수 없습니다. 개인정보나 민감한 정보가 들어있는 컬럼이 S3 로 Export 된다면, Network 기반이 아니라 IAM 단위로 관리되는 S3 에서는 접근 통제가 충분히 되지 않을 경우 문제가 될 수 있습니다.
- 2.Column 이름 변경이나 값을 변경할 수 없습니다. 일부 정보는 마스킹 하거나, 필요에 따라 타입과 값을 변경할 필요가 있는데, Snapshot S3 Export 기능으로는 불가능합니다.
- 3.타입은 특히나 중요한데, 저장된 데이터는 MySQL 등 RDB 타입에서 Parquet 타입으로 변경되고, 이렇게 만들어진 Parquet 파일은 Presto, Hive, Spark 등 다양한 시스템에서 호환되는 타입이어야만 합니다.
- 4.가장 중요한, 실행되는 컴퓨팅 리소스를 조절할 수 없습니다. 필요에 따라 크기가 큰 테이블은 컴퓨팅 리소스를 더 부어 넣어 원하는 시점에 빠르게 끝낼 수 있어야 하는데, Snapshot S3 Export 는 불가능합니다.
따라서 RDS Snapshot S3 Export 기능은 민감정보가 없는 DB 와 Table 의 백업을 단순히 보관하는 용도에 가깝다는것을 알 수 있습니다.