ruby의 require와 require_relative의 차이점

2013-12-02 17:12

얼마전 루비스터디에서 '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'로 통일할 수 있습니다.

훨씬 더 짧고 명확하지 않나요?

4개의 의견 from SLiPP

2013-12-04 17:35

@dongkuk 답변 고맙습니다. 다만 File.expand_path를 사용하는것이 편해보이긴 하지만 남용하게 되면 다른 사람이 코드를 파악할 때 어렵지 않을까 하는 걱정은 있네요. 위에 들어주신 예제처럼 require와 path가 붙어있으면 모르겠지만 흩어져있도록 구조를 잡아버린다면 독이 될 수 있겠네요. (사실 제 이해도가 떨어져서 글을 쓰면서도 헛소리하는건 아닌가 걱정스럽습니다 -,-;;)

더해서.. {quote}그래서 프로젝트 폴더 이외의 경로에 있는 파일을 끌어올 때에만 'require_relative' 메서드를 쓰는 것이 적당할 것 같습니다.{quote} 상대경로로 프로젝트 외부 경로에 있는 파일을 참조하는 케이스가 어떤 경우가 있을지 궁금하네요.

2013-12-04 18:30

@진우 님

좀더 자세히 말씀드리면 File.expand_path 메서드는 두번째 인자를 주지 않으면 자동으로 현재 파일 기준으로 상대경로를 절대경로로 바꿉니다.

그래서 File.expand_path('../lib/minesweeper/ruby', FILE)는 File.expand_path('../lib/minesweeper/ruby')와 같습니다;; 다만 인자 2개가 좀더 자세한 예제일 것 같아서 위와 같이 적었습니다. 오히려 더 헷갈리기만 했군요 :)

또 프로젝트 외부 경로에 있는 파일을 참조하는 예시로는 테스트 파일들이 있을 수 있겠네요. 테스트 클래스에서 테스트 데이터를 로드할때? 저도 이 밖에 'require_relative'를 사용할 일이 뭐가 있을지 궁금하네요 :)

의견 추가하기

연관태그

← 목록으로