저는 다음과 같이 작업하는 것에 대해 많은 이야기를 들었습니다. GraphQL 및 NoSQL을 Couchbase 내부적으로나 외부에서 사용했습니다. 뜨거운 주제인 것 같아서 웹 애플리케이션을 만들 때 어떻게 유용할 수 있는지 알아보는 데 시간을 할애하기로 했습니다.
클라이언트 대면 애플리케이션을 통해 데이터에 액세스하고 변경하는 유사한 문제를 해결하는 것을 목표로 하지만, RESTful API의 세계에서 온 저에게 GraphQL은 완전히 다른 개념입니다. 다행히도 Node.js와 데이터베이스는 함께 작동하므로 아래의 GraphQL-데이터베이스 예제에서는 다음을 수행합니다. Node.js 사용 와 함께 카우치베이스 우리의 NoSQL 데이터베이스 레이어입니다.
현재로서는 저는 GraphQL 전문가가 아닙니다. 저는 수년 동안 Express 및 Hapi와 같은 프레임워크를 사용하여 RESTful API를 개발해 왔습니다. 그렇지만 제가 이들에 대해 어떻게 배웠는지 설명해 보려고 합니다.
API는 훌륭하게 작동하지만 필요한 정보를 얻는 데 있어서는 더 나은 방법이 있을 수 있습니다. 예를 들어, 클라이언트를 위해 서로 관련이 없거나 느슨하게 연관된 여러 데이터가 필요한 경우 어떻게 해야 할까요? 많은 데이터를 반환하는 하나의 대규모 엔드포인트를 만들까요, 아니면 데이터를 포함할 수 있는 모든 API 엔드포인트에 요청을 하나요? 특정 엔드포인트에서 반환되는 데이터의 일부만 필요한 경우에는 어떻게 해야 할까요?
바로 여기서 GraphQL이 등장합니다. 쿼리 언어를 통해 모든 엔드포인트를 작성하지 않고도 특정 시점에 클라이언트에 반환할 데이터를 정확히 지정할 수 있습니다.
Express 프레임워크로 새 Node.js 애플리케이션 만들기
Node.js를 사용하여 다음을 사용하기 위한 인터페이스를 만들겠습니다. GraphQL 쿼리. 먼저 새 프로젝트를 생성하고 종속성을 가져와서 실제 로직을 준비하기 위해 프로젝트를 부트스트랩하는 것으로 시작하겠습니다.
Node.js가 설치된 상태에서 명령줄에서 실행합니다:
1 2 3 4 5 6 |
npm init -y npm 설치 카우치베이스 --저장 npm 설치 express --저장 npm 설치 express-그래프 쿼리 --저장 npm 설치 그래프 쿼리 --저장 npm 설치 uuid --저장 |
위의 명령은 새 프로젝트를 생성하여 초기화합니다. package.json 파일을 열고 필요한 종속 요소를 설치합니다. 종속성 중 Couchbase와 나중에 문서 키를 나타낼 UUID 문자열을 생성하기 위한 패키지를 설치합니다. 다른 패키지는 GraphQL과 관련된 것으로 Express Framework에 연결합니다.
라는 파일을 만듭니다. app.js 를 열고 다음 코드를 포함하세요:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
const Express = require("express"); const 카우치베이스 = require("couchbase"); const ExpressGraphQL = require("express-graphql"); const 빌드 스키마 = require("graphql").빌드 스키마; const UUID = require("uuid"); var 스키마 = 빌드 스키마(``); var 리졸버 = { }; var 앱 = Express(); 앱.사용("/그래프QL", ExpressGraphQL({ 스키마: 스키마, rootValue: 리졸버, graphiql: true })); 앱.듣기(3000, () => { 콘솔.로그("듣기 : 3000"); }); |
스키마 채우기 및 데이터베이스 구성에 대해서는 아직 걱정하지 않겠습니다. 위의 코드에서 각 종속성을 가져오고 Express를 초기화했음을 알 수 있습니다. 또한 단일 API 엔드포인트를 정의했는데, 이는 Couchbase와 GraphQL이 상호 작용할 수 있도록 하는 방법입니다. 기본적으로 모든 GraphQL 쿼리를 이 단일 엔드포인트에 발행하면 스키마와 리졸버에 따라 올바른 데이터로 응답할 것입니다.
GraphQL 스키마 및 해석기 정의하기
이제 애플리케이션 기반이 마련되었으므로 데이터를 잠재적인 쿼리 및 데이터 유형에 실제로 연결하기 위한 스키마와 리졸버를 파악해 보겠습니다.
이 예제에서는 간단한 블로그 애플리케이션을 만들어 보겠습니다. 따라서 다음과 같은 스키마 모델을 사용하는 것이 좋습니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var 스키마 = 빌드 스키마(` 유형 계정 { id: 문자열, 이름: 문자열, 성: 문자열, } 유형 블로그 { id: 문자열, 계정: 문자열!, title: 문자열, 콘텐츠: 문자열 } `); |
우리는 계정이 있을 것이고 특정 계정에 대한 블로그 글이 있을 것이라는 것을 알고 있습니다. 데이터 유형에 느낌표가 있는 것은 해당 데이터 유형이 필수 속성임을 의미합니다.
이제 데이터를 쿼리하거나 데이터를 생성할 수 있도록 모델을 Couchbase에 연결해야 합니다.
NoSQL 데이터베이스인 Couchbase Server에서 데이터 쿼리 및 변경하기
이미 다음이 있다고 가정하겠습니다. 카우치베이스 를 실행합니다. 이 특정 예제에 대한 Couchbase의 특별한 구성 요구 사항은 없습니다.
첫 번째 단계는 Node.js 애플리케이션에서 Couchbase Server에 연결하는 것입니다. 프로젝트의 app.js 파일에 다음 줄을 추가합니다:
1 2 3 |
var 클러스터 = new 카우치베이스.클러스터("couchbase://localhost"); 클러스터.인증("예제", "123456"); var 버킷 = 클러스터.오픈버킷("예제"); |
위의 줄은 Node.js와 데이터베이스(이 예에서는 Couchbase)가 로컬 컴퓨터에서 실행되고 있다고 가정합니다. 여기서는 다음과 같은 버킷을 사용하겠습니다. 예제
라는 RBAC 사용자 계정과 예제
.
GraphQL용 데이터 모델은 이미 마련되어 있지만 가능한 쿼리나 변형을 정의하지 않았습니다. 애플리케이션의 스키마를 다음과 같이 수정해 보겠습니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
var 스키마 = 빌드 스키마(` 유형 쿼리 { 계정(id: 문자열!): 계정, 계정: [계정], 블로그(id: 문자열!): 블로그, 블로그(계정: 문자열!): [블로그] } 유형 계정 { id: 문자열, 이름: 문자열, 성: 문자열, } 유형 블로그 { id: 문자열, 계정: 문자열!, title: 문자열, 콘텐츠: 문자열 } 유형 돌연변이 { createAccount(이름: 문자열!, 성: 문자열!): 계정 블로그 만들기(계정: 문자열!, title: 문자열!, 콘텐츠: 문자열!): 블로그 } `); |
쿼리와 돌연변이 모두에 대해 무거운 작업을 수행하는 특수 리졸버 함수가 호출됩니다. 결과적으로 계정
또는 블로그
가 반환됩니다.
돌연변이부터 시작하여, 저희는 createAccount
함수에 두 개의 매개 변수를 기대합니다. 다음과 같이 보일 수 있습니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var 리졸버 = { createAccount: (데이터) => { var id = UUID.v4(); 데이터.유형 = "계정"; 반환 new 약속((해결, 거부) => { 버킷.삽입(id, 데이터, (오류, 결과) => { 만약(오류) { 반환 거부(오류); } 해결({ "id": id }); }); }); } }; |
스키마에서 두 개의 매개변수를 전달했지만 리졸버 함수에는 하나의 매개변수만 있다는 것을 알 수 있습니다. 데이터에 대한 모든 매개변수는 데이터
변수를 반환합니다. 함수 자체는 프로미스를 반환할 것으로 예상합니다.
저희는 다음과 같이 반환하고 있습니다. id
그 외에는 아무것도 없습니다. 기억하세요. 계정
의 모든 부분이 반환되는 것은 아니지만 계정
가 있어야 합니다. 그러나 모든 것을 반환하는 것이 더 좋을 수도 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var 리졸버 = { 블로그 만들기: (데이터) => { var id = UUID.v4(); 데이터.유형 = "blog"; 반환 new 약속((해결, 거부) => { 버킷.삽입(id, 데이터, (오류, 결과) => { 만약(오류) { 반환 거부(오류); } 해결({ "id": id }); }); }); } }; |
그리고 블로그 만들기
함수는 입력 데이터가 다르다는 점과 유형
속성이 다른 것으로 설정되어 있습니다. 모든 함수는 동일한 리졸버
객체입니다.
돌연변이를 제거한 후에는 데이터를 쿼리할 수 있습니다. 데이터를 쿼리하려면 계정
함수를 예로 들 수 있습니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var 리졸버 = { 계정: (데이터) => { var id = 데이터.id; 반환 new 약속((해결, 거부) => { 버킷.get(id, (오류, 결과) => { 만약(오류) { 반환 거부(오류); } 해결(결과.값); }); }); } }; |
이 특정 쿼리 함수와 돌연변이 함수 사이에는 실제로 다른 점이 없습니다. 우리는 id
를 전달하고 이를 조회하는 데 사용하고 있습니다.
모든 계정을 검색하려면 N1QL 쿼리를 사용할 수 있습니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var 리졸버 = { 계정: () => { var 문 = "SELECT META(account).id, account.* FROM `" + 버킷._name + "` AS 계정 WHERE account.type = 'account'"; var 쿼리 = 카우치베이스.N1qlQuery.fromString(문); 반환 new 약속((해결, 거부) => { 버킷.쿼리(쿼리, (오류, 결과) => { 만약(오류) { 반환 거부(오류); } 해결(결과); }); }); } }; |
이제 데이터 쿼리 및 변경에 관한 트렌드를 알 수 있을까요? 작업을 마무리하기 위해 마지막으로 단일 블로그를 가져오는 함수와 모든 블로그를 가져오는 함수 두 가지를 살펴보겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
var 리졸버 = { 블로그: (데이터) => { var id = 데이터.id; 반환 new 약속((해결, 거부) => { 버킷.get(id, (오류, 결과) => { 만약(오류) { 반환 거부(오류); } 해결(결과.값); }); }); }, 블로그: (데이터) => { var 문 = "SELECT META(blog).id, blog.* FROM `" + 버킷._name + "` AS blog WHERE blog.type = 'blog' AND blog.account = $account"; var 쿼리 = 카우치베이스.N1qlQuery.fromString(문); 반환 new 약속((해결, 거부) => { 버킷.쿼리(쿼리, { "계정": 데이터.계정 }, (오류, 결과) => { 만약(오류) { 반환 거부(오류); } 해결(결과); }); }); } }; |
이 시점에서 애플리케이션이 완성되었습니다. 적어도 이 특정 예제에서는 충분히 완성되었습니다. 이제 몇 가지 GraphQL 쿼리로 테스트해 보겠습니다.
그래픽 인터페이스로 GraphQL 쿼리 실행하기
Node.js와 Express용 GraphQL 패키지를 사용하는 경우 쿼리 실행을 위한 멋진 그래픽 인터페이스가 제공됩니다. 웹 브라우저에서 http://localhost:3000/graphql 으로 이동하면 다음과 같은 화면이 표시됩니다:
이제 데이터를 삽입할 돌연변이 쿼리를 만들어 보겠습니다.
1 2 3 4 5 |
돌연변이 CreateAccount($이름: 문자열!, $성: 문자열!) { createAccount(이름: $이름, 성: $성) { id } } |
위의 변이는 두 개의 필수 매개 변수를 가져온 다음 우리의 createAccount
함수에 각 매개변수를 전달합니다. 매개 변수는 쿼리 변수 섹션으로 이동합니다. 매개 변수는 다음과 같이 표시됩니다:
1 2 3 4 |
{ "이름": "Erika", "성": "라보이" } |
돌연변이가 성공적으로 이루어지면 id
를 요청했습니다. 데이터베이스를 데이터로 채운 후에는 다음과 같이 좀 더 정교한 GraphQL 쿼리를 수행할 수 있습니다:
1 2 3 4 5 6 7 8 9 10 |
쿼리 계정 데이터 가져오기($id: 문자열!) { 계정(id: $id) { 이름 성 } 블로그(계정: $id) { title 콘텐츠 } } |
위의 쿼리에서는 유효한 계정을 전달하면 해당 계정이 작성한 블로그 정보뿐만 아니라 계정 정보도 반환합니다. GraphQL 쿼리를 통해 특정 속성 또는 모든 속성을 요청할 수 있으며 여러 번 요청하지 않아도 됩니다.
결론
에서 GraphQL을 활용하여 간단한 Node.js 데이터베이스를 만드는 방법을 살펴보았습니다. 카우치베이스. GraphQL이 필요한 데이터를 쿼리할 수 있는 수단을 제공한다고 해서 데이터베이스와 통신하는 양질의 쿼리를 작성할 필요가 없어지는 것은 아닙니다. GraphQL은 백엔드 데이터베이스 쿼리 언어가 아니라 클라이언트 대면 쿼리 언어일 뿐이라는 점을 기억하세요. 다시 말해, 어려운 작업은 Couchbase에 맡기세요.
카우치베이스용 Node.js SDK에 대한 자세한 도움이 필요하면 다음을 확인하세요. 카우치베이스 개발자 포털.