도구 선택 및 아키텍처
Pika는 기존 AWS 크레딧을 활용하여 CloudFront를 CDN으로, S3를 스토리지로 사용했습니다. 이미지 처리 파이프라인의 핵심은 John Nunemaker의 추천을 받은 Imgproxy입니다. Imgproxy는 이미지 리사이징, Exif 데이터 제거, 압축 등의 작업을 담당합니다. 전체적인 이미지 요청 흐름은 다음과 같습니다:
-
사용자 요청: 브라우저가 캐시되지 않은 이미지를 요청합니다.
-
CloudFront: 리전 노드에서 요청을 받아 캐시 여부를 확인합니다.
-
CloudFront Origin Shield: 캐시 미스 시 Origin Shield를 통해 Imgproxy로 요청을 전달합니다.
-
Imgproxy: S3에서 원본 이미지를 가져와 필요한 처리(Exif 제거, 크기 조정, 압축)를 수행합니다.
-
S3: 원본 이미지를 저장하는 역할을 합니다.
Imgproxy 설정
Imgproxy는 Render.com에 Docker 컨테이너로 배포되며, 환경 변수를 통해 광범위하게 설정됩니다. 주요 설정은 다음과 같습니다:
-
IMGPROXY_TTL: 1년 (30758400초)으로 설정하여 캐시 효율을 극대화합니다. -
IMGPROXY_FALLBACK_IMAGE_DATA: 1x1 투명 GIF를 대체 이미지로 사용합니다. -
IMGPROXY_FORMAT_QUALITY: JPEG=90, PNG=90, WebP=79 등으로 압축 품질을 설정하여 과도한 압축을 방지합니다. -
IMGPROXY_STRIP_COLOR_PROFILE:false로 설정하여 색상 정확도를 유지합니다. -
IMGPROXY_MAX_SRC_RESOLUTION: 이미지 폭탄 공격을 방지하기 위해 최대 원본 해상도를 제한합니다. -
IMGPROXY_USE_S3:true로 설정하여 Imgproxy가 S3에서 이미지를 직접 가져오도록 합니다. 이는 Rails 서버를 거치지 않아 효율적이지만, URL에 확장자가 없는 문제가 발생할 수 있습니다. -
IMGPROXY_KEY,IMGPROXY_SALT: 보안을 위한 필수 설정입니다.
CloudFront 및 DNS 설정
CloudFront는 cdn.u.pika.page 도메인으로 설정되었으며, 사용자 지정 SSL 인증서가 적용되었습니다. Origin은 u.pika.page로 설정된 Imgproxy 인스턴스를 가리키며, Origin Shield는 활성화되어 캐시 효율을 높입니다. 동작(Behaviors) 설정에서는 객체 자동 압축을 비활성화하고, GET, HEAD, OPTIONS 메서드를 허용하며, 레거시 캐시 설정을 사용합니다. DNS는 cdn.u.pika.page를 CloudFront 배포 도메인으로, u.pika.page를 Imgproxy Origin으로 연결합니다.
Rails 애플리케이션 통합
Pika는 이미지를 S3에 업로드하도록 설정되어 있습니다. 이미지 URL 생성에는 imgproxy Gem이 사용됩니다. imgproxy.yml 설정 파일에서 IMGPROXY_FREE_CDN 환경 변수를 CloudFront CDN URL로 지정하고, 프로덕션 환경에서는 use_s3_urls: true를 설정하여 Imgproxy가 S3에서 직접 이미지를 가져오도록 합니다.
-
아바타 URL 예시:
User모델에서avatar.imgproxy_url을 사용하여 다양한 크기의 아바타 URL을 쉽게 생성합니다. -
리치 텍스트 이미지 처리:
_blob.html.erb파일에서 GIF 파일은 Imgproxy를 거치지 않고 직접 서빙하며, 다른 이미지는imgproxy?헬퍼 메서드를 통해 Imgproxy URL을 생성합니다. -
백그라운드 작업: 이미지 과부하를 방지하기 위해 새로운 게시물이 생성되거나 이미지가 편집될 때, 백그라운드 작업을 통해 CDN URL을 미리 쿼리하여 캐시를 워밍업합니다.
-
이미지 해상도 검증: 이미지 폭탄을 서버 단에서 방지하기 위해 Active Storage 첨부 파일의 해상도를 검증하는 유효성 검사 로직을 구현했습니다.
로컬 개발 환경
로컬 개발을 위해 Docker와 Procfile_imgproxy.dev를 사용하여 Imgproxy 인스턴스를 http://localhost:7777에서 실행할 수 있도록 설정했습니다. 이는 개발 환경에서 Imgproxy의 동작을 쉽게 테스트할 수 있게 합니다.