webOS Article/1. Web Application 개발하기

Enact를 이용하여 webOS web app 만들기 2

Ebo 2021. 7. 19. 17:57

 

*이 포스팅은 Enact 홈페이지를 참고하여 작성되었습니다. 

 

 

본격적인 Enact app 개발에 앞서


지난 시간에는 Enact로 개발환경을 setting하고 app을 build한 뒤 직접 webOS에 설치하여 실행하는 것까지 실습해보았습니다. 이번 시간에는 Enact 앱 개발의 더 많은 부분을 다룹니다.

 

 본격적인 Enact app 개발에 앞서, Enact가 무엇인지 제대로 이해하고 갈 필요가 있습니다.

 

1. What is Enact?

  • Enact란, React를 기반으로 구축된 사용하기 쉽고 성능이 좋으며 사용자 정의 가능한 앱 개발 프레임워크입니다. (React가 렌더링 library로 도입) React와 마찬가지로 JavaScript로 쓰이며, 견고하고 유지보수가 쉬운 App을 작성하기 위한 기본요소를 제공합니다. Enact만의 component가 다수 존재합니다.
  • 또한, Enact는 상호 운용성을 중요하게 생각합니다. open source framework로서, Enact의 components를 다른 프로젝트에서 사용 가능하며, 자바스크립트의 components를 Enact와 함께 사용할 수 있습니다.
  • 따라서, Enact는 다른 React library와 잘 동작하며, npm에서 많은 components들을 가져와 사용할 수 있습니다.
  • 더 자세한 내용은 Enact 컴포넌트의 호환 참고바랍니다.

2. Components

  • 다양한 API library가 존재합니다. core Library, i18n library, sandstone library 등 Enact는 이러한 컴포넌트를 cli 툴을 통해 매끄럽게 결합하여 개발자가 구현에 집중할 수 있도록 합니다.

 

API library 소개


1. core library

  • Enact 기반의 응용 프로그램을 위한 필수 요소로 구성된 라이브러리

 

2. i18n library

  • iLib을 기반으로 한 i18n(internationalization) 라이브러리

 

3. moonstone library

  • Smart TV에 사용되는 Enact 기반의 component로 구성된 라이브러리

 

4. sandstone library

  • Smart TV에 사용되는 Enact 기반의 component로 구성된 라이브러리

*moonstone library는 webOS 6.0 이전에, sandstone library는 webOS 6.0 이후 webOS TV에 적용된 컴포넌트입니다. 두 라이브러리 모두 webOS TV에 적용하기 위해 만들어진 라이브러리로 enact 개발자를 위해 제공됩니다. 

 

5. spotlight library

  • 5-way navigation과 focus control을 위한 라이브러리

 

6. UI library

  • 재사용 가능한 동작 세트와 Enact 테마를 만들기 위한 스타일이 정해지지 않은 요소로 구성된  라이브러리

 

7. webOS library

  • webOS가 올라가는 장치들을 위한 유용한 기능을 포함한 라이브러리

 

API library - sandstone Library


1. What is sandstone library?

  • sandstone library는, Enact의 TV 중심 UI 라이브러리입니다. 이는 대형 스크린을 위해 설계된 애플리케이션을 만들 수 있는 견고한 기반을 제공합니다. 50개 이상의 많은 components가 존재하여 애플리케이션 개발자에게 필요한 기능을 제공합니다.

2. sandstone library의 components 소개

sandstone library에는 많은 유용한 components가 존재합니다. 그 중에서 몇 가지를 소개합니다.

Enact에선 component를 적용한 효과를 미리 볼 수 있도록 sandstone sample을 제공합니다.이를 참고하여 필요한 기능을 확인할 수 있습니다. 

 

  • Button

Button 기능을 사용할 수 있도록 MainPanel.js에 아래의 코드를 추가합니다.

import Button from '@enact/sandstone/Button';

Button을 구현하는 코드입니다.

<Button>click me</Button>

Button 구현 및 속성 확인

Button을 클릭하면 ActionsonClick 속성이 적용되어 있는 것을 확인할 수 있습니다.

onClick 속성으로 Button 클릭하면 다음 동작을 하도록 정의합니다.

 

  • Dropdown

Dropdown 기능을 사용할 수 있도록 MainPanel.js에 아래의 코드를 추가합니다.

import Dropdown from '@enact/sandstone/Dropdown';

Dropdown을 구현하는 코드입니다.

<Dropdown
  inline
  title="Options"
>
  {['Option 1', 'Option 2', 'Option 3', 'Option 4', 'Option 5']}
</Dropdown>

Dropdown을 열고 닫으면 각각 onOpen, onClose 속성 실행

Option3 선택 시, onSelect, onClose 속성 실행

component마다 가지는 속성을 활용하여 원하는 기능을 구현할 수 있습니다.

 

  • Switch

Switch 기능을 사용할 수 있도록 MainPanel.js에 아래의 코드를 추가합니다.

import Switch from '@enact/sandstone/Switch';

Switch를 구현하는 코드입니다.

<Switch />​

Switch를 ON시키면 onToggle 속성의 selected: true


Switch를 OFF시키면 onToggle 속성의 selected: false

 

  • TimePicker

TimePicker 기능을 사용할 수 있도록 MainPanel.js에 아래의 코드를 추가합니다.

import TimePicker from '@enact/sandstone/TimePicker';

TimePicker를 구현하는 코드입니다.

<TimePicker value={new Date()} />

 


TimePicker는 현재 시간을 받습니다.


시간을 변경할 때마다 onChange 속성이 적용됩니다.

 

Sandstone library의 component 구현해보기 (실습)


1. sandstone library의 component 가져오기

sandstone library의 원하는 components를 사용하기 위해 import하여 가져옵니다.

MainPanel.js 파일에서 사용해줍니다. 코드 제일 윗줄에 모든 components을 import 하는 것이 좋습니다.

import kind from '@enact/core/kind';
import {Panel, Header} from '@enact/sandstone/Panels';
import Switch from '@enact/sandstone/Switch';
import Dropdown from '@enact/sandstone/Dropdown';
import TimePicker from '@enact/sandstone/TimePicker';
import Button from '@enact/sandstone/Button';

vscode 에서 사용하지 않은 component의 import코드는 다른 코드보다 밝기가 어둡게 나타납니다.

사용되지 않은 Button component

 

사용된 Switch component

 

실습에서 react의 useState와 MainPanel의 css파일 이 두 가지도 import하여 불러왔습니다.

import {useState} from 'react';
import './MainPanel.style.css'

 

2. 코드 구성

  • Switch on/off 함수 코드
function TextOnOff() {
	let [isSelected, isSelectedChange] = useState(false);
	return (
	   <>
	   <div>
		  <span>
			 <Switch onToggle={ (e)=>{isSelectedChange(e.selected); console.log(isSelected)}}/></span>
		  <span>
		  {  isSelected === true
			 ? <span>Turn On</span>
			 : <span>Turn Off</span>
		  }
		  </span>
	   </div>
	   </>
	);
 }

Switch 를 on/off일 때 다른 결과가 나타나게 하고싶어 함수로 만들어 사용하였습니다.

위의 내용에서 Switch에 onToggle 이벤트가 적용이 된다는 것을 알고 있습니다.

Switchselected기본상태가 false이고 Toggle이 되면 true가 됩니다.

이 원리를 이용해 onToggle 이벤트State를 사용하여 Switch 가 꺼지고 켜질 때 다른 문구가 나오도록 함수를 만들었습니다.

 

  • Dropdown 사용 코드
<Dropdown
		className = "down"
		defaultSelected={0}
		inline
		title="공간을 선택하십시오 (Light)">
		{['거실', '안방', '침실1', '침실2', '부엌', '서재']}
</Dropdown>

defaultSelected 는 Dropdown의 배열 중 처음 나타나게 되는 기본값을 선택하는 속성입니다.

0부터 시작합니다. ex) 거실이 기본값 : defaultSelected={0}, 침실1이 기본값 : defaultSelected={2}

위의 내용에서 Dropdown에 onOpen, onClose, onSelect 이벤트가 적용된다는 것을 알 수 있습니다.

그리고 dataselected에는 각각 array의 값과 번호가 저장되어 있습니다.

세 개의 이벤트와 data, selected 값을 불러와 사용하면 더 응용된 코드도 만들 수 있습니다.

 

 

 

  • TimePicker 사용 코드
<TimePicker 
		defaultValue = {new Date()}
		label = {"webOS's Time"}
/>

위의 내용에서 TimePicker 에는 onChange 이벤트가 적용될 수 있습니다. 

그리고 value에 시간값이 저장이 됩니다.

onChange 이벤트value값을 받아와 사용하면 더 응용된 코드도 만들 수 있습니다.

 

  • 전체 코드 (MainPanel.js)
import kind from '@enact/core/kind';
import {Panel, Header} from '@enact/sandstone/Panels';
import Switch from '@enact/sandstone/Switch';
import Dropdown from '@enact/sandstone/Dropdown';
import TimePicker from '@enact/sandstone/TimePicker';

function TextOnOff() {
	let [isSelected, isSelectedChange] = useState(false);
	return (
	   <>
	   <div>
		  <span>
			 <Switch onToggle={ (e)=>{isSelectedChange(e.selected); console.log(isSelected)}}/></span>
		  <span>
		  {  isSelected === true
			 ? <span>Turn On</span>
			 : <span>Turn Off</span>
		  }
		  </span>
	   </div>
	   </>
	);
 }

 function ReserveOnOff() {
	let [isSelected, isSelectedChange] = useState(false);
	return (
	   <>
	   <div>
		  <span>
			 <Switch onToggle={ (e)=>{isSelectedChange(e.selected); console.log(isSelected)}}/></span>
		  <span>
		  {  isSelected === true
			 ? <span>Reserve On</span>
			 : <span>Reserve Off</span>
		  }
		  </span>
	   </div>
	   </>
	);
 }

const MainPanel = kind({
	name: 'MainPanel',
	
	render: (props) => (
		<Panel {...props}>
			<Header title="COSMOS IoT Dashboard" />
			<div className="main-container">
				<div className="temp-box box-three">
					<div>
						<Dropdown
							className = "down"
							defaultSelected={0}
							inline
							title="공간을 선택하십시오 (Light)">
							{['거실', '안방', '침실1', '침실2', '부엌', '서재']}
						</Dropdown>
					</div>
				</div>
				
				<div className="temp-box box-four">
					<div>
						<TextOnOff></TextOnOff>
					</div>
					<div>
						<ReserveOnOff></ReserveOnOff>
					</div>
					<div className="time-picker">
						<TimePicker 
							defaultValue = {new Date()}
							//value = {new Date()}
							label = {"webOS's Time"}
						/>
					</div>
				</div>

			</div>
		</Panel>
	)

	
});

	



export default MainPanel;

 

  • css 코드 (MainPanel.style.css) *참고*
.main-container {
    margin: auto;
    display: grid;
    grid-template-columns: 40% 60%;
    gap: 10px; /* 구역간의 간격 */
  }
  .temp-box {
    width: 100%;
    height: 100%;
    font-size: 40px;
    border: 1px solid #dee3eb;
  }
  .box-three {
    padding-top:100px;
    display: flex;
    flex-direction: column; /* 세로 정렬 */
    border: none; /* border를 지우고 3-1과 3-2에 각각 border를 적용해줍니다. */
  }
  .box-four {
    padding-top:100px;
    display: flex;
    flex-direction: column;
    border: none;
    
  }
  .box-four > div:first-child {
    flex: 1;
    margin-bottom: 20px;
  }

  .box-four > div:last-child {
    flex: 1;
    margin-bottom: 20px;
  }

  .time-picker {
      margin-top: 100px;
      margin-left: 30px;
  }

 

3. 구현 결과

  • Switch on/off

Switch off (기본)
Switch on (Toggle 한번)

 

  • Dropdown

Dropdown 기본 상태
Click 시 화면
Click 과 변경

 

  • TimePicker

TimePicker 기본 상태
TimePicker 값 변경 시 화면

 

전체 결과

전체 결과 (전체 화면)
전체 결과 (반 화면)