루비 메 서드 디스패치 시스템 이해 하 기 ( Part 1 ) 
 Harfang ' s Perch 
 en ko 루비 메 서드 디스패치 시스템 이해 하 기 ( Part 1 ) 
 이 글 에서 는 루비 에서 메 서 드 를 호출 했 을 때 , 루비 가 어떤 식 으로 이 를 처리 하 는지 를 살펴보 도록 하 겠 습니다 . 루비 언어 를 어느 정도 사용 할 줄 안다고 가정 합니다 . 
 두 개 의 글 로 나누 어서 구성 했 는데 첫 번 째 글 에서 는 일반 적 인 루비 프로그램 에서 알 아야 될 내용 을 다루 는데 , 구체 적 으로 는 조상 목록 , 클래스 상속 , 모듈 include 및 prepend 등 입니다 . 
 두 번 째 글 에서 는 더 드물 게 사용 되 는 기능 을 살펴보 는데 싱글턴 메 서드 , 싱글턴 클래스 , 클래스 메 서드 등 을 다룹니다 . 
 메 서드 디스패치 시스템 에서 가장 핵심 적 인 부분 은 객체 의 조상 입니다 . 여기 서 객체 의 조상 이 란 해당 객체 가 상속 을 받 는 모든 클래스 와 모듈 을 말 합니다 . 
 어떤 객체 에 메 서드 가 호출 되 면 루비 인터프리터 는 메 서드 의 정의 를 찾 기 위해 그 객체 의 클래스 를 살펴봅니다 . 거기 서 메 서드 의 정의 를 찾 지 못하 면 객체 의 조상 목록 을 거쳐 올라가 며 메 서드 의 정의 를 찾 아 봅니다 . 만약 마지막 조상 까지 살펴봤 는데 도 메 서드 의 정의 를 찾 지 못 한다면 다음 단계 로 넘어갑니다 . 
 루비 인터프리터 는 이번 에 는 method _ missing 메서 드가 정의 되 어 있 나 살펴보 면서 조상 목록 을 올라갑니다 . 조상 중 에 method _ missing 이 정의 된 것 이 없 다면 NoMethodError 를 반환 합니다 . 
 목록 으로 정리 해 볼까요 ? 
 메 서드 의 정의 를 찾 기 위해서 해당 객체 의 클래스 를 살펴본다 . 
 조상 목록 을 거슬러 올라가 면서 메 서드 의 정의 를 계속 찾아본다 . 
 method _ missing 이 정의 되 어 있 는지 해당 객체 의 클래스 를 살펴본다 . 
 method _ missing 의 정의 를 찾 기 위해 조상 목록 을 거슬러 올라간다 . 
 NoMethodError 를 반환 한다 . 
 method _ missing 은 메타 프로그래밍 에 매우 유용 하 게 사용 되 는 도구 로 , 정의 되 지 않 은 메서 드 를 프로그래머 가 런타임 에 다룰 수 있 도록 해줍니다 . 하지만 이 글 의 주제 를 벗어나 므로 여기 서 는 다시 언급 하 지 않 겠 습니다 . 
 Level 0 : 단일 클래스 
 먼저 루비 프로그램 에서 일반 적 으로 사용 되 는 구조 중 에서 가장 간단 한 것 을 살펴보 겠 습니다 . 이 글 에서 사용 할 기본 개념 과 도구 를 여기 서 다룰 것 이 기 때문 에 아마 가장 긴 부분 이 될 것 입니다 . 
 class BasicClass 
 def basic _ class _ method 
 basic _ class _ method 라는 인 스턴스 메서 드 를 가진 BasicClass 를 정의 했 고 , BasicClass 의 새 인 스턴스 를 생성 해서 basic _ class _ instance 라고 이름 붙였 습니다 . 
 basic _ class _ instance . class 
 BasicClass . class 
 class 메 서 드 는 루비 스탠다드 라이브러리 의 Class 에 정의 되 어 있 는 메서 드 인데 , 어떤 객체 에 이 를 호출 하 면 그 객체 의 클래스 를 반환 합니다 . 코드 에 나와 있 듯이 basic _ class _ instance 는 BasicClass 의 인 스턴스 입니다 . 생각 대로 입니다 . 
 하지만 흥미 롭 게 도 BasicClass 가 Class 의 인 스턴스 라는 것 도 볼 수 있 습니다 . 루비 에서 프로그래머 가 정의 하 는 모든 클래스 는 Class 클래스 의 인 스턴스 입니다 . 
 루비 에서 는 모든 것 이 객체 입니다 . 이 는 여러 가지 의미 를 가질 수 있 는데 , 여기 서 는 객체 가 생성 되 는 부분 에 대해서 만 생각 해 봅시다 . 대부분 의 객체 지향 언어 에서 객체 는 클래스 의 인 스턴스 로서 생성 됩니다 . 하지만 루비 에서 는 모든 것 이 객체 라고 앞서 말 했으며 , 클래스 도 예외 가 아닙니다 . 즉 , 프로그래머 가 정의 한 클래스 는 사실 Class 클래스 의 인 스턴스 로서 생성 되 는 것 이 죠 . 재귀 적 인 방식 이 니 처음 접하 는 개념 이 라면 한 번 시간 을 들여 생각 해 보 면 좋 습니다 . 
 BasicClass . ancestors 
 BasicClass . class . ancestors 
 BasicClass . instance _ method ( : basic _ class _ method ) 
 ancestors 메 서 드 는 루비 스탠다드 라이브러리 에 있 는 Module 에 정의 되 어 있 습니다 . 어떤 클래스 나 모듈 의 조상 을 전부 보여 줍니다 . 
 BasicClass 의 조상 은 Object , Kernel , BasicObject 셋 입니다 . 모든 루비 객체 는 이 셋 으로부터 상속 받 습니다 . 
 BasicClass 의 클 래스 인 Class 의 조상 은 Module , Object , Kernel , BasicObject 넷 입니다 . 루비 에서 Class 는 Module 의 서브 클래스 입니다 . 조금 이상 하 게 느껴질 수 도 있 지만 루비 에 는 그렇게 구현 되 어 있 습니다 . 
 Class 에 는 Module 에 없 는 기능 이 몇 가지 있 는데 , 예 를 들 어 객체 를 생성 하 는 기능 등 입니다 . Class 와 Module 의 차이점 에 대해서 는 별개 의 글 을 써야 할 것 같 으니 여기 서 는 더 이상 다루 지 않 겠 습니다 . 이 글 에서 사용 할 다음 도구 를 볼까요 . 
 instance _ method 는 Module 에 정의 되 어 있 는데 , 아규 먼 트 로 받 은 인 스턴스 메서 드 를 표현 하 는 UnboundMethod 를 반환 합니다 . 이 경우 에 는 basic _ class _ method 가 BasicClass 에 basic _ class _ method 라는 이름 으로 정의 되 어 있 는 UnboundMethod 라는 것 을 의미 합니다 . 이름 에 대한 부분 은 중복 되 는 것 처럼 느껴질 수 도 있 지만 alias 를 사용 한 메서 드 를 다룰 때 는 매우 유용 합니다 . 
 이 글 에서 는 instance _ method 를 사용 해서 인 스턴스 메서 드가 조상 목록 중 어디 에 정의 되 어 있 는지 만 살펴볼 것 이 므로 UnboundMethod 가 무엇 인지 에 대해서 는 다루 지 않 겠 습니다 . 
 Level 1 : 슈퍼 클래스 와 서브 클래스 
 이 부분 에서 는 일반 적 으로 사용 하 는 또 다른 구조 를 살펴보 겠 습니다 . 바로 슈퍼 클래스 와 서브 클래스 입니다 . 전 부분 에서 소개 한 도구 를 사용 해서 살펴보 기 만 할 것 이 며 새로운 개념 은 없 습니다 . 
 def super _ class _ method 
 SuperClass 를 새로 만들 고 BasicClass 가 그 로부터 상속 받 도록 했 습니다 . 조상 목록 을 살펴봅시다 . 
 SuperClass . ancestors 
 BasicClass 에 는 SuperClass 라는 조상 이 추가 됐 습니다 . 특별 할 것 없 는 내용 입니다 . 
 instance _ method 를 살펴봅시다 . 
 SuperClass . instance _ method ( : super _ class _ method ) 
 SuperClass . instance _ method ( : basic _ class _ method ) 
 NameError : undefined method ` basic _ class _ method ' for class ` SuperClass ' 
 BasicClass . instance _ method ( : super _ class _ method ) 
 세 번 째 까지 는 별다른 내용 이 없 습니다 . . SuperClass 에 는 super _ class _ method 가 있 고 , BasicClass 에 는 basic _ class _ method 가 있 고 , SuperClass 에 는 basic _ class _ method 가 없 습니다 . 
 마지막 으로 호출 한 결과 값 에 는 유용 한 정보 가 있 습니다 . BasicClass 가 super _ class _ method 를 인 스턴스 메서 드 로 가지 고 있 지만 , 메 서드 자체 는 SuperClass 에 정의 되 어 있 다는 것 을 알려 줍니다 . 
 메 서드 디스패치 시스템 관점 에서 이야기 하 자면 이 는 루비 인터프리터 가 조상 목록 을 한 단계 올라가 서 메 서드 의 정의 를 찾 았 다는 것 을 의미 합니다 . 
 Level 2 : 모듈 Include 와 Prepend 
 루비 에서 모듈 믹 싱 은 클래스 상속 과 더불 어 데이터 와 함수 를 관리 하 고 네임 스페이스 를 만들 기 위해 사용 됩니다 . 모듈 이 믹 싱 되 면 그 모듈 의 상수 , 메 서드 , 모듈 변수 가 대상 모듈 에 추가 됩니다 . 조상 목록 에서 모듈 믹 싱이 어떻게 표현 되 는지 살펴봅시다 . 
 module M oduleIncludedToBasicClass 
 def method _ included _ to _ basic _ class 
 def defined _ in 
 puts ' This method is defined in M oduleIncludedToBasicClass ' 
 module M o dulePrependedToBasicClass 
 def method _ prepended _ to _ basic _ class 
 puts ' This method is defined in M o dulePrependedToBasicClass ' 
 module M oduleIncludedToSuperClass 
 def method _ included _ to _ super _ class 
 puts ' This method is defined in M oduleIncludedToSuperClass ' 
 module M o dulePrependedToSuperClass 
 def method _ prepdended _ to _ super _ class 
 puts ' This method is defined in M o dulePrependedToSuperClass ' 
 include M oduleIncludedToSuperClass 
 prepend M o dulePrependedToSuperClass 
 puts ' This method is defined in SuperClass ' 
 include M oduleIncludedToBasicClass 
 prepend M o dulePrependedToBasicClass 
 puts ' This method is defined in BasicClass ' 
 M oduleIncludedToBasicClass , M o dulePrependedToBasicClass , M oduleIncludedToSuperClass , M o dulePrependedToSuperClass 라는 네 개 의 모듈 이 추가 되 었 는데 , 각자 하 는 일 은 자명 할 것 입니다 . 또 각 모듈 과 클 래스 마다 defined _ in 이 라는 인 스턴스 메서 드 를 새로 정의 했 습니다 . 호출 이 되 면 자신 이 정의 된 장소 를 출력 하 고 , super 를 호출 해 조상 목록 에서 자신 과 같 은 이름 을 가진 메서 드 를 호출 합니다 . 
 모듈 을 믹 싱하 는 방법 에 는 두 가지 가 있 는데 , 루비 스탠다드 라이브러리 의 Module 에 정의 되 어 있 습니다 . include 는 예전 부터 있 었 고 , prepend 는 루비 2 . 0 에 추가 되 었 습니다 . 어떻게 다른지 는 조상 목록 을 보 면 더 잘 이해 가 될 것 입니다 . 
 M o dulePrependedToSuperClass , SuperClass , M oduleIncludedToSuperClass , 
 Object , Kernel , BasicObject ] 
 실행 결과 에서 보이 듯이 prepend 는 조상 목록 에서 대상 모듈 이전 에 호출 된 모듈 을 추가 하 는 반면 include 는 대상 모듈 이후 에 호출 된 모듈 을 추가 합니다 . 이 는 메 서드 오버 라이드 와 super 메 서드 호출 에 영향 을 줍니다 . 
 basic _ class _ instance . defined _ in 
 This method is defined in M o dulePrependedToBasicClass 
 This method is defined in BasicClass 
 This method is defined in M oduleIncludedToBasicClass 
 This method is defined in M o dulePrependedToSuperClass 
 This method is defined in SuperClass 
 This method is defined in M oduleIncludedToSuperClass 
 메 서드 호출 순서 가 조상 목록 과 동일 한 것 을 볼 수 있 습니다 . 마지막 의 NoMethodError 는 Object 에 defined _ in 가 정의 되 어 있 지 않 아서 발생 합니다 . 
 여기 서 알 수 있 는 점 은 모듈 믹 싱이 뭔가 특별 한 것 이 아니 고 상속 을 구현 하 는 방법 중 하나 일 뿐 이 라는 것 입니다 . 그래도 매우 가볍 고 다루 기 쉽 게 다중 상속 을 구현 하 는 방식 으로 매우 가치 가 높 습니다 . 
 BasicClass . instance _ method ( : method _ included _ to _ super _ class ) 
 BasicClass . instance _ method ( : method _ prepended _ to _ basic _ class ) 
 instance _ method 를 호출 하 면 BasicClass 에 있 는 인 스턴스 메 서드 가 실제로 정의 가 된 곳 은 어디 인지 알 수 있 습니다 . 예상 외 의 결과 는 없 습니다 . 
 루비 메 서드 디스패치 시스템 의 기본 은 이 정도 입니다 . 일반 적 인 루비 프로그래밍 에 는 이 정도 만 이해 해도 큰 문제 가 없 습니다 . 
 다음 글 에서 는 메타 클래스 와 싱글턴 메서 드 를 다룰 예정 입니다 . 이 는 상대 적 으로 드물 게 사용 되 며 루비 에 대해서 도 더 잘 알 아야 사용 할 수 있 습니다 . 
 harfangk 
 소프트웨어 전반 에 대한 개인 블로그 . Ruby , Swift , Elixir