Rake는 Ruby 생태계에서 가장 널리 사용되는 작업 실행기(task runner)입니다.
태스크(Task)란 무엇일까요?
대표적인 예시를 살펴보겠습니다.
- 데이터베이스 백업 생성
- 테스트 스위트 실행
- 통계 데이터 수집 및 리포트 작성
이런 작은 작업들은 Rake가 없다면 프로젝트 곳곳의 여러 파일에 흩어져 관리하기 어려워집니다.
Rake는 이러한 작업들에 대한 접근을 하나의 곳에서 중앙 집중식으로 관리해 줍니다.
또한 특정 패턴에 일치하는 파일이나 최근에 수정된 파일을 찾는 것처럼 반복적인 작업도 훨씬 쉽게 처리할 수 있게 해줍니다.
한 가지 더 주의할 점:
Rake와 Rack을 혼동하지 마세요. 이름은 비슷하지만 완전히 다른 도구입니다.
- Rake: 작업 실행기(task runner)
- Rack: Ruby 서버와 웹 프레임워크가 상호 운용되도록 돕는 인터페이스
그럼 이제 Rake를 좀 더 자세히 살펴보겠습니다!
누가 Rake를 사용할까?
바로 Rails입니다!
Rails로 개발을 해본 적이 있다면 rake db:migrate 명령어를 이미 접해봤을 겁니다.
rake routes 역시 마찬가지죠. 이것이 바로 Rake가 실제로 동작하는 모습입니다.
참고로 Rails 5.0 버전부터는 대부분의 rake 명령어를 rails 명령으로 대신 호출할 수 있습니다.
즉, rails db:migrate처럼 실행할 수 있지만, 실제 작업은 여전히 Rake가 수행하는 것입니다.
Rake 태스크 작성 방법
간단한 Rake 태스크 예시입니다.
desc "Print reminder about eating more fruit." task :apple do puts "Eat more apples!" end
이 코드는 Rakefile이라는 파일에 작성하거나, Rails 프로젝트라면 lib/tasks/apple.rake 경로에 저장하면 됩니다.
태스크를 실행하려면:
rake apple # "Eat more apples!"
태스크 안에는 일반 Ruby 코드를 자유롭게 작성할 수 있으며, Rake가 제공하는 유용한 메서드들도 활용할 수 있습니다.
예를 들면:
ruby— Ruby 파일 실행sh— 시스템 명령어 실행safe_ln— 파일 시스템에 심볼릭 링크 생성
Rake에는 FileUtils 모듈이 포함되어 있습니다.
따라서 cp로 파일을 복사하고, mkdir_p로 디렉터리를 생성하고, 심지어 chown으로 파일 소유권까지 변경할 수 있습니다.
예시를 살펴보겠습니다:
task :clean_cache do rm_r FileList["tmp/cache/*"] end
rm_r(재귀적 삭제)는 확인 절차 없이 파일을 삭제하므로 주의해서 사용해야 합니다. 확인 단계를 추가하고 싶다면 의존 태스크(dependent task)(본문 뒤에서 다룹니다)를 추가하고, 계속 진행하지 않으려는 경우 예외를 발생시키는 방식으로 구현할 수 있습니다.
다른 디렉터리에서 Rake 명령 실행하기
특정 디렉터리 안에서 Rake 명령을 실행해야 할 때가 있습니다.
방법은 다음과 같습니다:
task :import do
puts "Importing data..."
Dir.chdir(Rails.root.join("data")) { ruby "load-data.rb" }
end
이 예시에서는 Rails 프로젝트의 data 폴더 안에서 Ruby 스크립트를 실행합니다.
Rake에서 네임스페이스(Namespace) 사용하기
태스크 이름이 서로 비슷하기 때문에 같은 이름을 중복으로 사용하게 되기 쉽습니다.
그래서 Rake에는 네임스페이스 기능이 존재합니다.
예를 들어, 백업 관련 태스크들을 묶기 위해 backup 네임스페이스를 만들 수 있습니다.
다음과 같이 말이죠:
namespace :backup do
task :create do
# ...
end
task :list do
# ...
end
task :restore do
# ...
end
end
네임스페이스가 지정된 태스크를 실행하려면:
rake backup:create
의존 태스크(Dependent Tasks)
Rake에서는 현재 태스크보다 먼저 실행되어야 하는 다른 태스크들의 목록을 정의할 수 있습니다.
이를 통해 태스크 실행에 필요한 사전 준비 작업을 손쉽게 처리할 수 있습니다.
예시:
task create_examples: "load_database" do # ... end
이 예시에서는 load_database가 create_examples보다 먼저 실행됩니다.
의존 태스크 목록은 문자열 배열이나 심볼 배열 형태로도 지정할 수 있습니다.
다른 태스크 내부에서 Rake 태스크 실행하기
현재 태스크 이전에 실행되는 의존 태스크를 두는 대신, 현재 태스크 내부에서 다른 태스크를 실행하고 싶다면 다음 코드를 사용하세요.
예시:
task :coverage do ENV['COVERAGE'] = 'true' Rake::Task["test"].execute end
테스트 커버리지 활성화 같은 옵션을 위한 환경 변수를 설정할 때 특히 유용합니다.
Rake 규칙(Rules) 사용법
규칙(rule)은 파일 확장자 간의 변환 작업을 정의합니다.
예시:
task compress: FileList["/tmp/*.txt"].ext(".txt.gz")
rule '.txt.gz' => '.txt' do |t|
sh "gzip", "-k", "-f", t.source
end
규칙을 사용하면 한 번 압축된 파일은 원본 파일이 변경되기 전까지 다시 압축되지 않는다는 큰 장점이 있습니다.
이 코드에서 주목해야 할 몇 가지 포인트:
- Rake에 포함된
FileList클래스를 사용해 작업 대상 파일 목록을 정의합니다. - 규칙은 대상(TARGET) 확장자로 시작합니다. 규칙이 매칭되려면
FileList에.ext(".txt.gz")를 적용해야 합니다. .txt.gz => .txt는 txt.gz에서 txt로 변환한다는 의미가 아니라 그 반대입니다. 화살표는 해시(hash) 문법입니다.
Rake 옵션 및 명령어 정리
실무에서 유용하게 쓰이는 Rake 옵션 목록입니다:
rake -T— 사용 가능한 태스크 목록 출력rake -P— 태스크와 각각의 의존성 목록 출력rake -W— 태스크와 해당 태스크가 정의된 위치 출력rake -V— 상세(verbose) 모드, 시스템 명령어 에코 출력rake -t— 디버깅 모드rake -f— 특정 Rakefile 지정하여 사용
예를 들어 Rails 앱에서 실행하면:
> rake -T test rake test # Runs all tests in test folder except system ones rake test:db # Run tests quickly, but also reset db rake test:system # Run system tests only
마치며
지금까지 Ruby의 대표적인 작업 실행기인 Rake에 대해 살펴봤습니다.
rake -T 명령으로 사용 가능한 태스크를 확인하고, 직접 만든 태스크는 Rakefile이나 lib/tasks 폴더에 추가하면 됩니다. 그리고 Rake와 Rack은 전혀 다른 도구라는 점도 꼭 기억하세요.

이 글이 도움이 되었다면 더 많은 사람들이 볼 수 있도록 공유해 주세요 🙂
읽어주셔서 감사합니다!