Github API 사용기(Feat. npm)

김서진·2021년 2월 23일
6


nodejs 환경에서 깃허브 API를 사용할 일이 있어서 여러 문서를 참고하여 활용해 보았다.
문서에 있는 코드들의 결과 값들을 위주로 정리해 두었다.

공식 문서를 보면서 하나하나 쳐 보면서 결과 값을 확인하는게 제일 좋지만 귀찮거나 급하신 분들께서 구글링을 하다가 내 글을 발견하고 많은 도움을 얻으신다면 좋겠다.

Github API 공식 Docs
이게 결국 정답인건데 요청하는 코드를 직접 짜는 것보다.. 더 편리한 방법을 찾기 위해 찾아보았다.

NPM github-api
이걸 직접 써보기 전까지는 여기 모든 기능이 있을 줄 알았는데, 생각보다 잘 되지 않아서(아마 버전 문제인 듯) 추가적으로 다른 모듈들을 사용해볼 수밖에 없었다.

1. github-api

githubjs 사이트에서 확인하면 알 수 있듯이, 인증 방식에는 세 가지가 있다.
1. No Auth
2. PW Auth
3. Token Auth
셋 중에서 No Auth는 잘 되고, PW Auth는 이상하게 되고, Token Auth는 시도해보지 않았기 때문에 No Auth로 시도한 코드를 쓰려 한다.

var GitHub = require('github-api');
var noAuth = new GitHub();

var seojinseojin = noAuth.getUser('seojinseojin');
seojinseojin.listStarredRepos(function(err, repos) {
    repos.forEach((repo) => {
        console.log(`" ${repo.name} " by  "${repo.owner.login}"`)
    })
});

이렇게 하면 Seojinseojin이라는 유저가 좋아요를 누른 레포지토리들을 확인할 수 있다.
json 배열 형식으로 나오며, 배열 요소 하나는 객체로 이뤄졌는데 다음과 같은 형식이다.

{
  id: 54997288,
  node_id: 'MDEwOlJlcG9zaXRvcnk1NDk5NzI4OA==',
  name: 'd3js',
  full_name: 'colorfest/d3js',
  private: false,
  owner: {
    login: 'colorfest',
    id: 6611620,
    node_id: 'MDQ6VXNlcjY2MTE2MjA=',
    avatar_url: 'https://avatars.githubusercontent.com/u/6611620?v=4',
    gravatar_id: '',
    url: 'https://api.github.com/users/colorfest',
    html_url: 'https://github.com/colorfest',
    followers_url: 'https://api.github.com/users/colorfest/followers',
    following_url: 'https://api.github.com/users/colorfest/following{/other_user}',
    gists_url: 'https://api.github.com/users/colorfest/gists{/gist_id}',
    starred_url: 'https://api.github.com/users/colorfest/starred{/owner}{/repo}',
    subscriptions_url: 'https://api.github.com/users/colorfest/subscriptions',
    organizations_url: 'https://api.github.com/users/colorfest/orgs',
    repos_url: 'https://api.github.com/users/colorfest/repos',
    events_url: 'https://api.github.com/users/colorfest/events{/privacy}',
    received_events_url: 'https://api.github.com/users/colorfest/received_events',
    type: 'User',
    site_admin: false
  },
  html_url: 'https://github.com/colorfest/d3js',
  description: 'd3.js tutorial series by Accio Code for beginners to intermediate',
  fork: false,
  url: 'https://api.github.com/repos/colorfest/d3js',
  forks_url: 'https://api.github.com/repos/colorfest/d3js/forks',
  keys_url: 'https://api.github.com/repos/colorfest/d3js/keys{/key_id}',
  collaborators_url: 'https://api.github.com/repos/colorfest/d3js/collaborators{/collaborator}',
  teams_url: 'https://api.github.com/repos/colorfest/d3js/teams',
  hooks_url: 'https://api.github.com/repos/colorfest/d3js/hooks',
  issue_events_url: 'https://api.github.com/repos/colorfest/d3js/issues/events{/number}',
  events_url: 'https://api.github.com/repos/colorfest/d3js/events',
  assignees_url: 'https://api.github.com/repos/colorfest/d3js/assignees{/user}',
  branches_url: 'https://api.github.com/repos/colorfest/d3js/branches{/branch}',
  tags_url: 'https://api.github.com/repos/colorfest/d3js/tags',
  blobs_url: 'https://api.github.com/repos/colorfest/d3js/git/blobs{/sha}',
  git_tags_url: 'https://api.github.com/repos/colorfest/d3js/git/tags{/sha}',
  git_refs_url: 'https://api.github.com/repos/colorfest/d3js/git/refs{/sha}',
  trees_url: 'https://api.github.com/repos/colorfest/d3js/git/trees{/sha}',
  statuses_url: 'https://api.github.com/repos/colorfest/d3js/statuses/{sha}',
  languages_url: 'https://api.github.com/repos/colorfest/d3js/languages',
  stargazers_url: 'https://api.github.com/repos/colorfest/d3js/stargazers',
  contributors_url: 'https://api.github.com/repos/colorfest/d3js/contributors',
  subscribers_url: 'https://api.github.com/repos/colorfest/d3js/subscribers',
  subscription_url: 'https://api.github.com/repos/colorfest/d3js/subscription',
  commits_url: 'https://api.github.com/repos/colorfest/d3js/commits{/sha}',
  git_commits_url: 'https://api.github.com/repos/colorfest/d3js/git/commits{/sha}',
  comments_url: 'https://api.github.com/repos/colorfest/d3js/comments{/number}',
  issue_comment_url: 'https://api.github.com/repos/colorfest/d3js/issues/comments{/number}',
  contents_url: 'https://api.github.com/repos/colorfest/d3js/contents/{+path}',
  compare_url: 'https://api.github.com/repos/colorfest/d3js/compare/{base}...{head}',
  merges_url: 'https://api.github.com/repos/colorfest/d3js/merges',
  archive_url: 'https://api.github.com/repos/colorfest/d3js/{archive_format}{/ref}',
  downloads_url: 'https://api.github.com/repos/colorfest/d3js/downloads',
  issues_url: 'https://api.github.com/repos/colorfest/d3js/issues{/number}',
  pulls_url: 'https://api.github.com/repos/colorfest/d3js/pulls{/number}',
  milestones_url: 'https://api.github.com/repos/colorfest/d3js/milestones{/number}',
  notifications_url: 'https://api.github.com/repos/colorfest/d3js/notifications{?since,all,participating}',
  labels_url: 'https://api.github.com/repos/colorfest/d3js/labels{/name}',
  releases_url: 'https://api.github.com/repos/colorfest/d3js/releases{/id}',
  deployments_url: 'https://api.github.com/repos/colorfest/d3js/deployments',
  created_at: '2016-03-29T17:43:21Z',
  updated_at: '2021-02-14T11:06:29Z',
  pushed_at: '2017-05-21T22:26:50Z',
  git_url: 'git://github.com/colorfest/d3js.git',
  ssh_url: 'git@github.com:colorfest/d3js.git',
  clone_url: 'https://github.com/colorfest/d3js.git',
  svn_url: 'https://github.com/colorfest/d3js',
  homepage: '',
  size: 24,
  stargazers_count: 50,
  watchers_count: 50,
  language: 'JavaScript',
  has_issues: true,
  has_projects: true,
  has_downloads: true,
  has_wiki: true,
  has_pages: false,
  forks_count: 53,
  mirror_url: null,
  archived: false,
  disabled: false,
  open_issues_count: 1,
  license: {
    key: 'mit',
    name: 'MIT License',
    spdx_id: 'MIT',
    url: 'https://api.github.com/licenses/mit',
    node_id: 'MDc6TGljZW5zZTEz'
  },
  forks: 53,
  open_issues: 1,
  watchers: 50,
  default_branch: 'master'
}

정말 많은 정보들을 가져온다.
내가 하고 싶었던 건 해당 유저의 레포를 보는건데, 아쉽게도 noAuth.getUser().getRepos()를 하면 없는 함수라고 나와서 나에게 상처를 주었기 때문에 다른 방법을 찾아보게 되었다.

2. ghrepos

내가 찾는 기능들은 여기 다 있었다.

유저의 레포지토리 출력하기

const ghrepos = require("ghrepos");
const authOptions = { use: "seojinseojin", token: process.env.PAT }

ghrepos.listUser(authOptions, "seojinseojin", (err, repolist) => {
    // console.log(repolist)
    repolist.forEach((repo) => {
        console.log(repo);
    })
})

seojinseojin이라는 유저의 모든 레포지토리를 출력한다.

{
  id: 244069909,
  node_id: 'MDEwOlJlcG9zaXRvcnkyNDQwNjk5MDk=',
  name: 'python_web-scrapping_practice',
  full_name: 'SeojinSeojin/python_web-scrapping_practice',
  private: false,
  owner: {
    login: 'SeojinSeojin',
    id: 48249505,
    node_id: 'MDQ6VXNlcjQ4MjQ5NTA1',
    avatar_url: 'https://avatars.githubusercontent.com/u/48249505?v=4',
    gravatar_id: '',
    url: 'https://api.github.com/users/SeojinSeojin',
    html_url: 'https://github.com/SeojinSeojin',
    followers_url: 'https://api.github.com/users/SeojinSeojin/followers',
    following_url: 'https://api.github.com/users/SeojinSeojin/following{/other_user}',
    gists_url: 'https://api.github.com/users/SeojinSeojin/gists{/gist_id}',
    starred_url: 'https://api.github.com/users/SeojinSeojin/starred{/owner}{/repo}',
    subscriptions_url: 'https://api.github.com/users/SeojinSeojin/subscriptions',
    organizations_url: 'https://api.github.com/users/SeojinSeojin/orgs',
    repos_url: 'https://api.github.com/users/SeojinSeojin/repos',
    events_url: 'https://api.github.com/users/SeojinSeojin/events{/privacy}',
    received_events_url: 'https://api.github.com/users/SeojinSeojin/received_events',
    type: 'User',
    site_admin: false
  },
  html_url: 'https://github.com/SeojinSeojin/python_web-scrapping_practice',
  description: '웹 스크래핑 연습',
  fork: false,
  url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice',
  forks_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/forks',
  keys_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/keys{/key_id}',
  collaborators_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/collaborators{/collaborator}',
  teams_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/teams',
  hooks_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/hooks',
  issue_events_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/issues/events{/number}',
  events_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/events',
  assignees_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/assignees{/user}',
  branches_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/branches{/branch}',
  tags_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/tags',
  blobs_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/git/blobs{/sha}',
  git_tags_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/git/tags{/sha}',
  git_refs_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/git/refs{/sha}',
  trees_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/git/trees{/sha}',
  statuses_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/statuses/{sha}',
  languages_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/languages',
  stargazers_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/stargazers',
  contributors_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/contributors',
  subscribers_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/subscribers',
  subscription_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/subscription',
  commits_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/commits{/sha}',
  git_commits_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/git/commits{/sha}',
  comments_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/comments{/number}',
  issue_comment_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/issues/comments{/number}',
  contents_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/contents/{+path}',
  compare_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/compare/{base}...{head}',
  merges_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/merges',
  archive_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/{archive_format}{/ref}',
  downloads_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/downloads',
  issues_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/issues{/number}',
  pulls_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/pulls{/number}',
  milestones_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/milestones{/number}',
  notifications_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/notifications{?since,all,participating}',  
  labels_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/labels{/name}',
  releases_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/releases{/id}',
  deployments_url: 'https://api.github.com/repos/SeojinSeojin/python_web-scrapping_practice/deployments',
  created_at: '2020-03-01T01:49:51Z',
  updated_at: '2021-02-19T15:43:06Z',
  pushed_at: '2020-07-13T13:26:54Z',
  git_url: 'git://github.com/SeojinSeojin/python_web-scrapping_practice.git',
  ssh_url: 'git@github.com:SeojinSeojin/python_web-scrapping_practice.git',
  clone_url: 'https://github.com/SeojinSeojin/python_web-scrapping_practice.git',
  svn_url: 'https://github.com/SeojinSeojin/python_web-scrapping_practice',
  homepage: '',
  size: 20,
  stargazers_count: 0,
  watchers_count: 0,
  language: 'Python',
  has_issues: true,
  has_projects: true,
  has_downloads: true,
  has_wiki: true,
  has_pages: false,
  forks_count: 0,
  mirror_url: null,
  archived: false,
  disabled: false,
  open_issues_count: 0,
  license: null,
  forks: 0,
  open_issues: 0,
  watchers: 0,
  default_branch: 'master',
  permissions: { admin: true, push: true, pull: true }
}

배열 형식으로 출력되고, 다 쓰기엔 너무 많아서 하나의 repo는 무슨 정보들을 갖고 있는지 보면 위의 형식과 같이 출력된다.
정말 많은 정보들이 출력되는데.. 그 중 가장 감동적인건 language_url이었다.
어느 언어가 얼마나 쓰였는지 알려주는데, 이걸 찾으려고 github api를 사용한거라 정말 감격스러웠다.

커밋 출력하기

ghrepos.listCommits(authOptions, 'seojinseojin', 'node-js_practice', function(err, refData) {
    console.log(refData)
})

seojinseojin의 레포지토리 중 node-js_practice에 있는 모든 커밋들을 출력했을 때,
각 커밋들은 다음과 같은 JSON형식으로 출력된다.

  {
    sha: '832e32ccc0f49ad9bf288581e447d2c020677388',
    node_id: 'MDY6Q29tbWl0MjgyODI4NTI0OjgzMmUzMmNjYzBmNDlhZDliZjI4ODU4MWU0NDdkMmMwMjA2NzczODg=',
    commit: {
      author: [Object],
      committer: [Object],
      message: 'github api - with noauth',
      tree: [Object],
      url: 'https://api.github.com/repos/SeojinSeojin/node-js_practice/git/commits/832e32ccc0f49ad9bf288581e447d2c020677388',
      comment_count: 0,
      verification: [Object]
    },
    url: 'https://api.github.com/repos/SeojinSeojin/node-js_practice/commits/832e32ccc0f49ad9bf288581e447d2c020677388',
    html_url: 'https://github.com/SeojinSeojin/node-js_practice/commit/832e32ccc0f49ad9bf288581e447d2c020677388',
    comments_url: 'https://api.github.com/repos/SeojinSeojin/node-js_practice/commits/832e32ccc0f49ad9bf288581e447d2c020677388/comments',
    author: {
      login: 'SeojinSeojin',
      id: 48249505,
      node_id: 'MDQ6VXNlcjQ4MjQ5NTA1',
      avatar_url: 'https://avatars.githubusercontent.com/u/48249505?v=4',
      gravatar_id: '',
      url: 'https://api.github.com/users/SeojinSeojin',
      html_url: 'https://github.com/SeojinSeojin',
      followers_url: 'https://api.github.com/users/SeojinSeojin/followers',
      following_url: 'https://api.github.com/users/SeojinSeojin/following{/other_user}',
      gists_url: 'https://api.github.com/users/SeojinSeojin/gists{/gist_id}',
      starred_url: 'https://api.github.com/users/SeojinSeojin/starred{/owner}{/repo}',
      subscriptions_url: 'https://api.github.com/users/SeojinSeojin/subscriptions',
      organizations_url: 'https://api.github.com/users/SeojinSeojin/orgs',
      repos_url: 'https://api.github.com/users/SeojinSeojin/repos',
      events_url: 'https://api.github.com/users/SeojinSeojin/events{/privacy}',
      received_events_url: 'https://api.github.com/users/SeojinSeojin/received_events',
      type: 'User',
      site_admin: false
    },
    committer: {
      login: 'SeojinSeojin',
      id: 48249505,
      node_id: 'MDQ6VXNlcjQ4MjQ5NTA1',
      avatar_url: 'https://avatars.githubusercontent.com/u/48249505?v=4',
      gravatar_id: '',
      url: 'https://api.github.com/users/SeojinSeojin',
      html_url: 'https://github.com/SeojinSeojin',
      followers_url: 'https://api.github.com/users/SeojinSeojin/followers',
      following_url: 'https://api.github.com/users/SeojinSeojin/following{/other_user}',
      gists_url: 'https://api.github.com/users/SeojinSeojin/gists{/gist_id}',
      starred_url: 'https://api.github.com/users/SeojinSeojin/starred{/owner}{/repo}',
      subscriptions_url: 'https://api.github.com/users/SeojinSeojin/subscriptions',
      organizations_url: 'https://api.github.com/users/SeojinSeojin/orgs',
      repos_url: 'https://api.github.com/users/SeojinSeojin/repos',
      events_url: 'https://api.github.com/users/SeojinSeojin/events{/privacy}',
      received_events_url: 'https://api.github.com/users/SeojinSeojin/received_events',
      type: 'User',
      site_admin: false
    },
    parents: [ [Object] ]
  }

object 형식인 committer은

{
  name: 'SeojinSeojin',
  email: '1106laura@naver.com',
  date: '2021-02-22T14:56:15Z'
}

tree는

{
  sha: '3168f6305d238ada53ed978b130bc66403efd9fe',
  url: 'https://api.github.com/repos/SeojinSeojin/node-js_practice/git/trees/3168f6305d238ada53ed978b130bc66403efd9fe'
}

위의 정보들을 위의 형식으로 보여준다.
커밋 자체에 대한 출력보다는 committer, author의 정보를 더 많이 출력해주는 느낌이었다.
사실 내가 얻고 싶던 건 그 커밋을 이루고 있는 언어들의 양이었는데.. 그런 정보는 없어서 정말 슬프다.

특정 유저의 모든 레포지토리의 모든 커밋 출력하기

listCommits()를 위의 listUser()와 엮어서 쓴다면 해당 유저의 레포지토리에 있는 모든 커밋들을 출력할 수 있다.

ghrepos.listUser(authOptions, "seojinseojin", (err, repolist) => {
    repolist.forEach((repo) => {
        ghrepos.listCommits(authOptions, "seojinseojin", repo.name, (err, refData) => {
            console.log(`\nRepository : ${repo.name} by ${repo.owner.login}`)
            refData.forEach((ref) => {
                console.log(`${ref.commit.author.date}\n${ref.commit.committer.name} committed : ${ref.commit.message}`)
            })
        })
    })
})

이 외에도 좋은 API들이 많으니.. 꼭 사용해보시길 바란다!!

profile
뭐라도 더 하자~

0개의 댓글