Skip to content

Instantly share code, notes, and snippets.

@yhk1038
Last active January 20, 2026 05:59
Show Gist options
  • Select an option

  • Save yhk1038/179c1e4ec221acb147abb66a60c290eb to your computer and use it in GitHub Desktop.

Select an option

Save yhk1038/179c1e4ec221acb147abb66a60c290eb to your computer and use it in GitHub Desktop.
RailsWay naming & convention rule set

Rails Way 네이밍·컨벤션 룰셋 (CLI 에이전트용)

이 문서는 Rails/Ruby 프로젝트에서 CLI 에이전트가 코드 생성·수정·리뷰를 수행할 때 지켜야 할 네이밍/컨벤션 규칙을 정리한 룰셋이야.

목표

  • 팀/커뮤니티에서 흔히 기대하는 Rails스러운 코드 형태로 유도
  • 의미 중복(DRY in naming)과 혼동을 줄이고, 도메인 모델을 선명하게 만들기
  • 자동 수정이 가능한 것과, “리뷰 제안”으로만 해야 하는 것을 구분

0. 적용 우선순위

  1. Ruby 문법/언어 규칙(절대)
  2. Rails 프레임워크 컨벤션(강함)
  3. 팀 룰(프로젝트별 설정이 있으면 그것이 최우선)
  4. 이 문서의 권고 룰(기본값)

에이전트는 2)와 3)이 충돌하면 프로젝트의 기존 패턴(3)을 우선한다.


1. 식별자 형태 규칙 (자동 수정 가능)

1.1 클래스/모듈(상수) 네이밍

  • 클래스/모듈/상수는 CamelCase로 작성한다.

    • User, Admin::UsersController, Billing::Invoice
    • user, user_controller, billing-invoice
  • 파일 경로는 Zeitwerk 기준으로 상수명과 일치하도록 둔다.

    • app/models/user.rbclass User
    • app/controllers/admin/users_controller.rbclass Admin::UsersController

1.2 메서드/변수/컬럼 네이밍

  • 메서드/로컬변수/컬럼은 snake_case를 기본으로 한다.

    • user_name, created_at, billing_address
    • userName, CreatedAt

1.3 Boolean 네이밍

  • 메서드 네이밍은 is_xxx? / has_xxx? 형태를 기본 컨벤션으로 사용한다.

    • is_active?, is_admin?, has_access?
    • ⚠️ active? 스타일도 Ruby 관용으로 널리 쓰이지만, Rails 전통 컨벤션과 DB 컬럼과의 대응을 위해 기본값은 is_xxx?로 둔다.
  • DB boolean 컬럼은 is_xxx 형태를 권장한다.

    • is_active (boolean)
    • is_published, is_deleted
    • active_flag, status_bool
  • ActiveRecord는 boolean 컬럼에 대해 자동으로 술어 메서드를 제공한다.

    • 컬럼: is_active → 메서드: is_active?
  • 컬럼 이름과 메서드 이름은 이중 접두어를 만들지 않는다.

    • ❌ 컬럼: active + 메서드: is_active? (혼용)
    • ❌ 컬럼: is_active + 메서드: is_is_active?
    • ✅ 컬럼: is_active + 메서드: is_active?
  • 프로젝트 기존 패턴(active? vs is_active?)이 있다면 반드시 기존 스타일을 우선한다.

1.4 날짜/시간(DateTime) 네이밍

  • 날짜/시간을 의미하는 컬럼과 메서드는 기본적으로 _at** 접미사**를 사용한다.

    • created_at, updated_at, deleted_at, published_at, last_signed_in_at
    • create_time, updateDate, deleted_time
  • _on날짜(Date)만 의미할 때 사용한다.

    • birthday_on, due_on, started_on
    • birthday_at (시간 정보가 없는데 _at 사용)
  • _at 컬럼에 대해서 ActiveRecord는 자동으로 Time/ActiveSupport::TimeWithZone 타입을 제공한다.

  • 이벤트/상태 변화 시점은 가능한 한 _at으로 통일한다.

    • confirmed_at, approved_at, archived_at
    • is_confirmed_time, confirm_time
  • boolean + datetime 혼용을 피한다.

    • is_deleted + deleted_time
    • deleted_at (soft delete 패턴)

1.5 상수

상수

  • 상수는 SCREAMING_SNAKE_CASE.

    • DEFAULT_TIMEOUT = 5

2. Rails 도메인 명명 규칙 (대부분 ‘리뷰/제안’ 중심)

아래 규칙은 정답이 아니라 “Rails스럽게 읽히는” 방향이야. 기존 코드베이스가 다른 패턴을 이미 채택했다면, 에이전트는 그 패턴을 따른다.

2.1 인스턴스 변수/로컬 변수: 클래스명 소문자 단수

  • ActiveRecord 모델 인스턴스는 가능하면 클래스명 소문자 단수로 잡는다.

    • user = User.find(...)
    • order = Order.new(...)
    • u = User.find(...) (짧은 스코프 제외)
    • user_obj, user_instance (중복 의미)

2.2 컬렉션 변수: 복수형

  • 관계/배열/컬렉션은 복수형을 권장.

    • users, orders, line_items
    • user_list, order_array (타입/구조를 이름에 넣지 말기)

2.3 중복 의미(DRY in naming) 피하기

  • 컨텍스트가 이미 말해주는 단어를 속성/메서드명에 반복하지 않는다.

    • user.username이 “유저의 이름” 의미라면 → ✅ user.name
    • order.order_status → ✅ order.status
    • post.post_title → ✅ post.title
    • user.user_email → ✅ user.email

예외

  • 도메인이 정말로 구분을 요구하면 분리한다: name vs display_name vs legal_name
  • 인증/로그인용 식별자라는 의미를 담아야 하면 username이 오히려 적절할 수 있다.

2.4 역할(role) vs 리소스(resource)

  • 컨트롤러/라우트는 리소스 중심으로 둔다.

    • UsersController, Admin::UsersController
    • ⚠️ UserManagementController (대부분 과한 추상화)

3. ActiveRecord / Association 네이밍

3.1 has_many / belongs_to

  • 관계 이름은 도메인 리소스 명사로.

    • belongs_to :user / has_many :posts
    • has_many :user_posts (대부분 중복)

3.2 조인 모델

  • join 모델은 보통 Membership, Enrollment처럼 의미 있는 명사로.

    • Membership (User ↔ Team)
    • Enrollment (Student ↔ Course)

3.3 스코프

  • 스코프는 상태/필터를 나타내는 형용사/구.

    • scope :active, -> { where(is_active: true) }
    • scope :recent, -> { order(created_at: :desc) }

3.5 ActiveRecord 컬럼/enum/association 기반 자동 메서드 가드레일

ActiveRecord는 컬럼 이름, enum, association, timestamp 등을 기반으로 많은 메서드와 스코프를 런타임에 자동 생성한다. 이 메서드들은 코드에 직접 정의돼 있지 않아도 이미 존재할 수 있으며, 에이전트가 이를 모르고 동일 이름의 메서드/스코프를 새로 만들면 충돌·오버라이드·미묘한 버그가 발생한다.

3.5.1 자동 생성되는 대표 메서드/스코프 유형

  • 속성 접근자

    • 컬럼: namename, name=, name?(boolean일 때)
  • boolean predicate

    • 컬럼: is_activeis_active?
  • timestamp / dirty tracking

    • created_at, updated_atcreated_at?
    • 변경 추적: saved_change_to_name?, name_before_last_save, will_save_change_to_name?
  • enum 기반 메서드 / 스코프

    • 컬럼: status (enum)

      • 인스턴스: active?, inactive!
      • 클래스 스코프: User.active, User.inactive
  • association 메서드

    • has_many :postsposts, posts=, posts.build, posts.create
    • belongs_to :useruser, user=, build_user
  • scope 체인 자동 생성

    • enum + association 조합으로 추가 메서드가 생길 수 있음

3.5.2 기본 원칙

  • 에이전트는 “코드에 없으면 없다”라고 가정하지 않는다.

  • 모델에 메서드/스코프/헬퍼를 추가하기 전에:

    1. 컬럼 이름
    2. enum 정의
    3. association 정의
    4. 기존 scope 로부터 자동 생성되는 이름과 충돌 가능성을 반드시 검사한다.

3.5.3 금지 / 주의 규칙

  • 다음 패턴은 기본적으로 새로 정의 금지 (리뷰 제안만 허용)

    • 컬럼명과 동일한 메서드

      • def name (컬럼 name 존재)
    • enum 상태와 동일한 메서드/스코프

      • scope :active (enum status: { active: ... } 존재)
    • association 이름과 동일한 메서드

      • def posts (이미 has_many :posts 존재)
  • 자동 생성 메서드를 덮어쓰는 override는:

    • 기본 금지
    • 반드시 리뷰 제안 + 변경 이유 + 테스트 근거 필요

3.5.4 동적 검사(권장 절차)

에이전트가 모델에 새 메서드/스코프를 추가하기 전, 가능하면 아래를 수행한다.

  1. 스키마 / 모델 정적 검사

    • db/schema.rb 또는 structure.sql에서 컬럼명 확인
    • 모델 파일에서 enum, has_many, belongs_to, scope 검색
  2. 런타임 introspection (가능할 때)

  • 특정 인스턴스 메서드 존재 여부:

    • bin/rails runner 'User.new.respond_to?(:active?)'
  • 클래스 스코프 존재 여부:

    • bin/rails runner 'User.respond_to?(:active)'
  • 전체 메서드 스캔(주의해서 사용):

    • bin/rails runner 'User.instance_methods.grep(/active/)'
  1. 충돌 가능성이 발견되면:
  • 새로 만들지 말고
  • 기존 자동 메서드 사용을 우선 고려하거나
  • 네이밍 변경(active_flagis_active, active_status 등) 또는
  • 리뷰 제안으로만 처리한다.

3.5.5 대표 사고 사례 (에이전트 방지 대상)

  • enum status가 있는데 scope :active를 다시 정의
  • boolean 컬럼 is_deleted가 있는데 def deleted?를 새로 정의
  • has_many :orders가 있는데 def orders로 커스텀 구현

요약: ActiveRecord 모델에서는 컬럼/enum/association이 이미 API를 만든다. 에이전트는 “새로 정의”보다 기존 자동 메서드 재사용을 기본 전략으로 삼는다.

4. 서비스 객체/쿼리 객체 네이밍 (Rails에서 흔한 패턴)

이 섹션은 프로젝트가 이미 서비스 레이어를 사용하고 있을 때만 적극 적용한다. 프로젝트에 app/services 등 관례가 없다면, 에이전트는 레이어를 새로 도입하지 않고 리뷰 제안으로만 다룬다.

4.1 서비스 객체

  • 동사+목적어 형태가 읽기 좋다.

    • Users::Create, Orders::Cancel, Billing::ChargeCard
    • CreateUser, CancelOrder (프로젝트 스타일에 따라)

4.2 쿼리 객체

  • ...Query 또는 도메인 명사+조건 형태.

    • Users::SearchQuery, Orders::OverdueQuery

4.5 Autoload/Override/Config 특수성 (중복 작성 방지 가드레일)

Rails는 autoload(Zeitwerk), reloading, initializer, configuration 등으로 인해 “이미 존재하는 상수/클래스/설정이 다른 곳에서 로드되어 덮어써지거나(override) 확장되는” 경우가 있다. 에이전트는 아래 규칙으로 중복 작성과 의도치 않은 override를 방지한다.

4.5.1 config/ 디렉토리의 의미

  • config/는 실행 환경을 규정하는 핵심 영역이다.

    • config/application.rb, config/environment.rb, config/environments/*.rb
    • config/initializers/*.rb
    • config/routes.rb
  • 에이전트는 config/를 수정할 때 반드시:

    1. 기존 파일에서 이미 설정된 값/미들웨어/초기화 로직을 검색하고
    2. 중복 설정(같은 키/같은 클래스/같은 미들웨어 추가)을 피하며
    3. 변경 이유와 영향 범위를 코멘트로 남긴다.

4.5.2 상수/클래스 중복 정의 금지

  • 에이전트는 새로운 클래스/모듈을 추가하기 전에:

    • 코드베이스에서 동일 상수명 검색(User, Billing::Invoice 등)
    • app/* + lib/ + 엔진/젬에서 동일 이름이 관례적으로 존재하는지 추정 을 수행한다.
  • 동일 이름이 이미 존재하면:

    • 새로 만들지 말고 기존 클래스를 확장/수정하거나
    • 네임스페이스를 분리(Admin::User 등) 하며, override가 필요한 경우는 리뷰 제안으로만 처리한다.

4.5.3 monkey patch / reopen class 정책

  • Ruby에서는 클래스를 reopen해서 메서드를 추가/교체할 수 있다.

  • 에이전트 기본 정책:

    • monkey patch(재정의)는 금지(기본값)
    • 반드시 필요하면 Module#prepend 또는 명시적 extension(Concern 등) 우선
    • 적용 시에는 변경 이유/로드 순서/테스트 근거를 함께 제공

4.5.4 엔진/젬/initializer로 인한 동적 변경 고려

  • config/initializers 및 의존 젬이 모델/컨트롤러에 메서드를 추가할 수 있다.

  • 에이전트는 “메서드가 없다고 가정하고 새로 만들기” 전에:

    • bin/rails runner로 실제 런타임에서 응답 여부를 확인(가능할 때)
    • 테스트/콘솔에서 respond_to? 확인(가능할 때) 하여 중복 구현을 줄인다.

5. Rails Generator/Scaffold 사용 규칙 (에이전트 실행 가이드)

Rails는 CLI 제너레이터 + 템플릿을 통해 규격화된 코드를 만드는 영역이 매우 크다. 따라서 에이전트가 제너레이터로 만들 수 있는 코드를 직접 손으로 작성하면, 프로젝트가 의도한 템플릿/옵션/플러그인과 어긋나거나 누락이 생길 수 있다.

5.1 원칙: Generator-first

  • 다음 범주에 속하면 무조건 ****bin/rails generate****를 우선한다.

    • 모델/마이그레이션/컨트롤러/리소스/스캐폴드
    • 채널(ActionCable), 잡(job), 메일러(mailer), 노티피케이션 등
    • 테스트/스펙 파일(프로젝트가 generator로 만들어주도록 설정돼 있는 경우)
  • 에이전트가 직접 파일을 새로 만드는 것은 아래의 경우로 제한한다.

    • (a) 제너레이터가 존재하지 않거나
    • (b) 프로젝트가 제너레이터를 금지/비활성화했고(팀 룰)
    • (c) 생성 이후 “소폭 편집”이 필요한 구간

5.2 동적 조사(실행 전 체크) — 필수 절차

에이전트는 코드 생성 전에 반드시 아래 순서로 프로젝트의 제너레이터 환경을 동적으로 조사한다.

  1. 사용 가능한 제너레이터 목록 확인

    • bin/rails generate (인자 없이)
  2. 대상 제너레이터의 도움말/옵션 확인

    • bin/rails generate <GEN> --help
  3. 생성 결과를 실제로 쓰기 전에 미리보기

    • --pretend(또는 -p)로 어떤 파일이 생성/수정되는지 확인
  4. 프로젝트가 커스텀 템플릿을 오버라이드하는지 확인

    • lib/templates/ 존재 여부
    • 특정 제너레이터(예: scaffold/controller/model)의 템플릿이 오버라이드 되어 있으면, 반드시 그 템플릿 기반으로 생성한다.
  5. 프로젝트 기본 생성 옵션(.railsrc 등) 확인

    • 프로젝트 루트 또는 홈의 .railsrc 등으로 기본 옵션이 강제될 수 있으니, 실행 커맨드에 반영한다.

5.3 실행 정책

  • 제너레이터 실행 후에는 에이전트가:

    1. 생성된 코드에서 도메인 규칙 반영
    2. 네이밍 중복 제거, 의미 정리
    3. 테스트/린트 통과 을 수행한다.
  • 제너레이터로 생성 가능한 파일을 에이전트가 직접 만들었다면, PR/커밋 전에 반드시:

    • “왜 제너레이터를 쓰지 않았는지” 이유를 남기고
    • 해당 제너레이터가 실제로 존재하는지(또는 템플릿 오버라이드 여부)를 다시 점검한다.

요약: Rails 프로젝트에서 ‘생성 가능한 코드’는 제너레이터가 소스 오브 트루스다.


5.5 데이터베이스 파괴 명령 가드레일 (절대 실행 금지)

데이터베이스 관련 명령은 한 번의 실수로 서비스 전체 데이터를 영구 손실시킬 수 있다. CLI 에이전트는 아래 규칙을 통해 파괴적(DB destructive) 명령을 원천 차단하고, 사람 승인 없이는 실행하지 않는다.

5.5.1 절대 실행 금지 명령 (환경 불문, 기본 하드 블록)

Rails / Rake 명령

  • bin/rails db:reset
  • bin/rails db:drop
  • bin/rails db:drop:all
  • bin/rails db:setup
  • bin/rails db:schema:load
  • bin/rails db:migrate:reset

위 명령들은 drop + recreate + load 계열로, 대부분의 경우 기존 데이터를 전부 삭제한다.

SQL 레벨 명령

  • DROP DATABASE, DROP SCHEMA
  • TRUNCATE TABLE
  • DELETE FROM <table>; (WHERE 없음)
  • UPDATE <table> SET ...; (WHERE 없음)

에이전트는 위 패턴을 감지하면:

  • 기본 실행 금지
  • 반드시 사람의 명시적 승인 + 환경 확인 + 백업 확인 없이는 진행하지 않는다.

5.5.2 환경 가드레일 (production / staging 보호)

에이전트는 모든 DB 명령 실행 전에 반드시:

  • Rails.env 또는 RAILS_ENV 확인

규칙:

  • production, staging 환경에서는:

    • 모든 destructive 명령 전면 금지
    • 마이그레이션 외 직접 SQL / reset / drop 계열 실행 금지

기본 원칙: 운영 환경에서는 구조 변경은 마이그레이션만 허용한다.


5.5.3 마이그레이션 위험 패턴 가드레일

다음 마이그레이션 API는 데이터 손실 또는 장시간 락 위험이 있으므로 자동 생성 금지 (리뷰 제안만 허용):

  • drop_table
  • remove_column
  • change_column (타입 변경)
  • 대규모 테이블에서의 rename_column

권장 대안:

  • 컬럼 제거 대신 deprecated 상태 유지 후 단계적 제거

  • soft delete: is_deleted ❌ → deleted_at

  • 타입 변경 시:

    • 새 컬럼 추가 → 데이터 마이그레이션 → 코드 전환 → 기존 컬럼 제거

5.5.4 Rails 콘솔 / runner 위험 메서드

에이전트는 아래 메서드를 기본 금지 또는 강한 경고 대상으로 취급한다.

  • Model.delete_all
  • Model.destroy_all
  • Model.update_all(...) (조건 없는 경우)

특히 금지 패턴:

User.all.each { |u| u.destroy }

→ 콜백 연쇄 실행 + 장시간 락 + 대량 데이터 손실 위험

권장 대안:

  • scope + batch 처리
  • in_batches, find_each 사용
  • 반드시 WHERE / LIMIT / 로그 포함

5.5.5 실행 정책 (에이전트 운영 규칙)

에이전트는 DB 관련 명령 실행 시 반드시:

  1. 환경 확인 (Rails.env)
  2. destructive 패턴 매칭 검사
  3. 최근 백업 존재 여부 확인 (가능할 때)
  4. dry-run / --pretend / SQL 미리보기

그리고:

  • destructive 명령은:

    • 자동 실행 ❌
    • 리뷰 제안 + 사람 승인 필수

5.5.6 대표 사고 사례 (방지 대상)

  • 운영 서버에서 db:reset 실행 → 전체 데이터 삭제
  • delete_all 조건 누락 → 전 테이블 삭제
  • 대형 테이블 change_column → 서비스 장시간 다운

요약: 데이터베이스 명령은 에이전트에게 가장 위험한 영역이다. 에이전트의 기본 전략은: 삭제하지 말고, 덮어쓰지 말고, 반드시 보호하라.

5.6 트랜잭션 / 락(Transaction & Lock) 가드레일

대량 데이터 처리, 장시간 트랜잭션, 테이블/행 락은 서비스 지연·데드락·장시간 장애의 주요 원인이다. 에이전트는 아래 규칙으로 트랜잭션과 락 사용을 제한한다.

5.6.1 기본 원칙

  • 트랜잭션은 짧고 작게 유지한다.

  • 트랜잭션 안에서:

    • 네트워크 호출 ❌
    • 외부 API ❌
    • 파일 I/O ❌
    • 대량 반복 처리 ❌

원칙: 트랜잭션은 DB 연산만 포함하고, 가능한 한 한 번의 SQL로 끝낸다.


5.6.2 위험 패턴 (자동 생성 금지 / 리뷰 제안만 허용)

  • 장시간 트랜잭션
ActiveRecord::Base.transaction do
  users.each do |u|
    u.update!(...)
  end
end
  • 트랜잭션 + 외부 호출 혼용
transaction do
  order.save!
  PaymentAPI.charge(...)   # ❌ 트랜잭션 안에서 외부 호출
end
  • 명시적 테이블 락
User.lock(true)
User.connection.execute("LOCK TABLE users")

5.6.3 with_lock / pessimistic lock 정책

  • with_lock, lock!, select ... FOR UPDATE 사용 시:

    • 기본 자동 생성 금지
    • 반드시 리뷰 제안 + 사용 이유 + 경쟁 조건 설명 필요

권장 조건:

  • 정말 동시성 충돌이 재현 가능한 경우에만 사용
  • 락 범위는 단일 레코드 단위로 제한

5.6.4 대량 업데이트 / 삭제 안전 패턴

금지 패턴:

User.where(...).each { |u| u.update!(...) }

권장 패턴:

  • SQL 단일 쿼리:

    • User.where(...).update_all(...)
  • 또는 배치 처리:

    • find_each, in_batches
    • batch 단위 커밋

5.6.5 실행 정책

에이전트는 트랜잭션/락 사용 시 반드시:

  1. 트랜잭션 범위 길이 추정
  2. 반복 루프 포함 여부 검사
  3. 외부 호출 포함 여부 검사

위험 패턴이면:

  • 자동 실행 ❌
  • 리뷰 제안 + 성능/락 영향 설명 필수

요약: 트랜잭션과 락은 데이터 정합성보다 장애 위험이 더 큰 경우가 많다. 에이전트의 기본 전략은: 락을 피하고, 짧게 쓰고, 배치로 나누라.


5.7 콜백(callback) / after_commit 가드레일

ActiveRecord 콜백은 실행 시점이 불명확하고, 트랜잭션·롤백·재시도와 얽혀 디버깅 불가능한 버그를 만들기 쉽다. 에이전트는 콜백에 비즈니스 로직이 들어가는 것을 기본적으로 제한한다.

5.7.1 기본 원칙

  • 콜백은:

    • 데이터 정합성 유지
    • 파생 컬럼 갱신
    • 로그 / 간단한 플래그 설정 에만 사용한다.
  • 비즈니스 로직, 외부 연동, 메일 발송, 결제 처리 등은:

    • 콜백 ❌
    • 서비스 객체 / 명시적 호출 ✅

5.7.2 금지 / 위험 패턴

  • 콜백 안에서 외부 호출
after_commit do
  PaymentAPI.charge(...)   # ❌
end
  • 콜백 안에서 다른 모델 대량 갱신
after_save do
  User.where(...).update_all(...)
end
  • 콜백 체인 의존
before_save :normalize
before_save :recalculate
before_save :sync

→ 실행 순서 변경 시 버그 발생 위험


5.7.3 after_commit / after_save 사용 가드레일

  • after_save, after_commit에서 허용되는 작업:

    • 캐시 무효화
    • 단일 레코드 파생 필드 계산
    • 내부 이벤트 enqueue (ActiveJob.perform_later)
  • 금지:

    • 동기 메일 발송
    • 결제 / 외부 API
    • 다른 모델 대량 수정

권장 대안:

  • 컨트롤러 / 서비스 객체에서 명시적 호출
  • 이벤트 / job 큐 사용

5.7.4 실행 정책

에이전트가 콜백을 추가/수정하려 할 때:

  1. 콜백 종류(before_*, after_*, around_*) 확인
  2. 내부 로직 길이 / 외부 호출 포함 여부 검사

위험 패턴이면:

  • 자동 추가 ❌
  • 리뷰 제안 + 실행 시점 / 롤백 영향 설명 필수

5.7.5 대표 사고 사례 (방지 대상)

  • after_commit에서 메일 발송 → 롤백 시 중복 발송
  • before_save에서 결제 호출 → 저장 실패 후 결제만 완료
  • 콜백 순서 변경 → 데이터 불일치 발생

요약: 콜백은 보이지 않는 제어 흐름이다. 에이전트의 기본 전략은: 콜백에 로직을 넣지 말고, 명시적으로 호출하라.

5.8 배포 / 마이그레이션 운영 가드레일 (Production Safety)

마이그레이션과 배포는 코드보다 훨씬 높은 장애 위험을 가진 영역이다. 에이전트는 운영 환경에서의 스키마 변경과 배포 절차를 아래 규칙으로 엄격히 제한한다.

5.8.1 기본 원칙 (Online / Backward-compatible Migration)

  • 운영 환경 마이그레이션은 항상:

    • Backward-compatible (이전 코드와 동시에 동작 가능) 해야 한다.
    • 한 번에 구조+코드 동시 변경 ❌
    • 최소 2단계 배포(Expand → Deploy → Contract) 원칙을 따른다.

원칙: 코드는 옛 스키마에서도 동작해야 하고, 스키마는 새 코드에서도 동작해야 한다.


5.8.2 절대 금지 패턴 (운영 환경)

자동 생성 / 자동 실행 전면 금지:

  • 대형 테이블에서:

    • add_column + default 동시에 추가
    • change_column (타입 변경)
    • rename_column
    • drop_column
  • 인덱스 관련:

    • add_index (lock 걸리는 기본 방식, PostgreSQL)
    • remove_index (동시성 고려 없이 실행)
  • 트랜잭션 안에서 DDL 실행

이유: 테이블 전체 락 → 요청 대기 → 서비스 장애


5.8.3 안전한 컬럼 변경 패턴 (권장 절차)

컬럼 추가

  • ❌ 위험
add_column :users, :active, :boolean, default: false
  • ✅ 안전 패턴
add_column :users, :active, :boolean   # default 없음

이후 단계:

  1. 배포
  2. 백필(batch update)
  3. default 추가 + NOT NULL 추가 (후속 마이그레이션)

5.8.4 인덱스 운영 규칙 (PostgreSQL 기준)

  • 기본 원칙: 항상 CONCURRENTLY 사용

  • ❌ 금지

add_index :users, :email
  • ✅ 권장
disable_ddl_transaction!
add_index :users, :email, algorithm: :concurrently
  • 인덱스 제거도 동일하게:
remove_index :users, :email, algorithm: :concurrently

5.8.5 strong_migrations 가드레일

  • 프로젝트에 strong_migrations 젬이 있으면:

    • 에이전트는 해당 룰을 최상위 규칙으로 준수한다.
    • 경고가 발생하는 마이그레이션은 자동 생성 금지
    • 반드시 안전한 대안 패턴으로 변환 후 제안

5.8.6 2단계 배포 (Expand / Contract) 패턴

권장 흐름:

  1. Expand 단계

    • 새 컬럼/인덱스 추가 (nullable, 미사용)
    • 기존 코드 영향 없음
  2. Deploy 단계

    • 코드에서 새 컬럼 사용 시작
  3. Contract 단계

    • 옛 컬럼 제거 / NOT NULL 추가 / 제약 강화

에이전트는 구조 변경 + 코드 변경을 같은 PR / 같은 배포에 넣지 않는다.


5.8.7 실행 전 필수 체크리스트

에이전트는 운영 마이그레이션 실행 전 반드시:

  • 테이블 크기 / 레코드 수 추정
  • 락 발생 가능 여부 분석
  • 트랜잭션 사용 여부 확인
  • strong_migrations 경고 여부 확인
  • dry-run / review 모드로 SQL 미리보기

위험도가 높으면:

  • 자동 실행 ❌
  • 리뷰 제안 + 예상 락 시간 / 영향 범위 설명 필수

5.8.8 대표 사고 사례 (방지 대상)

  • 대형 테이블 add_column default → 수십 분 락
  • add_index without concurrently → 전체 서비스 대기
  • 코드 먼저 배포 후 컬럼 rename → 즉시 에러 폭발

요약: 마이그레이션은 코드 변경보다 위험하다. 에이전트의 기본 전략은: 작게, 나눠서, 동시에 호환되게, 락 없이 바꿔라.

6. 자동 수정 vs 리뷰 제안: 운영 정책

6.1 자동 수정(안전)

  • snake_case / CamelCase / 상수 표기
  • 명백한 오탈자
  • 프로젝트에 이미 RuboCop/Formatter가 강제하는 범위

6.2 리뷰 제안(사람 확인 필요)

  • usernamename처럼 도메인 의미가 바뀔 수 있는 변경
  • association/route 이름 변경 (API/DB/외부 영향 가능)
  • public method rename

에이전트는 리뷰 제안의 경우:

  • 변경 이유(읽기 쉬움/중복 제거/도메인 명확화)
  • 영향 범위(검색된 참조 수, migration 필요 여부)
  • 대안 2~3개 를 같이 제시한다.

7. 프로젝트 적응(학습) 규칙

에이전트는 작업 시작 시 아래를 스캔해서 프로젝트의 실제 스타일을 우선 학습한다.

  • rubocop.yml, standardrb 설정, rubyfmt 여부
  • 기존 모델의 컬럼 네이밍 패턴(is_* vs 형용사형 boolean)
  • 컨트롤러 네이밍(Admin:: 네임스페이스 사용 여부)
  • 서비스 객체 디렉토리(app/services, app/interactors, lib/ 등)

학습 결과는 “프로젝트 프로필”로 캐시하고, 이후 제안/생성에 반영한다.


8. 간단 체크리스트(에이전트가 PR 전에 확인)


부록 A. 룰 예시 (before/after)

A1) 중복 의미 제거

  • Before: user.username (실제 의미가 ‘표시 이름’이라면)
  • After: user.name 또는 user.display_name

A2) 변수명 정리

  • Before: u = User.find(params[:id])
  • After: user = User.find(params[:id])

A3) 컬렉션명

  • Before: user_list = User.active
  • After: users = User.active

부록 B. 공식 문서 참고 링크 (에이전트 지식 소스)

에이전트는 아래 **공식 문서 링크를 1차 기준(소스 오브 트루스)**으로 삼아 규칙을 해석하고, 프로젝트별 차이가 있을 때는 이 문서들을 우선 조회한다.

B1) Rails Command Line / Generators

B2) Naming / Conventions (ActiveRecord, Rails 전반)

B3) Date / Time / Boolean 관련

B4) Autoload / 파일-상수 매핑 (Zeitwerk)

B5) Code Generation 커스터마이즈


운영 가이드

  • 에이전트는 규칙 충돌 또는 불확실 상황에서 위 링크를 자동 참조하거나, 최소한 해당 가이드를 근거로 리뷰 메시지를 생성한다.
  • Rails 버전 차이가 있을 경우, 프로젝트의 Rails.version에 맞는 가이드 URL을 우선 사용한다.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment