Grape API를 위한 OAS 3.1 문서화 솔루션을 구축하기 위한 과정은 두 가지 주요 단계로 진행되었습니다.
1. 사용 가능한 엔드포인트 확보
-
라우트 추출: 애플리케이션 내의 모든 Grape 엔드포인트를 식별하는 것이 첫 번째 과제였습니다. 이를 위해
grape-rails-routes젬의 코드를 참고하여Grape::API를 상속하는 모든 클래스에서 라우트 정보를 추출하는 방법을 고안했습니다.ruby def extract_grape_routes grape_klasses = ObjectSpace.each_object(Class).select { |klass| klass < Grape::API } routes = grape_klasses.flat_map(&:routes).uniq { |r| r.path + r.request_method.to_s } routes = routes.map { |route| OasRouteBuilder.build_from_grape_route(route) } filter_routes(routes) end이 코드를 통해 Grape 클래스에 정의된 모든 고유한 라우트 목록을 확보할 수 있었습니다. -
문서화 정보 접근의 난점: 그러나 Grape 엔드포인트의 실제 로직은 인스턴스 메서드가 아닌
Proc형태로 정의되어 있어, 주석을 직접 파싱하여 문서화 정보를 추출하는 것은 거의 불가능하다는 문제에 직면했습니다.
2. Grape의 desc 및 detail 활용
-
솔루션: 위 문제에 대한 가장 간단하고 효과적인 해결책으로, Grape 자체에서 제공하는
desc블록과detail태그를 활용하는 방식을 채택했습니다. -
OasCore 태그 삽입:
detail태그 내부에 OasCore의 문서화 태그(예:@summary,@parameter,@response,@response_example등)를 직접 포함시켜 OpenAPI 스펙을 정의합니다. -
예시:
ruby desc "Returns a list of Users." do detail <<~OAS_GRAPE # @summary Returns a list of Users. # @parameter offset(query) [Integer] Used for pagination of response data. default: (0) minimum: (0) # @parameter limit(query) [Integer] Maximum number of items per page. default: (25) minimum: (1) maximum: (100) # # @parameter status(query) [Array<String>] Filter by status. enum: (active,inactive,deleted) # # @parameter X-front(header) [String] Header for identifying the front. minLength: (1) maxLength: (50) # # @response Success response(200) [Array<Hash{ id: Integer}>] # # @response_example Success(200) # # [ JSON # # [ # # { "id": 1, "name": "John", "email": "[email protected]" }, # # { "id": 2, "name": "Jane", "email": "[email protected]" } # # ] # # ] OAS_GRAPE end get do { users: @@users } end이러한 접근 방식은 기존 OasCore 통합 방식과는 다소 차이가 있지만, Grape API를 위한 OAS 3.1 문서화 및 내장 UI 제공이라는 목표를 성공적으로 달성할 수 있게 합니다.