{"meta":{"title":"GraphQL을 사용하여 통화 구성","intro":"GraphQL API에 인증하는 방법을 알아본 다음 쿼리 및 변형을 만들고 실행하는 방법을 알아봅니다.","product":"GraphQL API","breadcrumbs":[{"href":"/ko/graphql","title":"GraphQL API"},{"href":"/ko/graphql/guides","title":"안내서"},{"href":"/ko/graphql/guides/forming-calls-with-graphql","title":"GraphQL을 사용하여 호출을 구성하기"}],"documentType":"article"},"body":"# GraphQL을 사용하여 통화 구성\n\nGraphQL API에 인증하는 방법을 알아본 다음 쿼리 및 변형을 만들고 실행하는 방법을 알아봅니다.\n\n## GraphQL을 사용하여 인증\n\npersonal access token, GitHub App 또는 OAuth app를 사용하여 GraphQL API에 인증할 수 있습니다.\n\n### personal access token를 사용하여 인증하기\n\npersonal access token로 인증하려면 [개인용 액세스 토큰 관리](/ko/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)의 단계를 따르세요. 요청하는 데이터는 필요한 범위 또는 권한을 지정합니다.\n\n예를 들어, 토큰이 접근할 수 있는 리포지토리의 모든 이슈를 읽으려면 \"issues:read\" 권한을 선택하십시오.\n\n모든 fine-grained personal access token항목에는 공용 리포지토리에 대한 읽기 권한이 포함됩니다.\npersonal access token (classic)를 사용해 공용 리포지토리에 액세스하려면 \"public\\_repo\" 범위를 선택합니다.\n\n토큰에 리소스를 access 데 필요한 범위 또는 권한이 없는 경우 API는 토큰에 필요한 범위 또는 사용 권한을 나타내는 오류 메시지를 반환합니다.\n\n### GitHub App를 사용하여 인증하기\n\n조직이나 다른 사용자를 대신하여 API를 사용하려면 GitHub에서 제안하는 GitHub App을 사용하는 것이 좋습니다. 앱의 활동을 추적하려면 앱 설치로 인증하도록 앱을 구성할 수 있습니다. 앱에 대한 활동을 사용자에게 특성화하기 위해 사용자를 대신하여 앱을 인증할 수 있습니다. 두 경우 모두 GraphQL API에 인증하는 데 사용할 수 있는 토큰을 생성합니다. 자세한 내용은 [GitHub 앱 등록](/ko/apps/creating-github-apps/registering-a-github-app/registering-a-github-app) 및 [GitHub 앱을 사용한 인증 정보](/ko/apps/creating-github-apps/authenticating-with-a-github-app/about-authentication-with-a-github-app) 참조하세요.\n\n### OAuth app를 사용하여 인증하기\n\nOAuth app의 OAuth 토큰으로 인증하려면 먼저 웹 애플리케이션 흐름이나 디바이스 흐름을 사용하여 OAuth app에 권한을 부여해야 합니다. 그런 다음 받은 access 토큰을 사용하여 API를 access 수 있습니다. 자세한 내용은 [OAuth 앱 만들기](/ko/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app) 및 [OAuth 앱 권한 부여](/ko/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps) 참조하세요.\n\n## GraphQL 엔드포인트\n\nREST API에는 수많은 엔드포인트가 있습니다. GraphQL API를 사용하면, 어떤 작업을 수행하든 엔드포인트는 일정하게 유지됩니다. 의 경우 GitHub.com해당 엔드포인트는 다음과 같습니다.\n\n<pre>https://api.github.com/graphql</pre>\n\n## GraphQL과 통신\n\nGraphQL 작업은 여러 줄 JSON으로 구성되므로 GitHub [GraphQL 클라이언트](/ko/graphql/guides/using-graphql-clients)를 사용하여 GraphQL을 호출하는 것이 좋습니다.\n`curl` 또는 다른 HTTP 말하기 라이브러리를 사용할 수도 있습니다.\n\nREST에서 [HTTP 동사](/ko/rest#http-verbs)는 수행되는 작업을 결정합니다. GraphQL에서는 쿼리를 수행하든 변형을 수행하든 관계없이 JSON으로 인코딩된 본문을 제공하므로, HTTP 동사는 `POST`입니다. 엔드포인트에 대한 간단한 [](/ko/graphql/guides/introduction-to-graphql#discovering-the-graphql-api)인 `GET`는 예외입니다. GraphQL 및 REST에 대한 자세한 내용은 [REST에서 GraphQL로 마이그레이션](/ko/graphql/guides/migrating-from-rest-to-graphql) 참조하세요.\n\n`curl` 명령에서 GraphQL을 쿼리하려면 JSON 페이로드로 `POST` 요청을 수행합니다. 페이로드에는 `query`라는 문자열이 포함되어야 합니다.\n\n```shell\ncurl -H \"Authorization: bearer TOKEN\" -X POST -d \" \\\n { \\\n   \\\"query\\\": \\\"query { viewer { login }}\\\" \\\n } \\\n\" https://api.github.com/graphql\n```\n\n> \\[!NOTE]\n> `\"query\"` 의 문자열 값에 포함된 줄 바꿈 문자는 반드시 이스케이프 처리를 해야 하며, 이를 누락할 경우 스키마 해석 과정에서 구문 오류가 발생할 수 있습니다. `POST` 본문의 경우 외부 큰따옴표와 이스케이프된 내부 큰따옴표를 사용합니다.\n\n### 쿼리 및 변형 작업 정보\n\nGitHub GraphQL API에서 허용되는 두 가지 작업은 *queries* 및 \\_mutations\\_입니다. GraphQL과 REST를 비교하면 쿼리는 `GET` 요청처럼 작동하고 변형은 `POST`/`PATCH`/`DELETE`처럼 작동합니다. 변형 이름은 어떤 수정이 실행되는지 결정합니다.\n\n속도 제한 규칙에 대한 자세한 내용은 [GraphQL API에 대한 속도 제한 및 쿼리 제한](/ko/graphql/overview/rate-limits-and-query-limits-for-the-graphql-api)을(를) 참조하세요.\n\n쿼리 및 변경은 몇 가지 중요한 차이점이 있지만 비슷한 형식을 공유합니다.\n\n### 쿼리 정보\n\nGraphQL 쿼리는 지정한 데이터만 반환합니다. 쿼리를 구성하려면 스칼라만 반환할 때까지 [필드 내의 필드](/ko/graphql/guides/introduction-to-graphql#field) ( \\_중첩 하위 필드\\_라고도 함)를 지정해야 합니다.\n\n쿼리는 다음과 같이 구성됩니다.\n\n<pre>query {\n  JSON-OBJECT-TO-RETURN\n}</pre>\n\n실제 예제는 [예제 쿼리](#example-query)를 참조하세요.\n\n### 변형 정보\n\n변형을 형성하려면 다음 세 가지를 지정해야 합니다.\n\n1. *변형 이름*. 수행하려는 수정의 유형입니다.\n2. *입력 개체*.\n   \\_입력 필드\\_로 구성된, 서버로 보내려는 데이터입니다. 이것을 변형 이름에 인수로서 전달합니다.\n3. *페이로드 개체*.\n   \\_반환 필드\\_로 구성된, 서버로부터 반환하려는 데이터입니다. 이것을 변형 이름의 본문으로서 전달합니다.\n\n변형은 다음과 같이 구성됩니다.\n\n<pre>mutation {\n  MUTATION-NAME(input: {MUTATION-NAME-INPUT!}) {\n    MUTATION-NAME-PAYLOAD\n  }\n}</pre>\n\n이 예제에서 입력 객체는 `MutationNameInput`, 페이로드 객체는 `MutationNamePayload`입니다.\n\n뮤테이션 참조에 나열된 \\_입력 필드\\_는 입력 객체로 전달하는 필드입니다. 나열된 \\_반환 필드\\_는 페이로드 개체로서 전달하는 것입니다.\n\n실제 예제는 [예제 변형](#example-mutation)을 참조하세요.\n\n## 변수 사용\n\n[변수](https://graphql.org/learn/queries/#variables)는 쿼리를 더욱 동적이고 강력하게 만들 수 있으며 변형 입력 개체를 전달할 때 복잡성을 줄일 수 있습니다.\n\n다음은 단일 변수를 사용하는 예제 쿼리입니다.\n\n```graphql\nquery($number_of_repos:Int!) {\n  viewer {\n    name\n     repositories(last: $number_of_repos) {\n       nodes {\n         name\n       }\n     }\n   }\n}\nvariables {\n   \"number_of_repos\": 3\n}\n```\n\n변수를 사용하는 세 단계가 있습니다.\n\n1. `variables` 개체에서 작업 외부의 변수를 정의합니다.\n\n   ```graphql\n   variables {\n      \"number_of_repos\": 3\n   }\n   ```\n\n   개체는 유효한 JSON이어야 합니다. 이 예제에서는 간단한 `Int` 변수 형식을 보여 주지만, 입력 개체와 같은 더 복잡한 변수 형식을 정의할 수 있습니다. 여기에서 여러 변수를 정의할 수도 있습니다.\n\n2. 변수를 인수로서 작업에 전달합니다.\n\n   ```graphql\n   query($number_of_repos:Int!){\n   ```\n\n   인수는 키-값 쌍이며, 여기서 키는 \\_\\_ 로 시작하는 `$`(예: `$number_of_repos`)이고 값은 *형식*(예: `Int`)입니다. 형식이 필요한지 여부를 나타내는 `!`를 추가합니다. 여러 변수를 정의한 경우 여기에 여러 인수로서 포함합니다.\n\n3. 작업 내에서 변수를 사용합니다.\n\n   ```graphql\n   repositories(last: $number_of_repos) {\n   ```\n\n   이 예제에서는 변수를 검색할 리포지토리의 수로 대체합니다. GraphQL은 강력한 입력을 적용하기 때문에 2단계에서 형식을 지정합니다.\n\n이 프로세스는 쿼리 인수를 동적으로 만듭니다. 이제 단순히 `variables` 개체의 값을 변경하고 쿼리의 나머지를 동일하게 유지할 수 있습니다.\n\n변수를 인수로서 사용하면 쿼리를 변경하지 않고도 `variables` 개체의 값을 동적으로 업데이트할 수 있습니다.\n\n## 예제 쿼리\n\n좀 더 복잡한 쿼리를 살펴보고 이 정보를 컨텍스트에 배치해 보겠습니다.\n\n다음 쿼리는 `octocat/Hello-World` 리포지토리를 조회하고, 가장 최근에 종료된 20개의 이슈를 찾고, 각 이슈의 제목, URL, 처음 5개 레이블을 반환합니다.\n\n```graphql\nquery {\n  repository(owner:\"octocat\", name:\"Hello-World\") {\n    issues(last:20, states:CLOSED) {\n      edges {\n        node {\n          title\n          url\n          labels(first:5) {\n            edges {\n              node {\n                name\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n컴퍼지션을 한 줄씩 살펴보기:\n\n* `query {`\n\n  서버의 데이터를 수정하는 것이 아니라 데이터를 읽고자 하므로, `query`는 루트 작업입니다. 작업을 지정하지 않으면 `query`가 기본값이기도 합니다.\n\n* `repository(owner:\"octocat\", name:\"Hello-World\") {`\n\n  쿼리를 시작하기 위해 [`repository`](/ko/graphql/reference/repos#object-repository) 개체를 찾으려고 합니다. 스키마 유효성 검사에 따르면 이 개체에 `owner` 및 `name` 인수가 필요합니다.\n\n* `issues(last:20, states:CLOSED) {`\n\n  리포지토리의 모든 이슈를 설명하기 위해 `issues` 개체를 호출합니다.\n  \\_\n  \\_에서 단일 `issue`를 쿼리할 수 있지만, 그렇게 할 경우 반환하려는 이슈의 번호를 알아야 하고 이를 인수로서 제공해야 합니다.`repository`\n\n`issues` 개체에 대한 몇 가지 세부 정보:\n\n* [문서](/ko/graphql/reference/repos#object-repository)에 따르면 이 개체의 형식은 `IssueConnection`입니다.\n\n* 스키마 유효성 검사에 따르면 이 개체에는 결과의 `last` 또는 `first` 숫자가 인수로서 필요합니다. 이 예제에서는 `20`을 사용합니다.\n\n* 또한 [문서](/ko/graphql/reference/repos#object-repository)에 따르면 이 개체는 `states` 열거형의 `IssueState` 인수를 허용하며, 이 열거형은 [](/ko/graphql/reference/issues#enum-issuestate) 또는 `OPEN` 값을 수용합니다. 종료된 이슈만 찾으려면 `states` 키에 `CLOSED` 값을 제공합니다.\n\n* `edges {`\n\n`issues` 형식을 가지고 있으므로 `IssueConnection`가 연결임을 알고 있습니다. 개별 문제에 대한 데이터를 검색하려면 `edges` 통해 노드를 access 합니다.\n\n* `node {`\n\n  여기서는 에지 끝에서 노드를 검색합니다.\n  [\n  `IssueConnection` 문서](/ko/graphql/reference/issues#object-issueconnection)에 따르면 `IssueConnection` 형식 끝에 있는 노드는 `Issue` 개체입니다.\n\n* 이제 `Issue` 개체를 검색하고 있다는 것을 알게 되었으므로 [문서](/ko/graphql/reference/issues#object-issue)를 살펴보고 반환할 필드를 지정할 수 있습니다.\n\n  ```graphql\n  title\n  url\n  labels(first:5) {\n    edges {\n      node {\n        name\n      }\n    }\n  }\n  ```\n\n  여기서 `title` 개체의 `url`, `labels`, `Issue` 필드를 지정합니다.\n\n`labels` 필드의 형식은 [`LabelConnection`](/ko/graphql/reference/issues#object-labelconnection)입니다.\n`issues` 개체와 마찬가지로 `labels`도 연결이므로 해당 에지를 연결된 노드인 `label` 개체로 이동해야 합니다. 노드에서, 반환하려는 `label` 개체 필드(이 경우 `name`)를 지정할 수 있습니다.\n\nOctocat의 퍼블릭 `Hello-World` 리포지토리에서 이 쿼리를 실행하면 많은 레이블이 반환되지 않습니다. 레이블을 사용하는 자체 리포지토리 중 하나에서 실행해 보면 차이를 확인할 수 있을 것입니다.\n\n## 예제 변형\n\n변형에는 쿼리를 먼저 수행해야만 알 수 있는 정보가 필요한 경우가 많습니다. 이 예제에서는 두 개의 작업을 보여 줍니다.\n\n1. 이슈 ID를 가져오기 위한 쿼리.\n2. 이슈에 이모지 반응을 추가하기 위한 변형.\n\n```graphql\nquery FindIssueID {\n  repository(owner:\"octocat\", name:\"Hello-World\") {\n    issue(number:349) {\n      id\n    }\n  }\n}\n\nmutation AddReactionToIssue {\n  addReaction(input:{subjectId:\"MDU6SXNzdWUyMzEzOTE1NTE=\",content:HOORAY}) {\n    reaction {\n      content\n    }\n    subject {\n      id\n    }\n  }\n}\n```\n\n예제를 하나 살펴보겠습니다. 간단한 작업처럼 보입니다. 이슈에 이모지 반응을 추가합니다.\n\n그렇다면 쿼리로 시작해야 하는지 어떻게 알 수 있을까요? 아직 하지 않았습니다.\n\n서버의 데이터를 수정하려고 하므로(이슈에 이모지 연결) 유용한 변형을 찾기 위해 스키마를 검색하는 것으로 시작합니다. 참조 문서는 다음 설명과 함께 [`addReaction`](/ko/graphql/reference/reactions#mutation-addreaction) 변형을 보여 줍니다. `Adds a reaction to a subject.` 완벽합니다!\n\n변형에 대한 문서에는 세 개의 입력 필드가 나열됩니다.\n\n* `clientMutationId`(`String`)\n* `subjectId`(`ID!`)\n* `content`(`ReactionContent!`)\n\n`!`는 `subjectId`와 `content`가 필수 필드임을 나타냅니다. 필수 `content`는 의미가 있습니다. 반응을 추가하려고 하므로 사용할 이모지 지정해야 합니다.\n\n하지만 `subjectId`가 왜 필요한가요?\n`subjectId`가 어떤 리포지토리의 어떤 이슈에 반응해야 하는지 식별하는 유일한 방법이기 때문입니다.\\_\\_\\_\\_\n\n`ID`를 얻기 위해 쿼리를 사용하여 이 예제를 시작합니다.\n\n쿼리를 한 줄씩 살펴보겠습니다.\n\n* `query FindIssueID {`\n\n  여기서는 쿼리를 수행하고 이름을 `FindIssueID`로 지정합니다. 쿼리 이름을 지정하는 것은 선택 사항입니다. 변경과 동일한 GUI 클라이언트 창에 포함할 수 있도록 여기에 이름을 지정합니다.\n\n* `repository(owner:\"octocat\", name:\"Hello-World\") {`\n\n`repository` 개체를 쿼리하고 `owner` 및 `name` 인수를 전달하여 리포지토리를 지정합니다.\n\n* `issue(number:349) {`\n\n`issue` 개체를 쿼리하고 `number` 인수를 전달하여 반응할 이슈를 지정합니다.\n\n* `id`\n\n  여기에서는 `id`에서 `https://github.com/octocat/Hello-World/issues/349`을(를) 검색하여 `subjectId`로 전달합니다.\n\n쿼리를 실행하여 `id`: `MDU6SXNzdWUyMzEzOTE1NTE=`를 가져옵니다.\n\n> \\[!NOTE]\n> 쿼리에서 반환되는 `id`가 변형에서 `subjectID`로서 전달할 값입니다. 문서나 스키마 내적 검사는 이 관계를 나타내지 않습니다. 이를 파악하려면 이름 뒤에 있는 개념을 이해해야 합니다.\n\nID를 알고 있으면 다음과 같이 변형을 진행할 수 있습니다.\n\n* `mutation AddReactionToIssue {`\n\n  여기서는 변형을 수행하고 이름을 `AddReactionToIssue`로 지정합니다. 쿼리와 마찬가지로 변경 이름 지정은 선택 사항입니다. 쿼리와 동일한 GUI 클라이언트 창에 포함할 수 있도록 여기에 이름을 지정합니다.\n\n* `addReaction(input:{subjectId:\"MDU6SXNzdWUyMzEzOTE1NTE=\",content:HOORAY}) {`\n\n  다음 줄을 살펴보겠습니다.\n\n  * `addReaction`은 변형의 이름입니다.\n  * `input`은 필수 인수 키입니다. 이 변형의 경우 항상 `input`입니다.\n  * `{subjectId:\"MDU6SXNzdWUyMzEzOTE1NTE=\",content:HOORAY}`는 필수 인수 키입니다. 이는 항상 뮤테이션을 위한 입력 필드(이 경우 `subjectId` 및 `content`)로 구성된 입력 객체이므로 중괄호를 사용합니다.\n\n  콘텐츠에 사용할 값을 어떻게 알 수 있나요?\n  [\n  `addReaction` 문서](/ko/graphql/reference/reactions#mutation-addreaction)에 따르면 `content` 필드의 형식은 [`ReactionContent`](/ko/graphql/reference/reactions#enum-reactioncontent)이며, GitHub 이슈에서는 특정 이모지 반응만 지원되므로 이는 열거형입니다. 다음은 반응에 허용되는 값입니다(일부 값은 해당 이모지 이름과 다름).\n\n  <table style=\"width:20%\">\n  <thead>\n  <tr>\n  <th scope=\"col\" style=\"text-align:left\">콘텐츠</th>\n  <th scope=\"col\" style=\"text-align:left\">이모티콘</th>\n  </tr>\n  </thead>\n  <tbody>\n  <tr>\n  <td style=\"text-align:left\"><code>+1</code></td>\n  <td style=\"text-align:left\">👍</td>\n  </tr>\n  <tr>\n  <td style=\"text-align:left\"><code>-1</code></td>\n  <td style=\"text-align:left\">👎</td>\n  </tr>\n  <tr>\n  <td style=\"text-align:left\"><code>laugh</code></td>\n  <td style=\"text-align:left\">😄</td>\n  </tr>\n  <tr>\n  <td style=\"text-align:left\"><code>confused</code></td>\n  <td style=\"text-align:left\">😕</td>\n  </tr>\n  <tr>\n  <td style=\"text-align:left\"><code>heart</code></td>\n  <td style=\"text-align:left\">❤️</td>\n  </tr>\n  <tr>\n  <td style=\"text-align:left\"><code>hooray</code></td>\n  <td style=\"text-align:left\">🎉</td>\n  </tr>\n  <tr>\n  <td style=\"text-align:left\"><code>rocket</code></td>\n  <td style=\"text-align:left\">🚀</td>\n  </tr>\n  <tr>\n  <td style=\"text-align:left\"><code>eyes</code></td>\n  <td style=\"text-align:left\">👀</td>\n  </tr>\n  </tbody>\n  </table>\n\n* 호출의 나머지는 페이로드 개체로 구성됩니다. 여기서는 변형을 수행한 후 서버에서 반환하도록 할 데이터를 지정합니다. 이러한 줄은 [`addReaction` 문서](/ko/graphql/reference/reactions#mutation-addreaction)에서 오는 것이며, 다음 세 가지 가능한 반환 필드가 있습니다.\n\n  * `clientMutationId`(`String`)\n  * `reaction`(`Reaction!`)\n  * `subject`(`Reactable!`)\n\n  이 예제에서는 필수 하위 필드(각각 `reaction` 및 `subject`)가 있는 두 개의 필수 필드(`content` 및 `id`)를 반환합니다.\n\n변형을 실행할 때 응답은 다음과 같습니다.\n\n```json\n{\n  \"data\": {\n    \"addReaction\": {\n      \"reaction\": {\n        \"content\": \"HOORAY\"\n      },\n      \"subject\": {\n        \"id\": \"MDU6SXNzdWUyMTc5NTQ0OTc=\"\n      }\n    }\n  }\n}\n```\n\n정말 간단하죠. 사용자 이름을 찾으려면 :tada를 마우스로 가리켜 [ 문제에 대한 반응](https://github.com/octocat/Hello-World/issues/349)을 확인합니다.\n\n마지막으로, 입력 개체에 여러 필드를 전달하면 구문이 다루기 어려워질 수 있습니다. 필드를 [변수](#working-with-variables)로 이동하면 도움이 될 수 있습니다. 변수를 사용하여 원래 변형을 다시 작성하는 방법은 다음과 같습니다.\n\n```graphql\nmutation($myVar:AddReactionInput!) {\n  addReaction(input:$myVar) {\n    reaction {\n      content\n    }\n    subject {\n      id\n    }\n  }\n}\nvariables {\n  \"myVar\": {\n    \"subjectId\":\"MDU6SXNzdWUyMTc5NTQ0OTc=\",\n    \"content\":\"HOORAY\"\n  }\n}\n```\n\n> \\[!NOTE]\n> 이전 예제에서 `content` 필드 값(변형에서 직접 사용됨)에는 `HOORAY` 주위에 따옴표가 없지만, 변수에 사용될 때는 따옴표가 있는 것을 알 수 있습니다. 그 이유는 다음과 같습니다.\n>\n> * 변이에서 `content`를 직접 사용하는 경우, 스키마는 값이 문자열이 아닌 [`ReactionContent`](/ko/graphql/reference/reactions#enum-reactioncontent) 형식의 \\_열거형\\_일 것으로 예상합니다. 따옴표는 문자열에 예약되어 있으므로 열거형 값 주위에 따옴표를 추가하면 스키마 유효성 검사에서 오류가 발생합니다.\n> * 변수에서 `content`를 사용하는 경우, 변수 섹션은 유효한 JSON이어야 하므로 따옴표가 필요합니다. 스키마 유효성 검사는 실행 중에 변수가 변형으로 전달될 때 `ReactionContent` 형식을 올바르게 해석합니다.\n>\n> 열거형과 문자열 간의 차이점에 대한 자세한 내용은 [공식 GraphQL 사양](https://spec.graphql.org/June2018/#sec-Enums)을 참조하세요.\n\n## 추가 참고 자료\n\nGraphQL 호출을 구성할 때 할 수 있는 작업이 훨씬 더 많습니다.\\_\\_ 다음에 살펴볼 내용은 아래와 같습니다.\n\n* [GraphQL API에서 페이지 매김 사용](/ko/graphql/guides/using-pagination-in-the-graphql-api)\n* [프래그먼트](https://graphql.org/learn/queries/#fragments)\n* [인라인 프래그먼트](https://graphql.org/learn/queries/#inline-fragments)\n* [지시문](https://graphql.org/learn/queries/#directives)"}