https://m.blog.naver.com/metooneis/221205368477
'공부 > 맥|OSX' 카테고리의 다른 글
[펌]nwjs를 통한 하이브리드 데스크탑 어플리케이션 만들기 (0) | 2016.12.19 |
---|---|
맥 파인더(Finder)와 서버 연결 (0) | 2013.08.12 |
맥 OSX 에서 NDK PATH설정하기 (0) | 2013.08.02 |
https://m.blog.naver.com/metooneis/221205368477
[펌]nwjs를 통한 하이브리드 데스크탑 어플리케이션 만들기 (0) | 2016.12.19 |
---|---|
맥 파인더(Finder)와 서버 연결 (0) | 2013.08.12 |
맥 OSX 에서 NDK PATH설정하기 (0) | 2013.08.02 |
nwjs를 이용하여 작동되는 웹사이트를 데스크탑 어플리케이션처럼 만드는 방법에 관해서 소개를 해봅니다. 우리가 이 글에서 논하고자하는 것은 웹기술을 이용하여 독립된 어플을 만드는 일반적인 SPA형 어플리케이션이 아니라, 그냥 웹서비스로 접속해도 되는 것을 단순하게 어플리케이션으로 랩핑만하여 제공하는 것에 대한 이야기입니다.
'어차피 브라우저를 통해서 접속하면 되는 것을 굳이 어플리케이션처럼 만들어서 뭐가 좋은가?'라고 할 수 있습니다. 사실 이미 만들어진 것을 랩핑하는 것이라서 환경을 셋팅하는 것 이외에는 그다지 힘이 들지 않습니다. 하지만 단순하게 랩핑하는 것만으로도 아래와 같은 많은 장점들이 있습니다.
웹 서비스를 런칭한 이후에는 우리는 많은 광고비를 뿌려 구글과 페이스북에서 사용자들을 유입시키려 노력합니다. 그럼에도 불구하고 웹서비스는 영원히 접근할 수 없는 앱 마켓라는 벽이 존재합니다. 아직까지 윈도우스토어는 활성화되어 있지 않지만 OSX의 경우에는 앱마켓의 접근성이 좋아서 많은 분들이 사용합니다. nwjs를 통해서 랩핑을 하는 경우에 이와 같은 마켓에 등록하여 마케팅 채널을 하나 확보하는 셈이 될 수 있습니다. 와 공짜 마케팅이다
익스플로러 최신버전은 HTML5나 CSS3 스펙을 무리없이 사용가능합니다. 그러나 아직까지 한국에서는 많은 사용자들이 익스플로러 엣지 이전버전을 사용하기 때문에, 웹서비스를 지속적으로 제공함에 있어서 의식할 수 밖에 없는 문제들이 있습니다. 죽어라 익스플로러!! 조삼모사같이 느껴질 수도 있지만, 이러한 고객분들에게 nwjs로 랩핑된 데스크탑 어플리케이션 설치를 유도하면 자연스럽게 지속적으로 웹키트 엔진으로의 사용을 유도하게 됩니다.
독립된 프로그램처럼 작동한다는 것은 곧 작업표시줄에서 브라우저안에 탭으로 존재하는 다른 서비스와 다르게 직접적인 접근성을 확보할 수 있다는 이야기가 됩니다. 창이 따로 논다는 것은 사용자의 활용도에 따라 여러가지로 이점을 제공합니다. 가상 화면을 통해서 하거나 단축키를 통해서 사용되어질 수도 있고, 특정 창크기로 고정하여 사용하게될 수도 있습니다.
브라우저상에서 동작하도록 설계된 원래의 웹사이트 목적상, 아무래도 랩핑한 프로그램에서 네이티브 API를 많이 활용하지는 않을 것입니다. 그래도 조건부라도 마음만 먹으면 활용할 수 있으니 일단 장점에 포함된다 생각합니다. nwjs가 활용할 수 있는 네이티브의 목록은 여기
에 있습니다.
랩핑을 하는 최초의 과정 이외에 추가적으로 드는 비용이 거의 제로에 가깝습니다. nwjs 전용으로 모든 정적 리소스들을 사용하는 경우라면 조금 다를지 모르겠습니다. 그런데 실제로 돌아가는 사이트를 랩핑하는 것은 모든 자원을 원격에서 끌어와서 동작시키는 것이라, 사실상 이 프로그램은 우리의 웹사이트 하나만을 띄우는 전용 브라우저가 되는 셈이 됩니다.
이전에는 Node-Webkit이라고 불리었으며, 요새 유행하는 Electron(aka atom-shell)과 비슷하게 Chromium과 Node.js 기반에 데스크탑 어플리케이션에서 웹을 구동할 수 있는 좋은 도구입니다. 그래서 데스크탑에서 실행하는 어플리케이션에다가 기존 웹 개발 방법대로 설계 코딩할 수 있습니다.
NWJS vs Electron 에서 둘을 비교한 표를 볼수 있습니다. 간단히 살펴보면,
최초에는Electron을 이용하여 제작을 시도하였으나, Electron의 webview
를 썼을 때에 기본 자바스크립트의 confirm
, alert
, prompt
, beforeunload
등이 정상적으로 작동되지 않는 문제점이 있었습니다. 즉, 웹브라우저라면 당연히 되어야하는 스펙들이 Electron Webview에서는 알게모르게 제한이 되는 경우가 있습니다. 분명 안되는것이 더 많겠지만 이쯤에서 깔끔하게 포기하고 nwjs로 돌아서서 더 이상은 모르겠습니다. Electron이 대세인 느낌은 있지만 이렇게 랩핑을 하는 목적으로는 적합하지 않았습니다.
항상 개발 처음 시작할 때 디렉토리 구조를 어떻게 잡을까 부터 고민을 하여 보일러플레이트를 참고하거나 자신만의 구조를 잡기 마련입니다. 저희는 처음 해보는 부분이라 보편적인 디렉토리 구조를 따랐습니다.
NWJS는 아래 예시와 같이 production 배포 부분과 빌드하기 위한 부분을 나뉘어 구조를 잡는게 편합니다. 왜냐하면 빌드에 필요한 node modules이나, resources나 그외 빌드 관련 소스들은 production에 포함되지 않아도 상관없기 때문입니다.
주요 부분
이외 특이한점은 package.json
가 빌드 디렉토리와 production 디렉토리에 각각 한개씩 존재합니다. 이는 node module 설치를 다르게 하고, NWJS Config 설정, 빌드 스크립특 작성등 각 용도에 맞게 분기 시키기 위함입니다.
iframe
으로 호출loaded
)와 Native Window Event Handler(close
) 등록기존 서비스중인 tyle.io를 iframe
으로 호출
// etnry point HTML에 iframe 쓰던 방식 적용
<iframe src="https://tyle.io" id="tyle" ></iframe>
상단에 Native Menu Bar를 설정
var MenuItems = {
"darwin" : { //mac
"history" : [ // menu label
{
label : '뒤로', click : function(){ window.history.back(); }, key: '[', modifiers: 'cmd'
},
{
label : '앞으로', click : function(){ window.history.forward(); }, key: ']', modifiers: 'cmd'
},
{
label : '새로고침', click : function(){ document.getElementById('tyle').contentDocument.location.reload(true); }, key: 'R', modifiers: 'cmd'
}
]
},
"win" : { //window
"history" : [ // menu label
{
label : '뒤로', click : function(){ window.history.back(); }, key: '[', modifiers: 'ctrl'
},
{
label : '앞으로', click : function(){ window.history.forward(); }, key: ']', modifiers: 'ctrl'
},
{
label : '새로고침', click : function(){ document.getElementById('tyle').contentDocument.location.reload(true); }, key: 'R', modifiers: 'ctrl'
}
]
}
}
// Menu 생성
var addMenu = function(){
var topMenu = new nw.Menu({type: "menubar"});
// mac이랑 winodw,linux는 다른 menu 프로세스를 제공하기 위해 또 Menubar 객체를 할당
var menuBar = topMenu;
//darwin===mac 이고, 따로 menubar를 생성 후에 시작.
if(process.platform === 'darwin'){
topMenu.createMacBuiltin("tyle");
menuBar = win.menu = topMenu;
}
// menuItems' 에서 메뉴들을 가져와 등록.
for (var menuKey in MenuItems) {
if (MenuItems.hasOwnProperty(menuKey)) {
var submenu = new nw.Menu();
MenuItems[menuKey].forEach(function(menuItem){
submenu.append(new nw.MenuItem(menuItem));
});
menuBar.append(new nw.MenuItem({
label : menuKey,
submenu : submenu
}));
}
}
// window,linux 는 따로 menu를 window에 등록.
if(process.platform !== 'darwin'){
win.menu = menuBar;
}
}
Window Event(loaded
)와 Native Window Event Handler(close
) 등록
window ifrmae이 호출 된 이후 loaded 이벤트가 호출 됩니다. (
dom ready
랑 비슷 합니다.)
Native Window 를 닫으면 close 이벤트가 호출 됩니다.
var nw = require('nw.gui');
// 이벤트 정의
var BrowserEvent = {
evtList : ['close','loaded'],
close : function(){},
loaded : function(){}
}
// 필요한 이벤트들 NW.GUI를 통해 등록
var addEvent = function(){
BrowserEvent.evtList.forEach(function(evt){
nw.Window.get().on(evt, BrowserEvent[evt]);
},this);
}
Mac(x64)용 dmg, Window(x64,32)용 MSI installer 생성(Linux 제외)
Grunt-nw-builder를 참고하고, nw-builder 레퍼런스와 비슷합니다.
grunt-nw-builder
는 grunt
기반으로 만들어진 nw-builder
모듈로써 nwjs를 빌드 패키징 작업을 통해서 저희가 실제로 데스크탑 어플리케이션 APP을 생성시켜주며, 인스톨러도 만들어줍니다. 또한 msi-pacakger
는 빌드된 결과물을 window installer로 만들어줍니다.
module.exports = function(grunt) {
grunt.initConfig({
nwjs: {
options: {
name : 'tyle',
platforms: ['osx64','win64'],
macIcns : './src/resources/osx/tyle_logo_electron.icns',
winIco : './src/resources/windows/tyle_logo_electron.ico',
cacheDir : './.cache',
buildDir: './build',
flavor: 'normal',
zip : true,
zipOptions : {
forceLocalTime : true,
comment : "tyle.io desktop app window version"
},
macPlist: {
CFBundleDevelopmentRegion: "ko",
CFBundleDisplayName: "tyle",
CFBundleName: "tyle",
}
},
src: './src/**/*' // Your NW.js app
},
appdmg: {
options: {
basepath: './',
title: 'tyle-mac',
icon: 'src/resources/osx/tyle_logo_electron.icns',
background: 'resources/osx/dmg-background.png',
contents: [
{x: 370, y: 160, type: 'link', path: '/Applications'},
{x: 140 , y: 160, type: 'file', path: 'build/tyle/osx64/tyle.app'}
]
},
target: {
dest: 'build/tyle/osx64/tyle-mac.dmg'
}
}
});
grunt.loadNpmTasks('grunt-nw-builder');
grunt.loadNpmTasks('grunt-appdmg');
grunt.registerTask('default', ['nwjs','appdmg']);
};
// window msi installer
var createMsi = require("msi-pacakger");
var options = {
// required
source: '~/tyle-nw/build/tyle/win64',
output: '~/tyle-nw/build/tyle/msi',
name: 'tyle',
upgradeCode: 'YOUR-GUID-HERE',
version: '1.0.0',
manufacturer: 'loopjs.com',
iconPath: '~/tyle-nw/src/resources/windows/tyle_logo_electron.ico',
executable: 'tyle.exe',
// optional
arch: 'x64',
localInstall: true
}
createMsi(options, function (err) {
if (err) throw err
console.log('Outputed to ' + options.output)
})
어플리케이션 종료 후 열때 종료할때 window size 로 resizing
window를 종료할 경우 close 이벤트에서 현재 종료창의 사이즈를 로컬 저장소에 json file
로 저장합니다. 그리고 다시 앱을 열었을 때 기존에 저장해놓은 사이즈를 가져와 window를 리사이징을 진행 하는 방식입니다.
tyle.windowSize = (function(){
var jetpack = require('fs-jetpack');
var win = require('nw.gui').Window.get();
var pjson = require('./package.json');
// window size를 저장할 공간(directory) 설정
var userDataDir = jetpack.cwd(nw.App.dataPath);
var stateStoreFile = 'window-state-tyle.json';
// 기본 window size (package.json 에서 가져온다)
var defaultSize = {
width : pjson.window.width,
height: pjson.window.height
};
// 상태 저장 객체
var state = {};
/*
저장된 window size 반환
*/
var restore = function(){
var restoredState = {};
try{
restoredState = userDataDir.read(stateStoreFile, 'json');
}catch(err){
}return Object.assign({}, defaultSize, restoredState);
}
/*
현재 window size 구하기
*/
var getCurrentPosition = function(){
return {
width : win.width,
height : win.height
}
}
/*
현재 window size 저장
*/
var saveState = function(){
Object.assign(state, getCurrentPosition());
userDataDir.write(stateStoreFile, state, {atomic : true});
}
/*
생성된 window resizing 하
*/
var resize = function(){
var resize = restore();win.width = resize.width;
win.height = resize.height;
}
return {
restore : restore,
save : saveState,
resize : resize
}
})();
위 요구사항에 맞게 개발을 진행하면 아래와 같이 기본적인 골격을 갖추게 됩니다. 전반적인 소스를 공유하진 않았지만, 큰 틀에서 벗어나지 않은 것이기 때문에 쉽게 적용할 수 있습니다.
iframe 방식으로 기존에 개발해놓은 웹을 그대로 가져다 쓸수있고 설치방식과 Chromium 기반이기 때문에 IE에서 겪던 문제를 해결 할 수 있는 좋은 기회를 가질 수 있습니다.
자 다들 시작 해보시죠?
위에 기술하였듯이 랩핑하는 것만으로 많은 효과들이 있습니다. 하지만 보다 이질감이 없는 사용자 경험을 위하여 데스크탑 어플과 같은 빠른 반응속도를 보장하여야합니다. 전통적인 페이지 리다이렉션으로 인해서 버튼 클릭마다 blank 화면이 번쩍거린다면 사용자로 하여금 내가 가짜 앱을 사용하고 있다고 느끼게 하기 때문이지요.
따라서 Single Page Application으로 제작하여 Spinner가 표시되더라도 UI가 사용자 행동에 즉각 반응하는 것이 좋고, 페이지 리다이렉션이라면 pjax
등을 통하여 어떻게든 빠른 반응이 나타나도록 하는 것이 좋습니다(참고 : https://blog.tyle.io/posts/52)
[출처 : https://blog.tyle.io/posts/67, https://nwjs.io/]
Adobe CC 크랙(2018) (2) | 2018.07.17 |
---|---|
맥 파인더(Finder)와 서버 연결 (0) | 2013.08.12 |
맥 OSX 에서 NDK PATH설정하기 (0) | 2013.08.02 |
apt-get install netatalk
nano /etc/netatalk/afpd.conf
add this line
- -tcp -noddp -uamlist uams_dhx.so,uams_dhx2_passwd.so -nosavepassword -setuplog "default log_info /var/log/afpd.log"
nano /etc/netatalk/AppleVolumes.default
~/ "Home Directory"
=>
~/ "$u@$h"
service netatalk restart
Adobe CC 크랙(2018) (2) | 2018.07.17 |
---|---|
[펌]nwjs를 통한 하이브리드 데스크탑 어플리케이션 만들기 (0) | 2016.12.19 |
맥 OSX 에서 NDK PATH설정하기 (0) | 2013.08.02 |
필요 사항
OS : OSX 10.7 이상 Lion
시작 합니다. ~
1. http://developer.android.com 에서 Download 항목을 클릭 합니다.
2. NDK 항목을 선택하고, 오른쪽에서 Mac OS X 항목을 클릭 하여 자료를 다운받습니다.
3. 받은 자료를 적당한 곳에 압축을 풀어 둡니다.
4. 터미널을 열어서 자신의 홈디렉토리에 .bash_profile 이 있는지 확인합니다.
( ls -al 명령을 치면 리스트가 나옵니다. 저는 없네요^^)
5. 있든 없든 일단 vi .bash_profile 이라고 입력합니다.
6. 편집 화면이 나오는데 빈화면인 사람은 ~ 표시들만 있고 빈화면 일 테고, 파일이 존재하는 사람은 export PATH=${PATH}:블라블라:블라블라 라고 되어 있을 겁니다.
(기본 vi 입력 방법 - i키를 누르면 입력을 하실 수 있습니다. 입력을 다 하셨으면 esc 키를 눌러 입력을 끝을 냅니다. :wq 를 입력하면 (w:write , q:quit) 저장하고 밖으로 나가실 수 있습니다.)
6.1 화면에 아무것도 없다면, export 부터 끝까지 다 쳐줍니다.
기본은 export PATH:${PATH}: 여기까지 입니다. 그 뒤는 아까 다운로드 받은 ndk의 주소입니다.
아래는 제 NDK가 설치되어 있는 주소입니다.
6.2 화면에 export 가 있으신 분은 맨 뒤에 :/ndk 주소/를 넣어주시면 되겠습니다.
7. 이제 ls -al 명령으로 제대로 만들어졌는지 확인을 해봅시다. 저는 잘 생성되었네요~
8. 이제 적용을 해봅시다. source .bash_profile 을 입력하여 path가 적용되도록 합시다.
9. 이제 완성입니다. ndk-build 를 입력하여 어느 곳에서나 잘 동작하는지 확인해봅니다.
출처 : http://blog.naver.com/hello20/150136506664
[출처] [Android] OSX에서 NDK Path 설정하기|작성자 옹식이
Adobe CC 크랙(2018) (2) | 2018.07.17 |
---|---|
[펌]nwjs를 통한 하이브리드 데스크탑 어플리케이션 만들기 (0) | 2016.12.19 |
맥 파인더(Finder)와 서버 연결 (0) | 2013.08.12 |