다형성 연관
Rails의 다형성 연관(Polymorphic Associations) 사용을 피해야 하는 이유와 별도 테이블을 사용하는 대안적 해결책을 설명합니다.
요약 : 다형성 연관 대신 항상 별도 테이블을 사용하세요. Rails에서는 소위 "다형성 연관(polymorphic associations)"을 정의하는 것이 가능합니다. 이는 보통 테이블에 두 개의 칼럼, 즉 타깃 타입 칼럼과 타깃 ID 칼럼을 추가함으로써 동작합니다. 예를 들어, 이 글을 작성하는 시점에 members 테이블에는 다음과 같은 칼럼이 있습니다: source_type : 사용할 모델을 정의하는 문자열로, Project 또는 Namespace 가 될 수 있습니다. source_id : source_type 을 기반으로 조회할 행의 ID입니다. 예를 들어, source_type 이 Project 이면 source_id 에는 프로젝트 ID가 포함됩니다. 이러한 설정이 유용해 보일 수 있지만, 많은 단점이 있으므로 반드시 피해야 합니다. 낭비되는 공간 # 이 설정은 사용할 모델을 결정하기 위해 문자열 값에 의존하기 때문에 많은 공간을 낭비합니다. 예를 들어, Project 와 Namespace 의 경우 최대 크기는 9바이트이며, PostgreSQL을 사용할 때 문자열마다 1바이트가 추가됩니다. 행당 10바이트에 불과해 보일 수 있지만, 이러한 설정을 사용하는 테이블과 행이 충분히 많아지면 디스크 공간과 메모리(인덱스를 위한)를 상당히 낭비하게 됩니다. 인덱스 # 연관이 두 개의 칼럼으로 분리되어 있기 때문에, 쿼리를 효율적으로 수행하기 위해 복합 인덱스가 필요할 수 있습니다. 복합 인덱스 자체가 잘못된 것은 아니지만, 최적의 성능을 보장하려면 인덱스 내 칼럼 순서가 중요하기 때문에 설정하기가 까다로울 수 있습니다. 일관성 # 다형성 연관의 매우 큰 문제점 중 하나는 외래 키를 사용하여 데이터베이스(DB) 수준에서 데이터 일관성을 강제할 수 없다는 것입니다. DB 수준에서 일관성을 강제하려면 다형성 연관을 지원하는 자체 외래 키 로직을 작성해야 합니다. DB 수준에서 일관성을 강제하는 것은 건강한 환경을 유지하는 데 절대적으로 중요하며, 따라서 이것이 다형성 연관을 피해야 하는 또 다른 이유입니다. 쿼리 오버헤드 # 다형성 연관을 사용할 때는 항상 두 칼럼 모두를 사용하여 필터링해야 합니다. 예를 들어, 다음과 같은 쿼리를 작성하게 될 수 있습니다: SELECT * FROM members WHERE source_type = 'Project' AND source_id = 13083; 여기서 두 칼럼 모두에 인덱스가 설정되어 있다면 PostgreSQL은 쿼리를 상당히 효율적으로 수행할 수 있습니다. 하지만 쿼리가 복잡해질수록 이러한 인덱스를 효과적으로 사용하지 못할 수 있습니다. 혼합된 책임 # 함수와 클래스와 마찬가지로, 테이블은 단일 책임을 가져야 합니다: 미리 정의된 특정 칼럼 집합으로 데이터를 저장하는 것입니다. 다형성 연관을 사용하면 서로 다른 유형의 데이터(경우에 따라 다른 칼럼 집합 포함)를 동일한 테이블에 저장하게 됩니다. 해결책 # 다행히도 이러한 문제들에 대한 해결책이 있습니다: 동일한 테이블에 저장하려는 각 유형에