{"id":2008,"date":"2024-10-03T13:28:52","date_gmt":"2024-10-03T04:28:52","guid":{"rendered":"https:\/\/hyunsu.com\/wordpress\/?p=2008"},"modified":"2024-10-03T13:28:52","modified_gmt":"2024-10-03T04:28:52","slug":"graphql%ec%9d%98-%ec%97%90%eb%9f%ac-%ec%b2%98%eb%a6%ac","status":"publish","type":"post","link":"https:\/\/hyunsu.com\/wordpress\/?p=2008","title":{"rendered":"GraphQL\uc758 \uc5d0\ub7ec \ucc98\ub9ac"},"content":{"rendered":"\n<p>GraphQL\uc5d0\uc11c\uc758 **\uc5d0\ub7ec \ucc98\ub9ac(Error Handling)**\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8\uc640 \uc11c\ubc84 \uac04\uc5d0 \uc77c\uc5b4\ub098\ub294 \ubb38\uc81c\ub97c \ud6a8\uc728\uc801\uc73c\ub85c \ucc98\ub9ac\ud558\uace0, \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \uc720\uc6a9\ud55c \uc815\ubcf4\ub97c \uc804\ub2ec\ud558\ub294 \ub370 \ub9e4\uc6b0 \uc911\uc694\ud55c \uc5ed\ud560\uc744 \ud569\ub2c8\ub2e4. GraphQL\uc740 **\ubd80\ubd84 \uc131\uacf5(Partial Success)**\uc774\ub77c\ub294 \uac1c\ub150\uc744 \uac00\uc9c0\uace0 \uc788\uc5b4, \ud55c \ucffc\ub9ac \ub0b4\uc5d0\uc11c \uc77c\ubd80 \ud544\ub4dc\uac00 \uc2e4\ud328\ud558\ub354\ub77c\ub3c4 \ub098\uba38\uc9c0 \ud544\ub4dc\uc758 \ub370\uc774\ud130\ub97c \uc815\uc0c1\uc801\uc73c\ub85c \ubc18\ud658\ud560 \uc218 \uc788\ub294 \uc720\uc5f0\ud55c \uc5d0\ub7ec \ucc98\ub9ac \ubc29\uc2dd\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<p>GraphQL\uc5d0\uc11c \uc5d0\ub7ec\ub294 \uc77c\ubc18\uc801\uc73c\ub85c \ub450 \uac00\uc9c0\ub85c \uad6c\ubd84\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>GraphQL \ub808\ubca8 \uc5d0\ub7ec<\/strong>: \ucffc\ub9ac \ubb38\ubc95\uc774\ub098 \uc2a4\ud0a4\ub9c8\uc640 \uad00\ub828\ub41c \uc5d0\ub7ec.<\/li>\n\n\n\n<li><strong>\ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1 \uc5d0\ub7ec<\/strong>: \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \ub370\uc774\ud130\ub97c \ucc3e\uc9c0 \ubabb\ud558\uac70\ub098, \uad8c\ud55c\uc774 \ubd80\uc871\ud560 \ub54c \ubc1c\uc0dd\ud558\ub294 \uc5d0\ub7ec.<\/li>\n<\/ol>\n\n\n\n<p>\uc774\uc81c GraphQL \uc5d0\ub7ec \ucc98\ub9ac\uc5d0 \ub300\ud574 \ucc28\uadfc\ucc28\uadfc \uc124\uba85\ud574\ub4dc\ub9b4\uac8c\uc694.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>1. GraphQL \uc5d0\ub7ec\uc758 \uae30\ubcf8 \uad6c\uc870<\/strong><\/h3>\n\n\n\n<p>GraphQL\uc758 \uc751\ub2f5\uc740 JSON \ud615\uc2dd\uc73c\ub85c \uc774\ub8e8\uc5b4\uc9c0\uba70, \uc131\uacf5\ud55c \ucffc\ub9ac\uc640 \ud568\uaed8 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc744 \uacbd\uc6b0 <strong><code>errors<\/code><\/strong> \ud544\ub4dc\uc5d0 \uc5d0\ub7ec \uba54\uc2dc\uc9c0\uac00 \ud3ec\ud568\ub429\ub2c8\ub2e4. \uae30\ubcf8\uc801\uc778 \uc751\ub2f5 \ud615\uc2dd\uc740 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\uc131\uacf5\uc801\uc778 \uc751\ub2f5:<\/h4>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>{<br>  \"data\": {<br>    \"user\": {<br>      \"id\": \"1\",<br>      \"name\": \"John\"<br>    }<br>  }<br>}<br><\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\uc5d0\ub7ec\uac00 \ud3ec\ud568\ub41c \uc751\ub2f5:<\/h4>\n\n\n\n<pre class=\"wp-block-preformatted\">json\ucf54\ub4dc \ubcf5\uc0ac<code>{\n  \"data\": {\n    \"user\": null\n  },\n  \"errors\": [\n    {\n      \"message\": \"User not found\",\n      \"locations\": [{ \"line\": 2, \"column\": 3 }],\n      \"path\": [\"user\"]\n    }\n  ]\n}\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>data<\/code><\/strong>: \ucffc\ub9ac\uc758 \uc131\uacf5\ud55c \uacb0\uacfc\ub97c \ub098\ud0c0\ub0c5\ub2c8\ub2e4. \uc77c\ubd80 \ud544\ub4dc\uac00 \uc2e4\ud328\ud558\ub354\ub77c\ub3c4 \ub098\uba38\uc9c0 \ud544\ub4dc\ub294 \uc131\uacf5\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/li>\n\n\n\n<li><strong><code>errors<\/code><\/strong>: \uc2e4\ud328\ud55c \ud544\ub4dc\uc640 \uad00\ub828\ub41c \uc5d0\ub7ec \uba54\uc2dc\uc9c0\ub97c \ud3ec\ud568\ud569\ub2c8\ub2e4.\n<ul class=\"wp-block-list\">\n<li><strong>message<\/strong>: \uc5d0\ub7ec \uba54\uc2dc\uc9c0.<\/li>\n\n\n\n<li><strong>locations<\/strong>: \ucffc\ub9ac\uc5d0\uc11c \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud55c \uc704\uce58(\uc904\uacfc \uc5f4).<\/li>\n\n\n\n<li><strong>path<\/strong>: \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud55c \ud544\ub4dc \uacbd\ub85c.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>2. GraphQL\uc5d0\uc11c \uc5d0\ub7ec \ucc98\ub9ac \ubc29\uc2dd<\/strong><\/h3>\n\n\n\n<p>GraphQL\uc5d0\uc11c\ub294 \uac01 \ub9ac\uc878\ubc84\uac00 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589\ub418\ubbc0\ub85c, \ud55c \ub9ac\uc878\ubc84\uc5d0\uc11c \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud558\ub354\ub77c\ub3c4 \ub2e4\ub978 \ub9ac\uc878\ubc84\ub294 \uc815\uc0c1\uc801\uc73c\ub85c \ub3d9\uc791\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc774\ub85c \uc778\ud574 <strong>\ubd80\ubd84 \uc131\uacf5<\/strong>\uc774\ub77c\ub294 \ud2b9\uc9d5\uc774 \uc788\uc2b5\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, \ud558\ub098\uc758 \ud544\ub4dc\uc5d0\uc11c \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud574\ub3c4, \ub2e4\ub978 \ud544\ub4dc\ub294 \uc815\uc0c1\uc801\uc73c\ub85c \ub370\uc774\ud130\ub97c \ubc18\ud658\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>3. \uc5d0\ub7ec \ucc98\ub9ac \uc608\uc2dc<\/strong><\/h3>\n\n\n\n<p>\ub2e4\uc74c\uc740 \uc0ac\uc6a9\uc790 \uc815\ubcf4\ub97c \uc870\ud68c\ud558\ub294 GraphQL \ub9ac\uc878\ubc84\uc5d0\uc11c \ubc1c\uc0dd\ud560 \uc218 \uc788\ub294 \uc5ec\ub7ec \uc0c1\ud669\uc744 \ucc98\ub9ac\ud558\ub294 \uc608\uc2dc\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>1) \uae30\ubcf8\uc801\uc778 \uc5d0\ub7ec \ucc98\ub9ac<\/strong><\/h4>\n\n\n\n<p>\uc544\ub798\ub294 \uc0ac\uc6a9\uc790\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc744 \ub54c \ubc1c\uc0dd\ud558\ub294 \uc5d0\ub7ec\ub97c \ucc98\ub9ac\ud558\ub294 \ub9ac\uc878\ubc84\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>const resolvers = {<br>  Query: {<br>    user: async (parent, { id }) => {<br>      const user = await User.findById(id);<br>      if (!user) {<br>        throw new Error('User not found');<br>      }<br>      return user;<br>    }<br>  }<br>};<br><\/code><\/pre>\n\n\n\n<p>\uc774 \ub9ac\uc878\ubc84\uc5d0\uc11c <code>User.findById()<\/code>\ub85c \uc0ac\uc6a9\uc790\ub97c \uc870\ud68c\ud558\ub294\ub370, \uc0ac\uc6a9\uc790\uac00 \uc874\uc7ac\ud558\uc9c0 \uc54a\uc73c\uba74 <code>throw new Error('User not found')<\/code>\ub85c \uc5d0\ub7ec\ub97c \ubc1c\uc0dd\uc2dc\ud0b5\ub2c8\ub2e4. \uc774 \uc5d0\ub7ec\ub294 GraphQL\uc758 <code>errors<\/code> \ud544\ub4dc\uc5d0 \ud3ec\ud568\ub418\uc5b4 \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0 \uc804\ub2ec\ub429\ub2c8\ub2e4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>2) \ucee4\uc2a4\ud140 \uc5d0\ub7ec \ucc98\ub9ac<\/strong><\/h4>\n\n\n\n<p>\ub2e8\uc21c\ud55c \uc5d0\ub7ec \uba54\uc2dc\uc9c0 \uc678\uc5d0, \ub354 \uad6c\uccb4\uc801\uc778 \uc5d0\ub7ec \uc815\ubcf4\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0 \uc81c\uacf5\ud558\uae30 \uc704\ud574 <strong>\ucee4\uc2a4\ud140 \uc5d0\ub7ec \ud074\ub798\uc2a4<\/strong>\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>class UserNotFoundError extends Error {<br>  constructor(message) {<br>    super(message);<br>    this.name = \"UserNotFoundError\";<br>  }<br>}<br><br>const resolvers = {<br>  Query: {<br>    user: async (parent, { id }) => {<br>      const user = await User.findById(id);<br>      if (!user) {<br>        throw new UserNotFoundError('The user with the given ID does not exist.');<br>      }<br>      return user;<br>    }<br>  }<br>};<\/code><\/pre>\n\n\n\n<p>\ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc774 \uc5d0\ub7ec\ub97c \ubc1b\uc544 \uc5d0\ub7ec\uc758 <strong>\uc774\ub984<\/strong>\uacfc <strong>\uba54\uc2dc\uc9c0<\/strong>\ub97c \ud1b5\ud574 \ub354\uc6b1 \uad6c\uccb4\uc801\uc778 \uc815\ubcf4\ub97c \uc54c \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>3) \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1 \uc5d0\ub7ec \ucc98\ub9ac<\/strong><\/h4>\n\n\n\n<p>\ub85c\uadf8\uc778 \uc2dc\uc2a4\ud15c\uc774\ub098 \uad8c\ud55c \uad00\ub9ac\uac00 \ud544\uc694\ud55c \uacbd\uc6b0, \ub2e4\uc74c\uacfc \uac19\uc740 \ubc29\uc2dd\uc73c\ub85c \uc778\uc99d \ubc0f \uad8c\ud55c \uc5d0\ub7ec\ub97c \ucc98\ub9ac\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>const resolvers = {<br>  Query: {<br>    secretData: async (parent, args, context) => {<br>      if (!context.user) {<br>        throw new Error('Not authenticated');<br>      }<br>      \/\/ \uc778\uc99d\ub41c \uc0ac\uc6a9\uc790\ub9cc secret data\ub97c \uc870\ud68c\ud560 \uc218 \uc788\uc74c<br>      return \"This is secret data!\";<br>    }<br>  }<br>};<br><\/code><\/pre>\n\n\n\n<p>\uc774 \ub9ac\uc878\ubc84\ub294 \uc778\uc99d\ub418\uc9c0 \uc54a\uc740 \uc0ac\uc6a9\uc790\uac00 \uc811\uadfc\ud558\ub824\uace0 \ud560 \ub54c **<code>Not authenticated<\/code>**\ub77c\ub294 \uc5d0\ub7ec\ub97c \ubc1c\uc0dd\uc2dc\ud0b5\ub2c8\ub2e4. \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc774 \uc5d0\ub7ec\ub97c \ubc1b\uc544 \ucc98\ub9ac\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>4. \uc5d0\ub7ec \ud655\uc7a5(Extension) \ud544\ub4dc \uc0ac\uc6a9\ud558\uae30<\/strong><\/h3>\n\n\n\n<p>GraphQL\uc5d0\uc11c\ub294 \uc5d0\ub7ec \uba54\uc2dc\uc9c0 \uc678\uc5d0\ub3c4 **\ud655\uc7a5 \ud544\ub4dc(<code>extensions<\/code>)**\ub97c \uc0ac\uc6a9\ud574 \ucd94\uac00\uc801\uc778 \uc815\ubcf4\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0 \uc81c\uacf5\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, \uc5d0\ub7ec \ucf54\ub4dc, \ub514\ubc84\uadf8 \uc815\ubcf4, \uc0c1\ud0dc \ucf54\ub4dc \ub4f1\uc744 \ud3ec\ud568\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>1) \ud655\uc7a5 \ud544\ub4dc \uc0ac\uc6a9 \uc608\uc2dc:<\/strong><\/h4>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>const resolvers = {<br>  Query: {<br>    user: async (parent, { id }) => {<br>      const user = await User.findById(id);<br>      if (!user) {<br>        const error = new Error('User not found');<br>        error.extensions = {<br>          code: 'USER_NOT_FOUND',<br>          httpStatus: 404<br>        };<br>        throw error;<br>      }<br>      return user;<br>    }<br>  }<br>};<\/code><\/pre>\n\n\n\n<p>\ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc774\ub807\uac8c \ud655\uc7a5\ub41c \uc5d0\ub7ec\ub97c \ubc1b\uc544, \ucf54\ub4dc\ub098 \uc0c1\ud0dc \ucf54\ub4dc\ub97c \ud1b5\ud574 \ucd94\uac00\uc801\uc778 \uc815\ubcf4\ub97c \ud65c\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<p><strong>\ud074\ub77c\uc774\uc5b8\ud2b8\ub85c\uc758 \uc751\ub2f5 \uc608\uc2dc<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>{<br>  \"data\": {<br>    \"user\": null<br>  },<br>  \"errors\": [<br>    {<br>      \"message\": \"User not found\",<br>      \"extensions\": {<br>        \"code\": \"USER_NOT_FOUND\",<br>        \"httpStatus\": 404<br>      }<br>    }<br>  ]<br>}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>2) GraphQL \uc5d0\ub7ec \ud655\uc7a5 \ud544\ub4dc\uc758 \uc7a5\uc810:<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\uc5d0\ub7ec \ucf54\ub4dc<\/strong>: \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc5d0\ub7ec \uba54\uc2dc\uc9c0 \uc678\uc5d0, \uc5d0\ub7ec\uc758 \uc885\ub958\ub098 \uc0c1\ud0dc\ub97c \ucf54\ub4dc\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\uac8c \ud574\uc90d\ub2c8\ub2e4.<\/li>\n\n\n\n<li><strong>HTTP \uc0c1\ud0dc \ucf54\ub4dc<\/strong>: GraphQL\uc740 \uae30\ubcf8\uc801\uc73c\ub85c HTTP 200 \uc751\ub2f5\uc744 \ubc18\ud658\ud558\uc9c0\ub9cc, \ud655\uc7a5 \ud544\ub4dc\ub97c \uc0ac\uc6a9\ud574 \uc0c1\ud0dc \ucf54\ub4dc\uc640 \ud568\uaed8 \uc5d0\ub7ec\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0 \uc81c\uacf5\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/li>\n\n\n\n<li><strong>\ub514\ubc84\uae45 \uc815\ubcf4<\/strong>: \uac1c\ubc1c \ud658\uacbd\uc5d0\uc11c\ub294 \ucd94\uac00\uc801\uc778 \ub514\ubc84\uae45 \uc815\ubcf4\ub97c \uc81c\uacf5\ud574 \ubb38\uc81c\ub97c \ucd94\uc801\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>5. \uc804\uc5ed \uc5d0\ub7ec \ucc98\ub9ac<\/strong><\/h3>\n\n\n\n<p>\uc11c\ubc84\uc5d0\uc11c \uc804\uc5ed\uc801\uc73c\ub85c \uc5d0\ub7ec\ub97c \ucc98\ub9ac\ud558\uace0, \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0 \uc5d0\ub7ec \uba54\uc2dc\uc9c0\ub97c \uc77c\uad00\ub418\uac8c \uc804\ub2ec\ud558\uae30 \uc704\ud574 <strong>\uc804\uc5ed \uc5d0\ub7ec \ucc98\ub9ac \ubbf8\ub4e4\uc6e8\uc5b4<\/strong>\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\uc804\uc5ed \uc5d0\ub7ec \ucc98\ub9ac \uc608\uc2dc (Express + GraphQL):<\/h4>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>const { graphqlHTTP } = require('express-graphql');<br><br>const app = express();<br><br>app.use('\/graphql', graphqlHTTP({<br>  schema: schema,<br>  rootValue: root,<br>  graphiql: true,<br>  customFormatErrorFn: (err) => {<br>    return {<br>      message: err.message,<br>      code: err.extensions?.code || 'INTERNAL_SERVER_ERROR',<br>      locations: err.locations,<br>      path: err.path<br>    };<br>  }<br>}));<br><\/code><\/pre>\n\n\n\n<p>\uc704 \uc608\uc2dc\uc5d0\uc11c **<code>customFormatErrorFn<\/code>**\uc744 \uc0ac\uc6a9\ud558\uc5ec GraphQL\uc758 \uc5d0\ub7ec\ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc988\ud569\ub2c8\ub2e4. \uc774 \ud568\uc218\ub294 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \uc5d0\ub7ec \uba54\uc2dc\uc9c0\uc640 \ud655\uc7a5 \ud544\ub4dc, \uadf8\ub9ac\uace0 \uc5d0\ub7ec \uacbd\ub85c \uc815\ubcf4\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0 \uc804\ub2ec\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>6. GraphQL \uc5d0\ub7ec \ucc98\ub9ac \ud328\ud134<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\ubd80\ubd84 \uc131\uacf5 \ud5c8\uc6a9<\/strong>: GraphQL\uc758 \ud2b9\uc131\uc0c1 \uc5ec\ub7ec \ud544\ub4dc\uc5d0\uc11c \uc77c\ubd80 \uc131\uacf5\uacfc \uc77c\ubd80 \uc2e4\ud328\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc774\ub7f0 \uc0c1\ud669\uc5d0\uc11c\ub294 \uc131\uacf5\ud55c \ub370\uc774\ud130\ub294 <code>data<\/code>\uc5d0, \uc2e4\ud328\ud55c \ub370\uc774\ud130\ub294 <code>errors<\/code> \ud544\ub4dc\uc5d0 \uac01\uac01 \ud3ec\ud568\ub429\ub2c8\ub2e4.<\/li>\n\n\n\n<li><strong>\uc0ac\uc6a9\uc790 \uc815\uc758 \uc5d0\ub7ec \ud578\ub4e4\ub9c1<\/strong>: \ub3c4\uba54\uc778 \ub85c\uc9c1\uc5d0 \ub530\ub77c \uc801\uc808\ud55c \ucee4\uc2a4\ud140 \uc5d0\ub7ec\ub97c \uc815\uc758\ud558\uace0 \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0 \ub354 \uc758\ubbf8 \uc788\ub294 \uc815\ubcf4\ub97c \uc804\ub2ec\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, <code>ValidationError<\/code>, <code>AuthenticationError<\/code>, <code>AuthorizationError<\/code> \ub4f1\uc758 \ucee4\uc2a4\ud140 \uc5d0\ub7ec \ud074\ub798\uc2a4\ub97c \ub9cc\ub4e4\uc5b4 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc2b5\ub2c8\ub2e4.<\/li>\n\n\n\n<li><strong>\uc5d0\ub7ec \ucf54\ub4dc \ubc0f \ud655\uc7a5 \uc815\ubcf4 \uc81c\uacf5<\/strong>: \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \ub2e8\uc21c\ud55c \uc5d0\ub7ec \uba54\uc2dc\uc9c0 \uc678\uc5d0 \uc5d0\ub7ec \ucf54\ub4dc\ub098 HTTP \uc0c1\ud0dc \ucf54\ub4dc\ub97c \ud1b5\ud574 \ucd94\uac00\uc801\uc778 \uc870\uce58\ub97c \ucde8\ud560 \uc218 \uc788\ub3c4\ub85d \ud655\uc7a5 \ud544\ub4dc\ub97c \ud65c\uc6a9\ud574 \uc5d0\ub7ec\ub97c \uc81c\uacf5\ud574\uc57c \ud569\ub2c8\ub2e4.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>7. GraphQL \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \uc5d0\ub7ec \ucc98\ub9ac<\/strong><\/h3>\n\n\n\n<p><strong>Apollo Client<\/strong>\uc640 \uac19\uc740 GraphQL \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c\ub294 \uc11c\ubc84\uc5d0\uc11c \ubc1c\uc0dd\ud55c \uc5d0\ub7ec\ub97c \uc27d\uac8c \ucc98\ub9ac\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 <code>errors<\/code> \ud544\ub4dc\ub97c \ud655\uc778\ud558\uace0, \uac01 \uc5d0\ub7ec\uc5d0 \ub300\ud55c \uc801\uc808\ud55c \ucc98\ub9ac\ub97c \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Apollo Client\uc5d0\uc11c \uc5d0\ub7ec \ucc98\ub9ac:<\/h4>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>import { useQuery, gql } from '@apollo\/client';<br><br>const GET_USER = gql`<br>  query getUser($id: ID!) {<br>    user(id: $id) {<br>      id<br>      name<br>    }<br>  }<br>`;<br><br>function User({ id }) {<br>  const { loading, error, data } = useQuery(GET_USER, {<br>    variables: { id }<br>  });<br><br>  if (loading) return &lt;p>Loading...&lt;\/p>;<br>  if (error) return &lt;p>Error: {error.message}&lt;\/p>;<br><br>  return &lt;p>{data.user.name}&lt;\/p>;<br>}<br><\/code><\/pre>\n\n\n\n<p>\uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc744 \uacbd\uc6b0, <code>error.message<\/code>\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \ucc98\ub9ac\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>\uacb0\ub860<\/strong><\/h3>\n\n\n\n<p>GraphQL\uc5d0\uc11c\uc758 \uc5d0\ub7ec \ucc98\ub9ac\ub294 <strong>\ubd80\ubd84 \uc131\uacf5<\/strong>\uc744 \ud5c8\uc6a9\ud558\uba74\uc11c\ub3c4, \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \uc720\uc758\ubbf8\ud55c \uc5d0\ub7ec \uc815\ubcf4\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub3c4\ub85d \uc124\uacc4\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4. \uc774\ub97c \ud1b5\ud574 \uc0ac\uc6a9\uc790\ub294 \ucffc\ub9ac\uc758 \uc77c\ubd80\ub9cc \uc2e4\ud328\ud558\ub354\ub77c\ub3c4 \ub098\uba38\uc9c0 \ub370\uc774\ud130\ub294 \uc815\uc0c1\uc801\uc73c\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\ub610\ud55c, \ud655\uc7a5 \ud544\ub4dc\ub97c \ud65c\uc6a9\ud574 \uc5d0\ub7ec \ucf54\ub4dc\ub098 \uc0c1\ud0dc \ucf54\ub4dc\ub97c \ucd94\uac00\ub85c \uc81c\uacf5\ud568\uc73c\ub85c\uc368, \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \ub354 \uad6c\uccb4\uc801\uc778 \uc5d0\ub7ec \ucc98\ub9ac\ub97c \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc804\uc5ed \uc5d0\ub7ec \ud578\ub4e4\ub7ec\ub098 \ucee4\uc2a4\ud140 \uc5d0\ub7ec \ud074\ub798\uc2a4\ub97c \ud1b5\ud574 \uc11c\ubc84\uc758 \uc5d0\ub7ec \uad00\ub9ac\ub97c \ub354\uc6b1 \ud6a8\uc728\uc801\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>GraphQL\uc5d0\uc11c\uc758 **\uc5d0\ub7ec \ucc98\ub9ac(Error Handling)**\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8\uc640 \uc11c\ubc84 \uac04\uc5d0 \uc77c\uc5b4\ub098\ub294 \ubb38\uc81c\ub97c \ud6a8\uc728\uc801\uc73c\ub85c \ucc98\ub9ac\ud558\uace0, \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \uc720\uc6a9\ud55c \uc815\ubcf4\ub97c \uc804\ub2ec\ud558\ub294 \ub370 \ub9e4\uc6b0 \uc911\uc694\ud55c \uc5ed\ud560\uc744 \ud569\ub2c8\ub2e4. GraphQL\uc740 **\ubd80\ubd84 \uc131\uacf5(Partial Success)**\uc774\ub77c\ub294 \uac1c\ub150\uc744 \uac00\uc9c0\uace0 \uc788\uc5b4, \ud55c \ucffc\ub9ac \ub0b4\uc5d0\uc11c \uc77c\ubd80 \ud544\ub4dc\uac00 \uc2e4\ud328\ud558\ub354\ub77c\ub3c4 \ub098\uba38\uc9c0 \ud544\ub4dc\uc758 \ub370\uc774\ud130\ub97c \uc815\uc0c1\uc801\uc73c\ub85c \ubc18\ud658\ud560 \uc218 \uc788\ub294 \uc720\uc5f0\ud55c \uc5d0\ub7ec \ucc98\ub9ac \ubc29\uc2dd\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. GraphQL\uc5d0\uc11c \uc5d0\ub7ec\ub294 \uc77c\ubc18\uc801\uc73c\ub85c \ub450 \uac00\uc9c0\ub85c \uad6c\ubd84\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4: \uc774\uc81c GraphQL [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[55],"tags":[],"class_list":["post-2008","post","type-post","status-publish","format-standard","hentry","category-coding"],"_links":{"self":[{"href":"https:\/\/hyunsu.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/2008","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hyunsu.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hyunsu.com\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hyunsu.com\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hyunsu.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2008"}],"version-history":[{"count":1,"href":"https:\/\/hyunsu.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/2008\/revisions"}],"predecessor-version":[{"id":2009,"href":"https:\/\/hyunsu.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/2008\/revisions\/2009"}],"wp:attachment":[{"href":"https:\/\/hyunsu.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2008"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hyunsu.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2008"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hyunsu.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2008"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}