1. 선택적 속성 처리의 문제점
Rails 애플리케이션에서 스캐폴딩(Scaffold)을 통해 생성된 기본 폼을 사용할 때, ‘선택 사항’인 텍스트 필드를 비워두고 제출하면 서버에는 빈 문자열("")이 전달됩니다. Rails의 기본 동작은 이 빈 문자열을 그대로 데이터베이스에 저장하는 것입니다.
- 데이터 혼재: 데이터베이스 내에 어떤 레코드는
NULL을 가지고, 어떤 레코드는""를 가지게 되어 쿼리 시where(attribute: nil)와where(attribute: "")를 모두 고려해야 하는 불편함이 생깁니다. - 일관성 결여: 데이터의 상태가 통일되지 않아 프레젠테이션 레이어에서 값을 출력할 때마다 추가적인 조건문 처리가 필요해집니다.
2. Rails normalizes 메서드 소개
Rails 7.1부터 도입된 normalizes 메서드는 속성 값이 할당될 때 특정 로직을 거쳐 데이터를 변환(정규화)할 수 있게 해줍니다. 이 메서드는 ActiveRecord 모델 내에서 선언적으로 사용됩니다.
ruby
class Example < ApplicationRecord
normalizes :optional_attribute, with: ->(value) { value.presence }
end
3. Object#presence의 역할
위의 코드에서 사용된 presence 메서드는 Rails의 ActiveSupport 확장 기능 중 하나로, 다음과 같이 동작합니다:
- 객체가 존재하면(present?) 자기 자신을 반환합니다.
- 객체가 비어있으면(blank?)
nil을 반환합니다. - 빈 문자열(
"")은 Rails에서blank로 간주되므로,presence를 호출하면 결과적으로nil이 반환됩니다.
4. 실제 적용 및 동작 확인
normalizes를 모델에 적용한 후의 변화는 다음과 같습니다.
- 데이터 입력: 사용자가 브라우저 폼에서 선택적 필드를 비워둔 상태로 제출합니다.
- 로그 확인: Rails 로그를 보면
optional_attribute에 빈 문자열("")이 전달된 것을 확인할 수 있습니다. - 자동 정규화: 모델에 값이 할당되는 순간
normalizes블록이 실행되어 빈 문자열이nil로 변환됩니다. - 데이터베이스 저장: 최종적으로 데이터베이스에는 빈 문자열 대신
NULL값이 저장됩니다. - 검증:
rails console에서 해당 레코드를 조회하면 속성 값이nil로 깔끔하게 정리되어 있음을 확인할 수 있습니다.
5. 활용 팁 및 권장 사항
- 전역적 적용: 애플리케이션 내에서
nil과 빈 문자열이 혼용되는 것을 방지하기 위해, 모든 선택적 문자열 속성에 대해 이 패턴을 적용하는 것이 좋습니다. - 대소문자 정규화:
normalizes는 단순히nil변환뿐만 아니라 이메일 주소를 소문자로 변환하거나(value.downcase), 문자열 앞뒤 공백을 제거하는(value.strip) 용도로도 매우 유용합니다. - 가독성 향상:
_1과 같은 단축 블록 인수를 사용하여with: -> { _1.presence }와 같이 더 간결하게 작성할 수 있습니다.