데이터 파이프라인

S3 업로드를 감지하여 EC2에서 자동 텍스처 변환

한 줄 요약

S3에 파일이 업로드되면 Lambda가 감지하여 EC2를 시작하고, Docker 컨테이너 안에서 3,561개 타일의 텍스처를 JPEG → KTX2로 변환한 뒤 자동 종료한다. 32 vCPU 인스턴스에서 8 worker 병렬 처리로 약 10분에 완료, 100% 변환 성공률을 달성했다.

왜 Lambda에서 직접 변환하지 않는가

AWS Lambda는 서버리스 함수로, 이벤트에 반응하여 코드를 실행하기에 적합하다. 그러나 텍스처 변환 작업에는 두 가지 근본적 제약이 있다:

시간 제한: Lambda의 최대 실행 시간은 15분이다. 3,561개의 b3dm 파일(2.6GB)을 변환하는 데는 이 시간으로 부족하다.

메모리 제한: Lambda의 최대 메모리는 10GB다. 대용량 3D 모델 파일을 메모리에 올려서 변환하기에는 제약이 크다.

대안 검토: 왜 EC2인가

Lambda에서 직접 변환이 불가능하다면, 별도의 컴퓨팅 리소스가 필요하다. AWS에서 이 역할을 할 수 있는 서비스 세 가지를 검토했다.

서비스장점단점우리 상황에서의 판단
AWS Batch다중 인스턴스 자동 오케스트레이션초기 설정 복잡, Job Queue/Compute Environment 구성 필요DevOps 인력이 없는 소규모 팀에서 설정·유지 부담이 과도
ECS Fargate서버리스, 인스턴스 관리 불필요동일 사양 대비 EC2보다 비용 20~30% 높음변환 빈도가 월 수십 회 수준이라 비용 차이가 누적됨
EC2비용 최저, 사양 자유 선택인스턴스 시작/종료를 직접 관리해야 함Lambda가 트리거하므로 관리 부담이 거의 없음

EC2를 선택한 핵심 근거는 "높은 사양을 짧게 돌리는 것이 낮은 사양을 오래 돌리는 것보다 총 비용이 적다"는 전략이다. 32 vCPU 인스턴스를 사용하면 CPU 코어 수만큼 병렬 처리가 가능하여, 3,561개 타일을 약 10분 만에 변환할 수 있었다.

다만, 변환 대상이 10만 개 이상으로 증가하면 단일 인스턴스의 한계에 부딪힌다. 그 시점에서는 AWS Batch로의 전환이 필요하다.

Docker 환경 구성

텍스처 변환 파이프라인은 여러 도구의 조합으로 동작한다:

  • gltf-transform CLI (v4): glTF/glb 파일의 텍스처를 KTX2로 변환하는 Node.js 기반 도구
  • KTX-Software (4.4.2): Khronos Group이 관리하는 공식 KTX2 인코더/디코더. 네이티브 바이너리

이 도구들의 실행 환경 의존성을 Docker 컨테이너로 패키징했다.

베이스 이미지: node:20-slim (~200MB)
  + gltf-transform CLI v4 (npm)
  + KTX-Software 4.4.2 (네이티브 바이너리)

node:20-slim을 선택한 이유: 세 가지 변형을 검토했다.

이미지크기특징판단
node:20~900MB전체 Debian OS불필요한 패키지 포함, 크기 과대
node:20-slim~200MB최소 Debianglibc 호환 유지 + 크기 최소화
node:20-alpine~130MBAlpine Linuxmusl libc 사용, KTX-Software 네이티브 바이너리 호환 문제

KTX-Software의 네이티브 바이너리가 glibc에 의존하므로, Alpine의 musl libc와 호환성 문제가 발생할 수 있었다. slim은 glibc 호환성을 유지하면서 크기를 최소화하는 균형점이었다.

아키텍처 구조

업로드 담당자: zip 파일을 S3에 업로드 (기존 워크플로우 변경 없음)
        ↓
S3: 업로드 이벤트 발생
        ↓
Lambda: S3 이벤트 감지 → EC2 인스턴스 시작 (트리거 역할만)
        ↓
EC2 (32 vCPU):
  1. S3에서 zip 다운로드
  2. 압축 해제
  3. Docker 컨테이너 내에서 JPEG → KTX2 변환 (8 worker 병렬)
  4. 변환 결과를 S3에 업로드
  5. 자동 종료

설계 원칙 세 가지:

Lambda는 트리거만 한다: Lambda의 코드는 EC2 인스턴스를 시작하는 API 호출 한 줄이다. 실행 시간은 수 초이므로 비용이 거의 발생하지 않는다.

업로드 담당자의 워크플로우는 변경되지 않는다: 담당자는 이전과 동일하게 zip 파일을 S3에 업로드하기만 하면 된다.

EC2는 작업 완료 후 자동 종료된다: 유휴 상태에서 비용이 발생하지 않는다. 사실상 서버리스에 가까운 비용 구조다.

파이프라인 처리 결과

지표
변환 대상3,561개 b3dm 파일 (2.6GB)
인스턴스 사양32 vCPU
병렬 워커 수8
총 변환 시간약 10분
변환 성공률100%

비용 구조:

  • Lambda: 월 수백 회 트리거 수준에서 프리 티어 범위 내
  • EC2: 변환 1회당 고사양 인스턴스 10분 사용 비용만 발생
  • S3: 저장 및 전송 비용

더 큰 규모에서는?

현재: 3,561개 타일, 단일 EC2(32 vCPU), 약 10분.

만약 타일이 10만 개 이상이라면:

  • EC2 단일 인스턴스 → AWS Batch (다중 인스턴스 오케스트레이션)
  • S3 이벤트 폭주 → SQS 큐 중간 배치 (Lambda 동시 실행 1,000개 제한 우회)
  • 비용 구조 전환 → 스팟 인스턴스 (최대 90% 절감, 중단 허용 배치 작업에 적합)

이 확장 경로를 미리 인식하고 있되, 현재 규모에서는 단일 EC2가 가장 단순하고 비용 효율적인 선택이다.

이 경험에서 추출한 원칙

  1. "서버리스의 한계"가 곧 "서버가 필요한 이유"다. Lambda의 시간·메모리 제한은 설계상 의도된 것이다. Lambda를 억지로 쓰는 것보다, Lambda는 트리거로만 쓰고 실제 작업은 적합한 도구(EC2)에 맡기는 것이 올바른 아키텍처다.

  2. 고사양 × 짧은 시간이 저사양 × 긴 시간보다 싸다. 클라우드 비용은 (인스턴스 단가 × 실행 시간)이다. CPU 병렬 처리가 가능한 작업에서는 코어 수를 늘리는 것이 거의 선형적으로 시간을 줄여준다.

  3. "환경을 코드로 관리한다"가 Docker의 본질이다. Dockerfile 하나에 모든 환경 설정이 선언적으로 정의된다. 서버가 바뀌어도 동일한 환경이 재현된다.

S3 업로드 이벤트를 Lambda로 트리거하는 것은 AWS 콘솔에서 10분이면 설정할 수 있다. 반복 작업을 자동화할 기회가 있다면 시도해 보라.

S3 업로드를 감지하여 EC2에서 자동 텍스처 변환

데이터 파이프라인
전체 노드