{"id":1230,"date":"2018-02-08T07:00:16","date_gmt":"2018-02-08T15:00:16","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/"},"modified":"2018-02-08T07:00:16","modified_gmt":"2018-02-08T15:00:16","slug":"use-openwhisk-for-faas-with-node-js-and-couchbase-nosql","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/ko\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","title":{"rendered":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">If you&#8217;ve been keeping up with my content, you&#8217;ll remember that I had written an article titled,\u00a0<a href=\"https:\/\/www.couchbase.com\/blog\/use-aws-lambda-api-gateway-node-js-couchbase-nosql\/\" target=\"_blank\" rel=\"noopener\">Use AWS Lambda and API Gateway with Node.js and Couchbase NoSQL<\/a>. In this article we had explored using Amazon&#8217;s Serverless services to create Lambda functions that interact with Couchbase, our NoSQL database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">However, Lambda isn&#8217;t the only serverless, otherwise known as functions as a service (FaaS), technology on the block. Take <a href=\"https:\/\/openwhisk.apache.org\/\" target=\"_blank\" rel=\"noopener\">Apache OpenWhisk<\/a> for example. With OpenWhisk you can create functions similarly to how you would with Lambda, but deploy them to a more diverse set of locations, the popular being IBM Bluemix.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;re going to see how to create serverless functions using OpenWhisk to communicate with our <a href=\"https:\/\/www.couchbase.com\" target=\"_blank\" rel=\"noopener\">Couchbase Server<\/a> database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><!--more--><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Going forward, there are a few things to note. You&#8217;ll need to be hosting Couchbase Server somewhere accessible by the outside world. This means that your local computer won&#8217;t work. You&#8217;re going to need Docker so we can compile our dependencies to work with OpenWhisk. Finally, you&#8217;re going to need a Bluemix account, for this example at least.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installing the Bluemix CLI Tools for OpenWhisk<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Like I previously mentioned, OpenWhisk is an Apache Foundation project. However, for convenience we&#8217;re going to be using it on IBM&#8217;s Bluemix.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create an account for the <a href=\"https:\/\/console.bluemix.net\/openwhisk\/\" target=\"_blank\" rel=\"noopener\">IBM Cloud<\/a> if you haven&#8217;t already.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Instead of using a framework tool like Serverless, we&#8217;re going to be using the Bluemix CLI. Download the <a href=\"https:\/\/console.bluemix.net\/openwhisk\/learn\/cli\" target=\"_blank\" rel=\"noopener\">IBM Cloud Functions CLI<\/a> so we can interact with OpenWhisk on IBM.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Before you can start working with your IBM Cloud account, you need to sign in via the CLI. From the command line, execute the following:<\/p>\n\n\n<p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]bx login -a api.ng.bluemix.net -o your_email@example.com -s dev[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When downloading the CLI, you&#8217;ll be given the exact command, but it should look similar to what I&#8217;ve presented above.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now we can start creating our project.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding the Project Structure and OpenWhisk Package Creation Process<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;ve never worked with FaaS before, things are done a little differently than building a stand-alone, hardly scalable application.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, each endpoint in our FaaS project will be a separate function. Combined, these functions create what is called a package. These functions scale as necessary to meet the changing demand of your application.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With that said, create the following:<\/p>\n\n\n<p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]create<br \/>\n&#8212; package.json<br \/>\n&#8212; create.js<br \/>\nretrieve<br \/>\n&#8212; package.json<br \/>\n&#8212; retrieve.js<br \/>\nupdate<br \/>\n&#8212; package.json<br \/>\n&#8212; update.js<br \/>\ndelete<br \/>\n&#8212; package.json<br \/>\n&#8212; delete.js[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The project should have a directory for each function that we wish to create. Each function will have its own\u00a0<strong>package.json<\/strong> file. Each\u00a0<strong>package.json<\/strong> file can be created by executing the following within each of the directories:<\/p>\n\n\n<p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]npm init -y[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Within each of the\u00a0<strong>package.json<\/strong> files, you&#8217;ll also need to define which file is your function code. For example, open\u00a0<strong>create\/package.json<\/strong> and add or change the following line:<\/p>\n\n\n<p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]&#8221;main&#8221;: &#8220;create.js&#8221;,[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">By setting the <code>main<\/code> file, we are stating which JavaScript file contains our function.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When we start deploying our functions, we&#8217;ll be doing it so they are part of the same package.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Designing a Function for Creating Data<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s start development with creating data in our database. Navigate to the\u00a0<strong>create<\/strong> directory and execute the following command from your command line:<\/p>\n\n\n<p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]npm install couchbase uuid joi &#8211;save[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The above command will install our function dependencies. We&#8217;ll be using the Couchbase SDK for Node.js, the UUID library for generating unique keys, and the Joi library for validating input.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We will be revisiting the dependency installation, but at least it will keep us going for now.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now open the project&#8217;s\u00a0<strong>create\/create.js<\/strong> file and include the following:<\/p>\n\n\n<p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]const Couchbase = require(&#8220;couchbase&#8221;);<br \/>\nconst UUID = require(&#8220;uuid&#8221;);<br \/>\nconst Joi = require(&#8220;joi&#8221;);<\/p>\n<p>var bucket = null;<\/p>\n<p>function main(params) {<br \/>\n    if(bucket == null) {<br \/>\n        var cluster = new Couchbase.Cluster(&#8220;couchbase:\/\/&#8221; + params.host);<br \/>\n        cluster.authenticate(params.username, params.password);<br \/>\n        bucket = cluster.openBucket(params.bucketName);<br \/>\n    }<br \/>\n    var schema = Joi.object().keys({<br \/>\n        firstname: Joi.string().required(),<br \/>\n        lastname: Joi.string().required(),<br \/>\n        type: Joi.string().forbidden().default(&#8220;person&#8221;)<br \/>\n    });<br \/>\n    var data = params;<br \/>\n    var response = {};<br \/>\n    return new Promise((resolve, reject) =&gt; {<br \/>\n        var validation = Joi.validate(data, schema, { stripUnknown: true });<br \/>\n        if(validation.error) {<br \/>\n            response = {<br \/>\n                statusCode: 500,<br \/>\n                body: JSON.stringify(validation.error.details)<br \/>\n            };<br \/>\n            reject(response);<br \/>\n        }<br \/>\n        var id = UUID.v4();<br \/>\n        bucket.insert(id, validation.value, (error, result) =&gt; {<br \/>\n            if(error) {<br \/>\n                response = {<br \/>\n                    body: JSON.stringify({<br \/>\n                        code: error.code,<br \/>\n                        message: error.message<br \/>\n                    })<br \/>\n                };<br \/>\n                reject(response);<br \/>\n            }<br \/>\n            data.id = id;<br \/>\n            response = {<br \/>\n                body: JSON.stringify(validation.value)<br \/>\n            };<br \/>\n            resolve(response);<br \/>\n        });<br \/>\n    });<br \/>\n}<\/p>\n<p>exports.main = main;[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The above code is a bit much, so we need to figure out what is going on. Let&#8217;s start with the variable that exists outside of our function:<\/p>\n\n\n<p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]var bucket = null;[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It isn&#8217;t the best idea to establish a new connection every time the function is called. Instead, we can keep a global instance of the open Couchbase Bucket and for as long as it exists, use it. Just note that it won&#8217;t always exist because OpenWhisk will destroy functions after a while of inactivity.<\/p>\n\n\n<p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]if(bucket == null) {<br \/>\n    var cluster = new Couchbase.Cluster(&#8220;couchbase:\/\/&#8221; + params.host);<br \/>\n    cluster.authenticate(params.username, params.password);<br \/>\n    bucket = cluster.openBucket(params.bucketName);<br \/>\n}[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Inside our function we check to see if the Bucket is already open. If the Bucket is not open, we establish a connection using parameters passed into the function. When the time comes, we&#8217;ll be defining default parameters which contain this connection information.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Since we&#8217;re creating data, we need to validate that the input is correct.<\/p>\n\n\n<p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]var schema = Joi.object().keys({<br \/>\n    firstname: Joi.string().required(),<br \/>\n    lastname: Joi.string().required(),<br \/>\n    type: Joi.string().forbidden().default(&#8220;person&#8221;)<br \/>\n});[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;re expecting a <code>firstname<\/code> and <code>lastname<\/code> value to be present. We&#8217;re also expecting a <code>type<\/code> to not be present. We can validate this with the following:<\/p>\n\n\n<p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]var validation = Joi.validate(data, schema, { stripUnknown: true });<br \/>\nif(validation.error) {<br \/>\n    response = {<br \/>\n        statusCode: 500,<br \/>\n        body: JSON.stringify(validation.error.details)<br \/>\n    };<br \/>\n    reject(response);<br \/>\n}[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>stripUnknown<\/code> option will remove data not defined in the scheme. We need to strip data because our input and connection information will exist in the same payload. We don&#8217;t want the connection information to be saved in our documents. If there is a validation error, it will be returned. If there was no validation error, we can proceed to inserting the data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]create<br \/>\n&#8212; package.json<br \/>\n&#8212; create.js<br \/>\nretrieve<br \/>\n&#8212; package.json<br \/>\n&#8212; retrieve.js<br \/>\nupdate<br \/>\n&#8212; package.json<br \/>\n&#8212; update.js<br \/>\ndelete<br \/>\n&#8212; package.json<br \/>\n&#8212; delete.js[\/crayon]<\/p>\n0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We can generate a new unique key and save the validated data as a document. The data itself will be returned as a response.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The other functions will follow this same strategy, more or less.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Designing a Function for Retrieving Data with N1QL<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now that we have data, let&#8217;s try to retrieve it from the database with a function invocation. Navigate to your\u00a0<strong>retrieve<\/strong> directory and execute the following from the command line:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]create<br \/>\n&#8212; package.json<br \/>\n&#8212; create.js<br \/>\nretrieve<br \/>\n&#8212; package.json<br \/>\n&#8212; retrieve.js<br \/>\nupdate<br \/>\n&#8212; package.json<br \/>\n&#8212; update.js<br \/>\ndelete<br \/>\n&#8212; package.json<br \/>\n&#8212; delete.js[\/crayon]<\/p>\n1<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Because we won&#8217;t be creating data, we don&#8217;t need to generate unique values or validate any user data. For this reason, we only need the Couchbase SDK for this function.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open the project&#8217;s\u00a0<strong>retrieve\/retrieve.js<\/strong> file and include the following:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]create<br \/>\n&#8212; package.json<br \/>\n&#8212; create.js<br \/>\nretrieve<br \/>\n&#8212; package.json<br \/>\n&#8212; retrieve.js<br \/>\nupdate<br \/>\n&#8212; package.json<br \/>\n&#8212; update.js<br \/>\ndelete<br \/>\n&#8212; package.json<br \/>\n&#8212; delete.js[\/crayon]<\/p>\n2<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s skip over what we&#8217;ve already seen in the previous function and jump to what&#8217;s new. Once we&#8217;re connected to an open Bucket, we can create a N1QL query.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]create<br \/>\n&#8212; package.json<br \/>\n&#8212; create.js<br \/>\nretrieve<br \/>\n&#8212; package.json<br \/>\n&#8212; retrieve.js<br \/>\nupdate<br \/>\n&#8212; package.json<br \/>\n&#8212; update.js<br \/>\ndelete<br \/>\n&#8212; package.json<br \/>\n&#8212; delete.js[\/crayon]<\/p>\n3<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This N1QL query is SQL-like and it will allow us to retrieve all documents that match certain criteria. If there are any errors, return them as a response, otherwise return the result set.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Because we&#8217;re not validating anything, this function for retrieving data was much simpler.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Designing a Function for Updating Data with Subdocument Mutations<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now let&#8217;s say that we want to update documents within the database. Instead of retrieving documents, making changes, then saving those changes, we&#8217;re going to submit changes directly to the database and let the database figure things out.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Navigate into the project&#8217;s\u00a0<strong>update<\/strong> directory and execute the following from the command line:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]create<br \/>\n&#8212; package.json<br \/>\n&#8212; create.js<br \/>\nretrieve<br \/>\n&#8212; package.json<br \/>\n&#8212; retrieve.js<br \/>\nupdate<br \/>\n&#8212; package.json<br \/>\n&#8212; update.js<br \/>\ndelete<br \/>\n&#8212; package.json<br \/>\n&#8212; delete.js[\/crayon]<\/p>\n4<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Because we&#8217;re accepting user data, we want to validate that data. We&#8217;re not creating data so we don&#8217;t need to generate any unique keys.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open the project&#8217;s\u00a0<strong>update\/update.js<\/strong> file and include the following:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]create<br \/>\n&#8212; package.json<br \/>\n&#8212; create.js<br \/>\nretrieve<br \/>\n&#8212; package.json<br \/>\n&#8212; retrieve.js<br \/>\nupdate<br \/>\n&#8212; package.json<br \/>\n&#8212; update.js<br \/>\ndelete<br \/>\n&#8212; package.json<br \/>\n&#8212; delete.js[\/crayon]<\/p>\n5<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Does the above code look familiar? It should, because we&#8217;re following the same strategy.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Our validation logic is slightly different in this example:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]create<br \/>\n&#8212; package.json<br \/>\n&#8212; create.js<br \/>\nretrieve<br \/>\n&#8212; package.json<br \/>\n&#8212; retrieve.js<br \/>\nupdate<br \/>\n&#8212; package.json<br \/>\n&#8212; update.js<br \/>\ndelete<br \/>\n&#8212; package.json<br \/>\n&#8212; delete.js[\/crayon]<\/p>\n6<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We want to edit a particular document so a key is required. We don&#8217;t know what the user wants to update so we set the properties as optional.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To do updates we&#8217;re going to be doing subdocument operations on our documents. To do this, we can use a mutation builder.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]create<br \/>\n&#8212; package.json<br \/>\n&#8212; create.js<br \/>\nretrieve<br \/>\n&#8212; package.json<br \/>\n&#8212; retrieve.js<br \/>\nupdate<br \/>\n&#8212; package.json<br \/>\n&#8212; update.js<br \/>\ndelete<br \/>\n&#8212; package.json<br \/>\n&#8212; delete.js[\/crayon]<\/p>\n7<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We provide a document to alter and whatever paths the properties exist at. The paths could be much more complex than the examples used here.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With the set of mutations defined, we can execute them against the database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]create<br \/>\n&#8212; package.json<br \/>\n&#8212; create.js<br \/>\nretrieve<br \/>\n&#8212; package.json<br \/>\n&#8212; retrieve.js<br \/>\nupdate<br \/>\n&#8212; package.json<br \/>\n&#8212; update.js<br \/>\ndelete<br \/>\n&#8212; package.json<br \/>\n&#8212; delete.js[\/crayon]<\/p>\n8<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Depending on the result, a response will be returned from the invocation of the function.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Designing a Function for Removing Data<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;re at our final function in a package of CRUD operations. The time has come to delete data from the database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Navigate to the\u00a0<strong>delete<\/strong> directory and execute the following command:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]create<br \/>\n&#8212; package.json<br \/>\n&#8212; create.js<br \/>\nretrieve<br \/>\n&#8212; package.json<br \/>\n&#8212; retrieve.js<br \/>\nupdate<br \/>\n&#8212; package.json<br \/>\n&#8212; update.js<br \/>\ndelete<br \/>\n&#8212; package.json<br \/>\n&#8212; delete.js[\/crayon]<\/p>\n9<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ll be accepting document keys to be deleted so we&#8217;ll need to validate the input. Likewise we also need the Couchbase SDK to work with the database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open the project&#8217;s\u00a0<strong>delete\/delete.js<\/strong> file and include the following JavaScript code:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]npm init -y[\/crayon]<\/p>\n0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You&#8217;re probably seeing the bigger picture now in regards to function creation with OpenWhisk and Couchbase, so we&#8217;re not going to walk through the above function for deleting documents.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Packaging and Deploying the Functions to OpenWhisk with Docker<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We have a set of functions ready to go, but we can&#8217;t just package and deploy them to Bluemix. If we did that, we&#8217;d get a bunch of errors. Bluemix uses a special flavor of Linux with a certain architecture. I downloaded the dependencies on my Mac which isn&#8217;t a match.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Remember that article I wrote a while back titled,\u00a0<a href=\"https:\/\/www.thepolyglotdeveloper.com\/2017\/12\/deploying-native-nodejs-dependencies-aws-lambda\/\" target=\"_blank\" rel=\"noopener\">Deploying Native Node.js Dependencies On AWS Lambda<\/a>? We need to do something similar for OpenWhisk with Docker.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With Docker installed and ready to go, execute the following from the CLI:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]npm init -y[\/crayon]<\/p>\n1<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The above commands will download an appropriate OpenWhisk Docker image for Node.js. Then we deploy a container with that image in interactive terminal mode. This container will also have a mapped volume. I am mapping my local project directory to a directory within the container.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After the command has executed and the container is deployed, you should be in the shell within the container.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For each function, execute the following:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]npm init -y[\/crayon]<\/p>\n2<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Remember, installing dependencies from our host machine isn&#8217;t good enough. We need to compile the dependencies for Bluemix. Docker will compile these dependencies and since the directory is mapped, we can use them from the host machine.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After each functions packages are installed, we can bundle them and deploy them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">From the host machine, create a ZIP archive of each of the functions. The archive should contain the\u00a0<strong>package.json<\/strong> file, the JavaScript file, and the\u00a0<strong>node_modules<\/strong> directory.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re on a Mac or computer with a ZIP CLI, execute the following:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]npm init -y[\/crayon]<\/p>\n3<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When you have a ZIP of each function, they can be deployed by executing the following:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]npm init -y[\/crayon]<\/p>\n4<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I introduced some new things in the above command.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, we&#8217;re creating a package called\u00a0<strong>couchbase<\/strong> and in this package we have a\u00a0<strong>delete<\/strong> function that is based off the\u00a0<strong>delete.zip<\/strong> file. I&#8217;m also passing some default parameters. These parameters will be our connection information. Since this information is sensitive, we are not passing them when invoking the function, rather creating the function.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Execute a variation of the above command for each of your functions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To execute your function, try running something like the following:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><p>[crayon lang=&#8221;default&#8221; decode=&#8221;true&#8221;]npm init -y[\/crayon]<\/p>\n5<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The above command should pass in a few parameters to pass validation. The function is invoked in a blocking manner, and if it succeeds, our data will be saved in the database and returned in the response.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You just saw how to create a package of serverless functions for OpenWhisk that communicate with the NoSQL database, <a href=\"https:\/\/www.couchbase.com\" target=\"_blank\" rel=\"noopener\">Couchbase<\/a>. OpenWhisk can be used as an alternative to AWS Lambda, but the two are certainly not the only options available. Regardless on what you choose, functions as a service (FaaS) are very scalable solutions for massive applications.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Want to see another OpenWhisk example? Check out a tutorial I wrote titled,\u00a0<a href=\"https:\/\/www.thepolyglotdeveloper.com\/2017\/12\/convert-nodejs-restful-api-serverless-openwhisk\/\">Convert a Node.js RESTful API to Serverless with OpenWhisk<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you&#8217;ve been keeping up with my content, you&#8217;ll remember that I had written an article titled,\u00a0Use AWS Lambda and API Gateway with Node.js and Couchbase NoSQL. In this article we had explored using Amazon&#8217;s Serverless services to create Lambda functions that interact with Couchbase, our NoSQL database. However, Lambda isn&#8217;t the only serverless, otherwise [&hellip;]<\/p>\n","protected":false},"author":63,"featured_media":18,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"_acf":"","footnotes":""},"categories":[127,54,49],"tags":[294,295,296,6,297],"ppma_author":[148],"class_list":["post-1230","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-application-design","category-couchbase-server","category-node-js","tag-actions","tag-faas","tag-functions","tag-nosql-database","tag-serverless"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.3 (Yoast SEO v28.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL<\/title>\n<meta name=\"description\" content=\"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.\" \/>\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\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\" \/>\n<meta property=\"og:locale\" content=\"ko_KR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL\" \/>\n<meta property=\"og:description\" content=\"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/ko\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/thepolyglotdeveloper\" \/>\n<meta property=\"article:published_time\" content=\"2018-02-08T15:00:16+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/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=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@nraboy\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12\ubd84\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/\"},\"author\":{\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/bb545ebe83bb2d12f91095811d0a72e1\"},\"headline\":\"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL\",\"datePublished\":\"2018-02-08T15:00:16+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/\"},\"wordCount\":2561,\"commentCount\":3,\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"keywords\":[\"actions\",\"faas\",\"functions\",\"NoSQL Database\",\"serverless\"],\"articleSection\":[\"Application Design\",\"Couchbase Server\",\"Node.js\"],\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/\",\"name\":\"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2018-02-08T15:00:16+00:00\",\"description\":\"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/#breadcrumb\"},\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL\"}]},{\"@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\\\/sites\\\/5\\\/2026\\\/06\\\/logo.svg\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/06\\\/logo.svg\",\"width\":\"1024\",\"height\":\"1024\",\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/bb545ebe83bb2d12f91095811d0a72e1\",\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g8863514d8bed0cf6080f23db40e00354\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"caption\":\"Nic Raboy, Developer Advocate, Couchbase\"},\"description\":\"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.\",\"sameAs\":[\"https:\\\/\\\/www.thepolyglotdeveloper.com\",\"https:\\\/\\\/www.facebook.com\\\/thepolyglotdeveloper\",\"https:\\\/\\\/x.com\\\/nraboy\"],\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/ko\\\/author\\\/nic-raboy-2\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL","description":"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.","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\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","og_locale":"ko_KR","og_type":"article","og_title":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL","og_description":"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.","og_url":"https:\/\/www.couchbase.com\/blog\/ko\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","og_site_name":"The Couchbase Blog","article_author":"https:\/\/www.facebook.com\/thepolyglotdeveloper","article_published_time":"2018-02-08T15:00:16+00:00","og_image":[{"width":1800,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","type":"image\/png"}],"author":"Nic Raboy, Developer Advocate, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@nraboy","twitter_misc":{"Written by":"Nic Raboy, Developer Advocate, Couchbase","Est. reading time":"12\ubd84"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/"},"author":{"name":"Nic Raboy, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1"},"headline":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL","datePublished":"2018-02-08T15:00:16+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/"},"wordCount":2561,"commentCount":3,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","keywords":["actions","faas","functions","NoSQL Database","serverless"],"articleSection":["Application Design","Couchbase Server","Node.js"],"inLanguage":"ko-KR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","url":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","name":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","datePublished":"2018-02-08T15:00:16+00:00","description":"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#breadcrumb"},"inLanguage":"ko-KR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/"]}]},{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL"}]},{"@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":"\uce74\uc6b0\uce58\ubca0\uc774\uc2a4, NoSQL \ub370\uc774\ud130\ubca0\uc774\uc2a4","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\/sites\/5\/2026\/06\/logo.svg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/06\/logo.svg","width":"1024","height":"1024","caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1","name":"\ub2c9 \ub77c\ubcf4\uc774, \uac1c\ubc1c\uc790 \uc560\ub4dc\ubcf4\ucf00\uc774\ud2b8, \uce74\uc6b0\uce58\ubca0\uc774\uc2a4","image":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g8863514d8bed0cf6080f23db40e00354","url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","caption":"Nic Raboy, Developer Advocate, Couchbase"},"description":"\ub2c9 \ub77c\ubcf4\uc774(Nic Raboy)\ub294 \ubaa8\ub358 \uc6f9 \ubc0f \ubaa8\ubc14\uc77c \uac1c\ubc1c \uae30\uc220\uc758 \uc639\ud638\uc790\uc785\ub2c8\ub2e4. \uadf8\ub294 \uc790\ubc14, \uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8, \uace8\ub791(Golang)\uc744 \ube44\ub86f\ud574 \uc575\uade4\ub7ec, \ub124\uc774\ud2f0\ube0c\uc2a4\ud06c\ub9bd\ud2b8, \uc544\ud30c\uce58 \ucf54\ub974\ub3c4\ubc14 \uac19\uc740 \ub2e4\uc591\ud55c \ud504\ub808\uc784\uc6cc\ud06c \uacbd\ud5d8\uc744 \uac00\uc9c0\uace0 \uc788\uc2b5\ub2c8\ub2e4. \ub2c9\uc740 \uc6f9 \ubc0f \ubaa8\ubc14\uc77c \uac1c\ubc1c\uc744 \ub354 \uc27d\uac8c \uc774\ud574\ud560 \uc218 \uc788\ub3c4\ub85d \ub3d5\ub294 \uc790\uc2e0\uc758 \uac1c\ubc1c \uacbd\ud5d8\uc5d0 \ub300\ud574 \uae00\uc744 \uc501\ub2c8\ub2e4.","sameAs":["https:\/\/www.thepolyglotdeveloper.com","https:\/\/www.facebook.com\/thepolyglotdeveloper","https:\/\/x.com\/nraboy"],"url":"https:\/\/www.couchbase.com\/blog\/ko\/author\/nic-raboy-2\/"}]}},"acf":[],"authors":[{"term_id":148,"user_id":63,"is_guest":0,"slug":"nic-raboy-2","display_name":"Nic Raboy, Developer Advocate, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/?s=96&d=mm&r=g","author_category":"","first_name":"Nic","last_name":"Raboy","user_url":"","job_title":"","description":"\ub2c9 \ub77c\ubcf4\uc774(Nic Raboy)\ub294 \ubaa8\ub358 \uc6f9 \ubc0f \ubaa8\ubc14\uc77c \uac1c\ubc1c \uae30\uc220\uc758 \uc639\ud638\uc790\uc785\ub2c8\ub2e4. \uadf8\ub294 \uc790\ubc14, \uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8, \uace8\ub791(Golang)\uc744 \ube44\ub86f\ud574 \uc575\uade4\ub7ec, \ub124\uc774\ud2f0\ube0c\uc2a4\ud06c\ub9bd\ud2b8, \uc544\ud30c\uce58 \ucf54\ub974\ub3c4\ubc14 \uac19\uc740 \ub2e4\uc591\ud55c \ud504\ub808\uc784\uc6cc\ud06c \uacbd\ud5d8\uc744 \uac00\uc9c0\uace0 \uc788\uc2b5\ub2c8\ub2e4. \ub2c9\uc740 \uc6f9 \ubc0f \ubaa8\ubc14\uc77c \uac1c\ubc1c\uc744 \ub354 \uc27d\uac8c \uc774\ud574\ud560 \uc218 \uc788\ub3c4\ub85d \ub3d5\ub294 \uc790\uc2e0\uc758 \uac1c\ubc1c \uacbd\ud5d8\uc5d0 \ub300\ud574 \uae00\uc744 \uc501\ub2c8\ub2e4."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts\/1230","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\/63"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/comments?post=1230"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts\/1230\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/media\/18"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/media?parent=1230"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/categories?post=1230"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/tags?post=1230"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/ppma_author?post=1230"}],"curies":[{"name":"\uc798\ud588\uc5b4","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}