얼마전 루비스터디에서 'require'메서드와 'require_relative'메서드의 차이점에 대한 이야기가 나왔습니다. 그 이후 알아본 차이점과 개선방안에 대해 공유해보겠습니다.
require_relative는 현재 파일위치를 기준으로 파일을 찾습니다. 반면 require는 Ruby Load Path에 등록된 디렉토리를 기준으로 파일을 찾습니다.
gemspec 파일을 보며 더 자세히 설명해보겠습니다. 다음은 gemspec 파일의 일부입니다.
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'minesweeper/ruby/version'
File 클래스에 있는 expand_path 메서드는 상대경로를 절대경로로 바꿔주는 기능을 수행합니다. 따라서 File.expand_path('../lib', FILE)은 현재 파일(__FILE__)을 기준으로 '../lib' 폴더로의 상대경로를 절대경로로 바꿔주는 역할을 합니다. 이 경로를 Ruby Load Path에 추가해 주면 require 메서드가 파일을 찾는 기준점이 됩니다.
하지만 우리 소스는 '/lib' 디렉토리에 있지 않고, '/lib/minesweeper/ruby' 디렉토리에 있기 때문에 다음과 같이 바꿔줄 필요가 있습니다.
# coding: utf-8
dir = File.expand_path('../lib/minesweeper/ruby', __FILE__)
$LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
require 'version'
그렇게 되면 'require' 작업이 더 손쉽게 됩니다. 기존에 require 'minesweeper/ruby/cell'이나 require_relative 'cell' 였던 것들을 require 'cell'로 통일할 수 있습니다.
훨씬 더 짧고 명확하지 않나요?
그렇다면
require_relative
는 어떤 경우에 사용하면 좋을까요? 단순히 안티패턴일까요?4개의 의견 from SLiPP
그렇다면
require_relative
는 어떤 경우에 사용하면 좋을까요? 단순히 안티패턴일까요?@진우 님 http://extensions.rubyforge.org/rdoc/classes/Kernel.html
루비 1.9.2부터는 LOAD_PATH에 현재 경로를 없앴다고 하네요. 보안적인 이유때문에 프로젝트 폴더 자체를 지정하도록 바꿨다고 합니다. 그래서 프로젝트 폴더 이외의 경로에 있는 파일을 끌어올 때에만 'require_relative' 메서드를 쓰는 것이 적당할 것 같습니다.
@dongkuk 답변 고맙습니다. 다만 File.expand_path를 사용하는것이 편해보이긴 하지만 남용하게 되면 다른 사람이 코드를 파악할 때 어렵지 않을까 하는 걱정은 있네요. 위에 들어주신 예제처럼 require와 path가 붙어있으면 모르겠지만 흩어져있도록 구조를 잡아버린다면 독이 될 수 있겠네요. (사실 제 이해도가 떨어져서 글을 쓰면서도 헛소리하는건 아닌가 걱정스럽습니다 -,-;;)
더해서.. {quote}그래서 프로젝트 폴더 이외의 경로에 있는 파일을 끌어올 때에만 'require_relative' 메서드를 쓰는 것이 적당할 것 같습니다.{quote} 상대경로로 프로젝트 외부 경로에 있는 파일을 참조하는 케이스가 어떤 경우가 있을지 궁금하네요.
@진우 님
좀더 자세히 말씀드리면 File.expand_path 메서드는 두번째 인자를 주지 않으면 자동으로 현재 파일 기준으로 상대경로를 절대경로로 바꿉니다.
그래서 File.expand_path('../lib/minesweeper/ruby', FILE)는 File.expand_path('../lib/minesweeper/ruby')와 같습니다;; 다만 인자 2개가 좀더 자세한 예제일 것 같아서 위와 같이 적었습니다. 오히려 더 헷갈리기만 했군요 :)
또 프로젝트 외부 경로에 있는 파일을 참조하는 예시로는 테스트 파일들이 있을 수 있겠네요. 테스트 클래스에서 테스트 데이터를 로드할때? 저도 이 밖에 'require_relative'를 사용할 일이 뭐가 있을지 궁금하네요 :)
의견을 남기기 위해서는 SLiPP 계정이 필요합니다.
안심하세요! 회원가입/로그인 후에도 작성하시던 내용은 안전하게 보존됩니다.
SLiPP 계정으로 로그인하세요.
또는, SNS 계정으로 로그인하세요.