{"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>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 their profile with data that they entered on Google+. In this tutorial, you\u2019ll learn how to:<\/p>\n<ul>\n<li>Write a Node.js app to handle the authentication with Sync Gateway.<\/li>\n<li>Use the Couchbase Sync Gateway Admin REST API to create users and sessions.<\/li>\n<li>Integrate Google Sign-In to an iOS app written with Swift 2.<\/li>\n<li>Build a simple iOS app in Swift to test the new login endpoint and replicate a few documents.<\/li>\n<\/ul>\n<p>The final project can be found on <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>\u00a0Prerequisites<\/h2>\n<p>The prerequisites for this tutorial are:<\/p>\n<ul>\n<li>Node.js<\/li>\n<li>Xcode 7+ (you will use Swift 2 to build the sample app)<\/li>\n<\/ul>\n<h2>Getting Started<\/h2>\n<p>Download Sync Gateway from the link below and unzip the file:<\/p>\n<p>https:\/\/www.couchbase.com\/nosql-databases\/downloads<\/p>\n<p>In a new file named <strong>sync-gateway-config.json<\/strong>, paste in the following:<\/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>In this config file, you\u2019re creating a database called <strong>simple-login<\/strong> and using the Sync Function to map each document to a different channel and grant a user access to the channel (the user name being stored in the <code>user_id<\/code> field of the document).<\/p>\n<p>Start Sync Gateway with the following command:<\/p>\n<pre><code class=\"language-bash\">$ ~\/Downloads\/couchbase-sync-gateway\/bin\/sync_gateway sync-gateway-config.json<\/code><\/pre>\n<h2>Reverse Proxy for Sync Gateway<\/h2>\n<p>With Sync Gateway running, you get to shift your focus to building the App Server to handle authentication between Google and Sync Gateway.<\/p>\n<p>You\u2019ll use the popular <a href=\"https:\/\/expressjs.com\/\">Express<\/a> module to handle the request to create a user and the <a href=\"https:\/\/github.com\/request\/request\">request<\/a> module to proxy all other traffic to Sync Gateway.<\/p>\n<p>Install the following Node.js modules:<\/p>\n<pre><code class=\"language-bash\">$ npm install express body-parser request --save<\/code><\/pre>\n<p>Create a new file called <strong>server.js<\/strong> and add the following:<\/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>Here are the different things happening:<\/p>\n<ol>\n<li>Require the Node.js module you installed previously.<\/li>\n<li>Instantiate a new instance of express and use the <strong>bodyParser<\/strong> middleware only for the <strong>\/google_signin<\/strong> endpoint.<\/li>\n<li>Proxy all other requests to Sync Gateway.<\/li>\n<li>Start the Node.js web server on port 8000.<\/li>\n<\/ol>\n<p>Start the server with <code>$ node server.js<\/code> and open <code>https:\/\/localhost:8000<\/code> in your browser. You should see the Sync Gateway welcome message:<\/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>From Google SignIn to Sync Gateway Sessions<\/h3>\n<p>With the reverse proxy in place you can now add some code to handle the Google SignIn request and return the session credentials:<\/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>A few things are happening on this diagram:<\/p>\n<ul>\n<li><strong>Black<\/strong> sends the Google user ID to the App Server.<\/li>\n<li><strong>Blue<\/strong> checks if a user exists in Sync Gateway with that user ID.<\/li>\n<li><strong>Orange<\/strong> creates the user if it doesn\u2019t already exist (typically the first time the user logs in with Google in your app).<\/li>\n<li><strong>Green<\/strong> creates a session, the response will contain session credentials that can be passed to the client iOS app for push\/pull replications. All of the Couchbase Lite SDKs have a method to specify session credentials to be used in push\/pull replications.<\/li>\n<\/ul>\n<p>In the <strong>\/google_signin<\/strong> handler, add the following:<\/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>Restart the Node.js application and run the following curl request to sign up a new user:<\/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>In the next section, you will create a simple a iOS app with Swift 2 to use the new functionality of your App Server.<\/p>\n<h2>Swift Time: Simple Login Screen for iOS<\/h2>\n<p>Switch to Xcode and create a new project with the <strong>Single View Application<\/strong> template:<\/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>We\u2019ll use Cocoapods to install dependencies in this project. Close the Xcode project and from the command line run <code>$ pod init<\/code> to migrate your project to using Cocoapods. Open the <strong>Podfile<\/strong> and add the statements:<\/p>\n<pre><code class=\"language-none\">pod 'Google\/SignIn'\r\npod 'couchbase-lite-ios'<\/code><\/pre>\n<p>Run <code>$ pod install<\/code> and open the <strong>SimpleLogin.xcworkspace<\/strong> file that was generated. Next, you will add a bridging header to access the Google SignIn and CouchbaseLite SDKs that use Objective-C from your Swift code. In the Xcode project navigator, right-click on SimpleLogin and select <strong>New File\u2026<\/strong>. Choose the Header File template and call it <strong>bridging-header.h<\/strong>. Add the following import statements:<\/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>Now you need to tell Xcode to use this file. In the <strong>SimpleLogin<\/strong> target, select the <strong>Build Settings<\/strong> tab and scroll down to the <strong>Objective-C Bridging Header<\/strong>. Add this filepath:<\/p>\n<p>SimpleLogin\/bridging-header.h<\/p>\n<h3>Google Sign-In Configuration file<\/h3>\n<p>Before you can use the Sign-In SDK in your app, you\u2019ll need to create a new project in the Google Developer Console and generate a client ID. Luckily for us, this can be done automatically with the following link:<\/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>On the page above, click the <strong>Choose and configure services<\/strong> button and you\u2019ll be taken to a new page where you can enable <strong>Google Sign-In<\/strong>. From there, click <strong>Generate configuration files<\/strong> and download the new plist file.<\/p>\n<p>Import <strong>GoogleServer-Info.plist<\/strong> to your Xcode project:<\/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>Adding URL schemes to your project<\/h3>\n<p>Google Sign-In requires two custom URL Schemes to be added to your project. To add the custom schemes:<\/p>\n<ol>\n<li>Open your project configuration: double-click the project name in the left tree view. Select your app from the <strong>TARGETS<\/strong> section, then select the <strong>Info<\/strong> tab, and expand the <strong>URL Types<\/strong> section.<\/li>\n<li>Click the <strong>+<\/strong> button, and add a URL scheme for your reversed client ID. To find this value, open the <code>GoogleService-Info.plist<\/code> configuration file, and look for the <code>REVERSED_CLIENT_ID<\/code> key. Copy the value of that key, and paste it into the <strong>URL Schemes<\/strong> box on the configuration page. Leave the other fields blank.<\/li>\n<li>Click the <strong>+<\/strong> button, and add a second URL scheme. This one is the same as your app\u2019s bundle ID. In this case, it should be <strong>com.couchbase.SimpleLogin<\/strong>.<\/li>\n<\/ol>\n<p>When completed, your config should look something similar to the following (but with your application-specific values):<\/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>Integrating Google Sign-In into your iOS app<\/h3>\n<p>Now your project is configured correctly you can start using the SDK to add the Login button on the UI and app logic to retrieve the user info. In <strong>AppDelegate.swift<\/strong>, declare that this class implements the <code>GIDSignInDelegate<\/code> and add the following in the <code>application:didFinishLaunchingWithOptions:<\/code> method:<\/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>Next, implement the <code>application:openURL:<\/code> method of your app delegate. The method should call the <code>handleURL<\/code> method of the <code>GIDSignIn<\/code> instance, which will properly handle the URL that your application receives at the end of the authentication process:<\/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>In the app delegate, implement the <code>GIDSignInDelegate<\/code> protocol to handle the sign-in process by defining the following methods:<\/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>Adding the Sign-In Button<\/h3>\n<p>Next, you will add the Google Sign-In button so that the user can initiate the sign-in process. In the view controller that manages your app\u2019s sign-in screen, make the class implement the <code>GIDSignInUIDelegate<\/code> protocol.<\/p>\n<p>In the view controller, override the viewDidLoad method to set the UI delegate of the GIDSignIn object, and (optionally) to sign in silently when possible.<\/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>Implement the <code>GIDSignInUIDelegate<\/code> protocol:<\/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>Add a <code>GIDSignInButton<\/code> to your storyboard, XIB file, or instantiate it programmatically. To add the button to your storyboard or XIB file, add a View and set its custom class to <code>GIDSignInButton<\/code>.<\/p>\n<p>Run the app and you should now see the Google styled button and be able to login:<\/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>Creating a Session with Sync Gateway<\/h3>\n<p>In <strong>AppDelegate.swift<\/strong>, find the <code>signIndidSignInForUserwithError<\/code> method and add the following below the existing code:<\/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>Here\u2019s what is happening above:<\/p>\n<ol>\n<li>The login URL on the App Server running locally.<\/li>\n<li>Create a request instance.<\/li>\n<li>Serialize the properties containing the Google userID as JSON to be sent in the request.<\/li>\n<li>Send POST request.<\/li>\n<li>Response object containing Sync Gateway Session credentials<\/li>\n<\/ol>\n<p><strong>NOTE:<\/strong> Before running the application, be sure the disable App Transport security since the App Server isn\u2019t using HTTPS. Open <strong>Info.plist<\/strong> and add the following:<\/p>\n<pre><code class=\"language-xml\">NSAppTransportSecurity\r\n\r\nNSAllowsArbitraryLoads\r\n<\/code><\/pre>\n<p>Build and run. Notice the response from the App Server in the Xcode debugger:<\/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>Finally, you will add the Couchbase code to start a pull replication with the session details. In <strong>AppDelegate.m<\/strong>, add the method <code>startReplications<\/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>Call this method in the callback of the uploadTask you added in the previous step.<\/p>\n<p>Et voil\u00e0! You now have a pull replication running for the user with name <code>google-{userID}<\/code>. You can test the access is working by adding a document with the following command (replace the Google user ID with that of a user already logged in):<\/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>Head over to the Users tab in the Admin UI at <a href=\"https:\/\/localhost:4985\/_admin\/db\/simple-login\/users\">https:\/\/localhost:4985\/_admin\/db\/simple-login\/users<\/a> and notice that user <code>google-102898171485172449137<\/code> now has access to channel <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>Where to Go From Here<\/h2>\n<p>Congratulations! You learnt 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.<\/p>\n<p>Feel free to share your feedback, findings or ask any questions in the comments below or in the forums. Talk to you soon!<\/p>\n","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>\n","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"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\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:\\\/\\\/secure.gravatar.com\\\/avatar\\\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g09977bdd14473dc23a125f2f74c3e816\",\"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":"\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\uc5ec \uc990\uac70\uc6b4 \ud658\uacbd\uc744 \ub9cc\ub4dc\ub294 \ubc29\ubc95\uc744 \uc54c\uc544\ubcf4\uc138\uc694.","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":"\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\uc5ec \uc990\uac70\uc6b4 \ud658\uacbd\uc744 \ub9cc\ub4dc\ub294 \ubc29\ubc95\uc744 \uc54c\uc544\ubcf4\uc138\uc694.","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:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g09977bdd14473dc23a125f2f74c3e816","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\/"}]}},"acf":[],"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","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_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}]}}