메인 컨텐츠로 가기

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

REST 서비스로 Dojo의 JsonRestStore 사용하기

간단한 일반 서비스 구현 방식 학습

Nick Maynard, 산업/비즈니스 솔루션 팀원내 선임 소프트웨어 기술자, IBM
Nick Maynard
Nick Maynard는 영국 허슬리의 IBM Software Solutions Transformation 팀에서 재직 중이다. 그의 전문 분야로는 웹 프로그래밍, Linux, 웹 서비스 및 비즈니스 통합 기술이 있다. 이메일 주소는 nick.maynard@uk.ibm.com이다.

요약:  Dojo의 JsonRestStore는 REST 서비스를 Dojo의 데이터 API로 연결하기 위한 더 고급 옵션 중 하나입니다. 서비스가 데이터 구조에 대한 JsonRestStore의 예상에 일치하지 않으면, JsonRestStore와 REST 서비스 사이에 연결이 어려워질 수 있습니다. 이 기사에서는 비표준 REST 서비스를 JsonRestStore로 연결하기 위한 간단한 일반 서비스 구현 방식에 대해 학습합니다. 몇 가지 예제를 탐색하여 자체적인 서비스를 위한 구현 방식을 사용하고 확장하는 방법을 학습합니다.

기사 게재일:  2011 년 12 월 14 일
난이도: 중급 원문:  보기 PDF:  A4 and Letter (39KB | 10 pages)Get Adobe® Reader®
페이지뷰:  1024 회
의견:  


소개

Dojo의 데이터 추상 계층인 dojo.data는 다양한 백엔드 서비스에 액세스하기 위해 Dojo 애플리케이션에 표준 API를 제공한다. Dojo 확장 라이브러리 DojoX에 위치한 JsonRestStore를 통해 애플리케이션을 백엔드 REST(Representational State Transfer) 서비스에 빠르게 연결할 수 있다.

JsonRestStore는 Dojo를 REST 서비스로 링크하기 위한 훌륭한 솔루션이다. 하지만, 기본적으로 JsonRestStore는 서비스로 전달되고 리턴되는 정보의 형식에 대한 예상이 있다. 이러한 상호작용을 사용자 정의하기 위한 SMD(Service Mapping Description) 설비는 아무리 낙관적으로 봐도 이해하기에 어렵다.

JsonRestStore는 GET, PUT, POST 및 DELETE 명령을 사용하는 서버와 HTTP/REST 상호작용에 따라 표준을 통해 전체 읽기, 쓰기 및 알림 기능을 제공하는 데이터 저장소이다. 이를 통해 JavaScript로 Dojo Data API를 사용하여 서버측 데이터베이스/지속적 데이터 스토리지와 통신할 수 있고 작성, 읽기, 업데이트 및 삭제(CRUD) 연산을 효율적으로 처리한다.

Dojo 애플리케이션 작성자가 전에 존재하는 백엔드 REST 저장소와 통신해야 할 때, 저장소의 통신이 변경될 수 없으면 사용자 정의 dojox.rpc.Service 구현 방식을 사용한다.

이 기사에서는 비표준 REST 서비스를 JsonRestStore로 연결하기 위한 간단한 일반 서비스 구현 방식을 학습한다. 실제적인 예제를 연습하여 자체 서비스에 이를 사용하고 확장하는 방법을 탐색한다.

이 기사의 소스 코드를 다운로드하려면 다운로드 섹션을 참조한다.


예제 서비스 구현 방식

EasyRestService는 네 가지 REST 연산인 POST(작성), GET(읽기), PUT(업데이트) 및 DELETE(삭제)에 구현 방식을 제공한다. 각 활동에 대해 이는 서비스 메소드의 이전과 이후 호출에서 후크하는 기능을 제공한다. 호출 라이프사이클은 다음과 같다.

  1. URL, 인수 및 데이터 형식 메타데이터가 들어 있는 표준 Dojo XHR 호출 구조를 구성한다.
  2. 메소드에 대해 인수 변환자를 호출한다. 이 메소드는 호출 구조(경로 포함)를 변경할 수 있고 REST 서비스의 예상에 일치하기 위해 호출 구조를 변환하는 데 사용될 수도 있다.
  3. 컨텐츠 노드를 JSON 표현으로 변환하여 호출 구조의 putData/postData/deleteData/getData 노드를 입력한다.
  4. XHR 메소드를 변경된 XHR 호출 구조로 호출한다.
  5. 결과 변환자를 XHR 콜백에 추가한다. 이 메소드는 결과의 데이터 구조를 변경할 수 있다. 이를 사용하여 결과를 JsonRestStore가 예상하는 구조로 변환한다.

목록 1은 예제 코드를 보여준다.


목록 1. EasyRestService 소스 코드 소스
        
dojo.provide("com.ibm.developerworks.EasyRestService");

(function() {
  var pa = com.ibm.developerworks.EasyRestService = function (path, serviceImpl, schema) {
    // Enforce the dojox.rpc.Rest trailing slash functionality
    path = path.match(/\/$/) ? path : (path + '/');
    
    // A dojox.rpc.Service implementation is a function with 3 function members
    var service;
    // GET function
    service = function(id, args) {
      return _execXhr("get", id, args);
    };
    // POST function member
    service['post'] = function(id, value) {
      return _execXhr("post", id, value);
    };
    // PUT function member
    service['put'] = function(id, value) {
      return _execXhr("put", id, value);
    };
    // DELETE function member
    service['delete'] = function(id) {
      return _execXhr("delete", id);
    };
    
    // Generic XHR function for all methods
    var _execXhr = function(method, id, content) {
      // Transform the method string
      var methodCapitalised = method.substring(0,1).toUpperCase() 
        + method.substring(1).toLowerCase();
      var methodUpperCase = method.toUpperCase();
      var methodLowerCase = method.toLowerCase();
      
      // Get the transformer functions
      var argumentsTransformer = service["transform" + methodCapitalised + "Arguments"];
      var resultTransformer = service["transform" + methodCapitalised + "Results"];
      
      // Construct the standard query
      var serviceArgs = {
        url : path + (dojo.isObject(id) ? '?' + dojo.objectToQuery(id) : 
          (id == null ? "" : id)), 
        handleAs : "json",
        contentType : "application/json",
        sync : false,
        headers : { Accept : "application/json,application/javascript" }
      };
      
      // Transform the arguments
      // NOTE: argumentsTransformer has a reference to "service"
      serviceArgs = argumentsTransformer(serviceArgs, arguments);

      // Copy the content into the appropriate *Data arg
      // getData, putData, postData, deleteData
      // NOTE: If you want your arguments transformer to edit the *Data arg directly, 
      // move the arguments transformer invocation to after this call 
      serviceArgs[methodLowerCase + 'Data'] = content;
            
      // Kick off the call
      var xhrFunction = dojo['xhr' + methodCapitalised];
      var deferred = xhrFunction(serviceArgs);
      // Add our result transformer
      // NOTE: resultTransformer has a reference to "service" too
      deferred.addCallback(dojo.partial(resultTransformer, deferred));
      
      return deferred;
    };

    // Mix in the service hooks
    // Uses a "default" implementation that does nothing
    // Service hooks will have a reference to the "service" object in their context
    dojo.mixin(service, 
      new com.ibm.developerworks.EasyRestService.DefaultHooks(), 
      serviceImpl);
    
    // Now remove any default _constructor() methods
    // This is necessary as the JsonRestStore stack uses _constructor() differently
    delete service['_constructor'];
    // Remove the declaredClass member if it has been added
    delete service['declaredClass'];
    
    // Save the path away
    service.servicePath = path;
    // Save the schema
    service._schema = schema;
    
    return service;
  };
})();

dojo.declare("com.ibm.developerworks.EasyRestService.DefaultHooks", null, {
  transformGetArguments: function(serviceArgs) {
    // Alter serviceArgs to provide the information the backend
    // service requires
    return serviceArgs;
  },
  transformPutArguments: function(serviceArgs) {
    // Alter serviceArgs to provide the information the backend
    // service requires
    return serviceArgs;
  },
  transformPostArguments: function(serviceArgs) {
    // Alter serviceArgs to provide the information the backend
    // service requires
    return serviceArgs;
  },
  transformDeleteArguments: function(serviceArgs) {
    // Alter serviceArgs to provide the information the backend
    // service requires
    return serviceArgs;
  },
  transformGetResults: function(deferred, results) {
    /*
     * JsonRestStore expects the following format:
     * [
     *  { id: "1", ... },
     *  { id: "2", ... },
     *  ...
     * ] 
     */
    return results;
  },
  transformPutResults: function(deferred, results) {
    /*
     * JsonRestStore does not expect any specific content here
     */
    return results;
  },
  transformPostResults: function(deferred, results) {
    /*
     * JsonRestStore expects:
     * 1) A "Location" response header with location of the new item.
     * 		From the Dojo API:
     * 			The server’s response includes a Location header
     * 			that indicates the id of the newly created object.
     * 			This id will be used for subsequent PUT and DELETE 
     * 			requests. JsonRestStore also includes a 
     * 			Content-Location header that indicates the temporary
     * 			randomly generated id used by client, and this 
     * 			location is used for subsequent PUT/DELETEs if no 
     * 			Location header is provided by the server or if 
     * 			a modification is sent prior to receiving a response 
     * 			from the server.
     *    NB: There is no JS method for altering response headers.  
     *      You might wish to try overriding the 
     *      deferred.ioArgs.xhr.getResponseHeader() method with your
     *      own implementation.
     * 2) The new item in the following format:
     * { id: "1", ... }
     */
    return results;
  },
  transformDeleteResults: function(deferred, results) {
    /*
     * JsonRestStore does not expect any specific content here
     */
    return results;
  }
});
      

목록 1의 코드는 dojox.rpc.Rest의 기본 함수를 복제한다. 이는 JsonRestStore로 사용될 수 있으며, 이는 목록 2에 표시된다.


목록 2. JsonRestStore로 EasyRestService의 기본 사용
        
dojo.require("com.ibm.developerworks.EasyRestService");
dojo.require("dojox.data.JsonRestStore");

var store = new dojox.data.JsonRestStore({
  service: new com.ibm.developerworks.EasyRestService("https://mydomain.com/restservice"),
  idAttribute : "id"
});

기본값으로 EasyRestService 인스턴스는 어떠한 방식으로든 인수와 결과를 변경하지 않는다. 필수 인수와 결과 변환을 수행하기 위해 DefaultHooks를 변경하는 대신에 EasyRestService는 인스턴스 단위로 이러한 변환을 대체하기 위한 메커니즘을 제공한다.


EasyRestService 사용자 정의하기

EasyRestService는 사용자 정의 변환자의 공급에 간단한 메커니즘을 제공한다. 목록 3의 예제는 실행하기 전에 GET 호출 구조를 로그하기 위해 EasyRestService의 작동을 변경한다.


목록 3. EasyRestService 사용자 정의하기
        
dojo.require("com.ibm.developerworks.EasyRestService");

var transformers = { 
  transformGetArguments: function(args) { 
    console.log(args); 
    return args; 
  }
};
var service = new com.ibm.developerworks.EasyRestService(
  "https://mydomain.com/restservice", transformers);

마찬가지로, DefaultHooks에서 모든 변환자는 인스턴스 단위로 대체될 수 있다.

예제

EasyRestService의 두 가지 인스턴스를 작성한다. 즉, 하나는 준수 서비스에 대한 것이고 하나는 비준수 서비스에 대한 것이다. 해당 예제는 이를 JsonRestStore의 두 가지 인스턴스의 서비스 제공자로 사용하고, 저장소에 대해 기본 페치를 실행한다.

데이터 저장소

목록 4목록 5에서 서비스는 JSON 구조가 들어 있는 두 개의 읽기 전용 파일을 사용하여 실물처럼 된다.


목록 4. 준수 REST 서비스, compliantService.json
        
[
	{ id: 1, name: "Phil" },
	{ id: 2, name: "John" }
]


목록 5. 비준수 REST 서비스, noncompliantService.json
        
{ items : [
	{ id: 1, name: "Phil" },
	{ id: 2, name: "John" }
] }

저장소 및 서비스 상호작용 코드

JavaScript는 목록 6에서 코드를 사용하여 저장소를 인스턴스화하고 쿼리할 것이다.


목록 6. 저장소와 상호작용하기 위한 JavaScript 코드
        

// Create a store using a service that needs no transformations
compliantStore = new dojox.data.JsonRestStore({
  service : new com.ibm.developerworks.EasyRestService(
      "./compliantService.json"),
  idAttribute : "id"
});

// Cause an async fetch from the compliant service
dojo.create("p", {
  innerHTML : "Requesting from compliant service"
}, dojo.body(), "last");
compliantStore.fetch({
  onComplete : function(items, request) {
    console.log(items);
    // Log the number of items fetched
    dojo.create("p", {
      innerHTML : "Got " + items.length + " items from compliant service."
    }, dojo.body(), "last");
  }
});

// Create a store using a service which needs transformations
// to interpret the results
noncompliantStore = new dojox.data.JsonRestStore({
  service : new com.ibm.developerworks.EasyRestService(
      "./noncompliantService.json", {
        transformGetResults : function(deferred, results) {
          // This store wraps its results in an items object
          // so return the items object
          return results.items;
        }
      }),
  idAttribute : "id"
});

// Cause an async fetch from the noncompliant service
dojo.create("p", {
  innerHTML : "Requesting from noncompliant service"
}, dojo.body(), "last");
noncompliantStore.fetch({
  onComplete : function(items, request) {
    console.log(items);
 	// Log the number of items fetched
    dojo.create("p", {
      innerHTML : "Got " + items.length
          + " items from noncompliant service."
    }, dojo.body(), "last");
  }
});


요약

이 기사에서는 자체적인 REST 서비스를 JsonRestStore로 연결하는 방법을 학습했다. 해당 예제는 JsonRestStore가 필요한 서명을 제공하기 위해 서비스 인터페이스를 변환하는 간단한 메소드를 보여 주었다. JsonRestStore가 예상하는 전체 데이터 구조에 대한 정보는 DefaultHooks의 주석, DojoCampus의 JsonRestStore 문서 및 API 문서를 참조해야 한다.

JsonRestStore가 예상하는 전체 데이터 구조에 대한 정보는 참고자료 섹션을 참조한다.



다운로드 하십시오

설명이름크기다운로드 방식
EasyRestService code sample - project archiveEasyRestServiceExample.zip6.5KBHTTP

다운로드 방식에 대한 정보


참고자료

교육

제품 및 기술

토론

필자소개

Nick Maynard

Nick Maynard는 영국 허슬리의 IBM Software Solutions Transformation 팀에서 재직 중이다. 그의 전문 분야로는 웹 프로그래밍, Linux, 웹 서비스 및 비즈니스 통합 기술이 있다. 이메일 주소는 nick.maynard@uk.ibm.com이다.

잘못된 도움말 신고

부정사용 신고

감사합니다. 이 항목은 운영자가 관심을 표시했습니다.


잘못된 도움말 신고

부정사용 신고

제출실패 신고. 나중에 다시 실행해주세요.


디벨로퍼웍스 로그인


IBM ID가 필요하세요?
IBM ID를 잊으셨습니까?


비밀번호를 잊으셨습니까?
비밀번호 변경

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

화면상에 보여지는 닉네임을 정하세요.

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

3개의 &이나 대쉬를 포함해주시고 31글자내로 제한해주세요.


developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


아티클 순위

의견

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=20
Zone=웹 개발, 자바
ArticleID=780625
ArticleTitle=REST 서비스로 Dojo의 JsonRestStore 사용하기
publish-date=12142011

태그

Help
검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오.

태그를 더 많이 보거나 적게 보기 위해 슬라이더 막대를 사용하십시오.

인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다.

내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.

검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오. 인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다. 내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.