본문으로 건너뛰기

ActiveRecord의 create_with를 활용한 레코드 생성 속성 사전 설정

Find or Create Records with Preset Attributes using create_with

작성자
발행일
2026년 01월 13일
https://joshfrankel.me/blog/find-or-create-records-with-preset-attributes-using-create-with/

핵심 요약

  • 1 RabbitMQ 메시지 처리 중 누락된 관련 레코드(User)를 find_or_create_by로 자동 생성하는 방법을 설명합니다.
  • 2 find_or_create_by의 블록 구문과 비교하여 create_with를 사용한 레코드 생성 속성 사전 설정의 장점을 제시합니다.
  • 3 create_with는 find_or_create_by와 연계하여 레코드 조회 조건은 유지하면서 생성 시 필요한 속성을 깔끔하게 지정하는 방법을 제공합니다.

도입

최근 RabbitMQ 메시지 브로커 인프라를 활용하여 두 Rails 애플리케이션 간 이벤트를 조율하고 데이터를 동기화하는 작업이 증가하고 있습니다. 특히, 특정 공유 데이터의 일관성을 유지하기 위해 이벤트 기반으로 레코드를 생성하거나 업데이트하는 과정에서 종종 필요한 연관 레코드가 존재하지 않아 문제가 발생합니다. 본 글에서는 이러한 상황에서 ActiveRecord의 find_or_create_by 메서드를 사용하여 누락된 연관 레코드를 자동으로 생성하는 기법과, 레코드 생성 속성을 미리 설정할 수 있는 create_with 구문의 활용법을 심도 있게 다룹니다.

RabbitMQ 메시지 처리 시 Group 레코드 생성 과정에서 Creator(User) 레코드가 존재하지 않아 발생하는 유효성 검사 오류는 흔한 문제입니다. 초기 구현에서는 retrieve_creator 메서드가 nil을 반환하여 Group 생성에 실패할 수 있습니다.

문제 상황: Creator(User) 부재 시 Group 생성 실패

ruby class GroupCreateEventProcessor # ... def work(message) parsed_message = JSON.parse(message) creator = retrieve_creator(external_id: parsed_message[:external_creator_id]) # creator가 nil이면 Group.create에서 creator_id: nil이 되어 유효성 오류 발생 group = Group.create( external_id: parsed_message[:external_id], name: parsed_message[:name], creator_id: creator.id # creator가 nil일 경우 에러 ) # ... end private def retrieve_creator(external_id:) User.find_by(external_id:) # User가 없으면 nil 반환 end end User 모델의 email 필드가 NOT NULL 제약 조건과 presence: true 유효성 검사를 가지고 있어, 단순히 User.create를 시도하면 email 누락으로 실패합니다.

해결책 1: find_or_create_by 블록 구문 활용

누락된 User 레코드를 자동으로 생성하려면 find_or_create_by 메서드를 사용하고, User 모델의 유효성 검사를 통과하기 위해 email과 같은 필수 속성을 블록 내에서 설정해야 합니다.

ruby class GroupCreateEventProcessor # ... private def retrieve_creator(external_id:, user_email:) User.find_or_create_by(external_id:) do |user| user.email = user_email # 누락된 User 생성 시 email 설정 end end end 이 방식은 필요한 레코드가 없을 경우 자체적으로 복구하는 흐름을 제공하여, 새로운 Group 생성에 필요한 User 레코드를 보장합니다.

해결책 2: create_with 구문 활용

`ActiveRecord::QueryMethods

create_with는 레코드 생성 시 사용될 속성을 미리 설정하는 기능을 제공합니다. 이를 find_or_create_by`와 함께 사용하여 코드를 더욱 간결하게 만들 수 있습니다.

ruby def retrieve_creator(external_id:, user_email:) User .create_with(email: user_email) # 생성 시 email 속성 사전 설정 .find_or_create_by(external_id:) # external_id로 조회 또는 생성 end 이 방식은 external_id로 레코드를 조회하는 특수성을 유지하면서, 레코드 생성 시 RabbitMQ 메시지에서 오는 user_email을 사용하도록 지시합니다. create_with는 블록 구문에 비해 단순한 속성 설정에 더 깔끔한 문법을 제공하지만, 복잡한 로직을 통해 값을 생성해야 할 경우에는 블록 구문이 더 유연합니다.

결론

본 글에서는 RabbitMQ 메시지 처리와 같은 이벤트 기반 시스템에서 ActiveRecord의 find_or_create_by와 create_with 메서드를 활용하여 누락된 연관 레코드를 효율적으로 관리하는 방법을 살펴보았습니다. find_or_create_by의 블록 구문은 생성 시 커스텀 로직을 포함할 수 있는 유연성을 제공하는 반면, create_with는 레코드 조회 조건과 생성 속성 설정을 명확하게 분리하여 코드를 더욱 간결하게 만드는 장점이 있습니다. 이 두 기법은 Rails 애플리케이션에서 데이터 동기화 및 일관성을 유지하는 데 필수적인 도구로, 개발자는 상황에 맞는 최적의 방법을 선택하여 견고하고 유지보수하기 쉬운 시스템을 구축할 수 있습니다.

댓글0

댓글 작성

댓글 삭제 시 비밀번호가 필요합니다.

이미 계정이 있으신가요? 로그인 후 댓글을 작성하세요.

0/1000
정중하고 건설적인 댓글을 작성해 주세요.