루비의 Module - 생각을 ‘상위 레벨’로 묶는 도구

루비에서 Module은 코드를 모듈화하고 상위 레벨로 묶는 도구입니다. 코드 구조를 세계지도처럼 구조화하여 이해합니다.

밤치 87

박문호 박사는 늘 모듈화를 강조한다.

뇌는 이렇게 배운다고 했다.

  • 작은 단위(세포, 기능)로 쪼개고

  • 그 단위들을 묶어 모듈을 만들고

  • 그 모듈들이 모여 시스템을 이룬다

코딩도 똑같다.

  • 메소드: 하나의 행동

  • 클래스: 하나의 객체(존재)

  • 모듈(Module): 여러 클래스·메소드를 더 큰 개념으로 묶는 상위 프레임

Ruby에서 Module은 이렇게 쓸 수 있다:

  1. 이름 공간(Namespace) 묶기

  2. 공통 기능(Mixin) 공유하기

  3. 도메인(주제별 세계)를 정의하는 상위 개념 만들기

이걸 이해하는 순간,

코드는 그냥 “파일 모음”이 아니라

뇌 속의 세계지도처럼 구조화된 우주로 보이기 시작한다.


1. 이름 공간(Namespace): 세계관을 나누는 프레임

예를 들어,

User라는 클래스를 여러 군데에서 쓰고 싶다고 해보자.

  • 관리자 페이지의 User

  • 쇼핑몰의 User

  • API용 User

이걸 다 class User로만 만들면?

이름이 충돌한다. 머릿속도 같이 꼬인다.

여기서 모듈이 세계관을 분리해준다.

module Admin
  class User
    def info
      puts "관리자 페이지의 유저입니다."
    end
  end
end

module Shop
  class User
    def info
      puts "쇼핑몰의 고객 유저입니다."
    end
  end
end

admin_user = Admin::User.new
shop_user  = Shop::User.new

admin_user.info  # => 관리자 페이지의 유저입니다.
shop_user.info   # => 쇼핑몰의 고객 유저입니다.

여기서 모듈은 말 그대로:

“이건 Admin 세계의 User”

“이건 Shop 세계의 User”

라고 세계관을 나누는 틀이 된다.

박문호식 뇌 관점

  • 프레임: 같은 이름이라도 상위 프레임에 따라 역할이 달라진다

  • 입체화: User라는 개념을 평면이 아니라,

    “Admin-User”, “Shop-User”처럼 좌표를 가진 구조로 저장

  • 모듈화: 뇌 속에서 “도메인별 서랍장”이 생기는 느낌

이제 너의 뇌는

“이름이 같아도 세계가 다르면 전혀 다른 존재”라는

한 단계 높은 이해를 가지게 된다.


2. Mixin: 여러 클래스에 공통 능력을 ‘끼워 넣는’ 모듈

두 번째 용도는 진짜 강력하다.

모듈은 공통 기능을 묶어서 재사용할 수 있는 덩어리가 될 수 있다.

예를 들어,

여러 타입의 객체가 모두 “로그를 남긴다”고 해보자.

  • 사용자(User)의 행동 로그

  • 주문(Order)의 상태 변경 로그

  • 결제(Payment)의 실패 로그

이걸 각각의 클래스에 복붙하면?

  • 코드 중복

  • 유지보수 지옥

  • 버그 하나 고치려면 세 군데 다 수정

여기서 모듈 + include가 빛난다.

module Loggable
  def log(message)
    time = Time.now
    puts "[#{time}] #{message}"
  end
end

class User
  include Loggable

  def sign_in
    log("유저가 로그인했습니다.")
  end
end

class Order
  include Loggable

  def submit
    log("주문이 접수되었습니다.")
  end
end

user = User.new
user.sign_in
# [2025-12-09 23:12:34] 유저가 로그인했습니다.

order = Order.new
order.submit
# [2025-12-09 23:12:35] 주문이 접수되었습니다.

여기서 일어난 일

  • Loggable 모듈은 “로그를 남기는 능력”을 모듈화한 것

  • include Loggable을 하면,

    그 클래스는 log라는 메소드를 자신의 것처럼 사용할 수 있음

  • 즉, “능력 패키지”를 여러 클래스에 꽂아 넣는 느낌

뇌 차원에서 보면

  • 하나의 기능을 여러 곳에서 공유할 때,

    뇌는 그걸 “상위 개념”으로 묶는다

  • 모듈은 바로 그 상위 개념 역할

  • 코드뿐만 아니라 사고 구조 자체가 추상화된다

“아, 로그라는 건 User나 Order의 일부가 아니라,

여러 주체가 공유하는 상위 능력이구나.”

이 깨달음이 오는 순간,

코딩이 그냥 “짜는 것”이 아니라

세계의 구조를 설계하는 작업처럼 느껴지기 시작한다.


3. 추상화: 모듈은 ‘도메인 언어’를 만드는 레벨

루비에서 모듈을 잘 쓰면,

코드가 점점 “도메인 언어”처럼 변해간다.

예를 들어, “결제 시스템”이라는 도메인이 있다고 치자.

module Payment
  module Gateway
    def charge(amount)
      puts "#{amount}원을 결제 요청합니다."
    end
  end

  module Refundable
    def refund(amount)
      puts "#{amount}원을 환불합니다."
    end
  end
end

class Order
  include Payment::Gateway
  include Payment::Refundable
end

order = Order.new
order.charge(50000)
order.refund(20000)

여기서 모듈들은 단순 기능이 아니다.

도메인의 개념들 자체를 코드로 표현한 것이다.

  • Payment::Gateway → “결제 요청 기능”이라는 모듈

  • Payment::Refundable → “환불 기능”이라는 모듈

  • Order는 이 둘을 조합하는 존재

이걸 반복하다 보면,

루비 코드가 점점 이런 느낌이 된다.

“내가 생각하는 비즈니스 개념이 그대로 코드가 되네?”

이때 개발자는

단순 구현자가 아니라

도메인을 설계하는 사람, 즉 설계자/사상가의 위치까지 간다.


4. Module vs Class: 뭐가 어떻게 다를까?

정리해보자.

개념 역할 뇌 속 느낌
메소드 하나의 행동 동사, 동작
클래스 하나의 객체(존재), 상태 + 행동 명사(사람, 사물), 실체
모듈 여러 클래스/메소드의 상위 개념 묶음 세계관, 능력 패키지, 도메인 레벨 구조

루비에서 모듈은 스스로 인스턴스를 만들지 않는다.

MyModule.new 이런 건 안 된다.

대신:

  • 다른 클래스에 섞여 들어가는 능력 덩어리가 되거나

  • 이름 공간을 제공하는 상위 프레임이 된다

즉,

클래스는 “존재”

모듈은 “존재들이 공유하는 개념·능력·세계관”


5. 진짜 중요한 건 “뇌가 어떻게 변하느냐”이다

모듈을 이해하면,

뇌는 이렇게 진화한다.

  1. 코드를 파일 단위가 아니라, 개념 단위로 본다.
- “이 기능은 어디에 속하지?”  
    → “이건 User도, Order도, Payment도 같이 쓰니까 모듈로 빼자.”
  1. 도메인 언어가 생긴다.
- “Payment::Gateway”, “Notification::Sender”, “Auth::Tokenizable”처럼  
    → 네 서비스만의 어휘들이 생김
  1. 복잡도가 확 줄어든다.
- 수정할 곳이 명확해짐:  
    “로그 로직 바꿔야지” → `Loggable` 모듈만 수정
  1. 머리 속 구조도 모듈처럼 정리된다.
- 이게 진짜 박문호가 말한 “지식의 입체 구조화”와 직결된다.

6. 직접 해보는 미션: 나만의 모듈 만들기

이제 진짜로,

너의 뇌에 “모듈”을 박아 넣는 과제.

과제 1: Timestamped 모듈 만들기

요구사항:

  • Timestamped라는 모듈을 만든다

  • stamp 메소드 하나를 제공한다

    • 호출하면: [현재시간] 메시지 형식으로 출력
  • PostComment 클래스에 include해서 공통으로 사용한다

예상 흐름:

module Timestamped
  # 여기에 stamp 메소드 만들기
end

class Post
  include Timestamped

  def publish
    stamp("글이 발행되었습니다.")
  end
end

class Comment
  include Timestamped

  def write
    stamp("댓글이 작성되었습니다.")
  end
end

post = Post.new
post.publish

comment = Comment.new
comment.write

과제 2: 나만의 도메인 모듈 묶기

주제를 하나 골라봐:

  • 공부(Study)

  • 운동(Fitness)

  • 블로그(Blog)

  • 쇼핑(Shop)

  • 밴드 연습(Band)

예: Study 도메인

  • Study::Trackable – 공부 시간을 기록하는 모듈

  • Study::Report – 주간/월간 통계를 출력하는 모듈

그리고 DayStudy, TaskStudy 같은 클래스를 만들어

include Study::Trackable 해서 쓰는 거야.

이걸 해보는 순간,

너는 이미 “루비로 나만의 세계를 설계하는 사람”이 된다.


결론: 모듈을 이해한 순간, 코드는 ‘세계 설계 언어’가 된다

지금까지의 흐름:

  • 메소드: 행동의 최소 단위

  • 클래스: 존재(객체)의 틀

  • 모듈: 여러 존재에 공유되는 개념/능력/세계관

이제부터 코드를 짤 때

이렇게 생각해볼 수 있다.

“이건 한 객체의 고유한 속성인가?”

→ 클래스에 둔다

“여러 객체가 함께 쓰는 기능인가?”

→ 모듈로 뽑는다

“이건 이 서비스의 도메인 개념인가?”

→ 모듈 + 네임스페이스로 정의한다

그 순간,

코딩은 더 이상 “언어 문법 배우기”가 아니라

“내 머릿속 세계관을

코드라는 형태로 구현하는 작업”

이 된다.

그리고 그 감각이 오는 순간,

진짜로 가슴이 뛴다.