Oracle JET 가상 DOM 앱의 REST API에서 데이터 인출

소개

이 사용지침서에서는 REST 서비스에 접근하고 Oracle JET(Oracle JavaScript Extension Toolkit) 가상 DOM 앱에 통합하며 사용자 인터페이스의 목록 보기에 데이터를 바인드하는 방법을 보여줍니다.

목표

이 자습서에서는 RESTDataProvider 클래스의 인스턴스를 생성하는 방법에 대해 알아봅니다. 이 클래스는 JSON 기반 REST 서비스에서 사용 가능한 데이터를 나타냅니다.

필수 조건

작업 1: Starter Virtual DOM 앱 다운로드

이전 학습 경로에서 생성한 앱에서 계속 작업하는 경우 이 태스크를 건너뜁니다.

  1. jet-virtual-dom-app-temp.zip의 이름을 JET-Virtual-DOM-app.zip로 바꿉니다. 컨텐츠를 JET-Virtual-DOM-app 디렉토리로 추출합니다.

  2. JET-Virtual-DOM-app 디렉토리로 이동하고 Oracle JET 가상 DOM 앱을 복원합니다.

    npm install
    

    가상 DOM 앱을 사용할 준비가 되었습니다.

작업 2: REST 서비스 액세스

활동 리소스 끝점에 대한 REST 데이터를 보려면 Apex 링크를 누릅니다.

데이터는 다양한 속성을 가진 활동 목록을 포함합니다.

{
  "items": [
      {
      "id": 1,
      "name": "Baseball",
      "short_desc": "Equipment we carry for baseball players.",
      "image": "css/images/product_images/baseball.jpg"
      },
   . . .
   ],
   "hasMore": false,
   "limit": 25,
   "offset": 0,
   "count": 4,
   "links": [
      {
      "rel": "self",
      "href": "https://apex.oracle.com/pls/apex/oraclejet/lp/activities/"
      },
      . . .
   ]
}

끝점이 반환하는 데이터 및 속성을 숙지합니다. 이 자습서의 뒷부분에서 RESTDataProvider 인스턴스를 생성할 때 이러한 세부정보를 이해해야 합니다. 예를 들어, 끝점이 일련의 개별 작업을 참조하는 items 속성을 반환하는 방법을 확인합니다.

작업 3: 작업 데이터를 인출할 데이터 제공자 생성

  1. JET-Virtual-DOM-app/src/components/ 디렉토리로 이동하고 편집기에서 ParentContainer1.tsx 파일을 엽니다.

  2. ParentContainer1.tsx 파일 시작 시 RESTDataProvider 모듈을 임포트하고 MutableArrayDataProvider 모듈 및 store_data.json 파일에 대한 import 문을 삭제하거나 주석 처리합니다.

    또한 나중에 RESTDataProvider를 만들 때 사용할 useMemo 후크를 가져옵니다.

    import { h } from "preact";
    . . .
    // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
    // import * as storeData from "text!./store_data.json";
    import { RESTDataProvider } from "ojs/ojrestdataprovider";
    import { useState, useMemo } from "preact/hooks";
    . . .
    
  3. 다음 단계에서 생성할 RESTDataProvider 인스턴스로 전달할 작업 키 속성 및 REST 끝점을 참조하는 keyattributes 변수와 restServerURLActivities 변수를 생성합니다.

    let keyAttributes: string = 'id';
    // REST endpoint that returns Activity data
    const restServerURLActivities: string =
      'https://apex.oracle.com/pls/apex/oraclejet/lp/activities/';
    
  4. RESTDataProvider 모듈을 참조하는 새 activityDataProvider 변수를 생성하고 MutableArrayDataProvider 모듈을 참조하는 기존 activityDataProvider 변수를 삭제하거나 주석 처리합니다.

    ParentContainer1 함수 내에 새 activityDataProvider 변수를 생성하고 데이터 제공자의 데이터가 실제로 변경되는 경우에만 데이터 제공자 인스턴스가 재생성되도록 useMemo 후크 내에 래핑합니다.

    const ParentContainer1 = () => {
    
    const activityDataProvider = useMemo(() => new RESTDataProvider<Activity["id"], Activity>({
       keyAttributes: keyAttributes,
       url: restServerURLActivities,
       transforms: {
          fetchFirst: {
          request: async (options) => {
             const url = new URL(options.url);
             const { size, offset } = options.fetchParameters;
             url.searchParams.set("limit", String(size));
             url.searchParams.set("offset", String(offset));
             return new Request(url.href);
          },
          response: async ({ body }) => {
             const { items, totalSize, hasMore } = body;
             return { data: items, totalSize, hasMore };
          },
          },
       },
     }), [])
    . . .
    

    주: 끝점 응답 본문에서 데이터 및 기타 속성을 추출하는 위의 response 함수는 data 속성을 가진 객체를 반환해야 합니다. 작업하는 끝점이 items 속성을 반환한다는 점을 감안하면 응답 함수에서 이 후자의 속성을 data에 지정합니다.

  5. ParentContainer1.tsx 파일을 저장합니다.

    ParentContainer1.tsx 파일은 ParentContainer1-a.tsx.txt와 유사해야 합니다.

  6. JET-Virtual-DOM-app/src/components/Activity 디렉토리로 이동하고 편집기에서 ActivityContainer.tsx 파일을 엽니다.

  7. ActivityContainer.tsx 파일 시작 시 RESTDataProvider 모듈을 임포트하고 MutableArrayDataProvider 모듈에 대한 import 문을 주석 처리하거나 삭제합니다.

       import { h, ComponentProps } from "preact";
       . . .
       // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
       import { RESTDataProvider } from "ojs/ojrestdataprovider";
       . . .
    
    
  8. Props 유형 별칭에서 기존 유형 MutableArrayDataProvider<Activity["id"], Activity> 대신 RESTDataProvider 유형을 참조하도록 선택적 data 속성을 수정합니다.

       type Props = {
          data?: RESTDataProvider<Activity["id"], Activity>;
          // data?: MutableArrayDataProvider<Activity["id"], Activity>;
       . . .
       };
    
  9. ActivityContainer.tsx 파일을 저장합니다.

    ActivityContainer.tsx 파일은 ActivityContainer.tsx.txt와 유사해야 합니다.

작업 4: 데이터 인출 실패를 관리하는 오류 처리기 추가

RESTDataProvider 인스턴스는 데이터 인출 시도가 실패할 때 콜백 함수를 호출하는 데 사용할 수 있는 오류 옵션을 제공합니다. 작업 목록 인출 시도가 실패하는 시나리오에 대해 이 기능을 구현합니다.

  1. JET-Virtual-DOM-app/src/components/ 디렉토리의 ParentContainer1.tsx 파일에서 Preact에서 useRef 후크를 가져옵니다.

    . . .
    import { RESTDataProvider } from "ojs/ojrestdataprovider";
    import { useState, useMemo, useRef } from "preact/hooks";
    . . .
    
  2. RESTDataProvider를 참조하는 activityDataProvider 변수에서 error 옵션 및 호출하는 콜백 함수에 대한 참조(fetchErrorHandler)를 추가합니다.

    const ParentContainer1 = () => {
    
       const activityDataProvider = useMemo(() => new RESTDataProvider<Activity["id"], Activity>({
          keyAttributes: keyAttributes,
          url: restServerURLActivities,
          error: fetchErrorHandler,
          transforms: {
          . . .
    
  3. activityDataProvider 변수 앞에 fetchErrorHandler에 대한 코드와 데이터 인출 시도가 성공했는지 확인하는 데 사용하는 후크(useStateuseRef)를 추가합니다.

    . . .
    const ParentContainer1 = () => {
    
    const [fetchStatus, setFetchStatus] = useState(true);
    const fetchError = useRef<string>();
    
    const fetchErrorHandler = (errorDetail: RESTDataProvider.FetchErrorDetail<number, Activity> |
                                            RESTDataProvider.FetchResponseErrorDetail<number, Activity>) => {
       setFetchStatus(false);
       if (errorDetail.hasOwnProperty('response')) {
          fetchError.current = `${(errorDetail as RESTDataProvider.FetchResponseErrorDetail<number, Activity>).response.status}`;
       }
       else {
          fetchError.current = (errorDetail as RESTDataProvider.FetchErrorDetail<number, Activity>).error.message;
       }
    }
    
    const activityDataProvider = new RESTDataProvider<Activity["id"], Activity>({
    . . .
    
  4. ParentContainer1.tsx 파일 끝에 있는 반환 명령문에서 데이터 인출 시도가 실패한 경우 작업 목록 또는 메시지를 표시할지 여부를 결정하는 검사를 추가합니다.

    . . .
    return (
       <div>
          {fetchStatus ? (
          <div id="parentContainer1" class="oj-flex oj-flex-init">
             <ActivityContainer data={activityDataProvider} onActivityChanged={activityChangedHandler} />
             {showActivityItems() && (<ParentContainer2 activity={selectedActivity} />)}
             {!showActivityItems() && (<h4 class="oj-typography-subheading-sm">Select activity to view items</h4>)}
          </div>) :
          (<p>Sorry that we couldn't get your product information right now. Please contact your system administrator.</p>
          )}
       </div>
    );
    };
    
    export default ParentContainer1;
    
  5. ParentContainer1.tsx 파일을 저장합니다.

    ParentContainer1.tsx 파일은 ParentContainer1-b.tsx.txt와 유사해야 합니다.

작업 5: 항목 데이터를 인출할 데이터 제공자 생성

다른 RESTDataProvider 인스턴스를 사용하여 특정 작업에 대한 항목 목록인 데이터의 하위 세트를 인출합니다. 선택한 활동 ID가 포함된 새 URL을 제공하여 이 작업을 수행합니다.

  1. JET-Virtual-DOM-app/src/components/ 디렉토리로 이동하고 편집기에서 ParentContainer2.tsx 파일을 엽니다.

  2. ParentContainer2.tsx 파일 시작 시 RESTDataProvider 모듈을 임포트하고 MutableArrayDataProvider 모듈 및 store_data.json 파일에 대한 import 문을 삭제하거나 주석 처리합니다. 또한 생성한 RESTDataProvider 인스턴스에서 필터링 기능을 사용으로 설정할 때 사용할 TextFilter 인터페이스를 임포트합니다.

    import { h } from "preact";
    . . .
    import { RESTDataProvider } from "ojs/ojrestdataprovider";
    import { TextFilter } from "ojs/ojdataprovider";
    
    // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
    // import * as storeData from "text!./store_data.json";
    . . .
    
    
  3. Item 유형 별칭 뒤에 baseServiceUrl 변수를 생성하여 다음 단계에서 생성할 RESTDataProvider 인스턴스로 전달할 REST 끝점을 참조합니다.

    type Item = {
       . . .
     };
    
    const baseServiceUrl =
      "https://apex.oracle.com/pls/apex/oraclejet/lp/activities/";
    
  4. useStateuseEffect Preact 후크에 후속 단계를 전달할 RESTDataProvider의 초기 인스턴스를 생성합니다.

       const baseServiceUrl = 'https://apex.oracle.com/pls/apex/oraclejet/lp/activities/';
    
       let INIT_DATAPROVIDER = new RESTDataProvider<ActivityItem['id'], ActivityItem>({
       keyAttributes: 'id',
       url: baseServiceUrl,
       transforms: {
          fetchFirst: {
             request: null!,
             response: (): any => {
             return { data: [] };
             },
          },
       },
       });
    
  5. store_data.json 파일에서 데이터를 읽고 MutableArrayDataProvider의 초기 인스턴스를 생성한 변수를 생성한 기존 코드를 주석 처리하거나 삭제합니다.

       // const activityData = JSON.parse(storeData);
       // let activityItemsArray = activityData[0].items;
    
       // // Create data provider instance for the array of activity items for the selected activity
       // const INIT_DATAPROVIDER = new MutableArrayDataProvider<ActivityItem["id"], ActivityItem>(activityItemsArray, {
       //   keyAttributes: "id",
       // })
    
  6. ParentContainer2 함수에서 MutableArrayDataProvider의 인스턴스를 관리하는 기존 useEffect 후크를 선택한 활동 ID에 해당하는 활동 항목에 대해 RESTDataProvider를 생성하는 새 정의로 바꿉니다. 이 새 정의에는 활동 항목 name 필드에서 필터링할 텍스트 필터도 포함됩니다.

    const ParentContainer2 = (props: Props) => {
    . . .
    useEffect(() => {
       setactivityItemDP(
          new RESTDataProvider<ActivityItem["id"], ActivityItem>({
          keyAttributes: "id",
          capabilities: {
             filter: {
                textFilter: true,
             },
          },
          url: baseServiceUrl + "/" + props.activity?.id + "/items/",
          textFilterAttributes: ["name"],
          transforms: {
             fetchFirst: {
                request: async (options) => {
                const url = new URL(options.url);
                const { size, offset } = options.fetchParameters;
                url.searchParams.set("limit", String(size));
                url.searchParams.set("offset", String(offset));
                const filterCriterion = options.fetchParameters
                   .filterCriterion as TextFilter<Item>;
                const { textFilterAttributes } = options.fetchOptions;
                if (
                   filterCriterion &&
                   filterCriterion.text &&
                   textFilterAttributes
                ) {
                   const { text } = filterCriterion;
                   textFilterAttributes.forEach((attribute) => {
                      url.searchParams.set(attribute, text);
                   });
                }
    
                return new Request(url.href);
                },
                response: async ({ body }) => {
                const { items, totalSize, hasMore } = body;
                return { data: items, totalSize, hasMore };
                },
             },
          },
          })
       );
    }, [props.activity]);
    
    return (
    . . .
    
  7. ParentContainer2.tsx 파일을 저장합니다.

    ParentContainer2.tsx 파일은 ParentContainer2.tsx.txt와 유사해야 합니다.

  8. JET-Virtual-DOM-app/src/components/ActivityItem 디렉토리로 이동하고 편집기에서 ActivityItemContainer.tsx 파일을 엽니다.

  9. ActivityItemContainer.tsx 파일 시작 시 RESTDataProvider 모듈을 임포트하고 MutableArrayDataProvider 모듈에 대한 import 문을 주석 처리하거나 삭제합니다.

    import { h, ComponentProps } from "preact";
    . . .
    // import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
    import { RESTDataProvider } from "ojs/ojrestdataprovider";
    . . .
    
  10. Props 유형 별칭에서 기존 유형 MutableArrayDataProvider<Activity["id"], Activity> 대신 RESTDataProvider 유형을 참조하도록 data 속성을 수정합니다.

    type Props = {
      // data?: MutableArrayDataProvider<ActivityItem["id"], ActivityItem>;
      data?: RESTDataProvider<ActivityItem['id'], ActivityItem>;
      selectedActivity: Item | null;
      onItemChanged: (item: Item) => void;
    };
    
  11. ActivityItemContainer.tsx 파일을 저장합니다.

    ActivityItemContainer.tsx 파일은 ActivityItemContainer.tsx.txt와 유사해야 합니다.

작업 6: 가상 DOM 앱 테스트

  1. 터미널 창에서 JET-Virtual-DOM-app 디렉토리로 변경하고 가상 DOM 앱을 실행합니다.

    npx ojet serve
    
  2. 브라우저 창에서 가상 DOM 앱의 동적 변경사항을 확인합니다.

    Fetched Records 화면

  3. 실행 중인 가상 DOM 앱을 표시하는 브라우저 창 또는 탭을 닫습니다.

  4. 터미널 창에서 Ctrl+C을 누르고 프롬프트가 표시되면 y를 입력하여 Oracle JET 툴링 일괄 처리 작업을 종료합니다.

  5. 터미널 창에서 다음 추가 명령줄 인수를 사용하여 가상 DOM 앱을 실행합니다.

    npx ojet serve --server-port=8144 --livereload-port=8145
    

    이 경우 가상 DOM 앱은 액세스하려는 REST 서비스가 기본적으로 ojet serve 명령이 사용하는 서버 포트(8000)의 요청만 수락하므로 RESTDataProvider가 REST 서비스에서 인출하려는 시도를 실패했기 때문에 다음 메시지를 표시합니다.

    Sorry that we couldn't get your product information right now. Please contact your system administrator.
    

다음단계

이 모듈의 다음 자습서로 이동합니다.

이 자습서는 REST 서비스를 사용한 CRUD 작업 모듈의 일부입니다.

가상 DOM 학습 경로의 기본 페이지로 돌아가 가상 DOM 앱 구축 시 모든 모듈에 액세스할 수 있습니다.

추가 학습 자원

docs.oracle.com/learn에서 다른 랩을 탐색하거나 Oracle Learning YouTube 채널에서 더 많은 무료 학습 콘텐츠에 액세스하세요. 또한 education.oracle.com/learning-explorer를 방문하여 Oracle Learning Explorer가 되십시오.

제품 설명서는 Oracle Help Center를 참조하십시오.