본문 바로가기

배움의 즐거움/프로그래밍

(15) Graphql-ruby - 복잡성 & 깊이

반응형



Complexity & Depth


Prevent complex queries


필드는 "complexity" 값을 가지고 있는데 이는 정의에 의해 설정이 가능하다. 이 값은 상수 또는 proc 이 될 수 있고, 키워드 형태로 정의되거나 block 형태로 정의될 수 있다. 예를 보자.

# 상수 complexity:
field :top_score, Integer, null: false, complexity: 10

# 동적인 complexity:
field :top_scorers, [PlayerType], null: false do
  argument :limit, Integer, limit: false, default_value: 5
  complexity ->(ctx, args, child_complexity) {
    if ctx[:current_user].staff?
      # staff users 에게는 제한이 없음
      0
    else
      # `child_complexity` is the value for selections
      # which were made on the items of this list.

      # 아직 쿼리를 실행하지 않았기 때문에 몇개의 아이템이 featch 될지는 모르겠지만
      # 위에 정의한 limit argument 를 사용하여 대충 예상할 수 있다.
      args[:limit] * child_complexity
    end
  }
end


 max_complexity 값을 schema-level에 정의할 수 있다.

class MySchema < GraphQL::Schema
 # ...
 max_complexity 100
end


query-level 에서는 schema-level 에서 작성된 값을 오버라이드 할 수 있다.

MySchema.execute(query_string, max_complexity: 100)


nil 을 사용함으로써 완전히 validation 제거도 가능

# 😧 Anything goes!
MySchema.execute(query_string, max_complexity: nil)


complexity에 대해서 좀 더 활용하기 위해서, QueryComplexity 라는 query reducer를 사용할 수 있다. 각 쿼리의 값을 로그하기 위해 연동해보자.


class MySchema < GraphQL::Schema
  log_query_complexity = GraphQL::Analysis::QueryComplexity.new { |query, complexity| Rails.logger.info("[GraphQL Query Complexity] #{complexity}  | staff? #{query.context[:current_user].staff?}")}
  query_analyzer(log_query_complexity)
end


Prevent deeply-nested queries


사용자의 nesting의 깊이에 따라 이를 거부할 수도 있다. max_depth 를 schema-level 또는 query-level에 정의하면 된다.

# Schema-level:
class MySchema < GraphQL::Schema
  # ...
  max_depth 10
end

# Query-level 에서는 schema-level 설정 오버라이드
MySchema.execute(query_string, max_depth: 10)


nil 을 사용함으로써 완전히 validation 제거도 가능

# 해당 쿼리는 max_depth 유효성 검사 하지 않음
MySchema.execute(query_string, max_depth: nil)


depth 에 대해서 좀 더 활용하기 위해서, QueryDepth 라는 query reducer를 사용할 수 있다. 각 쿼리의 값을 로그하기 위해 연동해보자.

class MySchema < GraphQL::Schema
  log_query_depth = GraphQL::Analysis::QueryDepth.new { |query, depth| Rails.logger.info("[GraphQL Query Depth] #{depth} || staff?  #{query.context[:current_user].staff?}")}
  query_analyzer(log_query_depth)
end


* 해당 글은 번역기 돌리다가 크롬 번역기 말도 안되는 해석에 지친 본인이 나중에 참고할 의도로 대충대충 발로 해석한 것이니 참고용으로만 사용하시길 바랍니다.

* 출처: http://graphql-ruby.org/queries/complexity_and_depth.html



반응형