GraphQL 배열 인수
GitLab v19.1GitLab GraphQL API의 모든 배열 인수에는 남용 방지 및 성능 문제 예방을 위한 크기 유효성 검사가 있어야 합니다. validates 옵션을 사용하여 배열 크기 제한을 명시적으로 선언합니다: GraphQL-Ruby의 내장 유효성 검사 활용
GraphQL에서 배열 인수 유효성 검사#
개요#
GitLab GraphQL API의 모든 배열 인수에는 남용 방지 및 성능 문제 예방을 위한 크기 유효성 검사가 있어야 합니다.
유효성 검사 방법#
권장 방법: 명시적 유효성 검사 (목표 상태)#
validates 옵션을 사용하여 배열 크기 제한을 명시적으로 선언합니다:
argument :assignee_usernames, [GraphQL::Types::String],
required: false,
validates: { length: { maximum: Types::BaseArgument::MAX_ARRAY_SIZE } },
description: "Usernames of users assigned to the merge request " \
"(maximum is #{Types::BaseArgument::MAX_ARRAY_SIZE} usernames)."
장점:
-
명확하고 명시적
-
인수 정의에서 직접 확인 가능
-
기존 코드베이스 패턴과 일관성 유지
-
GraphQL-Ruby의 내장 유효성 검사 활용
자동 유효성 검사 (전환 기간)#
전환 기간 동안, 명시적인 validates: { length: { maximum: ... } }가 없는 배열 인수는 BaseArgument에 의해 자동으로 100개 항목으로 제한됩니다.
# 이 인수는 자동으로 100개 항목으로 제한됩니다
argument :items, [GraphQL::Types::String],
required: false,
description: 'List of items.'
동작 방식#
BaseArgument 클래스는 스마트 감지를 구현합니다:
-
명시적 유효성 검사가 있는 경우: 명시된 제한값 사용 (자동 유효성 검사 없음)
-
명시적 유효성 검사가 없는 경우: 자동으로 100개 항목 제한 적용
# 명시적 유효성 검사 - 50을 제한값으로 사용
argument :limited_items, [GraphQL::Types::String],
validates: { length: { maximum: 50 } },
description: 'Limited to 50 items.'
# 명시적 유효성 검사 없음 - 자동으로 100개 항목으로 제한
argument :auto_limited_items, [GraphQL::Types::String],
description: 'Automatically limited to 100 items.'
마이그레이션 경로#
1단계: 자동 보호 (현재)#
모든 배열 인수는 자동으로 100개 항목 제한으로 보호됩니다.
2단계: 명시적 유효성 검사 추가#
모든 배열 인수에 명시적인 validates 선언을 점진적으로 추가합니다:
# 변경 전 (자동 유효성 검사에 의존)
argument :assignee_usernames, [GraphQL::Types::String],
required: false,
description: 'Usernames of users assigned to the merge request.'
# 변경 후 (명시적 유효성 검사)
argument :assignee_usernames, [GraphQL::Types::String],
required: false,
validates: { length: { maximum: Types::BaseArgument::MAX_ARRAY_SIZE } },
description: "Usernames of users assigned to the merge request " \
"(maximum is #{Types::BaseArgument::MAX_ARRAY_SIZE} usernames)."
3단계: 자동 유효성 검사 제거#
모든 배열 인수에 명시적 유효성 검사가 추가되면, BaseArgument에서 자동 유효성 검사를 제거할 수 있습니다.
상수#
Types::BaseArgument::MAX_ARRAY_SIZE#
배열 인수의 기본 최대 크기입니다 (현재 100).
일관성을 위해 이 상수를 사용하세요:
validates: { length: { maximum: Types::BaseArgument::MAX_ARRAY_SIZE } }
사용자 정의 제한#
특정 사용 사례에 대해 다른 제한값을 사용할 수 있습니다:
# 모듈 상수 사용
module WorkItems
module SharedFilterArguments
MAX_FIELD_LIMIT = 100
end
end
argument :ids, [::Types::GlobalIDType[::WorkItem]],
validates: { length: { maximum: WorkItems::SharedFilterArguments::MAX_FIELD_LIMIT } },
description: "Filter by global IDs (maximum is #{WorkItems::SharedFilterArguments::MAX_FIELD_LIMIT} IDs)."
오류 메시지#
유효성 검사가 실패하면, 사용자에게 명확한 오류 메시지가 표시됩니다:
"assigneeUsernames cannot accept more than 100 items"
예시#
올바른 예시#
# 예시 1: 기본 상수 사용
argument :user_ids, [GraphQL::Types::ID],
validates: { length: { maximum: Types::BaseArgument::MAX_ARRAY_SIZE } },
description: "User IDs (maximum is #{Types::BaseArgument::MAX_ARRAY_SIZE})."
# 예시 2: 사용자 정의 상수 사용
argument :label_names, [GraphQL::Types::String],
validates: { length: { maximum: WorkItems::SharedFilterArguments::MAX_FIELD_LIMIT } },
description: "Label names (maximum is #{WorkItems::SharedFilterArguments::MAX_FIELD_LIMIT})."
# 예시 3: 특정 사용 사례에 대한 사용자 정의 제한
argument :vulnerability_ids, [GraphQL::Types::ID],
validates: { length: { minimum: 1, maximum: 50 } },
description: "Vulnerability IDs (minimum 1, maximum 50)."
잘못된 예시#
# 잘못됨: 유효성 검사 없고 제한에 대한 설명도 없음
argument :items, [GraphQL::Types::String],
description: 'List of items.'
# 잘못됨: 상수 없이 하드코딩된 숫자 사용
argument :items, [GraphQL::Types::String],
validates: { length: { maximum: 100 } },
description: 'List of items (maximum is 100).'
테스트#
배열 인수가 있는 리졸버 또는 뮤테이션을 테스트할 때는 유효성 검사를 테스트합니다:
RSpec.describe Resolvers::MyResolver do
it 'accepts arrays within the limit' do
items = Array.new(50, 'item')
expect { resolve(items: items) }.not_to raise_error
end
it 'rejects arrays exceeding the limit' do
items = Array.new(101, 'item')
expect { resolve(items: items) }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
end
end