# REST API 및 JavaScript를 사용하여 스크립팅

Octokit.js SDK를 사용하여 REST API와 상호 작용하는 스크립트를 작성합니다.

## Octokit.js 정보

JavaScript를 사용하여 'REST APIGitHub'와 GitHub상호 작용하는 스크립트를 작성하려면 Octokit.js SDK를 사용하는 것이 좋습니다. Octokit.js 유지 관리됩니다 GitHub. SDK는 모범 사례를 구현하고 JavaScript를 통해 REST API와 보다 쉽게 상호 작용할 수 있도록 합니다. Octokit.js는 모든 최신 브라우저, Node.js 및 Deno에서 작동합니다. Octokit.js에 대한 자세한 정보는 [Octokit.js 추가 정보](https://github.com/octokit/octokit.js/#readme)를 참조하세요.

## 필수 조건

이 가이드에서는 사용자가 JavaScript 및 REST API에 GitHub 익숙하다고 가정합니다. REST API에 대한 자세한 내용은 [REST API 시작](/ko/enterprise-server@3.22/rest/using-the-rest-api/getting-started-with-the-rest-api)을(를) 참조하세요.

참고: Octokit.js 라이브러리를 사용하려면 `octokit`을(를) 설치하고 가져와야 합니다. 이 가이드에서는 ES6에 따라 import 문을 사용합니다. 다양한 설치 및 가져오기 메서드에 대한 자세한 정보는 [Octokit.js 추가 정보 사용 섹션](https://github.com/octokit/octokit.js/#usage)을 참조하세요.

## 인스턴스화 및 인증

> \[!WARNING]
> 인증 자격 증명을 암호처럼 처리합니다.
>
> 자격 증명을 안전하게 유지하려면 자격 증명을 비밀로 저장하고 스크립트를 실행할 GitHub Actions수 있습니다. 자세한 내용은 [GitHub Actions에서 비밀 사용](/ko/enterprise-server@3.22/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets)을(를) 참조하세요.

> 이러한 옵션을 사용할 수 경우 다른 CLI 서비스를 사용하여 자격 증명을 안전하게 저장하는 것이 좋습니다.

### personal access token를 사용하여 인증하기

개인 용도로 REST API를 GitHub 사용하려는 경우, personal access token를 만들 수 있습니다. 자세한 내용은 personal access token 만들기에 대해 [개인용 액세스 토큰 관리](/ko/enterprise-server@3.22/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)을 참조하세요.

먼저 `Octokit`에서 `octokit`를 가져옵니다. 그런 다음 personal access token의 인스턴스를 만들 때 `Octokit`를 전달합니다. 다음 예에서는 `YOUR-TOKEN`를 사용자의 personal access token에 대한 참조로 바꾸십시오. 의 이름으로 `HOSTNAME`바꿉다GitHub Enterprise Server 인스턴스.

```javascript copy
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  baseUrl: "http(s)://HOSTNAME/api/v3",
  auth: 'YOUR-TOKEN',
});
```

### GitHub App를 사용하여 인증하기

조직이나 다른 사용자를 대신하여 API를 사용하려면 GitHub에서 제안하는 GitHub App을 사용하는 것이 좋습니다. 엔드포인트를 사용할 수 있는 GitHub Apps경우 해당 엔드포인트에 대한 REST 참조 설명서에 필요한 토큰 유형 GitHub App 이 표시됩니다. 자세한 내용은 [GitHub 앱 등록](/ko/enterprise-server@3.22/apps/creating-github-apps/registering-a-github-app/registering-a-github-app) 및 [GitHub 앱을 사용한 인증 정보](/ko/enterprise-server@3.22/apps/creating-github-apps/authenticating-with-a-github-app/about-authentication-with-a-github-app)을(를) 참조하세요.

`Octokit`에서 `octokit`를 가져오는 대신 `App`을 가져옵니다. 다음 예제에서는 `APP_ID`을(를) 앱 ID에 대한 참조로 바꿉니다. 앱의 프라이빗 키에 대한 참조로 `PRIVATE_KEY`를 대체합니다.
`INSTALLATION_ID`를 대신하여 인증하려는 앱의 설치의 ID로 바꿉니다. 앱 ID를 찾고 앱의 설정 페이지 설정에서 프라이빗 키를 생성할 수 있습니다. 자세한 내용은 [GitHub 앱에 대한 프라이빗 키 관리](/ko/enterprise-server@3.22/apps/creating-github-apps/authenticating-with-a-github-app/managing-private-keys-for-github-apps)을(를) 참조하세요.
`GET /users/{username}/installation`, `GET /repos/{owner}/{repo}/installation`, `GET /orgs/{org}/installation` 엔드포인트를 사용하여 설치 ID를 가져올 수 있습니다. 자세한 내용은 [GitHub Apps에 대한 REST API 엔드포인트](/ko/enterprise-server@3.22/rest/apps/apps)을 참조하세요. 의 이름으로 `HOSTNAME`바꿉다GitHub Enterprise Server 인스턴스.

```javascript copy
import { App } from "octokit";

const app = new App({
  appId: APP_ID,
  privateKey: PRIVATE_KEY,
  Octokit: Octokit.defaults({
    baseUrl: "http(s)://HOSTNAME/api/v3",
  }),
});

const octokit = await app.getInstallationOctokit(INSTALLATION_ID);
```

### GitHub Actions에서 인증

워크플로 GitHub Actions 에서 API를 GitHub 사용하려면 토큰을 만드는 대신 기본 제공 `GITHUB_TOKEN` 으로 인증하는 것이 좋습니다.
`GITHUB_TOKEN` 키를 사용하여 `permissions`에 대한 사용 권한을 부여할 수 있습니다.
`GITHUB_TOKEN`에 대한 자세한 내용은 [GITHUB\_TOKEN](/ko/enterprise-server@3.22/actions/concepts/security/github_token)을(를) 참조하세요.

워크플로가 워크플로 리포지토리 외부의 리소스에 액세스해야 하는 경우 `GITHUB_TOKEN`을 사용할 수 없습니다. 이 경우 자격 증명을 비밀로 저장하고 아래 예제의 `GITHUB_TOKEN`을 비밀의 이름으로 바꿉니다. 비밀에 대한 자세한 내용은 [GitHub Actions에서 비밀 사용](/ko/enterprise-server@3.22/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets)을(를) 참조하세요.

키워드를 `run` 사용하여 워크플로에서 GitHub Actions JavaScript 스크립트를 실행하는 경우 값을 `GITHUB_TOKEN` 환경 변수로 저장할 수 있습니다. 스크립트는 환경 변수에 `process.env.VARIABLE_NAME`로 액세스할 수 있습니다.

예를 들어 이 워크플로 단계에서 `GITHUB_TOKEN`이라는 환경 변수에 `TOKEN`을 저장합니다.

```yaml
- name: Run script
  env:
    TOKEN: ${{ secrets.GITHUB_TOKEN }}
  run: |
    node .github/actions-scripts/use-the-api.mjs
```

워크플로가 실행하는 스크립트는 `process.env.TOKEN`을 인증하는 데 사용합니다.

```javascript copy
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  baseUrl: "http(s)://HOSTNAME/api/v3",
  auth: process.env.TOKEN,
});
```

### 인증 없는 인스턴스화

트래픽률 제한이 낮고 일부 엔드포인트를 사용할 수 없어도 인증 없이 REST API를 사용할 수 있습니다. 인증하지 않고 인스턴스 `Octokit` 를 만들려면 인수를 `auth` 전달하지 마세요. 기본 URL을 .로 `http(s)://HOSTNAME/api/v3`설정합니다. 의 이름으로 `[hostname]`바꿉다GitHub Enterprise Server 인스턴스.

```javascript copy
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  baseUrl: "http(s)://HOSTNAME/api/v3",
);
```

## 요청하기

Octokit은 요청을 만드는 여러 가지 방법을 지원합니다. 엔드포인트에 대한 HTTP 동사와 경로를 알고 있는 경우 `request` 메서드를 사용하여 요청을 수행할 수 있습니다. IDE에서 자동 완성 및 입력을 이용하려는 경우 `rest` 메서드를 사용할 수 있습니다. 페이지를 매긴 엔드포인트의 경우 `paginate` 메서드를 사용하여 여러 데이터 페이지를 요청할 수 있습니다.

### `request` 메서드를 사용하여 요청을 수행합니다.

`request` 메서드를 사용하여 요청을 만들려면 HTTP 메서드와 경로를 첫 번째 인수로 전달합니다. 개체의 본문, 쿼리, 경로 매개 변수를 두 번째 인수로 패스합니다. 예를 들어 `GET`에 `/repos/{owner}/{repo}/issues`을 요청하고 `owner`, `repo`, `per_page` 매개변수를 전달하려면 다음을 수행하세요.

```javascript copy
await octokit.request("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 2
});
```

`request` 메서드는 자동으로 `Accept: application/vnd.github+json` 머리글을 전달합니다. 추가 헤더 또는 다른 `Accept` 머리글을 전달하려면 두 번째 인수로 전달되는 개체에 `headers` 속성을 추가합니다.
`headers` 속성의 값은 헤더 이름을 키로, 헤더 값을 값으로 가지고 있는 개체입니다. 예를 들어 값이 `content-type`인 `text/plain` 머리글과 값이 `x-github-api-version`인 `2026-03-10` 머리글을 보내려면 다음을 수행합니다.

```javascript copy
await octokit.request("POST /markdown/raw", {
  text: "Hello **world**",
  headers: {
    "content-type": "text/plain",
    "x-github-api-version": "2026-03-10",
  },
});
```

### `rest` 엔드포인트 메서드를 사용하여 요청을 수행하기

모든 REST API 엔드포인트에는 Octokit에 연결된 `rest` 엔드포인트 메서드가 있습니다. 이러한 메서드는 일반적으로 편의를 위해 IDE에서 자동 완성됩니다. 모든 매개 변수를 개체로 메서드에 전달할 수 있습니다.

```javascript copy
await octokit.rest.issues.listForRepo({
  owner: "github",
  repo: "docs",
  per_page: 2
});
```

또한 TypeScript와 같은 형식화된 언어를 사용하는 경우 이러한 메서드와 함께 사용할 형식을 가져올 수 있습니다. 자세한 정보는 [plugin-rest-endpoint-methods.js 추가 정보에서 TypeScript 섹션](https://github.com/octokit/plugin-rest-endpoint-methods.js/#typescript)을 참조하세요.

### 페이지 나열된 요청 만들기

엔드포인트가 페이지 단위로 나뉘어 있고 둘 이상의 결과 페이지를 가져오려는 경우 `paginate` 메서드를 사용할 수 있습니다.
`paginate`는 마지막 페이지에 도달할 때까지 결과의 다음 페이지를 가져온 다음 모든 결과를 단일 배열로 반환합니다. 일부 엔드포인트는 페이지 매김된 결과를 배열이 아닌 객체 안의 배열로 반환합니다. 원시 결과가 개체인 경우에도 `paginate`는 항상 항목 배열을 반환합니다.

예를 들어 다음 예제에서는 `github/docs` 리포지토리에서 모든 이슈를 가져옵니다. 한 번에 100개의 이슈를 요청하지만 함수는 데이터의 마지막 페이지에 도달할 때까지 반환되지 않습니다.

```javascript copy
const issueData = await octokit.paginate("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});
```

`paginate` 메서드는 응답에서 원하는 데이터만 수집하는 데 사용할 수 있는 선택적 맵 함수를 수락합니다. 이렇게 하면 스크립트의 메모리 사용량이 줄어듭니다. map 함수는 마지막 페이지에 도달하기 전에 페이지 매김을 종료하기 위해 호출할 수 있는 두 번째 인수 `done`을 사용할 수 있습니다. 이렇게 하면 페이지의 하위 집합을 가져올 수 있습니다. 예를 들어 다음 예제에서는 제목에 "test"가 포함된 이슈가 반환될 때까지 결과를 계속 가져옵니다. 반환된 데이터 페이지의 경우 이슈 제목과 작성자만 저장됩니다.

```javascript copy
const issueData = await octokit.paginate("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
},
    (response, done) => response.data.map((issue) => {
    if (issue.title.includes("test")) {
      done()
    }
    return ({title: issue.title, author: issue.user.login})
  })
);
```

모든 결과를 한 번에 가져오는 대신 한 번에 단일 페이지를 반복하는 데 `octokit.paginate.iterator()`를 사용할 수 있습니다. 예를 들어 다음 예제에서는 결과의 한 페이지를 한 번에 가져오고 다음 페이지를 가져오기 전에 페이지에서 각 개체를 처리합니다. 제목에 "test"가 포함된 이슈에 도달하면 스크립트는 반복을 중지하고 처리된 각 개체의 이슈 제목 및 이슈 작성자를 반환합니다. 반복기는 페이지를 매긴 데이터를 가져오기 위한 가장 메모리 효율적인 메서드입니다.

```javascript copy
const iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});

let issueData = []
let breakLoop = false
for await (const {data} of iterator) {
  if (breakLoop) break
  for (const issue of data) {
    if (issue.title.includes("test")) {
      breakLoop = true
      break
    } else {
      issueData = [...issueData, {title: issue.title, author: issue.user.login}];
    }
  }
}
```

`paginate` 엔드포인트 메서드에서도 `rest` 메서드를 사용할 수 있습니다.
`rest` 엔드포인트 메서드를 첫 번째 인수로 전달합니다. 매개 변수를 두 번째 인수로 전달합니다.

```javascript copy
const iterator = octokit.paginate.iterator(octokit.rest.issues.listForRepo, {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});
```

페이지 매김에 대한 자세한 내용은 [REST API에서 페이지 매김 사용](/ko/enterprise-server@3.22/rest/using-the-rest-api/using-pagination-in-the-rest-api)을(를) 참조하세요.

## 오류 포착하기

### 모든 오류 포착하기

경우에 따라 REST API에서 GitHub 오류를 반환합니다. 예를 들어 액세스 토큰이 만료되었거나 필수 매개 변수를 생략하면 오류가 발생합니다. Octokit.js는 `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `404 Not Found`및 `422 Unprocessable Entity` 이외의 오류가 발생하면 요청을 자동으로 다시 시도합니다. 재시도 후에도 API 오류가 발생하면 Octokit.js는 응답(`response.status`) 및 응답 헤더(`response.headers`)의 HTTP 상태 코드를 포함하는 오류를 throw합니다. 코드에서 이러한 오류를 처리해야 합니다. 예를 들어 try/catch 블록을 사용하여 오류를 포착할 수 있습니다.

```javascript copy
let filesChanged = []

try {
  const iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/pulls/{pull_number}/files", {
    owner: "github",
    repo: "docs",
    pull_number: 22809,
    per_page: 100,
    headers: {
      "x-github-api-version": "2026-03-10",
    },
  });

  for await (const {data} of iterator) {
    filesChanged = [...filesChanged, ...data.map(fileData => fileData.filename)];
  }
} catch (error) {
  if (error.response) {
    console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`)
  }
  console.error(error)
}
```

### 의도한 오류 코드 처리하기

경우에 따라 GitHub 4xx 상태 코드를 사용하여 오류가 아닌 응답을 나타냅니다. 사용 중인 엔드포인트에서 이 작업을 수행하는 경우, 특정 오류에 대한 처리를 추가할 수 있습니다. 예를 들어 `GET /user/starred/{owner}/{repo}` 엔드포인트는 리포지토리에 별표를 하지 않은 경우 `404`를 반환합니다. 다음 예제에서는 `404` 응답을 사용하여 리포지토리가 별표 표시되지 않았음을 나타내고 다른 모든 오류 코드는 오류로 처리됩니다.

```javascript copy
try {
  await octokit.request("GET /user/starred/{owner}/{repo}", {
    owner: "github",
    repo: "docs",
    headers: {
      "x-github-api-version": "2026-03-10",
    },
  });

  console.log(`The repository is starred by me`);

} catch (error) {
  if (error.status === 404) {
    console.log(`The repository is not starred by me`);
  } else {
    console.error(`An error occurred while checking if the repository is starred: ${error?.response?.data?.message}`);
  }
}
```

### 트래픽률 제한 오류 처리

트래픽률 제한 오류가 표시되는 경우 대기 후 요청을 다시 시도할 수 있습니다. 속도 제한이 적용되면 GitHub은(는) `403 Forbidden` 오류를 반환하며, `x-ratelimit-remaining` 응답 헤더 값은 `"0"`입니다. 응답 헤더에는 현재 트래픽률 제한 창이 재설정되는 시간을 UTC Epoch 초 단위로 알려주는 `x-ratelimit-reset` 헤더가 포함됩니다.
`x-ratelimit-reset`에 지정된 시간 후에 요청을 다시 시도할 수 있습니다.

```javascript copy
async function requestRetry(route, parameters) {
  try {
    const response = await octokit.request(route, parameters);
    return response
  } catch (error) {
    if (error.response && error.status === 403 && error.response.headers['x-ratelimit-remaining'] === '0') {
      const resetTimeEpochSeconds = error.response.headers['x-ratelimit-reset'];
      const currentTimeEpochSeconds = Math.floor(Date.now() / 1000);
      const secondsToWait = resetTimeEpochSeconds - currentTimeEpochSeconds;
      console.log(`You have exceeded your rate limit. Retrying in ${secondsToWait} seconds.`);
      setTimeout(requestRetry, secondsToWait * 1000, route, parameters);
    } else {
      console.error(error);
    }
  }
}

const response = await requestRetry("GET /repos/{owner}/{repo}/issues", {
    owner: "github",
    repo: "docs",
    per_page: 2
  })
```

## 응답 사용

`request` 메서드는 요청이 성공한 경우 객체로 해결되는 프로미스를 반환합니다. 개체 속성은 `data`(엔드포인트에서 반환된 응답 본문), `status`(HTTP 응답 코드), `url`(요청의 URL) 및 `headers`(응답 머리글을 포함하는 개체)입니다. 달리 지정하지 않는 한 응답 본문은 JSON 형식입니다. 일부 엔드포인트는 응답 본문을 반환하지 않습니다. 이 경우 `data` 속성은 생략됩니다.

```javascript copy
const response = await octokit.request("GET /repos/{owner}/{repo}/issues/{issue_number}", {
  owner: "github",
  repo: "docs",
  issue_number: 11901,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});

console.log(`The status of the response is: ${response.status}`)
console.log(`The request URL was: ${response.url}`)
console.log(`The x-ratelimit-remaining response header is: ${response.headers["x-ratelimit-remaining"]}`)
console.log(`The issue title is: ${response.data.title}`)
```

마찬가지로 `paginate` 메서드는 프라미스를 반환합니다. 요청이 성공하면, 프로미스는 엔드포인트에서 반환된 데이터 배열로 해결됩니다.
`request` 메서드와 달리 `paginate` 메서드는 상태 코드, URL 또는 머리글을 반환하지 않습니다.

```javascript copy
const data = await octokit.paginate("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});

console.log(`${data.length} issues were returned`)
console.log(`The title of the first issue is: ${data[0].title}`)
```

## 예제 스크립트

다음은 Octokit.js를 사용하는 전체 예제 스크립트입니다. 스크립트는 `Octokit`를 가져오고 새 인스턴스 `Octokit`를 만듭니다.
GitHub App 대신 personal access token로 인증하려면 `App` 대신 `Octokit`를 가져와 인스턴스화하면 됩니다. 자세한 내용은 [GitHub App을(를) 사용한 인증](#authenticating-with-a-github-app)을 참조하세요.

`getChangedFiles` 함수는 끌어오기 요청에 대해 변경된 모든 파일을 가져옵니다.
`commentIfDataFilesChanged` 함수는 `getChangedFiles` 함수를 호출합니다. 끌어오기 요청이 변경된 파일이 파일 경로에 `/data/`가 포함된 경우 함수는 끌어오기 요청에 대해 설명을 달게 됩니다.

```javascript copy
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  baseUrl: "http(s)://HOSTNAME/api/v3",
  auth: 'YOUR-TOKEN',
});

async function getChangedFiles({owner, repo, pullNumber}) {
  let filesChanged = []

  try {
    const iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/pulls/{pull_number}/files", {
      owner: owner,
      repo: repo,
      pull_number: pullNumber,
      per_page: 100,
      headers: {
        "x-github-api-version": "2026-03-10",
      },
    });

    for await (const {data} of iterator) {
      filesChanged = [...filesChanged, ...data.map(fileData => fileData.filename)];
    }
  } catch (error) {
    if (error.response) {
      console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`)
    }
    console.error(error)
  }

  return filesChanged
}

async function commentIfDataFilesChanged({owner, repo, pullNumber}) {
  const changedFiles = await getChangedFiles({owner, repo, pullNumber});

  const filePathRegex = new RegExp(/\/data\//, "i");
  if (!changedFiles.some(fileName => filePathRegex.test(fileName))) {
    return;
  }

  try {
    const {data: comment} = await octokit.request("POST /repos/{owner}/{repo}/issues/{issue_number}/comments", {
      owner: owner,
      repo: repo,
      issue_number: pullNumber,
      body: `It looks like you changed a data file. These files are auto-generated. \n\nYou must revert any changes to data files before your pull request will be reviewed.`,
      headers: {
        "x-github-api-version": "2026-03-10",
      },
    });

    return comment.html_url;
  } catch (error) {
    if (error.response) {
      console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`)
    }
    console.error(error)
  }
}

await commentIfDataFilesChanged({owner: "github", repo: "docs", pullNumber: 191});
```

## 다음 단계

* Octokit.js에 대한 자세한 정보는 [Octokit.js 설명서](https://github.com/octokit/octokit.js/#readme)를 참조하세요.
* 실제 사례 몇 가지를 보려면 GitHub Docs가 [GitHub Docs 리포지토리를 검색하여](https://github.com/search?q=repo%3Agithub%2Fdocs%20path%3A.github%20octokit\&type=code) Octokit.js를 어떻게 사용하는지 살펴보세요.