pluck과 select는 Rails에서 데이터베이스로부터 컬럼 값을 가져오는 데 사용되지만, 그 목적과 반환하는 데이터의 형태에서 명확한 차이를 보입니다.
pluck 사용 시점pluck은 주로 특정 컬럼의 원시 데이터(raw data) 배열이 필요할 때 사용됩니다. 이는 ActiveRecord 객체를 인스턴스화하지 않으므로 메모리 사용량이 적고 성능이 뛰어납니다.
- 간단한 목록 및 드롭다운:
- 예시: User.pluck(:name) -> [‘Alice’, ‘Bob’, ‘Charlie’]* 예시: User.pluck(:id, :name) -> [[1, “Alice”], [2, “Bob”]]* WHERE IN 절의 서브쿼리: 다른 쿼리를 위한 ID 배열이 필요할 때 효율적인 방법입니다.
- 쿼리 후 map 대체: User.all.map(&:name)과 같은 코드는 모든 사용자 레코드를 메모리에 로드한 후 map을 실행하지만, User.pluck(:name)은 처음부터 필요한 데이터만 가져오므로 훨씬 효율적입니다.
select 사용 시점select는 제한된 컬럼만 필요하더라도 반환된 객체에 대해 ActiveRecord의 기능(메서드 호출, 연관 관계 사용 등)을 활용해야 할 때 선택됩니다. select는 ActiveRecord 객체를 반환합니다.
- ActiveRecord 기능 활용: 반환된 객체에 대해 메서드를 호출하거나 ActiveRecord 연관 관계를 사용해야 할 경우 select가 올바른 선택입니다.
- 예시: User.select(:name) -> [#<User id: nil, name: “Alice”>, #<User id: nil, name: “Bob”>]* 예시: User.select(:id, :name) -> [#<User id: 1, name: “Alice”>, #<User id: 2, name: “Bob”>]* 효율적인 서브쿼리 생성: 쿼리를 중첩할 때 select는 종종 단일 데이터베이스 쿼리를 사용하는 서브쿼리를 생성하여 더 나은 성능을 제공합니다.
- 효율적인 select 서브쿼리 예시:```ruby
select는 서브쿼리를 생성하여 단일 데이터베이스 쿼리를 발생시킵니다.Post.where(user_id: User.active.select(:id))
생성된 SQL: SELECT “posts”.
- FROM “posts” WHERE “posts”.”user_id” IN (SELECT “users”.”id” FROM “users” WHERE “users”.”active” = TRUE)
* **비효율적인 pluck 서브쿼리 예시:**ruby
pluck은 즉시 데이터베이스를 조회하고, 그 후에 IN 절을 포함한 두 번째 쿼리가 실행됩니다.Post.where(user_id: User.active.pluck(:id))
생성된 SQL: SELECT “users”.”id” FROM “users” WHERE “users”.”active” = TRUE
SELECT “posts”.
- FROM “posts” WHERE “posts”.”user_id” IN (1, 2, 3, …)```### 주의할 점 (Pitfalls)
- select 시 선택되지 않은 속성 접근: select로 부분 객체를 로드한 후 선택되지 않은 속성에 접근하려 하면 Rails는 MissingAttributeError를 발생시킵니다.
- 기존 Relation에 pluck 사용 시 추가 쿼리: 이미 실행된 쿼리의 결과로 ActiveRecord 객체 배열이 있는 경우, 해당 배열에 pluck을 호출하면 불필요한 새 데이터베이스 쿼리가 트리거됩니다. 이 경우에는 Ruby의 기본 map 메서드를 사용하는 것이 더 효율적입니다.