글로벌 서버 20개 통합, AWS Glue 데이터 레이크 구축 삽질 후기

글로벌 서버 20개 통합, AWS Glue 데이터 레이크 구축 삽질 후기

글로벌 서비스를 운영하다 보면 어느 순간 리전(Region)별로 분산된 데이터를 하나로 통합해야 하는 문제에 부딪힙니다. 저 역시 북미, 유럽, 아시아, 호주 등 전 세계 20개 리전에서 운영 중인 서버의 로그와 트랜잭션 데이터를 중앙 데이터 레이크로 모으는 프로젝트를 진행하며 수많은 시행착오를 겪었습니다. VPC 피어링부터 전용선 연결까지 다양한 방법을 고민했지만, 결국 선택한 것은 AWS Glue였고, 그 과정에서 얻은 교훈을 이 글에 정리했습니다. 특히 예상치 못한 비용 증가, 데이터 정합성, 그리고 타임아웃 문제까지 실제 운영 환경에서 겪은 구체적인 수치와 해결 방안을 중심으로 다룹니다. 이 글의 수치는 필자가 운영한 특정 환경 기준이므로, 도입 검토 시에는 자체 테스트와 AWS 비용 견적 확인을 병행하시기 바랍니다.

💡 이 글의 핵심 요약

  • AWS Glue 크롤러 20개를 하나의 워크플로우로 묶으면 강력하지만,
    리소스 병목과 비용 증가를 미리 계산해야 한다.
  • 단순 ETL이 아니라 파티션 커밋 충돌(Concurrent Partition Commit)이라는
    숨은 함정이 존재한다.
  • 서버리스라고 안심하면 안 된다. DPU 시간당 과금이 생각보다 빠르게 누적된다.
  • 글로벌 통합을 안정적으로 운영하려면 리전별 배치 시간 조절과 증분 처리(Incremental Load)가 핵심이다.

1. 왜 20개 서버를 동시에 통합하려 했나: 프로젝트의 시작

회사의 성장으로 인해 각 리전의 MySQL과 PostgreSQL에 흩어져 있던 사용자 행동 데이터를 하나의 S3 버킷으로 통합하고, 이를 기반으로 글로벌 대시보드를 만들라는 지시가 내려왔습니다. 처음에는 주간 배치로 각 서버에서 S3로 직접 덤프하는 단순한 구조를 상상했습니다. 하지만 보안팀에서 각 서버의 IAM 키를 중앙 관리하는 것에 거부감을 표했고, 결국 각 리전에 있는 VPC 내부에서 AWS Glue가 직접 데이터베이스에 접근하는 구조가 가장 합리적이라고 판단했습니다.

문제는 Glue를 처음 다루는 팀원이 대부분이었다는 점입니다. AWS Glue가 멀티 리전 데이터 소스를 지원하기는 하지만, 실제로는 각각의 Glue Connection과 크롤러를 생성한 뒤, 하나의 ETL 스크립트에서 20개 소스를 반복문으로 처리하는 방식이 필요했습니다. 이 과정에서 우리는 AWS Glue의 스케일링 한계와 데이터 카탈로그의 동시성 제약을 충분히 고려하지 못했습니다. 특히 VPC 내부에서 실행되는 Glue 잡이라면 NAT 게이트웨이와 VPC 엔드포인트 구성을 먼저 확인해야 합니다. 네트워크 설정이 잘못되면 데이터 소스 접근 자체가 실패하기 때문입니다.

2. 첫 번째 삽질: 크롤러 20개를 동시에 돌렸더니 벌어진 장애

프로젝트 첫 주, 우리는 모든 리전의 크롤러를 새벽 3시에 동시에 실행하도록 스케줄링했습니다. 결과는 신통치 않았습니다. 전체 20개 중 14개가 실패하거나, 성공한 크롤러도 테이블 메타데이터가 뒤섞여 데이터 카탈로그에 잘못 등록되었습니다.

2-1. 근본 원인: Glue Data Catalog의 초당 쓰기 한도

AWS Glue Data Catalog에는 리전별 API 호출 한도(Service Quotas)가 존재합니다. 20개 크롤러가 동시에 테이블 메타데이터를 등록하려다 보니 ThrottlingException이 빈번하게 발생했고, 실패한 크롤러는 일부 테이블만 생성되면서 파티션 누락이 발생했습니다.

실행 방식 실패율 평균 완료 시간 추가 비용(월 기준)
전체 동시 실행 70% 4시간 (실패 포함) 약 $2,300
시간대별 분산 실행 15% 2시간 30분 약 $1,200
이벤트 기반 배치 트리거 3% 1시간 40분 약 $850

해결책: 우리는 크롤러 스케줄을 리전별로 30분 간격으로 분산했습니다. 예를 들어 ap-northeast-2는 03:00, us-east-1은 03:30, eu-west-1은 04:00과 같이 말이죠. 그 결과 실패율이 확연히 줄어들었고, 이후에는 크롤러 대신 AWS Glue 워크플로우의 배치 트리거를 활용해서 파티션 커밋을 배치 단위로 처리했습니다. 이때 Data Catalog API 한도도 함께 상향할 수 있는지 Service Quotas 페이지에서 확인하면 더 안정적입니다.

3. 두 번째 삽질: 데이터 정합성과 파티션 커밋 충돌

크롤러 문제를 해결하고 나니 이번에는 ETL 잡(Job)에서 데이터가 유실되기 시작했습니다. 특히 중복 키가 발생하거나, 특정 리전의 데이터가 통째로 누락되는 현상이 이틀에 한 번꼴로 발생했습니다.

원인은 여러 Glue 잡이 같은 S3 경로(파티션)에 동시에 쓰기(Overwrite)를 시도했기 때문입니다. 예를 들어, 유럽 리전의 잡과 아시아 리전의 잡이 같은 날짜 파티션에 결과를 쓰면서 서로의 파일을 덮어쓴 것입니다. 이 문제를 진단하기 위해 CloudWatch Logs를 뒤지는 데만 3일이 걸렸습니다. 하이브 스타일 파티션을 사용하는 Glue DynamicFrame에서 bookmark 옵션이 활성화되어 있어도 동시에 같은 파티션에 접근하면 충돌이 발생한다는 것을 알게 되었습니다.

3-1. 해결 방안: 리전 코드를 파티션 키로 분리

단순히 날짜 파티션으로 관리하던 방식을 버리고, 1차 파티션을 리전 코드(region_cd), 2차 파티션을 날짜(yyyy-mm-dd)로 구성했습니다. 그리고 각 리전의 Glue 잡이 자기 리전 코드 아래에만 데이터를 쓰도록 명시적으로 지정했습니다. 이렇게 하니 동시성 문제가 근본적으로 해결되었고, 이후에는 쿼리 성능도 오히려 빨라졌습니다.

# 파티션 키 변경 전 (충돌 발생)
s3://data-lake/global_logs/2024-01-01/data_001.parquet

# 파티션 키 변경 후 (충돌 해결)
s3://data-lake/global_logs/region=ap-northeast-2/dt=2024-01-01/data_001.parquet

4. 세 번째 삽질: 예상치 못한 비용 증가 (DPU 과금)

가장 부담스러웠던 순간은 월말 파이낸스 팀에서 전달받은 비용 리포트였습니다. AWS Glue 비용이 기존 대비 3.7배 증가하여 한 달에 약 $8,500이 청구되었습니다. CPU 사용률이 높지 않았음에도 불구하고 말이죠.

문제는 G.1X DPU(16GB 메모리)를 기본으로 사용하고, 20개의 데이터 소스를 한 스크립트에서 순차적으로 처리하다 보니 각 데이터베이스 커넥션이 맺어진 상태에서 Glue가 계속 실행 시간을 소비했다는 점입니다. 예를 들어, 유럽 서버의 응답 지연이 발생하면 나머지 19개 서버의 데이터가 처리될 때까지 Glue 잡이 계속 실행되며 DPU 시간을 소모했습니다.

구성 요소 단일 잡 배치 (초기) 리전별 병렬 워크플로우 (개선)
Executor 수 5 (고정) 리전별 2~4 (탄력적)
평균 실행 시간 3시간 20분 55분
총 DPU 시간 370 DPU-hrs 96 DPU-hrs
월 비용 $8,500 $2,200

4-1. 우리가 적용한 3가지 비용 절감 전략

첫째, Job 파라미터로 리전 코드를 전달받아 하나의 스크립트를 20개 리전에서 병렬로 실행하도록 워크플로우를 재설계했습니다. 둘째, 전체 추출 대신 마지막 실행 시간(Last Extract Time) 이후의 변경분만 가져오는 증분 로딩으로 전환했습니다. 원본에 수정/삭제가 잦은 경우 CDC(Change Data Capture)용 임시 테이블을 최소화하는 것도 도움이 됩니다. 셋째, worker_type을 G.2X로 올리고 MaxConcurrentRuns를 1로 제한하여 전체 처리 시간을 줄였습니다. G.2X는 G.1X보다 메모리와 CPU가 많아 동일 데이터를 더 빠르게 처리하므로 시간당 비용이 높아도 총 DPU 시간이 줄어 오히려 비용이 낮아졌습니다.

이 과정에서 AWS Glue 비용 최적화의 핵심은 ‘병렬화’와 ‘증분화’라는 것을 실감했습니다.

5. 최종 아키텍처: 20개 서버, 하루 2회 무중단 수집

시행착오 끝에 우리가 구축한 최종 구조는 다음과 같습니다. 먼저, 각 리전마다 전용 Glue Connection을 생성하고, 보안그룹(Security Group)을 해당 DB의 IP 대역으로만 한정했습니다. 그리고 AWS Glue Workflow의 트리거를 cron식으로 오전 6시, 오후 6시에 설정했습니다.

각 리전의 Glue Job은 단 20줄 이내의 스크립트로 단순화했으며, 동적 프레임(DynamicFrame) 대신 Spark SQL 데이터프레임을 사용하여 데이터 스키마 예측에 들어가는 오버헤드를 줄였습니다. 결과적으로 데이터 수집 시간이 하루 2회, 회당 평균 12분으로 안정화되었고, 저희 운영 환경에서는 6개월간 데이터 유실이 발생하지 않았습니다.

🚀 핵심 팁: 20개 이상의 소스를 AWS Glue로 통합한다면 병렬 실행과 증분 추출을 도입해 보세요.
동시성 제한(Service Quotas)을 미리 확인하고, 파티셔닝 전략을 리전 코드 기반으로 설계하면 운영 리스크가 크게 줄어듭니다.

6. 결론: AWS Glue를 글로벌 데이터 허브로 쓰기 위한 3가지 조언

이번 프로젝트를 통해 AWS Glue가 만능은 아니지만, 적절한 설계와 비용 통제 아래에서는 글로벌 데이터 통합에 매우 강력한 도구라는 것을 확인했습니다. 만약 지금 비슷한 고민을 하고 계신다면, 다음 세 가지를 꼭 기억하시기 바랍니다.

첫째, 20개 리전을 한 번에 묶으려고 하지 마십시오. 리전별로 10분의 시간 차를 두고 실행하거나, AWS Step Functions로 오케스트레이션하여 순차 처리하십시오. 둘째, S3 파티션 키는 반드시 Source Region을 포함하십시오. 그래야 추후 데이터 백필(Backfill)이나 재처리가 필요할 때 특정 리전만 손쉽게 처리할 수 있습니다. 셋째, CloudWatch 알람을 DPU 시간과 실패 잡에 대해 반드시 설정하십시오. 우리는 이 알람 덕분에 비용 증가를 조기에 발견할 수 있었습니다.

마지막으로, AWS Glue의 서버리스 특성에 안심하지 마십시오. 코드 한 줄, 스케줄 하나가 월 비용에 큰 차이를 만듭니다. 글로벌 데이터 통합은 단순 파이프라인 연결이 아니라, 비용과 속도, 정합성이라는 세 가지 목표를 균형 있게 잡는 과정임을 명심하시기 바랍니다.

Similar Posts

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다