Restdocs+Swagger API문서 TroubleShooting (1)

dev_Hyun·2023년 12월 25일
0

문제 상황

북마크 관리 웹 프로젝트는 API 문서 생성 도구로 Spring REST DocsSwagger 를 결합한 형태를 선택했습니다.

openapi3 으로 생성된 OpenAPISpec의 문서 파일(open-api-3.0.1.json)을 swagger-ui으로 호출하여 동적인 API 문서를 보여주기 위함입니다.

로컬 상에서는 정상적으로 Swagger가 json 정적파일을 호출하는데 반해, 배포 후 아래와 같은 에러가 발생했습니다.

Errors
Parser error on line 15
end of the stream or a document separator is expected

정보 수집 및 원인 추론

  1. 백엔드 서버에 저장된 static 자원을 반환하기 위한 설정이 잘못되어 있을 수 있다.

    • addResourceHandlers 메서드의 오버라이드를 점검할 것.
  2. open-api-3.0.1.json 파일에 오타 또는 문법적 오류가 있다. (원인X)

  3. openapi3 으로 OpenAPISpec 문서를 생성하기 위한 설정 중, server 프로퍼티가 localhost:{port} 으로 시작되어 있다. (원인X)

    • localhost도메인 으로 변경해본 결과, API 테스트를 위한 server를 설정하기 위한 프로퍼티 였음을 알게됨.

Plan B

해당 이슈를 백엔드 서버에서 해결하지 못할 경우를 대비해, 다음 두 가지 대안을 떠올렸습니다.

  1. Docker Swagger Container에서 API 문서를 반환
  2. Github hosting을 통해 API 문서를 반환

API 문서를 다른 호스팅 도구로 배포할 수 있기에 반드시 백엔드 서버에서 제공해야할 의무는 없다고 판단했습니다. 그럼에도 별도의 도구를 추가하는 것 보다 현재의 상황 즉, 백엔드 서버에서 문서를 반환하도록 해결하는 것을 최우선 목표로 설정했습니다. 만약 데드라인 내에 시도할 수 있는 모든 방법으로 해결하지 못한다면 위 대안을 고려할 계획이었습니다.

과정 1) Github Actions, DB Test

Github Actions 를 통해 Auto CI/CD 되는 과정을 다시 살펴보니, 아직 해결하지 못한 문제가 남아있었습니다.

// github actions 일부

- name: Execute Gradle build
  run: ./gradlew clean build -x test

RESTdocs 도구를 사용하고 있기 때문에 API 문서를 생성하기 위해서는 Test가 수행되어야 하는데, 현재는 위와 같이 테스트 과정을 제외하고 build하고 있습니다. 제외된 이유는 Test가 정상 동작하기 위해서는 DB Connection이 되어야 하지만, Github Actions에서 local에 설치된 DB에 접근할 수 없기 때문입니다. 따라서, Github Actions 에서 build 시 test 과정에서 사용될 Database가 필요했습니다.

1-1) DB Test를 위한 설정 파일 업로드

DB Test를 위해 사용되는 파일은 세 가지 입니다. Test 수행시 동작할 설정파일(application.properties), Test DB에 필요한 Table을 생성하는 sql파일(schema-mariadb-init.sql) 그리고 Test 과정에서 사용될 데이터 생성을 위해 삽입 쿼리가 저장된 sql파일(data.sql)이 해당됩니다.

이들은 보안상의 이유로 .gitignore 파일에 의해 저장소에 제외됩니다. 따라서 github secrets 에 base64 방식으로 인코딩하여 저장하고, github actions workflow 에서 디코딩하여 파일을 생성하도록 합니다.

No such file or directory 오류

위에서 언급한 세 파일을 생성하기 위해, Remote 저장소에는 존재하지 않는 ./src/test/resources 경로를 생성하고 파일을 생성하고자 했으나 다음과 같이 No such file or directory 오류가 발생했습니다.

오류가 발생되는 workflow 파일을 살펴보면 mkdir 명령어를 통해 경로를 생성했음에도 다음번째 파일을 생성하는 시점에서는 명시한 경로를 찾지 못하고 있었습니다. mkdir 명령어를 통해 생성한 resources 폴더가 실제 remote 저장소에는 존재하지 않기 때문에 uses: actions/checkout 을 수행할 경우 해당 폴더를 인식하지 못하기 때문입니다.

따라서 세 가지 파일을 생성하는 과정을 아래와 같이 한 번의 run으로 통합하여 수정한 결과 정상적으로 경로 및 파일이 생성되었습니다.

      # Create files for database test
      - run: |
          mkdir -p ./src/test/resources
          touch ./src/test/resources/application.properties
          echo -e "${{secrets.APPLICATION_TEST}}" | base64 --decode > ./src/test/resources/application.properties
          touch ./src/test/resources/data.sql
          echo -e "${{secrets.DATA_SQL}}" | base64 --decode > ./src/test/resources/data.sql
          touch ./src/test/resources/schema-mariadb-init.sql
          echo -e "${{secrets.INIT_SQL}}" | base64 --decode > ./src/test/resources/schema-mariadb-init.sql
      - uses: actions/upload-artifact@v3
        with:
          name: application.properties
          path: ./src/test/resources/application.properties
          retention-days: 1
      - uses: actions/upload-artifact@v3
        with:
          name: data.sql
          path: ./src/test/resources/data.sql
          retention-days: 1
      - uses: actions/upload-artifact@v3
        with:
          name: schema-mariadb-init.sql
          path: ./src/test/resources/schema-mariadb-init.sql
          retention-days: 1

1-2) Github Actions에서 MariaDB 사용하기

필요한 파일은 정상적으로 업로드 하였으니 이제는 테스트를 수행할 데이터베이스가 필요합니다. Github Actions Market 에서 검색한 결과 두가지 도구가 존재했고 그 중 getong/mariadb-action@v1.1 을 사용했습니다.

github action 은 Mysql database를 기본적으로 탑재하고 있습니다. 그러나 해당 프로젝트는 mariaDB를 사용하고 있고, 두 데이터베이스가 모두 존재할 경우 충돌이 발생될 것을 고려하여 Mysql의 동작은 중지하는 과정을 workflow에 포함하였습니다.

	  # Shutdown the Default MySQL
      - name: Shutdown Ubuntu MySQL (SUDO)
        run: sudo service mysql stop

      # MariaDB for Springboot Test - getong/mariadb-action@v1.1
      - name: Set up MariaDB
        uses: getong/mariadb-action@v1.1
        with:
          host port: 3306
          container port: 3306
          mariadb version: '10.6'
          mysql database: '{사용할 데이터베이스 이름}'
          mysql root password: ${{ secrets.MARIADB_ROOT_PASSWORD }}
      # start mariadb
      - run: sudo systemctl start mariadb.service

정상적으로 MariaDB가 설치 되었음에도, db test 과정에서 아래와 같이 오류가 발생했습니다.

2편에서 계속됩니다.

profile
공룡, 다람쥐 그리고 돌고래!

0개의 댓글