헤드리스 Oracle Content Management로 Oracle JET에서 블로그 구축

소개

Oracle JET(Oracle JavaScript Extension Toolkit)는 개발자가 참여하는 사용자 인터페이스를 구축할 수 있도록 설계된 완전한 모듈식 오픈 소스 JavaScript 개발 툴킷입니다. 이 솔루션은 업계 표준과 널리 사용되는 오픈 소스 프레임워크인 사전 예방을 기반으로 하며 유사한 API로 React를 대체하는 간단한 대안입니다. Oracle JET는 개발자들이 더 나은 애플리케이션을 더 빠르게 구축할 수 있도록 돕는 고급 기능과 서비스를 제공합니다.

이 사용지침서에서는 가상 DOM(VDOM) 아키텍처의 Oracle JET에서 Oracle Content Management를 헤드리스 CMS로 활용하고 SDK(소프트웨어 개발 키트)를 구현하는 간단한 블로그를 구축하게 됩니다. 이 Oracle JET 샘플은 GitHub에서 사용할 수 있습니다.

이 튜토리얼은 다음 세 단계로 구성됩니다.

  1. Oracle Content Management 준비
  2. Oracle JET에서 블로그 구축
  3. 배치용 응용 프로그램 준비

필요 조건

이 자습서를 진행하기 전에 먼저 다음 정보를 읽는 것이 좋습니다.

이 자습서를 따르려면 다음이 필요합니다.

구축 중인 제품

우리의 블로그는 방문자가 주제로 구성된 블로그 기사를 탐색 할 수있는 2 페이지 사이트로 구성됩니다. 첫 번째 페이지인 홈 페이지는 브랜딩(회사 이름 및 로고), 일부 링크 및 주제별로 정렬된 문서 목록으로 구성됩니다. 두 번째 페이지, 기사 페이지는 블로그 작성자에 대한 정보를 포함하여 블로그 기사를 표시합니다.

홈 페이지는 이 자습서 끝에 표시됩니다.

이 이미지는 Cafe Supremo 데모 사이트의 홈 페이지와 사용 가능한 토픽 및 문서를 보여줍니다.

이 자습서 끝에는 문서 페이지가 표시됩니다.

이 이미지는 '아름다운 라떼 아트 만들기'라는 문서 페이지를 보여줍니다.

계속하려면 Oracle Content Management에 활성 가입하고 콘텐츠 관리자 롤로 로그인해야 합니다.

작업 1: Oracle Content Management 준비

Oracle Content Management 인스턴스가 아직 없는 경우 빠른 시작을 참조하여 Oracle Cloud에 등록하고, Oracle Content Management 인스턴스를 프로비전하고, Oracle Content Management를 헤드리스 CMS로 구성하는 방법을 알아보십시오.

이 자습서에서는 두 가지 방법 중 하나로 콘텐츠 모델을 생성해야 합니다. 빈 저장소를 콘텐츠 유형 및 연관된 콘텐츠로 채우거나 고유의 콘텐츠 모델 및 콘텐츠를 생성할 수 있는 다운로드 가능한 자산 팩이 있습니다.

Oracle Content Management를 준비하려면 다음을 수행합니다.

  1. 채널 및 자산 저장소 생성
  2. 다음 두 방법 중 하나를 사용하여 콘텐츠 모델 생성:

채널 및 자산 저장소 생성

먼저 Oracle Content Management에서 채널 및 자산 저장소를 생성해야 콘텐츠를 게시할 수 있습니다.

Oracle Content Management에서 채널 및 자산 저장소를 생성하려면 다음을 수행하십시오.

  1. 관리자로 Oracle Content Management 웹 인터페이스에 로그인합니다.

  2. 왼쪽 탐색 메뉴에서 콘텐츠를 선택한 다음 페이지 머리글의 선택 목록에서 채널 게시를 선택합니다.

    이 이미지는 [콘텐츠] 페이지 머리글의 드롭다운 메뉴에서 선택된 [게시 채널] 옵션을 보여줍니다.

  3. 오른쪽 맨 위에서 생성을 눌러 새 채널을 생성합니다. 이 자습서의 용도로 채널 이름을 'OCEGettingStartedChannel'로 지정하고 액세스를 공용으로 유지합니다. 저장을 눌러 채널을 생성합니다.

    이 이미지는 게시 채널 정의 패널을 보여줍니다. 채널 이름 필드에는 'OCEGettingStartedChannel'이 있습니다.

  4. 왼쪽 탐색 메뉴에서 콘텐츠를 선택한 다음 페이지 머리글의 선택 목록에서 저장소를 선택합니다.

    이 이미지는 [콘텐츠] 페이지 머리글의 드롭다운 메뉴에서 선택된 [저장소] 옵션을 보여줍니다.

  5. 오른쪽 맨 위에서 생성을 눌러 새 자산 저장소를 생성합니다. 이 자습서의 용도로 자산 저장소 이름을 'OCEGettingStartedRepository'로 지정합니다.

    이 이미지는 저장소 이름 필드에 'OCEGettingStartedRepository'가 있는 저장소 정의 패널을 보여줍니다.

  6. 게시 채널 필드에서 OCEGettingStartedChannel 채널을 선택하여 Oracle Content Management에 OCEGettingStartedRepository 저장소의 콘텐츠를 OCEGettingStartedChannel 채널에 게시할 수 있음을 나타냅니다. 완료되면 저장을 누릅니다.

    이 이미지는 [게시 채널] 필드에 'OCEGettingStartedChannel'가 있는 저장소 정의 패널을 보여줍니다.

콘텐츠 모델 생성

다음 단계는 컨텐트 모델을 생성하는 것입니다. 다음 두 가지 방법 중 하나를 사용할 수 있습니다.

Oracle Content Management 샘플 자산 팩 임포트

이 자습서에 필요한 모든 콘텐츠 유형 및 자산이 포함된 미리 구성된 Oracle Content Management 샘플 자산 팩을 다운로드할 수 있습니다. 원하는 경우 샘플 자산 팩을 다운로드하는 대신 고유한 콘텐츠 모델을 생성할 수도 있습니다.

Oracle Content Management 샘플 자산 팩에서 이 자습서에서 사용 중인 콘텐츠 사본을 업로드할 수 있습니다. 이렇게 하면 콘텐츠 유형을 테스트하고 콘텐츠를 수정할 수 있습니다. Oracle Content Management 샘플 자산 팩을 임포트하려면 자산 팩 아카이브 OCESamplesAssetPack.zip를 다운로드하여 선택한 디렉토리로 추출할 수 있습니다.

  1. Oracle Content Management 다운로드 페이지에서 Oracle Content Management 샘플 자산 팩(OCESamplesAssetPack.zip)을 다운로드합니다. 다운로드한 zip 파일을 컴퓨터의 위치로 추출합니다. 추출 후 이 위치에는 OCEGettingStarted_data.zip라는 파일이 포함됩니다.

  2. 관리자로 Oracle Content Management 웹 인터페이스에 로그인합니다.

  3. 왼쪽 탐색 메뉴에서 콘텐츠를 선택한 다음 페이지 머리글의 선택 목록에서 저장소를 선택합니다. 이제 OCEGettingStartedRepository을 선택하고 상단 작업 표시줄에서 콘텐츠 임포트 단추를 누릅니다.

    이 이미지는 OCEGettingStartedRepository 항목이 선택된 [저장소] 페이지를 보여줍니다.

  4. 로컬 컴퓨터에서 OCEGettingStarted_data.zip를 문서 폴더로 업로드합니다.

    이 이미지는 OCEGettingStarted_data.zip 파일의 업로드 확인 화면을 보여줍니다.

  5. 업로드되면 OCEGettingStarted_data.zip을 선택하고 확인을 눌러 자산 저장소로 콘텐츠를 임포트합니다.

    이 이미지는 OK 버튼이 사용으로 설정된 선택된 OCEGettingStarted_data.zip 파일을 보여줍니다.

  6. 콘텐츠를 성공적으로 임포트한 후 자산 페이지로 이동하여 OCEGettingStartedRepository 저장소를 엽니다. 이제 모든 관련 이미지 및 콘텐츠 항목이 자산 저장소에 추가되었음을 알 수 있습니다.

    이 이미지는 OCEGettingStartedRepository 저장소를 보여주며 방금 임포트된 모든 자산을 보여줍니다.

  7. 왼쪽 상단에 있는 모두 선택을 누른 다음 게시를 눌러 이전에 생성한 게시 채널(OCEGettingStartedChannel)에 모든 임포트된 자산을 추가합니다.

    이 이미지는 모든 자산이 선택되고 작업 표시줄에 [게시] 옵션이 표시되는 OCEGettingStartedRepository 저장소를 보여줍니다.

  8. 게시하기 전에 모든 자산을 검증해야 합니다. 먼저 OCEGettingStartedChannel를 선택한 채널로 추가한 다음 검증 단추를 누릅니다.

    이 이미지는 [채널] 필드에 OCEGettingStartedChannel 채널이 추가된 [검증 결과] 페이지, 검증할 모든 자산 및 [검증] 단추가 사용으로 설정된 [검증 결과] 페이지를 보여줍니다.

  9. 자산이 검증되면 오른쪽 맨 위에 있는 게시 단추를 눌러 선택한 채널에 모든 자산을 게시할 수 있습니다.

    이 이미지는 [채널] 필드에 OCEGettingStartedChannel 채널이 추가되고, 검증된 모든 자산 및 [게시] 단추가 사용으로 설정된 [검증 결과] 페이지를 보여줍니다.

완료되면 자산 페이지에서 모든 자산이 게시되었음을 확인할 수 있습니다. (자산 이름 위의 아이콘으로 확인할 수 있습니다.)

이 이미지는 모든 자산이 게시된 자산 페이지를 보여줍니다.

Oracle Content Management 샘플 자산 팩을 임포트한 후 Oracle JET에서 블로그 구축을 시작할 수 있습니다.

고유의 콘텐츠 모델 생성

Oracle Content Management Samples Asset Pack 임포트 대신 고유의 콘텐츠 모델을 생성할 수도 있습니다.

이 자습서에서는 'OCEGettingStartedHomePage'이라는 콘텐츠 유형을 사용하여 블로그의 홈 페이지를 작성합니다. 이 홈 페이지는 브랜딩(회사 이름 및 로고), 링크에 대한 일부 URL 및 페이지에 포함되어야 하는 블로그 항목 목록으로 구성됩니다.

콘텐츠 모델에 대한 콘텐츠 유형을 생성하려면 다음을 수행합니다.

  1. 관리자로 Oracle Content Management 웹 인터페이스에 로그인합니다.
  2. 왼쪽 탐색 메뉴에서 콘텐츠를 선택한 다음 페이지 머리글의 선택 목록에서 자산 유형을 선택합니다.
  3. 오른쪽 상단 모서리에서 생성을 누릅니다.
  4. 콘텐츠 유형(디지털 자산 유형 아님)을 생성하도록 선택합니다. 모든 필수 콘텐츠 유형에 대해 이 작업을 반복합니다.

이 이미지는 Oracle Content Management 웹 인터페이스의 [자산 유형 생성] 대화상자를 보여줍니다.

각각 고유한 필드 집합을 사용하여 네 개의 콘텐츠 유형을 생성합니다.

첫번째 컨텐츠 유형 OCEGettingStartedHomePage에는 다음 필드가 있어야 합니다.

표시 이름 필드 유형 필수 시스템 이름
회사 이름 단일 값 텍스트 필드 X company_name
회사 로고 단일 값 텍스트 필드 X company_logo
주제 다중 값 참조 필드 X 주제
담당자 URL 단일 값 텍스트 필드 X contact_url
URL 정보 단일 값 텍스트 필드 X about_url

OCEGettingStartedHomePage 콘텐츠 유형 정의는 다음과 같이 표시됩니다.

이 이미지는 'OCEGettingStartedHomePage' 콘텐츠 유형에 대한 정의를 보여줍니다. 여기에는 회사 이름, 회사 로고, 주제, 컨택트 URL 및 정보 URL과 같은 데이터 필드가 포함됩니다.

두번째 컨텐츠 유형 OCEGettingStartedTopic에는 다음 필드가 있어야 합니다.

표시 이름 필드 유형 필수 시스템 이름
작은 그림 단일 값 이미지 필드 X 작은 그림

OCEGettingStartedTopic 콘텐츠 유형은 다음과 같아야 합니다.

이 이미지는 'OCEGettingStartedTopic' 콘텐츠 유형에 대한 정의를 보여줍니다. 여기에는 썸네일 데이터 필드가 포함됩니다.

세번째 컨텐츠 유형 OCEGettingStartedAuthor에는 다음 필드가 있어야 합니다.

표시 이름 필드 유형 필수 시스템 이름
아바타 단일 값 이미지 필드 X 아바타

OCEGettingStartedAuthor 콘텐츠 유형은 다음과 같아야 합니다.

이 이미지는 'OCEGettingStartedAuthor' 콘텐츠 유형에 대한 정의를 보여줍니다. 여기에는 Avatar 데이터 필드가 포함됩니다.

네번째 및 최종 콘텐츠 유형 OCEGettingStartedArticle에는 다음 필드가 있어야 합니다.

표시 이름 필드 유형 필수 시스템 이름
게시 일자 단일 값 일자 필드 X published_name
작성자 단일 값 참조 필드 X 작성자
이미지 단일 값 이미지 필드 X 이미지
이미지 캡션 단일 값 텍스트 필드 X image_caption
문서 콘텐츠 단일 값 큰 텍스트 필드 X article_content
주제 단일 값 참조 필드 X 항목

OCEGettingStartedArticle 콘텐츠 유형은 다음과 같아야 합니다.

이 이미지는 'OCEGettingStartedArticlePage' 콘텐츠 유형에 대한 정의를 보여줍니다. 게시 날짜, 작성자, 이미지, 이미지 캡션, 문서 콘텐츠 및 항목 데이터 필드가 포함됩니다.

콘텐츠 유형을 생성한 후에는 이전에 생성한 저장소 OCEGettingStartedRepository에 해당 콘텐츠 유형을 추가할 수 있습니다.

  1. 관리자로 Oracle Content Management 웹 인터페이스에 로그인합니다.
  2. OCEGettingStartedRepository로 이동합니다.
  3. 저장소를 편집하고 자산 유형에서 새로 생성된 네 개의 콘텐츠 유형을 모두 지정합니다.
  4. 저장 단추를 눌러 변경사항을 저장합니다.

이 이미지는 새로 생성된 4개의 콘텐츠 유형이 OCEGettingStartedRepository 저장소와 연관된 Oracle Content Management의 [저장소 편집] 페이지를 보여줍니다.

콘텐츠 유형을 저장소에 추가한 후 자산 페이지에서 OCEGettingStartedRepository 저장소를 열고 모든 콘텐츠 유형에 대한 콘텐츠 항목 생성을 시작할 수 있습니다.

이 이미지는 모음, 채널, 언어, 유형, 콘텐츠 항목 선택 및 상태에 대한 옵션이 왼쪽에 있는 Oracle Content Management 웹 인터페이스의 자산 페이지에 있는 콘텐츠 항목을 보여줍니다.

작업 2: Oracle JET에서 블로그 작성

Oracle JET 응용 프로그램에서 Oracle Content Management 콘텐츠를 소비하려면 GitHub에서 오픈 소스 저장소로 제공되는 Oracle JET 블로그 샘플을 사용할 수 있습니다.

주: Oracle JET 샘플 사용은 선택 사항이며 이 자습서에서 이 샘플을 사용하여 빠르게 시작할 수 있습니다. Oracle JET 팀에서 제공하는 시작 템플리트 중 하나와 같은 고유의 Oracle JET 응용 프로그램을 빌드할 수도 있습니다.

Oracle JET에서 블로그를 구축하려면 다음을 수행하십시오.

  1. 샘플 저장소 복제 및 종속성 설치
  2. Oracle JET CLI 설치 및 Oracle Spectra UI 구성 요소 추가
  3. Oracle JET 응용 프로그램 구성
  4. Oracle Content Management Content SDK 사용
  5. Content SDK를 사용하여 컨텐트 가져오기

샘플 저장소 복제 및 종속성 설치

Oracle JET 블로그 샘플은 GitHub에서 오픈 소스 저장소로 제공됩니다.

먼저 GitHub에서 로컬 컴퓨터로 샘플을 복제하고 디렉토리를 저장소 루트로 변경해야 합니다.

git clone https://github.com/oracle-samples/oce-jet-blog-sample.git
cd oce-jet-blog-sample

이제 코드베이스가 있으므로 응용 프로그램에 대한 종속성을 다운로드해야 합니다. 루트 디렉토리에서 다음 명령을 실행합니다.

npm install

Oracle JET CLI 설치 및 Oracle Spectra UI 구성 요소 추가

다음으로 Oracle JET 명령을 실행하려면 Oracle JET CLI를 설치해야 합니다. package.json 파일에 설치된 종속성이므로 부품에 필요한 작업이 없어야 합니다. Oracle JET CLI에 문제가 있는 경우 Oracle JET CLI 설명서의 지침을 따르십시오. Oracle JET CLI는 GitHub에서 찾을 수 있습니다. 일부 커스텀 구성 요소를 설치하고 응용 프로그램을 실행하려면 Oracle JET CLI가 필요합니다.

그런 다음 이 Oracle JET 샘플에서 사용할 일부 사용자 정의 구성 요소를 설치해야 합니다. 이러한 구성요소에는 사용할 자체 CSS가 연관되어 있습니다. Spectra UI 구성 요소는 다음과 같습니다.

이러한 구성 요소를 추가하려면 Exchange URL을 참조로 구성하고 사용자 정의 Oracle JET 구성 요소(US 인스턴스의 경우)를 설치해야 합니다.

ojet configure --exchange-url=https://devinstance4wd8us2-wd4devcs8us2.uscom-central-1.oraclecloud.com/profile/devinstance4wd8us2-wd4devcs8us2/s/devinstance4wd8us2-wd4devcs8us2_compcatalog_3461/compcatalog/0.2.0
ojet add component oj-sp-welcome-page oj-sp-image-card oj-sp-item-overview-page oj-sp-item-overview --username=comp.catalog --password=bXwphh6RMFjn#g

구성요소 교환 URL에 접속하는 방법에 대한 자세한 내용은 Visual Builder 설명서를 참조하십시오.

Oracle JET 응용 프로그램 구성

이 Oracle JET 블로그 샘플에서는 Oracle Content Management Content SDK(및 기타 요청)가 올바른 채널 토큰으로 올바른 인스턴스 URL 및 API 버전을 대상으로 할 수 있도록 몇 가지 정보를 구성해야 합니다. 이러한 값은 새 전달 클라이언트를 인스턴스화하기 위해 src/scripts/server-config-utils.js에 사용됩니다.

텍스트 편집기에서 src/config/content.json를 엽니다. 다음 정보가 표시됩니다.

{
  "serverUrl": "https://samples.mycontentdemo.com",
  "apiVersion": "v1.1",
  "channelToken": "47c9fb78774d4485bc7090bf7b955632"
}

각 키-값 쌍을 변경하여 인스턴스 URL, 대상 API 버전 및 게시 채널과 연관된 채널 토큰을 반영합니다. 이 자습서의 채널은 OCEGettingStartedChannel입니다. 채널 토큰은 src/config/content.json 파일에 있습니다. 로컬 호스트 포트 번호에 대해 여기에 'expressServerPort' 값을 추가할 수도 있습니다.

주: 이러한 값을 호스팅 제공자 또는 로컬 .env 파일에 환경 변수로 저장하는 것이 좋습니다. 인스턴스 URL 또는 채널 토큰을 공개적으로 공개하면 분산 서비스 거부(DDoS) 공격이 발생할 수 있습니다. 인스턴스에 대한 CORS(Cross-Origin Resource Sharing)가 제대로 구성되었는지 확인하면 이 위험이 완화됩니다.

Oracle Content Management Content SDK 사용

Oracle Content Management는 애플리케이션의 컨텐츠를 검색하고 사용할 수 있도록 SDK를 제공합니다. SDK는 NPM 모듈로 게시되며 프로젝트는 GitHub에 호스팅됩니다.

SDK에 대한 자세한 내용은 여기에서 확인하십시오.

SDK가 package.json 파일에서 이 프로젝트의 런타임 종속성으로 등록되었습니다.

Content SDK를 사용하여 컨텐트 가져오기

이제 Content SDK를 활용하여 컨텐츠를 인출할 수 있으므로 Oracle JET 애플리케이션에서 렌더링할 수 있습니다.

src/scripts 폴더에는 Content SDK를 사용하여 Oracle Content Management에서 데이터를 가져오는 코드가 포함되어 있습니다.

src/scripts/server-config-utils.js 파일은 Content SDK를 임포트한 다음 src/config/content.json에 지정된 구성을 사용하여 전달 클라이언트를 생성합니다.

다음 명령은 SDK를 가져옵니다.

import { createDeliveryClient, createPreviewClient } from '@oracle/content-management-sdk';

다음 명령은 전달 클라이언트를 생성합니다.

return createDeliveryClient(serverconfig);

src/scripts/services.js 파일에는 응용 프로그램의 데이터를 가져오는 모든 코드가 포함되어 있습니다. 응용 프로그램의 각 페이지 구성 요소에 대해 해당 페이지의 모든 데이터를 가져오는 하나의 기본 함수가 있습니다.

이미지를 렌더링하기 위해 services.js은 자산의 표현에서 구성된 자산에 대한 소스 집합을 검색하는 도우미 방법을 제공합니다.

function getSourceSet(asset) {
  const urls = {};
  urls.srcset = '';
  urls.jpgSrcset = '';
  if (asset.fields && asset.fields.renditions) {
    asset.fields.renditions.forEach((rendition) => {
      addRendition(urls, rendition, 'jpg');
      addRendition(urls, rendition, 'png');
      addRendition(urls, rendition, 'webp');
    });
  }
  // add the native rendition to the srcset as well
  urls.srcset += `${asset.fields.native.links[0].href} ${asset.fields.metadata.width}w`;
  urls.native = asset.fields.native.links[0].href;
  urls.width = asset.fields.metadata.width;
  urls.height = asset.fields.metadata.height;
  return urls;
}

홈 페이지 데이터

홈 페이지의 모든 데이터를 가져오려면 여러 데이터 호출이 필요합니다.

  1. 먼저 src/config/content.json에 지정된 채널의 항목을 질의합니다.
  2. 그런 다음 각 항목 항목에 대해 해당 세부정보를 인출합니다.
  3. 마지막으로 각 주제에 대한 모든 문서 데이터를 가져옵니다.

src/scripts/services.js를 열고 홈 페이지의 모든 항목 데이터를 가져오는 getTopicsListPageData() 함수를 찾습니다.

export function getTopicsListPageData() {
  const client = getClient();

  return fetchHomePage(client)
    .then((data) => (
      getRenditionURLs(client, data.logoID)
        .then((renditionUrls) => {
          data.companyThumbnailRenditionUrls = renditionUrls;
          return data;
        })
    ));
}

getTopicsListPageData() 함수로 호출되는 fetchHomePage() 함수는 채널의 모든 항목을 가져옵니다. 로고 ID, 회사 이름, 정보 및 연락처 URL, 항목 목록을 가져옵니다. 이 샘플 블로그의 'HomePage_JET' 홈 페이지를 쿼리하고 있습니다.

function fetchHomePage(client) {
  return client.queryItems({
    q: '(type eq "OCEGettingStartedHomePage" AND name eq "HomePage_JET")',
  }).then((data) => {
    const logoID = data.items[0].fields.company_logo.id;
    const title = data.items[0].fields.company_name;
    const aboutUrl = data.items[0].fields.about_url;
    const contactUrl = data.items[0].fields.contact_url;

    const { topics } = data.items[0].fields;
    const promises = [];

    topics.forEach((origTopic) => {
      // add a promise to the total list of promises to get the full topic details
      promises.push(
        fetchTopic(client, origTopic.id)
          .then((topic) => topic),
      );
    });

    // execute all the promises returning a single dimension array of all
    // of the topics and the other home page data
    return Promise.all(promises)
      .then((allTopics) => (
        {
          logoID,
          companyTitle: title,
          aboutUrl,
          contactUrl,
          topics: flattenArray(allTopics),
        }
      )).catch((error) => logError('Fetching topics failed', error));
  }).catch((error) => logError('Fetching home page data failed', error));
}

그런 다음 각 항목 ID에 대해 fetchTopic() 함수를 호출하여 전체 항목 세부 정보를 가져옵니다.

function fetchTopic(client, topicId) {
  return client.getItem({
    id: topicId,
    expand: 'fields.thumbnail',
  }).then((topic) => {
    topic.renditionUrls = getSourceSet(topic.fields.thumbnail);
    return topic;
  }).catch((error) => logError('Fetching topic failed', error));
}

getTopicsListPageData()는 또한 getRenditionURLs()를 호출하여 렌더링할 이미지의 URL을 가져옵니다.

function getRenditionURLs(client, identifier) {
  return client.getItem({
    id: identifier,
    expand: 'fields.renditions',
  }).then((asset) => getSourceSet(asset))
    .catch((error) => logError('Fetching Rendition URLs failed', error));
}

다음으로 홈 페이지에서 각 항목에 대해 fetchTopicArticles(topicId) 함수를 호출합니다. 지정된 항목 및 변환 URL에 대한 모든 문서를 가져오는 데 사용됩니다.

export function fetchTopicArticles(topicId) {
  const client = getClient();
  return client.queryItems({
    q: `(type eq "OCEGettingStartedArticle" AND fields.topic eq "${topicId}")`,
    orderBy: 'fields.published_date:desc',
  }).then((data) => {
    const promises = [];
    const articles = data.items;

    articles.forEach((article) => {
      // add a promise to the total list of promises to get the article url
      promises.push(
        getRenditionURLs(client, article.fields.image_16x9.id)
          .then((renditionUrls) => {
            article.renditionUrls = renditionUrls;
            return {
              ...article,
            };
          }),
      );
    });

    // execute all the promises and return all the data
    return Promise.all(promises)
      .then((allArticles) => ({
        topicId,
        articles: flattenArray(allArticles),
      }));
  }).catch((error) => logError('Fetching topic articles failed', error));
}

fetchTopicArticles() 메소드는 또한 이전에 본 것처럼 getRenditionURLs()을 사용하여 문서에 대한 이미지를 가져옵니다.

문서 페이지 데이터

문서 페이지는 문서 ID를 수신하며 모든 데이터를 가져오려면 여러 개의 데이터 호출이 필요합니다.

  1. 지정된 문서에 대한 문서 세부정보를 가져옵니다. 각 문서에 대해 해당 변환 URL을 가져옵니다.
  2. 작성자 아바타의 변환 URL을 가져옵니다.

src/scripts/services.js를 열고 문서 페이지에 대한 데이터를 가져오는 fetchArticleDetails(articleId) 함수를 찾습니다.

export function fetchArticleDetails(articleId) {
  const client = getClient();
  return client.getItem({
    id: articleId,
    expand: 'fields.author,fields.image',
  }).then((article) => {
    const title = article.fields.author.name;
    const date = article.fields.published_date;
    const content = article.fields.article_content;
    const imageCaption = article.fields.image_caption;
    const { name } = article;
    const renditionUrls = getSourceSet(article.fields.image);
    const avatarID = article.fields.author.fields.avatar.id;
    // Get the author's avatar image
    return getRenditionURLs(client, avatarID)
      .then((authorRenditionUrls) => (
        // return an object with just the data needed
        {
          id: articleId,
          name,
          title,
          date,
          content,
          imageCaption,
          renditionUrls,
          authorRenditionUrls,
        }
      ));
  }).catch((error) => logError('Fetching article details failed', error));
}

또한 fetchArticleDetails() 메소드는 앞에서 살펴본 것처럼 getRenditionURLs()을 사용하여 아바타 이미지를 가져옵니다.

Oracle JET 구조 및 페이지

다음 섹션에서는 Oracle JET가 데이터를 렌더링하는 방법에 대한 개요를 제공합니다.

Oracle JET 블로그 애플리케이션 플로우

이 Oracle JET 응용 프로그램의 주 시작점은 src/app.tsx 파일입니다. 이 파일은 사전 실행 라우터와 응용 프로그램의 모든 페이지를 가져옵니다.

우리 사이트에서는 세 가지 경로를 제공합니다.

아래 라우터 코드에서 볼 수 있듯이 기본 홈 페이지 경로 '/'는 TopicsListPage용이며 각 문서는 ArticleDetailsPage의 서버 + 'article/:articleId'에 호스팅됩니다. 사전 인증 라우터의 route() 메서드를 사용하여 여기서 라우팅됩니다. 잘못된 경로는 NotFoundPage로 전송됩니다.

주: 기본 라우터 경로에 대한 추가 지원은 원하는 경로 앞에 base_url를 추가하여 Preact Router에서 여기에서 수정할 수 있습니다. base_url의 경우 Preact Router route() 메소드를 대체하기 위한 특수 appRoute() 메소드가 샘플 코드에 포함됩니다.

<Router>
  <TopicsListPage path="/" />
  <ArticleDetailsPage path="/article/:articleId" />
  <NotFoundPage default />
</Router>

TopicsList 페이지

TopicsList 페이지(홈)는 개별 항목으로 구성된 항목 목록과 선택한 항목에 대한 문서 목록으로 구성됩니다.

TopicsListPage 클래스는 런타임의 componentDidMount 단계에서 호출되는 fetchData() 함수를 사용하여 데이터를 인출합니다.

fetchData() 함수는 다음과 같습니다.

fetchData() {
  this.setState(() => ({
    loading: true,
  }));

  getTopicsListPageData()
    .then((data) => {
      const promiseArr = [];
      for (let i = 0; i < data.topics.length; i += 1) {
        promiseArr.push(
          fetchTopicArticles(data.topics[i].id).then(
            (topicArticlesData) => { data.topics[i].articleData = topicArticlesData; },
          ),
        );
      }
      Promise.all(promiseArr).then(() => {
        this.setState({
          data,
          loading: false,
        });
      });
    });
}

처음에 로드할 때 진행 상황 원을 표시하기 위해 로드 중으로 설정된 다음 로드가 완료되면 false로 설정됩니다. 함수 getTopicsListPageData()은 한 번 호출되고 각 항목에 대해 fetchTopicArticles()가 호출됩니다. 결과는 코드의 이 섹션에서 해결되는 약속입니다.

모든 데이터가 있으면 본문과 함께 본문 시작 페이지를 만듭니다.

본문은 다음과 같이 생성되며 oj-sp-image-card 구성 요소를 사용합니다.

const bodyElems = [];
let articleCards = [];
topics.forEach(
  (topic) => {
    bodyElems.push(
      <div className='topicType'>
        <div className='topicHeading'>{topic.name}</div>
        <div>{topic.description}</div>
      </div>,
    );
    topic.articleData.articles.forEach((article) => {
      articleCards.push(
        <oj-sp-image-card
          primaryText={article.name}
          secondaryText={article.description}
          imageSrc={article.renditionUrls.native}
          footerType='none'
          onClick={ function openArticleLink() { route(`/article/${article.id}`); } }
        />,
      );
    });
    bodyElems.push(
      <div className='articleItem'>
        {articleCards}
      </div>,
    );
    articleCards = [];
  },
);

여기서 bodyElems는 oj-sp-welcome-page 구성 요소에 슬롯할 HTML 요소의 배열입니다. bodyElems는 항목 헤더와 해당 항목 아래의 각 문서에 대한 실제 이미지 카드 간에 대체됩니다.

각 이미지 카드에는 가로 세로 비율이 16:9인 이미지가 있습니다. 이는 oj-sp-image-card 구성 요소에 대해 16:9 이미지 크기를 사용하는 제한 사항이며 renditionUrls에 이 Oracle JET 샘플 블로그 코드에 대한 ojspcard 이름과 함께 16:9 표현이 나열됩니다. 또한 이미지 카드의 onClick 작업은 문서 페이지로 이동하는 함수입니다.

다음은 TopicsListPage에 의해 반환되며, 여기에는 bodyElems가 내부에 슬롯된 oj-sp-welcome-page 구성 요소가 포함됩니다.

<oj-sp-welcome-page
  pageTitle={companyTitle}
  overlineText= 'Home'
  displayOptions={{
    imageStretch: 'full',
  }}
  illustrationForeground={companyThumbnailRenditionUrls.native}
  primaryAction={{
    label: 'About Us',
    icon: 'oj-ux-ico-information',
    display: 'on',
  }}
  onspPrimaryAction={ function openAboutLink() { window.open(aboutUrl, '_blank'); } }
  secondaryAction={{
    label: 'Contact Us',
    icon: 'oj-ux-ico-contact-edit',
    display: 'on',
  }}
  onspSecondaryAction={ function openContactLink() { window.open(contactUrl, '_blank'); } }
>
{bodyElems}
</oj-sp-welcome-page>

oj-sp-welcome-page 구성 요소는 페이지 헤더를 생성하고 bodyElems에 넣을 공간을 제공합니다. 보시다시피 페이지 제목, '홈' 개요 텍스트, 일부 버튼 및 표시 이미지가 있습니다. 표시 이미지의 소스는 illustrationForeground 필드에 있고 이미지는 displayOptions 매개변수를 사용하여 확장됩니다. oj-ux 라이브러리에 아이콘이 있는 'About Us' 및 'Contact Us'라는 두 개의 버튼이 있으며, 두 버튼은 모두 새 탭에서 우리에 대한 링크를 열고 저희에게 연락합니다.

ArticleDetails 페이지

ArticleDetails 페이지는 작성자, 이미지 및 텍스트와 같은 문서 자체와 관련된 모든 데이터로 구성됩니다.

ArticleDetails 클래스는 런타임의 componentDidMount 단계에서 호출되는 fetchData() 함수를 사용하여 데이터를 인출합니다.

fetchData() 함수는 다음과 같습니다.

fetchData(articleId) {
  this.setState(() => ({
    loading: true,
  }));

  fetchArticleDetails(articleId)
    .then((data) => this.setState(() => ({
      data,
      loading: false,
    })));
  }
}

처음에 로드할 때 진행 상황 원을 표시하기 위해 로드 중으로 설정된 다음 로드가 완료되면 false로 설정됩니다. fetchArticleDetails() 함수는 현재 켜져 있는 articleId에 대해 한 번 호출됩니다. 결과는 코드의 이 섹션에서 해결되는 약속입니다.

모든 데이터가 있으면 articleDetails 페이지를 생성합니다.

페이지는 다음과 같이 생성됩니다. 여기서 'overview' 섹션에 슬롯이 지정된 oj-sp-item-overview 구성요소와 'main' 섹션에 슬롯이 지정된 기본 콘텐츠가 있는 oj-sp-item-overview-page 구성요소를 사용합니다.

<oj-sp-item-overview-page
  overviewExpanded={false}
  translations={{
    goToParent: 'Back to Home',
  }}
  onspGoToParent={ function goToParent() { route('/'); } }
>
  <div slot='overview'>
    <oj-sp-item-overview
      itemTitle={title}
      itemSubtitle={formattedDate}
      photo={{
        src: data.authorRenditionUrls.small,
      }}
    />
  </div>
  <div slot='main'>
    <h1 style='text-align:center'>{name}</h1>
    <figure>
      {data.renditionUrls && (
        <picture>
          <source type='image/webp' srcSet={data.renditionUrls.srcset} />
          <source srcSet={data.renditionUrls.jpgSrcset} />
          <img
            src={data.renditionUrls.small}
            alt='Article'
            width={parseInt(data.renditionUrls.width, 10) * 0.66}
            height={parseInt(data.renditionUrls.height, 10) * 0.66}
          />
        </picture>
      )}
      <figcaption style='text-align:center'>{imageCaption}</figcaption>
    </figure>
    {/* eslint-disable-next-line @typescript-eslint/naming-convention */}
    <div dangerouslySetInnerHTML={{ __html: cleancontent }} />
  </div>
</oj-sp-item-overview-page>

oj-sp-item-overview-page 구성 요소는 articleDetails 페이지의 레이아웃을 제공합니다. 특히 overviewExpanded는 이제 전체 페이지를 대체하기 위해 false이고, goToParent의 번역은 'Back to Home'이며, onspGoToParent는 topicsList 페이지로 다시 경로 지정하기 위한 논리를 완료하는 함수입니다.

oj-sp-item-overview-page에서 사용할 수 있는 두 개의 슬롯이 있으며, 해당 슬롯은 '개요' 슬롯과 '기본' 슬롯이며, 여기에는 기사 작성자에 대한 세부 정보가 포함되어 있으며 문서의 내용을 제공합니다.

oj-sp-item-overview 구성 요소는 '개요' 섹션으로 슬롯되어 작성자 세부 정보에 대한 열 레이아웃을 제공합니다. itemTitle는 작성자 이름이고 부제는 형식이 지정된 날짜이며 사진은 작성자 사진의 소스입니다.

'기본' 슬롯 섹션에는 문서의 제목, 캡션 이미지 및 문서 블로그 텍스트를 포함하는 문서의 모든 세부정보가 포함되어 있습니다.

작업 3: 배치용 응용 프로그램 준비

이제 Oracle JET 블로그 사이트를 구축했으므로 로컬 개발 서버에서 문제를 디버그하고 실제 운영 전에 애플리케이션을 미리 볼 수 있어야 합니다.

프로젝트 루트에 있는 package.json 파일에는 번들을 쉽게 작성하고 응용 프로그램을 실행할 수 있는 스크립트가 포함되어 있습니다.

개발

개발 중에 dev 스크립트를 사용할 수 있습니다.

npm run dev

이 스크립트는 클라이언트 및 서버 번들을 작성하고 로컬 서버에서 응용 프로그램을 시작합니다. 필요한 경우 Webpack은 코드 변경을 감시하고 클라이언트 및 서버 번들을 재생성합니다.

생산

프로덕션의 경우 빌드 스크립트를 사용하여 클라이언트 및 서버 번들을 빌드합니다.

npm run build

스크립트가 완료되면 다음 명령을 사용하여 응용 프로그램을 실행할 수 있습니다.

npm run start

결론

이 자습서에서는 Oracle JET에서 Github에서 찾을 수 있는 블로그 사이트를 생성했습니다. 이 사이트는 헤드리스 CMS로 Oracle Content Management를 사용합니다. 블로그 사이트 자습서에 게시된 콘텐츠 채널로 Oracle Content Management를 설정 및 구성한 후 Oracle JET 사이트를 설치 및 실행하여 필요한 콘텐츠를 인출하고 사이트를 구축했습니다.

Oracle JET에 대한 자세한 내용은 Oracle JET 웹 사이트를 참조하십시오.

문서에서 중요한 Oracle Content Management 개념에 대해 알아봅니다.

Oracle Content Management 샘플 페이지의 Oracle Help Center에서 이와 같은 더 많은 샘플을 찾을 수 있습니다.