ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OpenAPI와 스웨거를 활용한 실전 API 설계를 읽고 ... (4, 마지막)
    개발하면서/타인글보면서 2024. 5. 12. 20:42
    반응형

    지금까지 구현한 API에서 오류가 발생하는 상황을 살펴보고 예외 처리를 어떻게 하는지 알아본다.

    그리고 JSON 스키마를 이용하여 엄격하게 입력값 유효성 검증 하는 방법도 알아본다.

     

    모든 일이 다 잘되기를 바라지만 현실은 그렇지 못하다.
    실패를 항상 피해 갈 수는 없지만 그 실패를 발견하고, 복구하고, 고치는 방법을 찾아내야 한다.

     

    모든 API에 대해 클라이언트 에러가 발생할 상황을 나열하고 범주화해서 상태 코드 3개로 매핑한다.

    상태 설명 발생 위치
    400 유효하지 않은 입력 POST, PUT, 쿼리 파라미터가 포함된 GET을 사용하는 엔드포인트
    403 허용되지 않은 접근 권한 관련 비즈니스 로직이 포함된 모든 엔드포인트
    404 자원이 존재하지 않음 리소스 엔드포인트 및 서브 리소스 컬렉션 엔드포인트

     

    오류 메시지가 사람이 이해하는 것을 넘어 클라이언트에서 에러 처리를 하기 위해선 일관된 형식의 에러 메시지가 필요하다.

    두 개의 에러 형식을 알아보자.

     

    1. OAS 도구 형식

    {
      "message": "error",  # 전반에 걸쳐 사람이 이해할 수 있는 에러 메시지
      "errors": [
        {
          "path": "/jobs",   # 입력값 유효성 오류일 때는 JSONPath, 그 외에는 URL 경로
          "message": "error",  # 필드에 발생한 특정 에러에 대해 사람이 읽을 수 있는 에러 메시지
          "errorCode": "식별자"  # 에러 타입을 알려주는 식별자 ex: "type.openapi.validation"
        }
      ]
    }

     

    2. problem+json 형식

    응답을 반환할 때 Content-Type 헤더가 application/json이 아닌 application/problem+json 으로 지정한다. RFC 7807

    {
      "type": "https://petsitter.designapis.com/problem/not-found",  # 에러 타입을 설명하는 URI
      "title": "not found resource",  # 사람이 읽을 수 있는 짧은 에러 제목
      "status": 404, # HTTP status code
      "detail": "not found resource #2 in jobs", # 사람이 읽을 수 있는 상세한 에러 설명
      "instance": "/jobs/2"  #문제 발생을 가리키는 URI
    }

     

    두개의 에러 응답을 components에 추가해 보자.

    openapi: 3.0.3
    #...
    components:
      schemas:
        OASError:   # <-- OAS 도구 에러 형식 공통 스키마
          type: object
          properties:
            message:
              type: string
              description: Human-readable error message
            errors:
              type: array
              items:
                type: object
                properties:
                  path:
                    type: string
                    description: |
                      For input validation errors, identifies where
                      in the JSON request body the error occurred.
                  message:
                    type: string
                    description: Human-readable error message.
                  errorCode:
                    type: string
                    description: Code indicating error type.
        Problem:    # <-- problem+json 에러 형식 공통 스키마
          type: object
          properties:
            type:
              type: string
              description: URI indicating error type.
            title:
              type: string
              description: Human-readable error title.
            status:
              type: integer
              description: HTTP status code.
            detail:
              type: string
              description: Human-readable error details.
            instance:
              type: string
              description: URI indicating error instance.

     

    OAS 도구 처리: 입력값 유효성 검사(400), 인증 오류(401)

    Problem 처리: 리소스가 존재하지 않은 경우(404), 권한 오류(403)

     

    고급 JSON 스키마를 이용한 입력값 유효성 검증

    • 필드를 읽기 전용 또는 쓰기 전용으로 설정
    • 숫자 제약 조건 강제
    • 문자열 형식 강제
    • 배열 제약 조건 강제
    • 열거형 데이터 정의
    • 필수 및 선택 프로퍼티 나열
    • 기본값 설정

    readOnly: 값을 읽을 수만 있고 값을 변경할 수는 없다. 응답에만 사용. ex: id property

    writeOnly: 값을 읽을 수는 없고 값을 변경할 수는 있다. 요청에만 사용. ex: password property

     

    multipleOf: 입력한 수의 배수만 입력 가능

    minimum: 하한값(입력값 포함)

    exclusiveMinimum: 하한값 입력값 제외 여부

    maximum: 상한값(입력값 포함)

    exclusiveMaximum: 상한값 입력값 제외 여부

     

    minLength: 문자열 최소 길이

    maxLength: 문자열 최대 길이

    pattern: 정규표현식 지정

    format: JSON 스키마와 OpenAPI 명세에서 유효성 검증할 때 사용하는 공통 형식  strings

     

    minItems: 배열에 저장 가능한 최소 개수

    maxItems: 배열에 저장 가능한 최대 개수

    uniqueItems: 중복 허용 여부

     

    정의된 값만 입력으로 받는다면 enum사용을 추천한다.

    파라미터는 개별 파라미터에 required: true/false 지정이 가능한데
    프로퍼티는 객체에 required를 사용하고 프로퍼티 이름을 지정한다.

     

    마지막으로 프로퍼티의 기본값 설정은 default를 이용한다.

     

    지금까지 알아본 JSON 스키마 기능을 예제로 알아보자

    openapi: 3.0.3
    info:
      title: PetSitter API
      version: "0.1"
      
    paths: {}
      
    components:
      schemas:
        SchemaName:
          type: object
          properties:
            id:
              type: integer
              readOnly: true    # readOnly
            password:
              type: string
              format: password  # password format
              writeOnly: true   # writeOnly
            my_number:
              type: integer
              multipleOf: 2     # 숫자형 제약조건
              minimum: 2
              maximum: 20
              exclusiveMinimum: true
              exclusiveMaximum: true
            
        MyBingoNumber:
          type: object
          properties:
            my_numbers:
              type: array
              minItems: 1     # 배열 제약조건
              maxItems: 2
              uniqueItems: true
              items:
                type: integer
            gender:
              type: string
              enum:            # enum
                - male
                - female
                - others
        Contact:
          type: object
          properties:
            name:
              type: string
            email:
              type: string
              format: email    # email format
            phone:
              type: string
              default: 010-0000-0000   # default keyword
            address:
              type: object
          required:            # 필수 프로퍼티 지정
            - name
            - email

     


    지금까지 "OpenAPI와 스웨거를 활용한 실전 API 설계" 소개한 내용 중 기술적인 내용들을 나름 정리해 보았다.

    이렇게 편안하게 읽히는 책을 접하면 다음번에 저자 또는 번역가 분이 책을 내면 관심이 가는 건 어쩔 수 없다.

     

    주식 쪽 OpenAPI 연동을 쉽게 하려고 책을 집었는데 생각 외로 좋은 시간이었다.

    반응형

    댓글

Designed by Tistory.