NOTE: 우리는 이 프로젝트를 지난 일요일 FOSDEM에서 발표했습니다. 하지만 모든 사람이 브뤼셀(Brussels)에 있었던 것은 아니기 때문에 node-firefox가 무엇이고 어떻게 Firefox OS 앱 개발의 모든 것!을 도울 수 있는지 설명하기 위해 이 글을 작성합니다.
모질라는 항상 개발자들의 삶을 편하게 할 수 있는 방법을 찾고 있습니다. 앱 개발을 희망하는 사람들이 Open Web Apps 개발 시작 절차가 다소 번거롭다고 하는 이야기를 듣고, 우리는 App Manager를 좀 더 초보자에게 친절한 환경으로 만드는 작업을 시작했습니다. 그리고 그 결과는 순차적으로 WebIDE에 반영되었습니다. WebIDE는 손이 많이 가고 번거롭던 일들을 쉽게 만들었습니다. 그러니까 새로운 앱을 만들고, 시뮬레이터를 다운로드해서 설치하고, 앱을 디버깅하는 일들 말입니다.
그런데 세상에는 다른 종류의 개발자들도 있습니다. 파워 개발자들 말입니다! 파워 개발자들은 이미 node.js 기반의 빌드 툴체인(toolchain)을 갖고 있습니다. 그들은 애셋(asset)을 최적화하고, 코드의 문법을 검사하고(code hinting), 테스트를 실행하기 위한 툴체인을 이미 갖고 있습니다. 파워 개발자들은 종종 Browserify 같은 툴도 사용합니다. 그리고 아마 JavaScript를 작성하지 않고 대신 CoffeeScript 같은 대체 언어를 사용할지도 모릅니다. 이런 도구들을 사용하려면 앱이나 웹사이트를 당신의 디바이스에 밀어넣거나 브라우저에서 리로드하기 전에 사전 빌드 과정을 거쳐야 합니다.
원칙적으로 모질라는 파워 개발자들에게 그들이 사랑하는 커맨드라인 (또는 에디터 쇼트컷!)을 버리고 WebIDE로 전향해서 앱을 설치할 때 버튼을 클릭한 다음 다시 그들의 에디터로 복귀하는 방법을 쓰라고 말해왔습니다. 그러면 파워 개발자들은 입을 모아 이렇게 대답했습니다. “우리는 클릭하는 것이 싫습니다! 우리는 터미널이 좋아요!”
어떻게 하면 좀 더 효율적으로 일할 수 있을까요?
사람들은 우리가 제안한 방법을 좋아하지 않았습니다. 왜냐하면 이 방법은 암묵적으로 컨텍스트 전환을 의미하기 때문입니다. 컨텍스트를 전환하는 것은 비효율적입니다. 우리는 엔지니어입니다. 만약 엔지니어가 새로운 것 만드는 것보다 더 좋아하는 무엇이 있다면 그것은 아마도 프로세스를 최적화하고 자연스럽게 만드는 것일 겁니다.
우리는 이미 빌드 스크립트를 갖고 있기 때문에, 우리의 앱을 Firefox 런타임 위에 올리기 위해 남은 필요한 단계는 단지 배치(deploying) 뿐입니다. 그리고 그것이 WebID의 용도입니다. 그래서 우리가 해야 하는 질문은 아마도 이것일 겁니다. “WebIDE가 배치(deploying)를 위해 하는 일을 프로그램적으로 실행시킬 수 있을까요?”
서버와 액터 (Servers and actors)
모든 Firefox 런타임은 remote debugger server라고 불리는 속성을 갖고 있습니다. 이 속성은 디폴트로 활성화되어 있지 않습니다. 명백한 보안 문제가 있기 때문입니다. 하지만 일단 활성화되면 클라이언트는 이것에 연결해서 다양한 기능을 이용할 수 있습니다. 예를 들어 앱을 설치하고, 콘솔을 이용하는 것 말이죠. 그리고 바로 이것이 WebIDE가 내부적으로 하는 일입니다.
이 기능들 각각은 액터(actor)에 의해 제공됩니다. 예를 들어, 우리가 설치된 앱(app) 목록을 나열한다고 가정해봅시다. 우리는 아마도…
- 먼저 webApps 액터를 검색할 것입니다
- 그리고 getAll 명령을 실행할 것입니다
- 그러면 앱 목록을 응답으로 얻게 될 것입니다
또 다른 예로 패키지드 앱을 설치하는 절차를 들 수 있습니다. 그 절차는 다음과 같습니다.
- 먼저 앱 컨텐츠를 zip 압축합니다. 당신이 원하는 어떤 라이브러리를 사용해도 상관 없습니다
- 그리고 나서 webApps 액터를 검색합니다
- ZIP으로 묶은 파일을 컨텐츠로 이용해서 webApps 액터에 있는 uploadPackage 명령을 호출합니다
- 이 명령의 호출 결과는 File 액터입니다
- 이 때 반환된 File 액터를 인자로 webApps 액터에 있는 install 명령을 호출합니다
- 끝났습니다!
그러므로 앱 설치에 관한 모든 마술은 WebIDE에 존재하는 것이 아닙니다. 마술은 서버(server)에 존재합니다! 우리는 이 마술을 프로그램적으로 이용할 수 있습니다. 하지만 클라이언트를 바닥부터 만들자면 TCP 커넥션을 만들고 패킷을 파싱해야 합니다. 아마도 당신은 이런 일을 하고 싶지 않을 것입니다. 당신이 원하는 것은 앱을 만들고 디바이스에 설치하는 것 뿐입니다!
실망하지 마세요. node-firefox가 이런 일을 대신 해줍니다. node-firefox는 단단한 코드 덩어리가 아닙니다. node-firefox는 일련의 node.js 모듈들입니다. 각 모듈은 각기 다른 타스크(task)를 담당하며 분리된 레파지토리를 통해 제공됩니다. 그리고 다른 선량한 모듈들과 마찬가지로 npm registry를 통해 배포됩니다. 당신이 작성하는 스크립트나 타스크 실행기가 필요로 하는 만큼 node-firefox 모듈을 가져다 쓸 수 있습니다. 그래서 당신은 결국 커맨드라인 환경을 벗어나지 않고도 앱을 빌드하고 실행시킬 수 있습니다.
말만 하지말고, 보여주세요
말로 설명하는 것은 여기까지 하겠습니다. 이제 어떻게 시뮬레이터를 시작하는 스크립트를 작성하는지 살펴봅시다!
먼저 npm을 이용해서 당신의 프로젝트에 모듈을 설치합니다.
npm install --save node-firefox-start-simulator |
그리고 다음과 같이 스크립트를 작성합니다.
var startSimulator = require('node-firefox-start-simulator'); startSimulator({ version: '2.2' }) .then(function(simulator) { console.log('Listening in port', simulator.port); }); |
이게 전부입니다! 단지 몇 개의 라인만으로 버전 2.2 시뮬레이터를 실행시킬 수 있습니다. 만약 특정 버전을 적시할 필요가 없다면, startSimulator 명령을 호출할 때 옵션을 전달하지 마세요. 그러면 가장 먼저 발견되는 시뮬레이터가 구동될 것입니다.
startSimulator().then(function(simulator) { // 당신의 코드 }); |
또 보여드릴 것이 있습니다. 이제 node.js 스크립트로 시뮬레이터를 실행시키고, 앱을 설치하고 실행시키는 것을 볼 것입니다.
이 예제를 위한 코드는 실제로는 node-firefox-uninstall-app 모듈을 위한 예제입니다. node-firefox 모듈들 각각은 examples 폴더를 갖고 있습니다. examples 폴더를 살펴보면 조금 더 빨리 작업을 시작할 수 있을 것입니다.
처음 이야기했던 것처럼, 앱 개발을 시작하려는 많은 수의 웹 개발자들은 자기가 쓰던 타스크 실행기를 계속 쓰고 싶어 합니다. 그래서 우리는 node-firefox를 gulp와 함께 사용하는 예제 코드도 작성했습니다.
default-one 타스크를 실행시켜 봅시다. 이 타스크는 시뮬레이터를 구동시키고, 앱을 설치합니다. 그리고나서, 약간 도전적인 시도인데, CSS가 변경되는지 계속 관찰합니다. 당신이 앱의 스타일쉬트를 조금이라도 수정하고 저장하면 파일 감시자가 변경 사실을 인지해서 새 파일을 Firefox 런타임에 전달할 것입니다. 그러면 바뀐 파일이 즉시 반영됩니다. 앱을 중단시키거나 통채로 다시 설치하고 다시 실행시킬 필요가 없습니다. 제가 배경을 진한 군청색에서 유행을 타지 않는 멋진 Paul Rouget 핑크색으로 바꾸는 것을 보세요!
라이브 CSS 리로딩은 UI 인터페이스를 빌드하면서 실험하는 정말 훌륭한 방법입니다. 앱을 리로드해서 레이아웃을 조정할 특정 페이지로 찾아갈 필요가 없기 때문에 많은 시간이 절약됩니다. 제가 예전에 안드로이드 앱을 개발했을 때 이런 기능이 있었으면 얼마나 좋았을까요!
이것이 전부가 아닙니다. default-all 타스크는 default-one 타스크와 같은 작업을 수행합니다. 하지만 당신 시스템에 설치된 모든 시뮬레이터들을 대상으로 작업을 수행합니다. 그래서 당신은 CSS 수정 결과를 여러개의 시뮬레이터들에서 동시에 확인할 수 있습니다.
불행히도 2.1과 2.2 시뮬레이터에는 버그가 있습니다. 두 시뮬레이터는 스타일쉬트가 변경되어도 앱을 리로드하지 않습니다. 하지만 이 버그는 이슈 트래커에 등록되었고 고쳐질 것입니다.
여기까지, 그래서 우리가 할 수 있는 일은 무엇인가요?
현재의 모듈들로 당신은 런타임(runtime)이 리스닝(listening)하고 있는 포트(port)를 찾는 일, 시뮬레이터를 찾아서 구동시키는 일, 런타임에 커넥트(connect)하는 일, 앱을 찾는 일, 앱을 인스톨하는 일, 앱을 언인스톨하는 일, 앱을 실행시키는 일, 그리고 스타일쉬트를 리로드(reload)하는 일을 할 수 있습니다.
철학
이미 어떤 패턴을 눈치 챘을지도 모르겠습니다. 하지만 정황이 불충분한 경우를 위해 설명하자면, 우리는 의도적으로 작은 모듈을 만들려고 노력합니다. 각 모듈은 단지 한가지 액션(action)만 수행하고, Promise를 리턴하고, 가능한 적은 의존관계(dependencies)만 이용합니다.
작은 모듈이 이해하기 쉽고, 사용하기 쉽고, 테스트하기 쉽습니다. 또, 미래에 있을 대부분의 Web API들이 Promises를 활용하도록 설계되어 있습니다. 우리는 과거지향적이 아닌 미래지향적인 코드를 작성하고 싶습니다. 또, 의존관계를 줄이면 새로운 사람들이 모듈 개발에 기여하는 활동을 시작하기가 수월해집니다. 이해해야 하는 낯선 엘리먼트의 숫자가 줄어들기 때문입니다.
마지막으로, 모든 모듈들이 같은 방식으로 동작하기 때문에 어떤 한 모듈의 사용법을 익히면 다른 모듈들도 같은 방식으로 사용할 수 있습니다. 바뀌는 것은 단지 파라메터와 결과 뿐입니다.
궁극적인 지향점 (또는: 아직 할 수 없는 일들)
미래에 가능해지기를 희망하는 목표 기능이 몇개 있습니다. 사람들은 그것을 목표 기능이라고 부르지만, 저는 그것을 ‘궁극적인 지향점(dream ideas)’이라고 부릅니다.
반복적으로 언급되는 것들 중 하나는 WebCLI: WebIDE의 대체품입니다. WebCLI를 이용하면 WebIDE로 할 수 있는 모든 일을 커맨드라인 환경에서 처리할 수 있습니다. 개인적으로는 “이것은 훌륭한 아이디어야”라는 생각과 “이것은 전혀 필요하지 않을지도 몰라. 그냥 타스크들을 처리할 수 있는 라이브러리만 있으면 충분하잖아”라는 생각들 사이에서 계속 갈팡질팡하고 있습니다. 하지만 많은 사람들이 이 아이디어를 좋게 보고 있습니다. 그러니까 나쁜 아이디어는 아닐 것입니다!
또다른 목표 기능은 커맨드라인에서 실행되어서 방금 비정상 종료(crash)된 앱에 DevTools 디버거를 연결하는 기능입니다. 커맨드라인에서 앱을 실행시키는 것은 멋진 일입니다. 하지만 커맨드라인 디버거는 그다지 멋지지 않습니다! 양쪽 세상의 최고의 것을 골라 쓰지 않을 이유가 있을까요?
또 커맨드라인에서 모든 브라우저를 조종하는 기능도 편리할 것입니다. Valence를 통해 인터페이스하는 거죠!
그리고 마지막으로, 제가 정말 바라는 목표 기능이 있습니다. Firefox OS의 커스텀 에디션 입니다. 우리가 스크립트를 통해서 텅빈 Firefox OS 토대 위에 개인적인 취향에 따라 앱들과 설정들을 추가해서 완전한 Firefox OS 이미지를 만들고 디바이스에 구워넣을 수 있다고 생각해봅시다. 이때 이용하는 것은 커다란 바이너리 파일이 아니라 단지 스크립트입니다. 그렇기 때문에, 레파지토리를 통해 쉽게 배포할 수 있습니다. 그러면 다른 사람들이 배포된 스크립트를 기반으로 자신만의 또다른 Firefox OS 에디션을 만들 수도 있을 것입니다.
어떻게 하면 더 멀리 갈 수 있을까요?
아직 가야할 길이 멉니다. 그리고 여러 영역에 걸쳐 할 일이 많이 있습니다. 아마도 가장 시급한 일은 멀티플랫폼을 지원하는 것일 겁니다. 현재 우리는 네트워크를 통해서만 런타임과 상호작용할 수 있습니다. 그리고 물리적인 디바이스와는 상호작용할 수 없습니다. 또, Mac OS가 아닌 플랫폼에 대한 지원이 상당히 부실합니다.
테스트 역시 또다른 중요한 측면입니다. 우리가 조기에, 자주, 양껏 테스트할 수 있었다면 제가 gulp 데모를 만들면서 고생했던 CSS 버그 같은 문제점들을 미리 발견했을 겁니다. 우리는 모듈들이 여러 플랫폼 위에서 실행되는 것을 원합니다. 그리고 모듈들이 다른 플랫폼에 연결되는 것을 원합니다. 물리적인 디바이스를 포함해서요.
물론 더 많은 모듈과 더 많은 예제가 필요합니다! 어떤 두 사람이 동일한 모듈을 작성하기 시작하는 것을 막기 위해, 우리는 프로젝트 이슈 트래커의 new modules에서 토론과 제안을 하고 있습니다. 우리는 더 많은 예제를 보고 싶습니다. 기존의 다른 노드 모듈(node module)에 코드를 보태서 더 괜찮게 만든 예제라도 좋습니다. 예를 들어, 누군가는 firefox-app-validator-manifest 모듈 같은 매니페스트 유효성 체크 모듈을 더 괜찮게 만들 수도 있을 것입니다.
언제나처럼, 우리는 당신을 필요로 합니다. 우리는 당신이 아니기 때문에, 당신이 무엇을 필요로 하는지 또 당신이 무엇을 생각하는지 알 수 없습니다. 우리는 분명히 당신과 다른 방식으로 소프트웨어를 사용할 것입니다. 당신의 의견과 공헌이 필요합니다!
당신이 node-firefox를 이용해서 무언가 만들기를 기대합니다. 질문이 있다면 File issues나 irc를 통해서 일러주세요. 우리는 보통 irc.mozilla.org의 #apps 채널과 #devtools 채널에서 대기하고 있습니다.
감사합니다
Nicola Greco에게 반드시 감사의 말을 전해야 겠습니다. 그가 지난 여름 모질라에서 인턴 생활을 했을 때 나는 그의 멘토였습니다. 그가 처음으로 Firefox OS 앱 개발을 지원하는 노드 모듈을 만들자는 아이디어를 냈습니다. 그의 마지막 인턴 프리젠테이션을 확인해보세요. 정말 재미있고 화려합니다!
우리가 리모트 서버와 액터와 기타 여러가지 개발 이슈들에 대해 고민할 때 도움을 준 (정말 참을성이 많은) DevTool 멤버들 Ryan Stinnet, Alexandre Poirot, Jeff Griffith, Dave Camp에게 큰 감사를 전합니다. Heather Arthur에게도 감사를 전합니다. 그는 firefox-client를 작성했고 node-firefox 이용 방식을 이전에 비해 더욱 쾌적하게 만들었습니다.
이 글은 Soledad Penades가 쓴 Introducing node-firefox의 한국어 번역본입니다.
작성자: ingeeKim
"누구에게나 평등하고 자유로운 웹"에 공감하는 직장인.
댓글이 없습니다.