webOS Article/2. Luna Service 활용하기

Database 사용하기 (DB8)

하이하정 2021. 8. 14. 16:07

이 포스팅은 webOS OSE 개발자 사이트: com.webos.service.db, webOS TV 개발자 사이트: DB8 Basics, webOS TV 개발자 사이트: DB8, webOS TV 개발자 사이트: Database 를 참고하여 작성되었습니다.

 

 

DB8이란 무엇인가?


1. Database API DB8

데이터베이스란 여러 사람에게 공유되어 사용될 목적으로 통합하여 관리되는 데이터의 집합입니다. 이를 이용하면 데이터가 중복되는 문제를 없앨 수 있어 데이터를 효율적으로 사용할 수 있게 됩니다.

 

DB8은 webOS TV에서 사용하는 저장 방식입니다. Luna Bus에서 사용할 수 있는 서비스이며 내장된 JSON 데이터베이스에 대한 인터페이스입니다.

DB8의 주요한 기능에는 고속 액세스 및 쿼리 활성화, JSON objects 저장, 앱 인식 액세스 제어, 쿼리 페이징 지원(한 번에 최대 500개의 개체를 검색), change notification 지원, 스키마 적용을 통한 data object 유효성 검사 등이 있습니다

 

2. DB8의 기본구조

  • Kind object : 데이터베이스의 'table'을 의미합니다. JSON data objects의 owner, schema, indexes를 정의합니다. putKind() method를 사용하여 Kind object를 만들 수 있습니다.
{
    "id"      :  "com.yourdomain.contact:1",
    "owner"   :  "com.yourdomain.contacts",
    "extends" :  ["PimObject:1"],
    "indexes" :  [{"name":"dname", "props":[{"name":"displayName"}]}]
}​

id : property value 필드의 끝에 숫자가 추가됩니다. 이 숫자는 처음에 1이어야 하며, 이러한 kind의 버전이 업데이트될 때마다 DB Service에 의해 숫자가 증가됩니다.

owner : 소유자의 앱 ID로, 소유자에게만 kind를 수정하는 권한이 있습니다.

extends : kinds가 다른 kind를 확장할 수 있습니다. 위의 예에서는 contacts kind는 PimObject kind로부터 확장됩니다. 

indexes : 만들 수 있는 쿼리 유형을 결정합니다. 위의 예에서는 하나의 index만 정의됩니다.

 

  • Data object : 데이터가 포함된 특정 kind의 JSON object입니다. 객체 지향 프로그래밍에서 classes의 instances인 objects와 유사합니다.

다음과 같은 연락처를 저장하기로 했을 때

{
    "displayName"  : "John Doe",
    "name"         : {"familyName":"Doe", "givenName":"John"},
    "nickname"     : "Skippy",
    "emails"       : [ "jdoe@gmail.com", "john.doe@palm.com", "jdoe99@gmail.com" ]
}​

 

위의 JSON object의 정의는 다음과 같습니다.

{
    "displayName" : string,
    "name"        : {
        "familyName" : string,
        "givenName"  : string
    },
    "nickname"    : string,
    "emails"      : string array
}

 

 

 

DB8 method 


1.  putKind

데이터 베이스에 Kind를 등록할 때 사용한다.

 

AGC : database.operation

 

Parameters

Call Returns

2.  putPermission

데이터 개체에 엑세스 할 수 있는 권한을 부여할 때 사용한다.

 

AGC : database.operation

 

Parameters

Call Returns

3. put

데이터 베이스에 특정 Kind의 json 데이터 객체를 저장할 때 사용한다.

 

AGC : database.operation

 

Parameters

 

Call Returns

4. delKind

데이터 베이스에  Kind를 삭제할 때 사용한다. Kind를 삭제하면 해당 Kind의 모든 데이터가 삭제된다.

 

AGC : database.operation

 

Parameters

Call Returns

 

5. del

데이터 베이스의 json 데이터 객체를 삭제할 때 사용한다.

 

AGC : database.operation

 

Parameters

Call Returns

6. find

qurey parameter에 지정된 qurey와 일치하는 개체 집합을 반환할 때 사용한다.

 

AGC : database.operation

 

Parameters

Call Returns

 

DB8 실습하기


1. 목표

디바이스의 이름과 위치를 입력하면 데이터가 데이터베이스에 저장되고, 데이터베이스를 화면에 나타낸다.

 

2. 권한 추가하기

webOS OSE Luna Sevice API를 사용하기 위해 appinfo.json파일의 requiredPermissions에 사용하고자 하는 API method의 ACG를 추가해야 합니다.

 

저희는 Database API의 putKind, put등의 method 사용하기 위해 홈페이지의 ACG 가이드를 참고하여 database.operation를 추가했습니다.

 

기존에 API이용시 ls-monitor -i 명령어를 사용하여 requiredPermission을 직접 확인해주어야 했는데요, 이번 업데이트 후 webOS OSE사이트 API 문서에서  ACG 값을 쉽게 확인할 수 있는 ACG 가이드가 추가되었습니다.

 

 

3. 코드확인

  • 웹페이지 만들기

본격적으로 database를 사용하기 전에, html과 css를 사용하여 database 웹페이지를 만들었습니다.

 

 

Device Name에 디바이스의 이름을 입력하고 Location에 디바이스의 위치를 입력한 후 add를 눌러 디바이스의 이름과 위치를 데이터베이스에 저장하겠습니다.

 

  • 데이터베이스 만들기

 

kindID와 bridge를 지정해줍니다.

window.onload를 사용하여 앱이 실행되었을 때 putKind(), putPermissions(), emptyDB()가 실행되도록 합니다.

각 함수는 아래에서 정의합니다.

bridge는 다음 포스팅에서 참고할 수 있습니다. https://webos-supporters.tistory.com/20

 

 

putKind

kind를 생성해주는 putKind를 정의합니다.

prop으로 deviceName, location, status을 추가하여 디바이스의 이름, 위치, 현재 상태를 확인할 수 있게 했습니다.

 

 

 

읽기, 쓰기, 수정하기, 삭제하기의 권한을 주기 위해 putPermissions를 정의합니다.

operations에서 read, create, update, delete를 allow로 설정해주었습니다.

object, type, caller도 필수로 작성해야 하는데 type은 반드시 db.kind로 설정해야 합니다.

 

 

 

데이터를 삭제하는 del method를 정의합니다.

query, from을 사용하여 kindID의 모든 데이터를 삭제합니다.

where를 사용하면 원하는 조건의 데이터만 삭제할 수도 있습니다.

 

더 자세한 내용은 webOS OSE사이트를 참고바랍니다. https://www.webosose.org/docs/reference/ls2-api/com-webos-service-db/#del

 

 

 

findDeviceHandler를 정의해줍니다.

데이터를 text로 화면에 나타냅니다. 

 

 

find method를 사용하여 원하는 데이터를 찾아낼 수 있습니다.

query, from과 함께 where를 사용하면 원하는 조건의 데이터만 불러올 수 있습니다.

이번 실습에서는 모든 데이터를 불러오기 위해 where를 주석처리 했습니다.

 

 

putDeviceHandler를 정의했습니다.

에러없이 성공했을 경우 findDevice를 합니다.

 

 

데이터를 추가하는 put method를 정의합니다.

kindID에 deviceName과 location은 입력한 값으로 status는 false로 추가합니다.

135-136코드는 입력칸을 비워주기 위해 추가해주었습니다.

 

  • 결과

 

데이터베이스에 deviceName이 각각 cosmos, comoss, cocomos인 기기를 추가했습니다.

각 기기는 room1, room2, room3에 위치해 있는 것을 확인할 수 있습니다.

 

디바이스의 이름과 위치를 입력하면 데이터가 데이터베이스에 저장되고, 데이터베이스를 화면에 나타낸다.

 

 

 

 

DeviceName과 Location의 값을 입력하여 데이터를 데이터베이스에 추가한 후 화면에 나타내는 과정을 동영상으로도 담아보았습니다.

 

이번 포스팅에서는 DB8의 기본 기능을 활용해보았습니다.

전체 코드도 첨부해드릴테니 참고하시길 바랍니다.

감사합니다:)

 

  • index.html 전체코드
더보기
<!DOCTYPE html>
<html>
<head>
<title>Example Web App - DB</title>
    <link rel="stylesheet" href="styles.css">
    <script src="main.js"></script>
</head>

<body>
    <h1> WebOS DB Example </h1>
    <div class="input-section">
        <div> Device Name </div> <input id="text-input-name" type="text"> <div></div>
        <div> Location </div> <input id="text-input-loc" type="text"> <div></div>
        <button onclick="putDevice()"> add </button>
    </div>
    <div id="item-text-field"></div>
</body>
</html>

 

  • main.js 전체코드
더보기
const kindID = "com.sample.db.owner:1";
const bridge = new WebOSServiceBridge();

window.onload = function() {
    putKind();
    putPermissions();
    emptyDB();
}

function putKind() {
    let url = 'luna://com.webos.service.db/putKind';
    bridge.onservicecallback = (msg) => {console.log(msg)};
    let params = {
        "id":kindID,
        "owner":"com.cosmos.sample.db",
        "indexes": [
            { 
                "name": "index0",
                "props": [
                    {"name": "deviceName"}
                ]
            },
            {
                "name": "index1",
                "props": [
                    {"name": "location"}
                ]
            },
            {
                "name": "index2",
                "props": [
                    {"name": "status"}
                ]
            }
        ]
    };
    bridge.call(url, JSON.stringify(params));
}

function putPermissions() {
    let url = 'luna://com.webos.service.db/putPermissions';
    bridge.onservicecallback = (msg) => {console.log(msg)};
    let params = {
        "permissions":[ 
            { 
               "operations":{ 
                  "read":"allow",
                  "create":"allow",
                  "update":"allow",
                  "delete":"allow"
               },
               "object":kindID,
               "type":"db.kind",
               "caller":"com.cosmos.sample.db"
            }
         ]
    };
    bridge.call(url, JSON.stringify(params));
}

function emptyDB() {
    let url = 'luna://com.webos.service.db/del';
    bridge.onservicecallback = (res)=>{console.log(res);};
    
    let params = {
        "query":{ 
            "from":kindID
        }
    };
    bridge.call(url, JSON.stringify(params));
}

function findDeviceHandler(res) {
    console.log(res);
    let results = JSON.parse(res).results;
    
    let text = '';
    for (let i in results) {
        text += `deviceName: ${results[i].deviceName} | location: ${results[i].location} | status: ${results[i].status} </br>`
    }
    document.getElementById('item-text-field').innerHTML = text;
}

function findDevice() {
    let url = 'luna://com.webos.service.db/find';
    bridge.onservicecallback = findDeviceHandler;
    
    let params = {
        "query":{ 
            "from":kindID,
            // "where":[ 
            //    { 
            //       "prop":"deviceName",
            //       "op":"=",
            //       "val":"CML001",
            //       "limit":10
            //    }
            // ]
        }
    };
    bridge.call(url, JSON.stringify(params));
}

function putDeviceHandler(res) {
    let response = JSON.parse(res);
    console.log(res);

    if(response.returnValue) {
        findDevice();
    }
    else {
        alert("Put device error.");
        console.log("Put device error.");
    }
}

function putDevice() {
    let url = 'luna://com.webos.service.db/put';
    bridge.onservicecallback = putDeviceHandler;
    
    let params = {
        "objects" : [
            {
                "_kind": kindID,
                "deviceName": document.getElementById('text-input-name').value,
                "location": document.getElementById('text-input-loc').value,
                "status": false
            }
        ]
    };
    bridge.call(url, JSON.stringify(params));
    
    console.log('putDevice', params);

    document.getElementById('text-input-name').value = '';
    document.getElementById('text-input-loc').value = '';
}