# API 연동 자동화(feat. OAS codegen)

{% embed url="<https://github.com/team-moeum/checkmate-backend/blob/develop/.github/workflows/oas.yml>" %}

{% embed url="<https://github.com/team-moeum/checkmate-frontend/blob/main/.github/workflows/oas.yml>" %}

## 문제 상황

Backend Engineer분들께서 Swagger로 API 문서를 작성하면 Frontend Engineer분들이 그걸 보면서 필요한 타입과 API 함수를 직접 만들어서 사용했어요.

하지만 시간이 지날수록 이 방식의 문제점이 드러났는데요. 크게 두 가지가 있었어요.

먼저 API 스펙이 변경될 때마다 프론트엔드 개발자가 수동으로 코드를 수정해야 했어요. 이 과정에서 휴먼에러 및 동기화 문제가 일어나기도 했어요.

두번째는 쓰는 단어가 다르기도 했어요. 예를 들어 회원가입을 register라고 부르는 사람이 있는 반면, signup이라고 부르는 것처럼 말이에요.

이런 문제들을 겪다 보니 "이걸 좀 더 효율적으로 할 수 있는 방법이 없을까?" 하는 고민이 커졌고, 결국 API 연동 프로세스를 자동화해보기로 했어요.

***

## 기존 방식

1. 백엔드 개발자가 Swagger로 API 문서 작성
2. 프론트엔드 개발자가 Swagger 문서 참고하여 아래의 정의를 작성
   * Interface 타입 수동 정의
   * axios 요청 함수 수동 작성
   * API 응답 타입 수동 정의
3. API 스펙 변경 시 위 과정을 반복

이러한 수동 프로세스는 시간이 많이 소요되고 휴먼 에러가 발생하기 쉬웠습니다.

***

## 도입 방법

### 프로세스

* Backend: API 문서 변경사항을 Frontend 레포지토리에 PR로 전달
* Frontend: API 클라이언트 코드 생성하는 PR 테스트 후 머지

### Backend to Frontend

{% embed url="<https://github.com/team-moeum/checkmate-backend/blob/develop/.github/workflows/oas.yml>" %}

#### Target Repository 설정

```yaml
env:
  PERSONAL_ACCESS_TOKEN:
  TARGET_REPO: team-moeum/checkmate-frontend                             # 프론트엔드 레포지토리
  TARGET_BRANCH: main                                                    # 대상 브랜치
  SOURCE_BRANCH: oas-${{ github.run_number }}-${{ github.run_attempt }}  # 생성될 브랜치
  API_DOCS_URL: ${{ secrets.API_DOCS_URL }}                              # API DOCS URL(<http://localhost:3000/v3/api-docs>)
  PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}            # repo, workflow 권한 TOKEN

```

#### Pull Request 생성

```yaml
steps:
  - name: Create Pull Request
    run: |
      cd target-repo

      # Git 설정
      git config --local user.email "moeum[bot]@users.noreply.github.com"
      git config --local user.name "moeum[bot]"

      # 브랜치 생성 및 문서 복사
      git checkout -b $SOURCE_BRANCH
      cp ../swagger.json ./docs/api-doc.json

      # 커밋 및 푸시
      git add docs/api-doc.json
      git commit -m "Update API documentation"
      git push origin $SOURCE_BRANCH

      # PR 생성
      curl -X POST \\\\
        -H "Authorization: token $PERSONAL_ACCESS_TOKEN" \\\\
        -H "Accept: application/vnd.github.v3+json" \\\\
        <https://api.github.com/repos/$TARGET_REPO/pulls> \\\\
        -d '{
          "title": "Update API Documentation",
          "body": "Automatically generated API documentation update",
          "head": "'$SOURCE_BRANCH'",
          "base": "'$TARGET_BRANCH'"
        }'

```

### Frontend API 생성

{% embed url="<https://github.com/team-moeum/checkmate-frontend/blob/main/.github/workflows/oas.yml>" %}

#### workflow

```yaml
on:
  pull_request:
    types: [opened, synchronize]
    paths:
      - "docs/api-doc.json" # API 문서가 업데이트될 때만 실행
    branches:
      - main

jobs:
  generate-api:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      ...
      - name: Generate documentation
        run: pnpm run generate
      ...

```

#### API 클라이언트 생성 스크립트

```json
{
  "scripts": {
    "generate": "openapi-generator-cli generate -g typescript-axios -i ./docs/api-doc.json -o ./src.shared/apis -c ./openapi.json",
  }
}

```

***

## 결론

아래와 같이 프로세스를 개선하면서 자동화할 수 있었고 도입과정에서 나왔던 문제 대부분을 해결할 수 있었습니다.

다만, 앞으로 사용하는 과정에서 문제가 발생한다면 그 문제를 해결해나가는 과정도 기록해보려 합니다.

***

### 참고문서

* <https://hmos.dev/en/how-to-use-oas-generator>
* <https://openapi-generator.tech/>
* <https://openapi-generator.tech/docs/generators/typescript-axios>
* <https://docs.github.com/en/actions>
* 예시 PR: <https://github.com/team-moeum/checkmate-frontend/pull/7>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://akk9132.gitbook.io/seungdeok-log/dev/frontend/api-feat.-oas-codegen.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
