Skip to main content

GitHub์˜ REST API ๋ฐ GraphQL API ๋น„๊ต

GitHub์˜ API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ GitHub ํ™˜๊ฒฝ์„ ํ™•์žฅํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ด…๋‹ˆ๋‹ค.

GitHub์˜ API ์ •๋ณด

GitHub์€(๋Š”) REST API์™€ GraphQL API๋ผ๋Š” ๋‘ ๊ฐ€์ง€ API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. GitHub CLI, curl, ๊ณต์‹ Octokit ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฐ ํƒ€์‚ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‘ API์™€ ์ƒํ˜ธ ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ํ•œ API์—์„œ ๊ธฐ๋Šฅ์ด ์ง€์›๋  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‹ค๋ฅธ API์—์„œ๋Š” ์ง€์›๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์š”๊ตฌ ์‚ฌํ•ญ์— ๊ฐ€์žฅ ์ž˜ ๋ถ€ํ•ฉํ•˜๊ณ  ๊ฐ€์žฅ ํŽธ์•ˆํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” API๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ API๋ฅผ ๋‹ค๋ฅธ API๋ณด๋‹ค ๋…์ ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๋…ธ๋“œ ID๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด REST API ๋ฐ GraphQL API ๊ฐ„์— ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ „์—ญ ๋…ธ๋“œ ID ์‚ฌ์šฉ์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

์ด ๋ฌธ์„œ์—์„œ๋Š” ๊ฐ API์˜ ์ด์ ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. GraphQL API์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ GraphQL API ์ •๋ณด์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”. REST API์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ REST API ์ •๋ณด์„(๋ฅผ) ์ฐธ์กฐํ•˜์„ธ์š”.

GraphQL API ์„ ํƒ

GraphQL API๋Š” ์š”์ฒญํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ GraphQL์€ ์š”์ฒญ์— ๋”ฐ๋ผ ๋ฏธ๋ฆฌ ์•Œ๋ ค์ง„ ๊ตฌ์กฐ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด REST API๋Š” ์š”์ฒญํ•œ ๋ฐ์ดํ„ฐ๋ณด๋‹ค ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๋ฏธ๋ฆฌ ๊ฒฐ์ •๋œ ๊ตฌ์กฐ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ผ GraphQL ์š”์ฒญ์—์„œ ์—ฌ๋Ÿฌ REST API ์š”์ฒญ์— ํ•ด๋‹นํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ์ ์€ ์ˆ˜์˜ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋” ์ ์€ ๋ฐ์ดํ„ฐ๋ฅผ ํŽ˜์น˜ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํ†ตํ•ด GraphQL์€ ๋ชจ๋ฐ”์ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋งค๋ ฅ์ ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ํŒ”๋กœ์›Œ 10๋ช…์˜ GitHub ๋กœ๊ทธ์ธ๊ณผ ๊ฐ ํŒ”๋กœ์›Œ์˜ ํŒ”๋กœ์›Œ 10๋ช…์˜ ๋กœ๊ทธ์ธ์„ ์–ป๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ์ผ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

{
  viewer {
    followers(first: 10) {
      nodes {
        login
        followers(first: 10) {
          nodes {
            login
          }
        }
      }
    }
  }
}

์‘๋‹ต์€ ํ•ด๋‹น ์š”์ฒญ์˜ ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฅด๋Š” JSON ๊ฐœ์ฒด์ž…๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด REST API์—์„œ ์ด ๋™์ผํ•œ ์ •๋ณด๋ฅผ ์–ป์œผ๋ ค๋ฉด ๋จผ์ € GET /user/followers์— ๋Œ€ํ•œ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค . API๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์€ ํŒ”๋กœ์›Œ์— ๋Œ€ํ•œ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ๊ฐ ํŒ”๋กœ์›Œ์˜ ๋กœ๊ทธ์ธ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ฐ ํŒ”๋กœ์›Œ์— ๋Œ€ํ•ด GET /users/{username}/followers์— ๋Œ€ํ•œ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ผ GraphQL ์š”์ฒญ์—์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ์ •๋ณด์™€ ๋™์ผํ•œ ์ •๋ณด๋ฅผ ์–ป์œผ๋ ค๋ฉด ์ด 11๊ฐœ์˜ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋ฉฐ ์ดˆ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

REST API ์„ ํƒ

REST API๋Š” GraphQL API๋ณด๋‹ค ๋” ์˜ค๋ž˜ ์‚ฌ์šฉ๋˜์—ˆ์œผ๋ฏ€๋กœ ์ผ๋ถ€ ๊ฐœ๋ฐœ์ž๋Š” REST API์— ๋” ์ต์ˆ™ํ•ฉ๋‹ˆ๋‹ค. REST API๋Š” ํ‘œ์ค€ HTTP ๋™์‚ฌ ๋ฐ ๊ฐœ๋…์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋Š” REST API๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ณธ ๊ฐœ๋…์— ์ด๋ฏธ ์ต์ˆ™ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, octocat/Spoon-Knife ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ์ด์Šˆ๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด JSON ์š”์ฒญ ๋ณธ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ POST /repos/octocat/Spoon-Knife/issues์— ์š”์ฒญ์„ ๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

{
  "title": "Bug with feature X",
  "body": "If you do A, then B happens"
}

๋ฐ˜๋ฉด, GraphQL API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด์Šˆ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด octocat/Spoon-Knife ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ ๋…ธ๋“œ ID๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์š”์ฒญ์„ ๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

mutation {
  createIssue(
    input: {
      repositoryId: "MDEwOlJlcG9zaXRvcnkxMzAwMTky"
      title: "Bug with feature X"
      body: "If you do A, then B happens"}
  ) {
    issue {
      number
      url
    }
  }
}