Web

OpenAPI 3.0

dev_roach 2021. 11. 12. 09:28
728x90

최근 회사 API DOC 라이브러리를 Swagger 에서 호환할 수 있게 하면서 Swagger 가 OpenAPI 를 준수하고 있다는 것을 처음알았다.

그래서 회사 공고에도 많은 OpenAPI 는 도대체 무엇일까? 라는 생각이 들게 되었다.

OpenAPI 3.0?

공식문서에 정의되어 있는 내용은 아래와 같다.

 

"OpenAPI Specification(OAS) 는 RESTful API 에 대한 표준 언어에 구애받지 않는 인터페이스를 정의하여 소스코드 또는, 설명서 또는 네트워크 트래픽 검사 없이도 서비스의 기능을 이해하고 찾을 수 있게 도와줍니다."

 

OpenAPI 는 위의 설명과 같이 RESTful API 에 대한 인터페이스를 생성해야 하므로 지켜야할 몇가지 규칙이 있다.

 

첫번째로는 OpenAPI 문서는 API 에 대한 설명을 적어야 한다는 것이다. 너무 당연하니 다음으로 넘어가겠다.

두번째로는 URL 의 PathParameters 는 '{}' 로 마킹하는 것이 가능하다고 합니다.

세번째로는 미디어 정의는 RFC6838 을 준수해야 한다고 합니다.

네번째로는 HTTP 상태코드는 RFC7231 을 준수해야 하며 대략적인 내용은 아래와 같습니다.

규격

OpenAPI 문서를 만들기 위해서는 규격이 필요합니다.

즉 어떤 파일 타입으로 OpenAPI 문서를 만드는 것이 가능한지를 알아야 합니다.

공식 문서에 적혀있는 가능한 파일타입은 "JSON, YAML" 형태의 타입입니다.

데이터 타입

OPEN API 3.0 규격에서 지원해주는 데이터 타입은 정해져 있습니다.

Git-Hub 공식 문서 데이터 타입 사진

일단 기본적으로 우리가 보통 사용하는 많은 타입을 지원한다.

다만 Null 이 없다는 점이 있는데 OpenAPI 에서는 null 을 데이터 타입으로 보지 않는다.

그래서 null 이 가능한 경우에는 Nullable 옵션 을 통해 대체하면 된다.

Rich Text Formatting

Description 필드를 통해서 Document 에 대한 설명을 달 수 있다.

해당 description 필드에는 Markdown 형태로도 작성이 가능하다.

다만 CommonMark 2.7 을 준수해야 하며 document 를 Rendering 하는 Site 에 Markdown Rendering 기능이 지원해야 한다.

Schema

OpenAPI 3.0 문서를 작성하기 위해서는 Schema property 규격을 지켜야 하는데

이 Property 들에는 반드시 필요한 속성들과 Optional 한 속성들이 있다. 여기서는 REQUIRED / OPTIONAL 이라고 할 것이다.

openapi(REQUIRED)

openapi(REQUIRED) 이며 반드시 OAS version 을 명시해주어야 한다.

Info(REQUIRED)

info(REQUIRED) 이며 여기에는 Tool 에서 사용되는 Metadata 를 기입해주어야 한다.

{
  "title(REQUIRED)": "Sample Pet Store App",
  "description": "This is a sample server for a pet store.",
  "termsOfService": "http://example.com/terms/",
  "contact": {
    "name": "API Support",
    "url": "http://www.example.com/support",
    "email": "support@example.com"
  },
  "license": {
    "name": "Apache 2.0",
    "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
  },
  "version(REQUIRED)": "1.0.1"
}

위의 형태처럼 info 를 적어주면 된다.

위에서 설명했듯이 description 필드는 Markdown 형태로 작성이 가능하다.

servers(OPTIONAL)

여기에는 연결 가능한 서버 정보주소를 적어주면 된다.

형태는 아래와 같다.

{
  "servers": [
    {
      "url": "https://development.gigantic-server.com/v1",
      "description": "Development server"
    },
    {
      "url": "https://staging.gigantic-server.com/v1",
      "description": "Staging server"
    },
    {
      "url": "https://api.gigantic-server.com/v1",
      "description": "Production server"
    }
  ]
}

paths(REQUIRED)

API가 수행가능한 URL 을 명시해주면 된다.

{
  "/pets": {
    "get": {
      "description": "Returns all pets from the system that the user has access to",
      "responses": {
        "200": {          
          "description": "A list of pets.",
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/pet"
                }
              }
            }
          }
        }
      }
    }
  }
}

components(OPTIONAL)

명세에 대한 사양 정보를 담고 있는 속성입니다.

재사용 가능한 Object 집합을 보유하고 있으며 JSON 형태는 아래와 같습니다.

"components": {
  "schemas": {
    "Category": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        }
      }
    },
    "Tag": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        }
      }
    }
  },
  "parameters": {
    "skipParam": {
      "name": "skip",
      "in": "query",
      "description": "number of items to skip",
      "required": true,
      "schema": {
        "type": "integer",
        "format": "int32"
      }
    },
    "limitParam": {
      "name": "limit",
      "in": "query",
      "description": "max records to return",
      "required": true,
      "schema" : {
        "type": "integer",
        "format": "int32"
      }
    }
  },
  "responses": {
    "NotFound": {
      "description": "Entity not found."
    },
    "IllegalInput": {
      "description": "Illegal input for operation."
    },
    "GeneralError": {
      "description": "General Error",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/GeneralError"
          }
        }
      }
    }
  },
  "securitySchemes": {
    "api_key": {
      "type": "apiKey",
      "name": "api_key",
      "in": "header"
    },
    "petstore_auth": {
      "type": "oauth2",
      "flows": {
        "implicit": {
          "authorizationUrl": "http://example.org/api/oauth/dialog",
          "scopes": {
            "write:pets": "modify pets in your account",
            "read:pets": "read your pets"
          }
        }
      }
    }
  }
}

security(OPTIONAL)

API 를 실행하는데 필요한 보안 매커니즘을 명시합니다.

{
  "petstore_auth": [
    "write:pets",
    "read:pets"
  ]
}

tags(OPTIONAL)

부수적으로 추가할 Metadata 를 이곳에 기술해주면 된다.

{
	"name": "pet",
	"description": "Pets operations"
}

externalDocs(OPTIONAL)

추가적으로 다른 Docs 가 있다면 추가적으로 표기해줄 수 있다.

{
  "description": "Find more info here",
  "url": "https://example.com"
}

 

공식문서를 읽어보면 더 세세하게 옵션들에 대해서 설명이 되어있다.

만약 궁금하면 읽어보는걸 추천하는데, 더 잘 이해하려면 실제 자신 API 하나를 명세에 맞게 작성해 보는것도 좋은 방법이라고 생각한다.

오늘은 간단하게 OAS 에 대해서 공부해보았다.

728x90

'Web' 카테고리의 다른 글

Spring Request Body Binding 파헤쳐보기  (0) 2022.01.02
Postman 헤더로 세션 로그인하기  (0) 2021.12.28