레일스 3.1 Asset Pipeline 들여다보기 by sjoonk

조만간 출시될 레일스 3.1 버전에는 에셋 파이프라인(asset pipeline)이 탑재될 예정입니다. 에셋 파이프라인(이하 'AP')이란 한마디로 웹 애플리케이션의 프론트엔드에서 사용되는 각종 자원(이미지 파일이나 CSS 또는 자바스크립트 파일과 같은)을 한 곳에 모아서 처리하고 제공한다는 발상입니다. 게임 개발에서 흔히 말하는 바로 그 파이프라인 개념을 웹 개발에도 도입했다고 보면 되겠습니다.


물론 지금까지 레일스에 이런 자원 파일의 처리와 관련된 기능이 없었던 것은 아니지만, 기본적으로 자원 파일은 애플리케이션 개발의 입장에서 보면 '별로 중요하지 않은' 부분에 속했던 것이 사실입니다. 따라서 이번에 AP가 프레임워크 속으로 들어왔다는 사실은 그만큼 웹 개발에 있어 프론트엔드 개발의 중요성이 높아졌음을 반영합니다. 예전에는 그저 정적인(static) 자원에 불과했던 자바스크립트나 CSS 가 HTML5나 CSS3, 하이브리드 웹앱 개발 등과 맞물려 이제는 그야말로 웹 개발의 중심으로 떠오르고 있고, 레일스 팀 역시 이런 흐름을 놓치지 않고 과감하게 프레임워크 속에 집어 넣는 시도를 한 것입니다. 조금 더 자세한 설명은 레일스 창시자인 DHH가 지난 RailsConf 2011에서 했던 키노트 연설을 참고하면 좋을 것 같습니다.


이미 AP가 무엇이며 어떻게 사용하는지에 대해서는 자료들이 많이 나와 있기에 이 글에서는 간략히 요약만 해 보겠습니다 (개발자 관점입니다).


  • 자원 파일들을 놓는 위치가 변경됩니다. 예전에는 public 디렉터리 아래의 images, javascripts, stylesheets 디렉터리 속에 각각 이미지와 자바스크립트, 그리고 CSS 파일들을 두었는데, 이제는 app/assets 디렉터리, 또는 lib/assets 이나 vendor/assets 디렉터리 아래에 자원 파일을 놓게 됩니다.

  • 이렇게 놓인 자원들은 모두 /assets 라는 단일 URL로 접근하게 됩니다. 따라서 예를 들어 hello.js 라는 자바스크립트 파일을 app/assets/javascripts 디렉터리에 두었다면, 브라우저에서는 /assets/hello.js 와 같이 접근 가능합니다.

  • 모든 자바스크립트와 CSS 자원 파일들은 자동으로 합쳐지고 코드 최소화 및 압축이 이루어진 상태로 제공됩니다. 이를 위해 내부적으로 레일스는 Sprockets라는 에셋 패키징 도구(asset packager)를 사용합니다.

  • CSS 대신 SASS/SCSS를, 그리고 자바스크립트 대신 CoffeeScript를 사용할 수 있으며, SASSCoffeeScript로 작성된 파일은 자동으로 각각 CSS와 자바스크립트 파일로 컴파일되어 마찬가지로 에셋 파이프라인을 통해 제공됩니다. CSS 대신 SASS를, 그리고 자바스크립트 대신 CoffeeScript 를 쓰게 되면 프론트엔드 개발의 생산성이 향상됩니다.

  • 프로덕션 환경에서는 이런 자원 파일들을 정적인 파일로 생성해서 웹 서버나 CDN에 둘 수 있도록 하고 있습니다.

개발자 입장에서는, 얼핏 보기에 그저 자원 파일을 두는 위치만 바꿔주면 되는 수준의 사소한 변화이지만, 이 "사소한 변화"의 밑바닥에는 레일스의 "Fast by default" 전략이 반영되어 있습니다. 바로 웹 개발의 생산성을 높이자는 것이죠.


그럼 이제 실제로 이 AP가 어떤 메커니즘으로 작동하는지 확인하기 위해 레일스 소스코드 속으로 한번 들어가 보겠습니다. ActionPack 부터 시작해 보겠습니다. actionpack 속엔 레일스 프레임워크에 AP 기능을 추가하는 sprockts/railtie 가 정의되어 있습니다. (모든 설명은 rails 3.1.0-rc6 을 기반으로 합니다)



이 코드는 레일스 애플리케이션이 로드될 때 AP를 초기화하는 부분에 해당됩니다. (이글루스 블로그가 코드 내장을 허용하지 않기 때문에 어쩔 수 없이 스크린샷으로 대신합니다) 여기서 보면 app.assets 를 할당하는 부분이 보이는데, 바로 이 부분이 에셋 파이프라인을 설정하고 있는 부분입니다. 여기 나와 있는 Sprockets::Environment 객체가 바로 AP인 셈입니다.


또한 에셋의 캐시 저장소(cache_store)를 설정하는 부분도 보입니다. 별도의 캐시 저장소를 지정하지 않으면 레일스의 디폴트 캐시 저장소인 ActiveSupport::Cache::FileStore를 사용하여 레일스 애플리케이션의 tmp/cache/assets 디렉터리 아래에 모든 에셋의 캐시를 저장합니다.


코드를 조금 더 읽다 보면 다음과 같은 부분이 나옵니다. 레일스 애플리케이션의 초기화의 끝자락에서 호출되는 콜백 루틴입니다.



AP의 경로를 설정하고 각종 자원별 압축 도구(compressor)를 설정한 다음 라우터에 AP를 마운트(mount) 시키고 있습니다. 코드에 나와 있는 mount app.assets => config.assets.prefix 에 의해 이제 모든 /assets URL 호출은 앞서 설정한 에셋 파이프라인 객체인 Sprockets::Environment 가 받아서 처리하게 됩니다.


그렇다면 이 Sprockets::Environment는 과연 무엇일까요? 예상했겠지만, 다름아닌 rack middleware 입니다. 따라서 /assets 로 시작하는 URL 호출이 들어 오면 바로 이 미들웨어에서 웹 요청을 처리하게 됩니다. 코드는 sprockets/server 이며, rack 서버에 의해 호출될 call() 메서드는 다음과 같습니다. 에셋을 찾아(asset_find) 그 에셋의 내용을 응답으로 반환합니다.



지금까지의 내용만으로 다음과 같은 몇 가지 AP의 내부 메커니즘을 확인할 수 있습니다.


  1. /assets 으로 시작하는 모든 웹 요청은 rack 미들웨어인 Sprockets::Environment 가 받아서 처리합니다.
  2. 이 때 Sprockets는 자원 파일들을 묶고, 최소화시키고, 압축하고, SASS나 CoffeeScript를 pre-compile 하는 일을 담당합니다.
  3. development 모드에서 파일들은 기본적으로 tmp/cache/assets 디렉터리 아래에 캐시되어 제공됩니다.
  4. production  모드에서는 Sprockets::Index 라는 캐시된 Environment 가 사용되어 액세스 속도를 높여 줍니다.
이 모든 AP 기능들은 레일스 3.1부터는 디폴트로 켜져 있으며, 기능을 끄려면 애플리케이션의 config/appliction.rb 파일에서 config.assets.enabled = false 로 처리해 주면 됩니다. AP와 관련해서 더 자세한 내용은 다음 자료를 참고하시면 좋을 것입니다.

RailsCast #279 Understanding the Asset Pipeline
Rails Guide on Asset Pipeline
Sprockets 소스코드

덧글

  • andy_pe_kr 2011/08/25 00:45 # 삭제

    레일스 초보자로써 잘 보고 갑니다.
※ 이 포스트는 더 이상 덧글을 남길 수 없습니다.



Follow me on Twitter

Follow sjoonk on Twitter