{"id":1987,"date":"2015-12-16T01:06:40","date_gmt":"2015-12-16T01:06:39","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=1987"},"modified":"2019-01-02T06:19:31","modified_gmt":"2019-01-02T14:19:31","slug":"adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/ko\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/","title":{"rendered":"\uce74\uc6b0\uce58\ubca0\uc774\uc2a4 \ubaa8\ubc14\uc77c \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 Node.js\ub85c \uad6c\uae00 \ub85c\uadf8\uc778 \ucd94\uac00\ud558\uae30"},"content":{"rendered":"<p>Google+\uc640 \uac19\uc740 \ud0c0\uc0ac \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 OAuth API\ub97c \uc0ac\uc6a9\ud558\uc5ec \ubaa8\ubc14\uc77c \uc571\uc5d0 \ub85c\uadf8\uc778\ud558\uba74 \uc0ac\uc6a9\uc790\uc5d0\uac8c \uc990\uac70\uc6b4 \uccab \uacbd\ud5d8\uc744 \uc81c\uacf5\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc0ac\uc6a9\uc790\ub294 \uc774\ubbf8 \uc54c\uace0 \uc788\uace0 \uc2e0\ub8b0\ud558\ub294 \uacc4\uc815\uc73c\ub85c \ub85c\uadf8\uc778\ud558\uace0 Google+\uc5d0 \uc785\ub825\ud55c \ub370\uc774\ud130\ub85c \ud504\ub85c\ud544\uc744 \ucc44\uc6b8 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc774 \ud29c\ud1a0\ub9ac\uc5bc\uc5d0\uc11c\ub294 \uadf8 \ubc29\ubc95\uc744 \uc54c\uc544\ubd05\ub2c8\ub2e4:<\/p>\n<ul>\n<li>\ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774\ub85c \uc778\uc99d\uc744 \ucc98\ub9ac\ud558\ub294 Node.js \uc571\uc744 \uc791\uc131\ud558\uc138\uc694.<\/li>\n<li>\uce74\uc6b0\uce58\ubca0\uc774\uc2a4 \ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774 \uad00\ub9ac\uc790 REST API\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790 \ubc0f \uc138\uc158\uc744 \uc0dd\uc131\ud569\ub2c8\ub2e4.<\/li>\n<li>Swift 2\ub85c \uc791\uc131\ub41c iOS \uc571\uc5d0 Google \ub85c\uadf8\uc778\uc744 \ud1b5\ud569\ud569\ub2c8\ub2e4.<\/li>\n<li>Swift\uc5d0\uc11c \uac04\ub2e8\ud55c iOS \uc571\uc744 \ube4c\ub4dc\ud558\uc5ec \uc0c8 \ub85c\uadf8\uc778 \uc5d4\ub4dc\ud3ec\uc778\ud2b8\ub97c \ud14c\uc2a4\ud2b8\ud558\uace0 \uba87 \uac00\uc9c0 \ubb38\uc11c\ub97c \ubcf5\uc81c\ud558\uc138\uc694.<\/li>\n<\/ul>\n<p>\ucd5c\uc885 \ud504\ub85c\uc81d\ud2b8\ub294 \ub2e4\uc74c\uc5d0\uc11c \ud655\uc778\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. <a href=\"https:\/\/github.com\/couchbaselabs\/mini-hacks\/tree\/master\/google-sign-in\">GitHub<\/a>.<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2015\/october\/adding-google-sign-in-with-node.js-to-a-couchbase-mobile-application\/thumbnail.png\" \/><\/p>\n<h2>\u00a0\uc804\uc81c \uc870\uac74<\/h2>\n<p>\uc774 \ud29c\ud1a0\ub9ac\uc5bc\uc758 \uc804\uc81c \uc870\uac74\uc740 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4:<\/p>\n<ul>\n<li>Node.js<\/li>\n<li>Xcode 7+(\uc0d8\ud50c \uc571\uc744 \ube4c\ub4dc\ud560 \ub54c Swift 2\ub97c \uc0ac\uc6a9\ud568)<\/li>\n<\/ul>\n<h2>\uc2dc\uc791\ud558\uae30<\/h2>\n<p>\uc544\ub798 \ub9c1\ud06c\uc5d0\uc11c \ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774\ub97c \ub2e4\uc6b4\ub85c\ub4dc\ud558\uace0 \ud30c\uc77c\uc758 \uc555\ucd95\uc744 \ud489\ub2c8\ub2e4:<\/p>\n<p>https:\/\/www.couchbase.com\/nosql-databases\/downloads<\/p>\n<p>\ub77c\ub294 \uc0c8 \ud30c\uc77c\uc5d0 <strong>\ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774-config.json<\/strong>\ub97c \ud074\ub9ad\ud558\uace0 \ub2e4\uc74c\uc744 \ubd99\uc5ec\ub123\uc2b5\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-javascript\">{\r\n  \"log\": [\"*\"],\r\n  \"databases\": {\r\n    \"simple-login\": {\r\n      \"server\": \"walrus:\",\r\n      \"users\": { \"GUEST\": { \"disabled\": true } },\r\n      \"sync\": `\r\n        function(doc, oldDoc) {\r\n          channel(doc._id);\r\n          access(doc.user_id, doc._id);\r\n        }\r\n      `\r\n    }\r\n  }\r\n}<\/code><\/pre>\n<p>\uc774 \uad6c\uc131 \ud30c\uc77c\uc5d0\uc11c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub97c \uc0dd\uc131\ud569\ub2c8\ub2e4. <strong>\uac04\ud3b8 \ub85c\uadf8\uc778<\/strong> \ub3d9\uae30\ud654 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc5ec \uac01 \ubb38\uc11c\ub97c \ub2e4\ub978 \ucc44\ub110\uc5d0 \ub9e4\ud551\ud558\uace0 \uc0ac\uc6a9\uc790\uc5d0\uac8c \ucc44\ub110\uc5d0 \ub300\ud55c \uc561\uc138\uc2a4 \uad8c\ud55c\uc744 \ubd80\uc5ec\ud569\ub2c8\ub2e4(\ucc44\ub110\uc5d0 \uc800\uc7a5\ub418\ub294 \uc0ac\uc6a9\uc790 \uc774\ub984\uc740 <code>user_id<\/code> \ud544\ub4dc\uc5d0 \uc785\ub825\ud569\ub2c8\ub2e4).<\/p>\n<p>\ub2e4\uc74c \uba85\ub839\uc73c\ub85c \ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774\ub97c \uc2dc\uc791\ud569\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-bash\">$ ~\/Downloads\/couchbase-sync-gateway\/bin\/sync_gateway sync-gateway-config.json<\/code><\/pre>\n<h2>\ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774\uc6a9 \uc5ed\ubc29\ud5a5 \ud504\ub85d\uc2dc<\/h2>\n<p>\ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774\ub97c \uc2e4\ud589\ud558\uba74 Google\uacfc \ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774 \uac04\uc758 \uc778\uc99d\uc744 \ucc98\ub9ac\ud558\uae30 \uc704\ud55c \uc571 \uc11c\ubc84 \uad6c\ucd95\uc5d0 \uc9d1\uc911\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc778\uae30 \uc788\ub294 <a href=\"https:\/\/expressjs.com\/\">Express<\/a> \ubaa8\ub4c8\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790 \uc0dd\uc131 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\uace0 <a href=\"https:\/\/github.com\/request\/request\">\uc694\uccad<\/a> \ubaa8\ub4c8\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub2e4\ub978 \ubaa8\ub4e0 \ud2b8\ub798\ud53d\uc744 \ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774\ub85c \ud504\ub85d\uc2dc\ud569\ub2c8\ub2e4.<\/p>\n<p>\ub2e4\uc74c Node.js \ubaa8\ub4c8\uc744 \uc124\uce58\ud569\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-bash\">$ npm install express body-parser request --save<\/code><\/pre>\n<p>\ub77c\ub294 \uc0c8 \ud30c\uc77c\uc744 \ub9cc\ub4ed\ub2c8\ub2e4. <strong>server.js<\/strong> \ub97c \ud074\ub9ad\ud558\uace0 \ub2e4\uc74c\uc744 \ucd94\uac00\ud569\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-javascript\">\/\/ 1\r\nvar express = require('express')\r\n  , bodyParser = require('body-parser')\r\n  , request = request('request').defaults({json: true});\r\n\r\n\/\/ 2\r\nvar app = express();\r\napp.use('\/google_signin', bodyParser.json());\r\n\r\napp.post('\/google_signin', function (req, res) {\r\n  \/\/ TODO: handle login request\r\n});\r\n\r\n\/\/ 3\r\napp.all('*', function (req, res) {\r\n  var url = 'https:\/\/0.0.0.0:4984' + req.url;\r\n  req.pipe(request(url)).pipe(res);\r\n});\r\n\r\n\/\/ 4\r\nvar server = app.listen(8000, function () {\r\n  var host = server.address().address;\r\n  var port = server.address().port;\r\n\r\n  console.log('App listening at https:\/\/%s:%s', host, port);\r\n});<\/code><\/pre>\n<p>\ub2ec\ub77c\uc9c0\ub294 \uc810\uc740 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4:<\/p>\n<ol>\n<li>\uc774\uc804\uc5d0 \uc124\uce58\ud55c Node.js \ubaa8\ub4c8\uc774 \ud544\uc694\ud569\ub2c8\ub2e4.<\/li>\n<li>Express\uc758 \uc0c8 \uc778\uc2a4\ud134\uc2a4\ub97c \uc989\uc2dc \uc2e4\ud589\ud558\uace0 <strong>bodyParser<\/strong> \ubbf8\ub4e4\uc6e8\uc5b4 \uc804\uc6a9 <strong>\/google_signin<\/strong> \uc5d4\ub4dc\ud3ec\uc778\ud2b8.<\/li>\n<li>\ub2e4\ub978 \ubaa8\ub4e0 \uc694\uccad\uc744 \ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774\ub85c \ud504\ub85d\uc2dc\ud569\ub2c8\ub2e4.<\/li>\n<li>\ud3ec\ud2b8 8000\uc5d0\uc11c Node.js \uc6f9 \uc11c\ubc84\ub97c \uc2dc\uc791\ud569\ub2c8\ub2e4.<\/li>\n<\/ol>\n<p>\ub2e4\uc74c\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc11c\ubc84\ub97c \uc2dc\uc791\ud569\ub2c8\ub2e4. <code>$ \ub178\ub4dc server.js<\/code> \ub97c \ud074\ub9ad\ud558\uace0 <code>https:\/\/localhost:8000<\/code> \ub97c \ud074\ub9ad\ud569\ub2c8\ub2e4. \ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774 \ud658\uc601 \uba54\uc2dc\uc9c0\uac00 \ud45c\uc2dc\ub418\uc5b4\uc57c \ud569\ub2c8\ub2e4:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2015\/october\/adding-google-sign-in-with-node.js-to-a-couchbase-mobile-application\/server-root.png\" \/><\/p>\n<h3>Google \ub85c\uadf8\uc778\uc5d0\uc11c \ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774 \uc138\uc158\uae4c\uc9c0<\/h3>\n<p>\uc774\uc81c \uc5ed\ubc29\ud5a5 \ud504\ub85d\uc2dc\uac00 \uc124\uc815\ub418\uc5c8\uc73c\ubbc0\ub85c Google \ub85c\uadf8\uc778 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\uace0 \uc138\uc158 \uc790\uaca9 \uc99d\uba85\uc744 \ubc18\ud658\ud558\ub294 \ucf54\ub4dc\ub97c \ucd94\uac00\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2015\/october\/adding-google-sign-in-with-node.js-to-a-couchbase-mobile-application\/google-sign-in.png\" \/><\/p>\n<p>\uc774 \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc5d0\uc11c \uba87 \uac00\uc9c0 \uc77c\uc774 \uc77c\uc5b4\ub098\uace0 \uc788\uc2b5\ub2c8\ub2e4:<\/p>\n<ul>\n<li><strong>\ube14\ub799<\/strong> \ub294 Google \uc0ac\uc6a9\uc790 ID\ub97c \uc571 \uc11c\ubc84\ub85c \uc804\uc1a1\ud569\ub2c8\ub2e4.<\/li>\n<li><strong>\ud30c\ub780\uc0c9<\/strong> \ub294 \ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774\uc5d0 \ud574\ub2f9 \uc0ac\uc6a9\uc790 ID\ub97c \uac00\uc9c4 \uc0ac\uc6a9\uc790\uac00 \uc874\uc7ac\ud558\ub294\uc9c0 \ud655\uc778\ud569\ub2c8\ub2e4.<\/li>\n<li><strong>\uc624\ub80c\uc9c0<\/strong> \uc0ac\uc6a9\uc790\uac00 \uc544\uc9c1 \uc874\uc7ac\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \uc0ac\uc6a9\uc790\ub97c \uc0dd\uc131\ud569\ub2c8\ub2e4(\uc77c\ubc18\uc801\uc73c\ub85c \uc0ac\uc6a9\uc790\uac00 \uc571\uc5d0\uc11c Google\uc5d0 \ucc98\uc74c \ub85c\uadf8\uc778\ud560 \ub54c).<\/li>\n<li><strong>\ub179\uc0c9<\/strong> \uac00 \uc138\uc158\uc744 \uc0dd\uc131\ud558\uba74 \uc751\ub2f5\uc5d0 \ud478\uc2dc\/\ud480 \ubcf5\uc81c\ub97c \uc704\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8 iOS \uc571\uc5d0 \uc804\ub2ec\ud560 \uc218 \uc788\ub294 \uc138\uc158 \uc790\uaca9 \uc99d\uba85\uc774 \ud3ec\ud568\ub429\ub2c8\ub2e4. \ubaa8\ub4e0 \uce74\uc6b0\uce58\ubca0\uc774\uc2a4 \ub77c\uc774\ud2b8 SDK\uc5d0\ub294 \ud478\uc2dc\/\ud480 \ubcf5\uc81c\uc5d0 \uc0ac\uc6a9\ud560 \uc138\uc158 \uc790\uaca9 \uc99d\uba85\uc744 \uc9c0\uc815\ud558\ub294 \uba54\uc11c\ub4dc\uac00 \uc788\uc2b5\ub2c8\ub2e4.<\/li>\n<\/ul>\n<p>\uc5d0\uc11c <strong>\/google_signin<\/strong> \ud578\ub4e4\ub7ec\uc5d0 \ub2e4\uc74c\uc744 \ucd94\uac00\ud569\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-javascript\">\/** URL of the Sync Gateway instance running locally *\/\r\nvar stringURL = 'https:\/\/0.0.0.0:4985\/simple-login';\r\n\r\n\/** Given the name of a user that exists in Sync Gateway, create a new session *\/\r\nvar sessionRequest = function (name, callback) {\r\nreturn request({\r\n  method: 'POST',\r\n  url: stringURL + '\/_session',\r\n  json: true,\r\n  body: {\r\n    name: name\r\n  }\r\n}, callback);\r\n};\r\n\r\nvar json = req.body;\r\nvar name = json.auth_provider + '-' + json.user_id.toString();\r\nrequest\r\n\/** Check if the user already exists *\/\r\n.get(stringURL + '\/_user\/' + name)\r\n.on('response', function (userExistsResponse) {\r\n  if (userExistsResponse.statusCode === 404) {\r\n    \/** If the user doesn't exist, create one with the Google user ID as the name *\/\r\n    return request\r\n      .put({\r\n        url: stringURL + '\/_user\/' + name,\r\n        json: true,\r\n        body: {\r\n          name: name,\r\n          password: Math.random.toString(36).substr(2)\r\n        }\r\n      })\r\n      .on('response', function (createUserResponse) {\r\n        if (createUserResponse.statusCode === 201) {\r\n          \/** If the user was created successfully, create the session *\/\r\n          sessionRequest(name, function (sessionError, sessionResponse, body) {\r\n            res.send(body);\r\n          });\r\n        }\r\n      });\r\n  }\r\n  \/** The user already exists, simply create a new session *\/\r\n  sessionRequest(name, function (sessionError, sessionResponse, body) {\r\n    res.send(body);\r\n  });\r\n});<\/code><\/pre>\n<p>Node.js \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ub2e4\uc2dc \uc2dc\uc791\ud558\uace0 \ub2e4\uc74c curl \uc694\uccad\uc744 \uc2e4\ud589\ud558\uc5ec \uc0c8 \uc0ac\uc6a9\uc790\ub97c \ub4f1\ub85d\ud569\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-bash\">$ curl -vX POST \r\n            -H 'Content-Type: application\/json' \r\n            https:\/\/localhost:8000\/google_signin \r\n            -d '{\"user_id\": \"123\", \"auth_provider\": \"google\"}'\r\n\r\n\/\/ Response         \r\n{\r\n    \"session_id\":\"8520c19159a4154abf5fb9b9003ff9677e035929\",\r\n    \"expires\":\"2015-10-13T12:48:05.879325313+01:00\",\r\n    \"cookie_name\":\"SyncGatewaySession\"\r\n}<\/code><\/pre>\n<p>\ub2e4\uc74c \uc139\uc158\uc5d0\uc11c\ub294 \uc571 \uc11c\ubc84\uc758 \uc0c8\ub85c\uc6b4 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uae30 \uc704\ud574 Swift 2\ub97c \uc0ac\uc6a9\ud558\uc5ec \uac04\ub2e8\ud55c iOS \uc571\uc744 \ub9cc\ub4e4\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<h2>\uc2a4\uc704\ud504\ud2b8 \ud0c0\uc784: iOS\uc6a9 \uac04\ud3b8 \ub85c\uadf8\uc778 \ud654\uba74<\/h2>\n<p>Xcode\ub85c \uc804\ud658\ud558\uace0 \ub2e4\uc74c\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc0c8 \ud504\ub85c\uc81d\ud2b8\ub97c \uc0dd\uc131\ud569\ub2c8\ub2e4. <strong>\ub2e8\uc77c \ubcf4\uae30 \uc560\ud50c\ub9ac\ucf00\uc774\uc158<\/strong> \ud15c\ud50c\ub9bf\uc744 \uc0ac\uc6a9\ud569\ub2c8\ub2e4:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2015\/october\/adding-google-sign-in-with-node.js-to-a-couchbase-mobile-application\/xcode-new-project.png\" \/><\/p>\n<p>\uc774 \ud504\ub85c\uc81d\ud2b8\uc5d0 \uc885\uc18d\uc131\uc744 \uc124\uce58\ud558\uae30 \uc704\ud574 Cocoapods\ub97c \uc0ac\uc6a9\ud558\uaca0\uc2b5\ub2c8\ub2e4. Xcode \ud504\ub85c\uc81d\ud2b8\ub97c \ub2eb\uace0 \uba85\ub839\uc904\uc5d0\uc11c \ub2e4\uc74c\uc744 \uc2e4\ud589\ud569\ub2c8\ub2e4. <code>$ \ud3ec\ub4dc \ucd08\uae30\ud654<\/code> \ub97c \ud074\ub9ad\ud574 \ud504\ub85c\uc81d\ud2b8\ub97c Cocoapods\ub97c \uc0ac\uc6a9\ud558\ub3c4\ub85d \ub9c8\uc774\uadf8\ub808\uc774\uc158\ud558\uc138\uc694. \ud504\ub85c\uc81d\ud2b8\uc758 <strong>\ud3ec\ub4dc\ud30c\uc77c<\/strong> \ub97c \ud074\ub9ad\ud558\uace0 \ubb38\uc744 \ucd94\uac00\ud569\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-none\">pod 'Google\/SignIn'\r\npod 'couchbase-lite-ios'<\/code><\/pre>\n<p>\uc2e4\ud589 <code>$ \ud3ec\ub4dc \uc124\uce58<\/code> \uc744 \ud074\ub9ad\ud558\uace0 <strong>SimpleLogin.xc\uc791\uc5c5\uacf5\uac04<\/strong> \ud30c\uc77c\uc744 \uc0dd\uc131\ud569\ub2c8\ub2e4. \ub2e4\uc74c\uc73c\ub85c, Swift \ucf54\ub4dc\uc5d0\uc11c Objective-C\ub97c \uc0ac\uc6a9\ud558\ub294 Google SignIn \ubc0f CouchbaseLite SDK\uc5d0 \uc561\uc138\uc2a4\ud558\uae30 \uc704\ud55c \ube0c\ub9ac\uc9d5 \ud5e4\ub354\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. Xcode \ud504\ub85c\uc81d\ud2b8 \ud0d0\uc0c9\uae30\uc5d0\uc11c SimpleLogin\uc744 \ub9c8\uc6b0\uc2a4 \uc624\ub978\ucabd \ubc84\ud2bc\uc73c\ub85c \ud074\ub9ad\ud558\uace0 <strong>\uc0c8 \ud30c\uc77c...<\/strong>. \ud5e4\ub354 \ud30c\uc77c \ud15c\ud50c\ub9bf\uc744 \uc120\ud0dd\ud558\uace0 <strong>\ube0c\ub9bf\uc9d5 \ud5e4\ub354.h<\/strong>. \ub2e4\uc74c \uac00\uc838\uc624\uae30 \ubb38\uc744 \ucd94\uac00\ud569\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-objectivec\">#import &lt;Google\/SignIn.h&gt;\r\n#import &lt;CouchbaseLite\/CouchbaseLite.h&gt;<\/code><\/pre>\n<p>\uc774\uc81c Xcode\uc5d0 \uc774 \ud30c\uc77c\uc744 \uc0ac\uc6a9\ud558\ub3c4\ub85d \uc9c0\uc2dc\ud574\uc57c \ud569\ub2c8\ub2e4. \uc5d0\uc11c <strong>SimpleLogin<\/strong> \ub300\uc0c1\uc744 \uc120\ud0dd\ud558\uace0 <strong>\ube4c\ub4dc \uc124\uc815<\/strong> \ud0ed\uc744 \ud074\ub9ad\ud558\uace0 \uc544\ub798\ub85c \uc2a4\ud06c\ub864\ud558\uc5ec <strong>Objective-C \ube0c\ub9ac\uc9d5 \ud5e4\ub354<\/strong>. \uc774 \ud30c\uc77c \uacbd\ub85c\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4:<\/p>\n<p>SimpleLogin\/\ube0c\ub9ac\uc9d5\ud5e4\ub354.h<\/p>\n<h3>Google \ub85c\uadf8\uc778 \uad6c\uc131 \ud30c\uc77c<\/h3>\n<p>\uc571\uc5d0\uc11c \ub85c\uadf8\uc778 SDK\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \uba3c\uc800 Google \uac1c\ubc1c\uc790 \ucf58\uc194\uc5d0\uc11c \uc0c8 \ud504\ub85c\uc81d\ud2b8\ub97c \uc0dd\uc131\ud558\uace0 \ud074\ub77c\uc774\uc5b8\ud2b8 ID\ub97c \uc0dd\uc131\ud574\uc57c \ud569\ub2c8\ub2e4. \ub2e4\ud589\ud788\ub3c4 \ub2e4\uc74c \ub9c1\ud06c\ub97c \ud1b5\ud574 \uc774 \uc791\uc5c5\uc744 \uc790\ub3d9\uc73c\ub85c \uc218\ud589\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4:<\/p>\n<p>https:\/\/developers.google.com\/mobile\/add?platform=ios&#038;cntapi=signin&#038;cntapp=Simple%20Login&#038;cntpkg=com.couchbase.SimpleLogin<\/p>\n<p>\uc704 \ud398\uc774\uc9c0\uc5d0\uc11c <strong>\uc11c\ube44\uc2a4 \uc120\ud0dd \ubc0f \uad6c\uc131<\/strong> \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uba74 \uc0ac\uc6a9 \uc124\uc815\ud560 \uc218 \uc788\ub294 \uc0c8 \ud398\uc774\uc9c0\ub85c \uc774\ub3d9\ud569\ub2c8\ub2e4. <strong>Google \ub85c\uadf8\uc778<\/strong>. \uac70\uae30\uc5d0\uc11c <strong>\uad6c\uc131 \ud30c\uc77c \uc0dd\uc131<\/strong> \ub97c \ud074\ub9ad\ud558\uace0 \uc0c8 plist \ud30c\uc77c\uc744 \ub2e4\uc6b4\ub85c\ub4dc\ud569\ub2c8\ub2e4.<\/p>\n<p>\uac00\uc838\uc624\uae30 <strong>GoogleServer-Info.plist<\/strong> \ub97c Xcode \ud504\ub85c\uc81d\ud2b8\uc5d0 \ucd94\uac00\ud569\ub2c8\ub2e4:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2015\/october\/adding-google-sign-in-with-node.js-to-a-couchbase-mobile-application\/xcode-import-plist.png\" \/><\/p>\n<h3>\ud504\ub85c\uc81d\ud2b8\uc5d0 URL \uad6c\uc131\ud45c \ucd94\uac00\ud558\uae30<\/h3>\n<p>Google \ub85c\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\ub824\uba74 \ud504\ub85c\uc81d\ud2b8\uc5d0 \ub450 \uac1c\uc758 \uc0ac\uc6a9\uc790 \uc9c0\uc815 URL \uc2a4\ud0a4\ub9c8\ub97c \ucd94\uac00\ud574\uc57c \ud569\ub2c8\ub2e4. \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc2a4\ud0a4\ub9c8\ub97c \ucd94\uac00\ud558\ub824\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 \ud558\uc138\uc694:<\/p>\n<ol>\n<li>\ud504\ub85c\uc81d\ud2b8 \uad6c\uc131 \uc5f4\uae30: \uc67c\ucabd \ud2b8\ub9ac \ubcf4\uae30\uc5d0\uc11c \ud504\ub85c\uc81d\ud2b8 \uc774\ub984\uc744 \ub450 \ubc88 \ud074\ub9ad\ud569\ub2c8\ub2e4. \uc67c\ucabd \ud2b8\ub9ac \ubcf4\uae30\uc5d0\uc11c \uc571\uc744 \uc120\ud0dd\ud569\ub2c8\ub2e4. <strong>\ub300\uc0c1<\/strong> \uc139\uc158\uc744 \ud074\ub9ad\ud55c \ub2e4\uc74c <strong>\uc815\ubcf4<\/strong> \ud0ed\uc744 \ud074\ub9ad\ud558\uace0 <strong>URL \uc720\ud615<\/strong> \uc139\uc158\uc73c\ub85c \uc774\ub3d9\ud569\ub2c8\ub2e4.<\/li>\n<li>\ub97c \ud074\ub9ad\ud569\ub2c8\ub2e4. <strong>+<\/strong> \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uace0 \ubc18\uc804\ub41c \ud074\ub77c\uc774\uc5b8\ud2b8 ID\uc5d0 \ub300\ud55c URL \uccb4\uacc4\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. \uc774 \uac12\uc744 \ucc3e\uc73c\ub824\uba74 <code>GoogleService-Info.plist<\/code> \uad6c\uc131 \ud30c\uc77c\uc744 \uc5f4\uace0 <code>\uc5ed\ubc29\ud5a5_\ud074\ub77c\uc774\uc5b8\ud2b8_ID<\/code> \ud0a4\ub97c \ud074\ub9ad\ud569\ub2c8\ub2e4. \ud574\ub2f9 \ud0a4\uc758 \uac12\uc744 \ubcf5\uc0ac\ud558\uc5ec \ud574\ub2f9 \ud0a4\ub97c <strong>URL \uad6c\uc131\ud45c<\/strong> \uc0c1\uc790\ub97c \uc120\ud0dd\ud569\ub2c8\ub2e4. \ub2e4\ub978 \ud544\ub4dc\ub294 \ube44\uc6cc\ub461\ub2c8\ub2e4.<\/li>\n<li>\ub97c \ud074\ub9ad\ud569\ub2c8\ub2e4. <strong>+<\/strong> \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uace0 \ub450 \ubc88\uc9f8 URL \uccb4\uacc4\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. \uc774 URL\uc740 \uc571\uc758 \ubc88\ub4e4 ID\uc640 \ub3d9\uc77c\ud569\ub2c8\ub2e4. \uc774 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc544\uc57c \ud569\ub2c8\ub2e4. <strong>com.couchbase.SimpleLogin<\/strong>.<\/li>\n<\/ol>\n<p>\uc644\ub8cc\ub418\uba74 \uad6c\uc131\uc740 \ub2e4\uc74c\uacfc \ube44\uc2b7\ud558\uac8c \ubcf4\uc77c \uac83\uc785\ub2c8\ub2e4(\ub2e8, \uc560\ud50c\ub9ac\ucf00\uc774\uc158\ubcc4 \uac12\uc744 \uc0ac\uc6a9\ud574\uc57c \ud569\ub2c8\ub2e4):<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2015\/october\/adding-google-sign-in-with-node.js-to-a-couchbase-mobile-application\/xcode-url-types.png\" \/><\/p>\n<h3>iOS \uc571\uc5d0 Google \ub85c\uadf8\uc778 \ud1b5\ud569<\/h3>\n<p>\uc774\uc81c \ud504\ub85c\uc81d\ud2b8\uac00 \uc62c\ubc14\ub974\uac8c \uad6c\uc131\ub418\uc5c8\uc73c\ubbc0\ub85c SDK\ub97c \uc0ac\uc6a9\ud558\uc5ec UI\uc5d0 \ub85c\uadf8\uc778 \ubc84\ud2bc\uacfc \uc0ac\uc6a9\uc790 \uc815\ubcf4\ub97c \uac80\uc0c9\ud558\ub294 \uc571 \ub85c\uc9c1\uc744 \ucd94\uac00\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. In <strong>AppDelegate.swift<\/strong>\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc774 \ud074\ub798\uc2a4\uac00 <code>GIDSignInDelegate<\/code> \ub97c \ud074\ub9ad\ud558\uace0 <code>application:didFinishLaunchWithOptions:<\/code> \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud569\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-swift\">func application(application: UIApplication,\r\n  didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -&gt; Bool {\r\n    \/\/ Initialize sign-in\r\n    var configureError: NSError?\r\n    GGLContext.sharedInstance().configureWithError(&amp;configureError)\r\n    assert(configureError == nil, \"Error configuring Google services: (configureError)\")\r\n\r\n    GIDSignIn.sharedInstance().delegate = self\r\n\r\n    return true\r\n}<\/code><\/pre>\n<p>\uadf8\ub7f0 \ub2e4\uc74c <code>application:openURL:<\/code> \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud569\ub2c8\ub2e4. \uba54\uc11c\ub4dc\ub294 \uc571 \ub378\ub9ac\uac8c\uc774\ud2b8\uc758 <code>handleURL<\/code> \uba54\uc11c\ub4dc\uc758 <code>GIDSignIn<\/code> \uc778\uc2a4\ud134\uc2a4\ub97c \uc0dd\uc131\ud558\uc5ec \uc778\uc99d \ud504\ub85c\uc138\uc2a4\uac00 \ub05d\ub0a0 \ub54c \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc774 \uc218\uc2e0\ud558\ub294 URL\uc744 \uc62c\ubc14\ub974\uac8c \ucc98\ub9ac\ud569\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-swift\">func application(application: UIApplication,\r\n  openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -&gt; Bool {\r\n    return GIDSignIn.sharedInstance().handleURL(url,\r\n        sourceApplication: sourceApplication,\r\n        annotation: annotation)\r\n}<\/code><\/pre>\n<p>\uc571 \ub378\ub9ac\uac8c\uc774\ud2b8\uc5d0\uc11c <code>GIDSignInDelegate<\/code> \ud504\ub85c\ud1a0\ucf5c\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub2e4\uc74c \ubc29\ubc95\uc744 \uc815\uc758\ud558\uc5ec \ub85c\uadf8\uc778 \ud504\ub85c\uc138\uc2a4\ub97c \ucc98\ub9ac\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-swift\">func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!,\r\n  withError error: NSError!) {\r\n    if (error == nil) {\r\n      \/\/ Perform any operations on signed in user here.\r\n      let userId = user.userID                  \/\/ For client-side use only!\r\n      let idToken = user.authentication.idToken \/\/ Safe to send to the server\r\n      let name = user.profile.name\r\n      let email = user.profile.email\r\n      \/\/ ...\r\n    } else {\r\n      println(\"(error.localizedDescription)\")\r\n    }\r\n}<\/code><\/pre>\n<h3>\ub85c\uadf8\uc778 \ubc84\ud2bc \ucd94\uac00\ud558\uae30<\/h3>\n<p>\ub2e4\uc74c\uc73c\ub85c \uc0ac\uc6a9\uc790\uac00 \ub85c\uadf8\uc778 \ud504\ub85c\uc138\uc2a4\ub97c \uc2dc\uc791\ud560 \uc218 \uc788\ub3c4\ub85d Google \ub85c\uadf8\uc778 \ubc84\ud2bc\uc744 \ucd94\uac00\ud569\ub2c8\ub2e4. \uc571\uc758 \ub85c\uadf8\uc778 \ud654\uba74\uc744 \uad00\ub9ac\ud558\ub294 \ubdf0 \ucee8\ud2b8\ub864\ub7ec\uc5d0\uc11c \ud074\ub798\uc2a4\uc5d0\uc11c <code>GIDSignInUIDelegate<\/code> \ud504\ub85c\ud1a0\ucf5c\uc744 \uc0ac\uc6a9\ud569\ub2c8\ub2e4.<\/p>\n<p>\ubdf0 \ucee8\ud2b8\ub864\ub7ec\uc5d0\uc11c viewDidLoad \uba54\uc11c\ub4dc\ub97c \uc7ac\uc815\uc758\ud558\uc5ec GIDSignIn \uac1d\uccb4\uc758 UI \ub378\ub9ac\uac8c\uc774\ud2b8\ub97c \uc124\uc815\ud558\uace0 (\uc120\ud0dd \uc0ac\ud56d\uc73c\ub85c) \uac00\ub2a5\ud55c \uacbd\uc6b0 \uc790\ub3d9\uc73c\ub85c \ub85c\uadf8\uc778\ud558\ub3c4\ub85d \uc124\uc815\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-swift\">override func viewDidLoad() {\r\n  super.viewDidLoad()\r\n\r\n  GIDSignIn.sharedInstance().uiDelegate = self\r\n\r\n  \/\/ Uncomment to automatically sign in the user.\r\n  \/\/GIDSignIn.sharedInstance().signInSilently()\r\n\r\n  \/\/ TODO(developer) Configure the sign-in button look\/feel\r\n  \/\/ ...\r\n}<\/code><\/pre>\n<p>\uad6c\ud604 <code>GIDSignInUIDelegate<\/code> \ud504\ub85c\ud1a0\ucf5c\uc744 \uc0ac\uc6a9\ud569\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-swift\">\/\/ Implement these methods only if the GIDSignInUIDelegate is not a subclass of\r\n\/\/ UIViewController.\r\n\r\n\/\/ Stop the UIActivityIndicatorView animation that was started when the user\r\n\/\/ pressed the Sign In button\r\nfunc signInWillDispatch(signIn: GIDSignIn!, error: NSError!) {\r\n  myActivityIndicator.stopAnimating()\r\n}\r\n\r\n\/\/ Present a view that prompts the user to sign in with Google\r\nfunc signIn(signIn: GIDSignIn!,\r\n    presentViewController viewController: UIViewController!) {\r\n  self.presentViewController(viewController, animated: true, completion: nil)\r\n}\r\n\r\n\/\/ Dismiss the \"Sign in with Google\" view\r\nfunc signIn(signIn: GIDSignIn!,\r\n    dismissViewController viewController: UIViewController!) {\r\n  self.dismissViewControllerAnimated(true, completion: nil)\r\n}<\/code><\/pre>\n<p>\ucd94\uac00 <code>GIDSignInButton<\/code> \ub97c \uc2a4\ud1a0\ub9ac\ubcf4\ub4dc, XIB \ud30c\uc77c\uc5d0 \ucd94\uac00\ud558\uac70\ub098 \ud504\ub85c\uadf8\ub798\ubc0d \ubc29\uc2dd\uc73c\ub85c \uc778\uc2a4\ud134\uc2a4\ud654\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc2a4\ud1a0\ub9ac\ubcf4\ub4dc \ub610\ub294 XIB \ud30c\uc77c\uc5d0 \ubc84\ud2bc\uc744 \ucd94\uac00\ud558\ub824\uba74 \ubcf4\uae30\ub97c \ucd94\uac00\ud558\uace0 \ud574\ub2f9 \uc0ac\uc6a9\uc790 \uc9c0\uc815 \ud074\ub798\uc2a4\ub97c \ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uc815\ud569\ub2c8\ub2e4. <code>GIDSignInButton<\/code>.<\/p>\n<p>\uc571\uc744 \uc2e4\ud589\ud558\uba74 \uc774\uc81c Google \uc2a4\ud0c0\uc77c \ubc84\ud2bc\uc774 \ud45c\uc2dc\ub418\uace0 \ub85c\uadf8\uc778\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2015\/october\/adding-google-sign-in-with-node.js-to-a-couchbase-mobile-application\/run-signin-button.png\" \/><\/p>\n<h3>\ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774\ub85c \uc138\uc158 \ub9cc\ub4e4\uae30<\/h3>\n<p>In <strong>AppDelegate.swift<\/strong>\uc5d0\uc11c <code>signIndidSignInForUserwithError<\/code> \uba54\uc18c\ub4dc\ub97c \ud638\ucd9c\ud558\uace0 \uae30\uc874 \ucf54\ub4dc \uc544\ub798\uc5d0 \ub2e4\uc74c\uc744 \ucd94\uac00\ud569\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-swift\">\/\/ 1\r\nlet loginURL = NSURL(string: \"https:\/\/localhost:8000\/google_signin\")!\r\n\r\n\/\/ 2\r\nlet session = NSURLSession.sharedSession()\r\nlet request = NSMutableURLRequest(URL: loginURL)\r\nrequest.addValue(\"application\/json\", forHTTPHeaderField: \"Content-Type\")\r\nrequest.HTTPMethod = \"POST\"\r\n\r\n\/\/ 3\r\nvar properties = [\r\n    \"user_id\": userId,\r\n    \"auth_provider\": \"google\"\r\n]\r\nlet data = try! NSJSONSerialization.dataWithJSONObject(properties, options: NSJSONWritingOptions.PrettyPrinted)\r\n\r\n\/\/ 4\r\nlet uploadTask = session.uploadTaskWithRequest(request, fromData: data, completionHandler: { (data, response, error) -&gt; Void in\r\n    \/\/ 5\r\n    let json = try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as! Dictionary&lt;String, AnyObject&gt;\r\n    print(\"(json)\")\r\n    \r\n    \/\/ TODO: pull\/push replications with authenticated user\r\n    \r\n})\r\nuploadTask.resume()<\/code><\/pre>\n<p>\uc704\uc758 \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4:<\/p>\n<ol>\n<li>\ub85c\uceec\ub85c \uc2e4\ud589\ub418\ub294 \uc571 \uc11c\ubc84\uc758 \ub85c\uadf8\uc778 URL\uc785\ub2c8\ub2e4.<\/li>\n<li>\uc694\uccad \uc778\uc2a4\ud134\uc2a4\ub97c \ub9cc\ub4ed\ub2c8\ub2e4.<\/li>\n<li>\uc694\uccad\uc5d0 \uc804\uc1a1\ud560 Google \uc0ac\uc6a9\uc790 ID\uac00 \ud3ec\ud568\ub41c \uc18d\uc131\uc744 JSON\uc73c\ub85c \uc9c1\ub82c\ud654\ud569\ub2c8\ub2e4.<\/li>\n<li>POST \uc694\uccad\uc744 \ubcf4\ub0c5\ub2c8\ub2e4.<\/li>\n<li>\ub3d9\uae30\ud654 \uac8c\uc774\ud2b8\uc6e8\uc774 \uc138\uc158 \uc790\uaca9 \uc99d\uba85\uc774 \ud3ec\ud568\ub41c \uc751\ub2f5 \uac1c\uccb4<\/li>\n<\/ol>\n<p><strong>\ucc38\uace0:<\/strong> \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc2e4\ud589\ud558\uae30 \uc804\uc5d0 \uc571 \uc11c\ubc84\uac00 HTTPS\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uc73c\ubbc0\ub85c \uc571 \uc804\uc1a1 \ubcf4\uc548\uc744 \ube44\ud65c\uc131\ud654\ud574\uc57c \ud569\ub2c8\ub2e4. Open <strong>Info.plist<\/strong> \ub97c \ud074\ub9ad\ud558\uace0 \ub2e4\uc74c\uc744 \ucd94\uac00\ud569\ub2c8\ub2e4:<\/p>\n<pre><code class=\"language-xml\">NSAppTransportSecurity\r\n\r\nNSAllowsArbitraryLoads\r\n<\/code><\/pre>\n<p>\ube4c\ub4dc\ud558\uace0 \uc2e4\ud589\ud569\ub2c8\ub2e4. Xcode \ub514\ubc84\uac70\uc5d0\uc11c \uc571 \uc11c\ubc84\uc758 \uc751\ub2f5\uc744 \ud655\uc778\ud569\ub2c8\ub2e4:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2015\/october\/adding-google-sign-in-with-node.js-to-a-couchbase-mobile-application\/run-logs.png\" \/><\/p>\n<p>\ub9c8\uc9c0\ub9c9\uc73c\ub85c \uc138\uc158 \uc138\ubd80 \uc815\ubcf4\ub85c \ud480 \ubcf5\uc81c\ub97c \uc2dc\uc791\ud558\uae30 \uc704\ud574 Couchbase \ucf54\ub4dc\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. In <strong>AppDelegate.m<\/strong>\uba54\uc11c\ub4dc\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. <code>\uc2dc\uc791\ubcf5\uc81c<\/code>:<\/p>\n<pre><code class=\"language-swift\">func startReplications(sessionInfo: Dictionary&lt;String, String&gt;) {\r\n    \/\/ 1\r\n    let dateString = sessionInfo[\"expires\"]!\r\n    let dateFormatter = NSDateFormatter()\r\n    dateFormatter.dateFormat = \"yyyy-MM-dd'T'HH:mm:ss.SSSZ\"\r\n    let date = dateFormatter.dateFromString(dateString)!\r\n    \r\n    \/\/ 2\r\n    let manager = CBLManager.sharedInstance();\r\n    let database = try! manager.databaseNamed(\"simple-login\")\r\n    \r\n    \/\/ 3\r\n    let syncGatewayURL = NSURL(string: \"https:\/\/localhost:8000\/simple-login\")!\r\n    let pull = database.createPullReplication(syncGatewayURL)\r\n    pull?.continuous = true\r\n    \r\n    \/\/ 4\r\n    pull?.setCookieNamed(sessionInfo[\"cookie_name\"]!, withValue: sessionInfo[\"session_id\"]!, path: \"\/\", expirationDate: date, secure: false)\r\n    pull?.start()\r\n}<\/code><\/pre>\n<p>\uc774\uc804 \ub2e8\uacc4\uc5d0\uc11c \ucd94\uac00\ud55c uploadTask\uc758 \ucf5c\ubc31\uc5d0\uc11c \uc774 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud569\ub2c8\ub2e4.<\/p>\n<p>\uc774\uc81c \ub05d\ub0ac\uc2b5\ub2c8\ub2e4! \uc774\uc81c \uc774\ub984\uc744 \uac00\uc9c4 \uc0ac\uc6a9\uc790\uc5d0 \ub300\ud55c \ud480 \ubcf5\uc81c\uac00 \uc2e4\ud589 \uc911\uc785\ub2c8\ub2e4. <code>google-{userID}<\/code>. \ub2e4\uc74c \uba85\ub839\uc744 \uc0ac\uc6a9\ud558\uc5ec \ubb38\uc11c\ub97c \ucd94\uac00\ud558\uc5ec \uc561\uc138\uc2a4\uac00 \uc791\ub3d9\ud558\ub294\uc9c0 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4(Google \uc0ac\uc6a9\uc790 ID\ub97c \uc774\ubbf8 \ub85c\uadf8\uc778\ud55c \uc0ac\uc6a9\uc790\uc758 ID\ub85c \ubc14\uafb8\uae30):<\/p>\n<pre><code class=\"language-bash\">$ curl -vX POST \r\n        -H 'Content-Type: application\/json' \r\n        https:\/\/localhost:4985\/simple-login\/ \r\n        -d '{\"_id\": \"1234\", \"user_id\": \"google-102898171485172449137\"}'<\/code><\/pre>\n<p>\uad00\ub9ac\uc790 UI\uc758 \uc0ac\uc6a9\uc790 \ud0ed\uc73c\ub85c \uc774\ub3d9\ud569\ub2c8\ub2e4. <a href=\"https:\/\/localhost:4985\/_admin\/db\/simple-login\/users\">https:\/\/localhost:4985\/_admin\/db\/simple-login\/users<\/a> \ub97c \ud074\ub9ad\ud558\uace0 \uc0ac\uc6a9\uc790 <code>google-102898171485172449137<\/code> \uc774\uc81c \ucc44\ub110\uc5d0 \uc561\uc138\uc2a4\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. <code>1234<\/code>:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2015\/october\/adding-google-sign-in-with-node.js-to-a-couchbase-mobile-application\/final-test.png\" \/><\/p>\n<h2>\uc55e\uc73c\ub85c \ub098\uc544\uac08 \ubc29\ud5a5<\/h2>\n<p>\ucd95\ud558\ud569\ub2c8\ub2e4! \uce74\uc6b0\uce58\ubca0\uc774\uc2a4 \ubaa8\ubc14\uc77c\uc5d0\uc11c Google \ub85c\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub85c\uadf8\uc778\ud55c \uc0ac\uc6a9\uc790\uc758 \uc0ac\uc6a9\uc790 ID\uc5d0 \ub530\ub77c \ubb38\uc11c\ub97c \ub3d9\uae30\ud654\ud558\ub294 \ubc29\ubc95\uc744 \ubc30\uc6e0\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc544\ub798 \ub313\uae00\uc774\ub098 \ud3ec\ub7fc\uc5d0\uc11c \uc5ec\ub7ec\ubd84\uc758 \uc758\uacac\uacfc \uacb0\uacfc\ub97c \uacf5\uc720\ud558\uac70\ub098 \uad81\uae08\ud55c \uc810\uc774 \uc788\uc73c\uba74 \uc5b8\uc81c\ub4e0\uc9c0 \uc9c8\ubb38\ud574 \uc8fc\uc138\uc694. \uace7 \uc5f0\ub77d\ub4dc\ub9ac\uaca0\uc2b5\ub2c8\ub2e4!<\/p>","protected":false},"excerpt":{"rendered":"<p>Using OAuth APIs provided by 3rd party applications such as Google+ to login in your mobile app can provide a delightful first time experience to users. They can login with an account that they already know and trust and populate [&hellip;]<\/p>","protected":false},"author":51,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1810],"tags":[],"ppma_author":[9028],"class_list":["post-1987","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-mobile"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.8 (Yoast SEO v25.8) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Google SignIn with Node.js to a Couchbase Mobile Application<\/title>\n<meta name=\"description\" content=\"Learn how to use Google SignIn with Couchbase Mobile to create a delightful experience and synchronize documents per the user ID of the logged in user.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/ko\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/\" \/>\n<meta property=\"og:locale\" content=\"ko_KR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Adding Google Sign-In with Node.js to a Couchbase Mobile application\" \/>\n<meta property=\"og:description\" content=\"Learn how to use Google SignIn with Couchbase Mobile to create a delightful experience and synchronize documents per the user ID of the logged in user.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/ko\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2015-12-16T01:06:39+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-01-02T14:19:31+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"James Nocentini, Technical Writer, Mobile, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"James Nocentini, Technical Writer, Mobile, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11\ubd84\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/\"},\"author\":{\"name\":\"James Nocentini, Technical Writer, Mobile, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ec4dfbd349cb4a321fb6a92b71a9a7f6\"},\"headline\":\"Adding Google Sign-In with Node.js to a Couchbase Mobile application\",\"datePublished\":\"2015-12-16T01:06:39+00:00\",\"dateModified\":\"2019-01-02T14:19:31+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/\"},\"wordCount\":1424,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"articleSection\":[\"Couchbase Mobile\"],\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/\",\"name\":\"Google SignIn with Node.js to a Couchbase Mobile Application\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2015-12-16T01:06:39+00:00\",\"dateModified\":\"2019-01-02T14:19:31+00:00\",\"description\":\"Learn how to use Google SignIn with Couchbase Mobile to create a delightful experience and synchronize documents per the user ID of the logged in user.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#breadcrumb\"},\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Adding Google Sign-In with Node.js to a Couchbase Mobile application\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ko-KR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ec4dfbd349cb4a321fb6a92b71a9a7f6\",\"name\":\"James Nocentini, Technical Writer, Mobile, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/09977bdd14473dc23a125f2f74c3e816\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g\",\"caption\":\"James Nocentini, Technical Writer, Mobile, Couchbase\"},\"description\":\"James Nocentini is the Technical Writer in charge of the documentation for Couchbase Mobile. Previously, he worked as a Developer Advocate and before that as a front-end developer for HouseTrip. He also enjoys writing Android tutorials for raywenderlich.com in his spare time.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/ko\/author\/james-nocentini\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Google SignIn with Node.js to a Couchbase Mobile Application","description":"Learn how to use Google SignIn with Couchbase Mobile to create a delightful experience and synchronize documents per the user ID of the logged in user.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/ko\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/","og_locale":"ko_KR","og_type":"article","og_title":"Adding Google Sign-In with Node.js to a Couchbase Mobile application","og_description":"Learn how to use Google SignIn with Couchbase Mobile to create a delightful experience and synchronize documents per the user ID of the logged in user.","og_url":"https:\/\/www.couchbase.com\/blog\/ko\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/","og_site_name":"The Couchbase Blog","article_published_time":"2015-12-16T01:06:39+00:00","article_modified_time":"2019-01-02T14:19:31+00:00","og_image":[{"width":1800,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png","type":"image\/png"}],"author":"James Nocentini, Technical Writer, Mobile, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"James Nocentini, Technical Writer, Mobile, Couchbase","Est. reading time":"11\ubd84"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/"},"author":{"name":"James Nocentini, Technical Writer, Mobile, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ec4dfbd349cb4a321fb6a92b71a9a7f6"},"headline":"Adding Google Sign-In with Node.js to a Couchbase Mobile application","datePublished":"2015-12-16T01:06:39+00:00","dateModified":"2019-01-02T14:19:31+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/"},"wordCount":1424,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","articleSection":["Couchbase Mobile"],"inLanguage":"ko-KR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/","url":"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/","name":"Google SignIn with Node.js to a Couchbase Mobile Application","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2015-12-16T01:06:39+00:00","dateModified":"2019-01-02T14:19:31+00:00","description":"Learn how to use Google SignIn with Couchbase Mobile to create a delightful experience and synchronize documents per the user ID of the logged in user.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#breadcrumb"},"inLanguage":"ko-KR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/"]}]},{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/adding-google-sign-in-with-node-js-to-a-couchbase-mobile-application\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Adding Google Sign-In with Node.js to a Couchbase Mobile application"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"\uce74\uc6b0\uce58\ubca0\uc774\uc2a4 \ube14\ub85c\uadf8","description":"NoSQL \ub370\uc774\ud130\ubca0\uc774\uc2a4, Couchbase","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ko-KR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"\uce74\uc6b0\uce58\ubca0\uc774\uc2a4 \ube14\ub85c\uadf8","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ec4dfbd349cb4a321fb6a92b71a9a7f6","name":"\uc81c\uc784\uc2a4 \ub178\uc13c\ud2f0\ub2c8, \ubaa8\ubc14\uc77c \ud14c\ud06c\ub2c8\uceec \ub77c\uc774\ud130, Couchbase","image":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/09977bdd14473dc23a125f2f74c3e816","url":"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g","caption":"James Nocentini, Technical Writer, Mobile, Couchbase"},"description":"\uc81c\uc784\uc2a4 \ub178\uc13c\ud2f0\ub2c8\ub294 \uce74\uc6b0\uce58\ubca0\uc774\uc2a4 \ubaa8\ubc14\uc77c\uc758 \ubb38\uc11c\ub97c \ub2f4\ub2f9\ud558\ub294 \ud14c\ud06c\ub2c8\uceec \ub77c\uc774\ud130\uc785\ub2c8\ub2e4. \uc774\uc804\uc5d0\ub294 \uac1c\ubc1c\uc790 \uc9c0\uc6d0 \ub2f4\ub2f9\uc790\ub85c \uc77c\ud588\uc73c\uba70 \uadf8 \uc804\uc5d0\ub294 HouseTrip\uc758 \ud504\ub860\ud2b8\uc5d4\ub4dc \uac1c\ubc1c\uc790\ub85c \uc77c\ud588\uc2b5\ub2c8\ub2e4. \ub610\ud55c \uc5ec\uac00 \uc2dc\uac04\uc5d0\ub294 raywenderlich.com\uc5d0 \uc548\ub4dc\ub85c\uc774\ub4dc \ud29c\ud1a0\ub9ac\uc5bc\uc744 \uc791\uc131\ud558\ub294 \uac83\uc744 \uc990\uae41\ub2c8\ub2e4.","url":"https:\/\/www.couchbase.com\/blog\/ko\/author\/james-nocentini\/"}]}},"authors":[{"term_id":9028,"user_id":51,"is_guest":0,"slug":"james-nocentini","display_name":"James Nocentini, Technical Writer, Mobile, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g","author_category":"","last_name":"Nocentini","first_name":"James","job_title":"","user_url":"","description":"\uc81c\uc784\uc2a4 \ub178\uc13c\ud2f0\ub2c8\ub294 \uce74\uc6b0\uce58\ubca0\uc774\uc2a4 \ubaa8\ubc14\uc77c\uc758 \ubb38\uc11c\ub97c \ub2f4\ub2f9\ud558\ub294 \ud14c\ud06c\ub2c8\uceec \ub77c\uc774\ud130\uc785\ub2c8\ub2e4. \uc774\uc804\uc5d0\ub294 \uac1c\ubc1c\uc790 \uc9c0\uc6d0 \ub2f4\ub2f9\uc790\ub85c \uc77c\ud588\uc73c\uba70 \uadf8 \uc804\uc5d0\ub294 HouseTrip\uc758 \ud504\ub860\ud2b8\uc5d4\ub4dc \uac1c\ubc1c\uc790\ub85c \uc77c\ud588\uc2b5\ub2c8\ub2e4. \ub610\ud55c \uc5ec\uac00 \uc2dc\uac04\uc5d0\ub294 raywenderlich.com\uc5d0 \uc548\ub4dc\ub85c\uc774\ub4dc \ud29c\ud1a0\ub9ac\uc5bc\uc744 \uc791\uc131\ud558\ub294 \uac83\uc744 \uc990\uae41\ub2c8\ub2e4."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts\/1987","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/users\/51"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/comments?post=1987"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts\/1987\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/media?parent=1987"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/categories?post=1987"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/tags?post=1987"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/ppma_author?post=1987"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}