애셋 파이프라인의 핵심 기능과 진화
과거 웹 개발은 애셋을 수동으로 로드하는 방식이었으며, 이는 HTTP/1의 한계로 인해 성능 문제를 야기했습니다. 애셋 파이프라인은 이 문제를 해결하기 위해 등장했습니다.
- 번들링: 다수의 애셋 파일을 하나로 합쳐 HTTP 요청 수를 줄였습니다 (Gulp, Grunt 등 사용).
- 핑거프린팅: 애셋 내용 기반의 고유 해시를 파일 이름에 추가하여 효율적인 캐시 무효화 및 장기 캐싱을 가능하게 했습니다.
- 트랜스파일링: SAS를 CSS로, CoffeeScript를 JavaScript로 변환하거나, 벤더 프리픽스 적용, 이미지 최적화 등의 작업을 수행했습니다 (Sprockets의 주요 역할).
현재 Rails의 애셋 관리 도구
HTTP/2의 등장과 CSS, JavaScript 언어 자체의 발전으로 애셋 관리 패러다임이 변화했습니다.
- Propshaft: Sprockets의 경량 대체재로, 핑거프린팅, 개발 서버, 최소한의 트랜스파일링, 로드 경로 설정에 집중합니다.
- Import Maps: 브라우저가 JavaScript 모듈을 직접 가져오도록 지시하는 기술로, Propshaft와 함께 작동하여 빌드 단계 없이 모듈 사용을 지원합니다.
- JS/CSS Bundling Gem: 기존의 전문 번들링 도구(Tailwind, ESBuild 등)를 Rails에 통합하여 Sprockets의 번들링 및 트랜스파일링 기능을 대체합니다.
- Vit Rails: 번들링, 트랜스파일링, 프로덕션 빌드, 개발 서버 등을 포괄하는 강력하고 우아한 솔루션입니다.
Rails Gem 개발자를 위한 애셋 배포 전략
Gem 개발자는 다양한 사용자 앱 환경에 맞춰 애셋을 효과적으로 배포해야 합니다.
- Import Maps 활용: Gem 내부에
import_map.rb
를 정의하고 Propshaft를 통해 애셋을 제공하여 사용자 앱의 빌드 단계 없이 JavaScript를 사용할 수 있게 합니다. - npm 패키지 처리:
- Gem 내부에 번들링:
js-import-map-rails
를 사용하여 npm 종속성을 Gem에 포함시키고 Propshaft가 이를 감시하도록 합니다. - 사용자에게 번들링 지시: 사용자 앱이 직접 npm 종속성을 관리하도록 안내하여 버전 제어 권한을 사용자에게 부여합니다.
- Gem 내부에 번들링:
- Gem 내부 빌드 단계: Gem 자체에 JS Bundling을 추가하여 TypeScript 등 고급 기능을 사용하고, 빌드된 애셋을 Propshaft가 감시하는 디렉토리에 저장합니다.
- JS Bundling 앱 지원 (npm 패키지 생성): 외부 빌드 도구(ESBuild 등)를 사용하는 앱을 위해 Gem의 애셋을 npm 패키지로 만들어
npm publish
하고, 사용자가yarn add
로 설치하도록 하는 것이 가장 일반적인 방법입니다.
비정형적 접근 방식 (참고용)
- Rake 태스크를 통한 파일 복사/심볼릭 링크: 애셋 동기화 문제가 발생할 수 있습니다.
- AVO의 플러그인 시스템: 사용자에게 빌드 단계를 요구하지 않으면서 Gem의 JavaScript와 Stimulus 컨트롤러를 동적으로 주입하고 등록하는 정교한 방법을 사용합니다.
- 미들웨어를 통한 애셋 제공: 초기 AVO는 사용자 빌드 파이프라인에 영향을 주지 않기 위해 미들웨어를 활용하여 컴파일된 애셋을
public/avo_assets
경로로 노출했습니다. - CSS 관리: Propshaft는
stylesheet_link_tag
와url()
함수를 통해 CSS 파일 및 핑거프린팅된 애셋을 쉽게 관리할 수 있도록 합니다.