Taryn Fox
jewelfox@fursona.net 2012
첫 그놈 프로그램!
조성호
shcho@gnome.org 2017-2019.

# 1. 안녕, 그놈!

        이 지침서에서는 자바스크립으로 첫 그놈 프로그램을 작성하는 방법을 알려드립니다. 웹 프로그램을 작성했던 것처럼 동일한 방식으로 그놈 프로그램 작성시 자바스크립트언어를 활용합니다. 그 다음, 다른 그놈 앱 처럼 보이는 프로그램을 작성할 목적으로 "자체" 위젯을 활용하는 방법을 알아보겠습니다.
        컴퓨터에 그놈을 설치하고 코드를 작성할 지에디트를 설정하셨죠? 우선 이 과정을 거쳐야합니다.

# 웹 페이지로 시작하죠

HTML, CSS, JavaScript 기본 코드가 몇개 있습니다. 어디서 많이 본 것 같죠?

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello, GNOME!</title>

<!-- Use JavaScript to show a greeting when someone clicks the button --> <script type="application/javascript"> function greeting () { document.getElementById ("greeting").innerHTML = ("O hai!"); } </script>

<!-- Very basic CSS style using the GNOME font --> <style type="text/css"> body { font-face: Cantarell, sans-serif; text-align: center; } </style>

</head> <body> <br /> <br /> <button type="button" onclick="greeting()">Hello, GNOME!</button>

<!-- Empty H1 element gets filled in when the button is clicked --> <h1 id="greeting"></h1> </body> </html>

이걸 hellognome.html 파일로 저장하고 실행했을 때 어떻게 나오는지 살펴보도록 하죠!

웹 브라우저에서 hellognome.html 파일을 열면 위 코드를 실행할 수 있습니다. 하지만 스크린샷으로 보시듯이 웹 앱을 실행할 그놈 프로그램을 만들려고 합니다. 창 크기를 조절하거나 최대로 확대할 수 있으며, 다른 그놈 앱처럼 구석의 X를 눌러 닫을 수 있습니다. 차이점이 있다면 프로그램에서 왭 코드를 실행한다는 점입니다.

대부분은요? 그놈에서 동작하는 앱의 모든 부분을 작성할 때 JavaScript를 사용하는 편으로 계속 진행하겠습니다. 코드를 보고 어떻게 돌아가는지 보도록 하죠!

# 웹 앱에 맞출 그놈 창 만들기

우선 그놈에게 gjs를 사용하는 JavaScript 프로그램임을 알려야 합니다. gjs는 JavaScript 코드를 이해할 수 있는 기계 명령으로 바꾸는 그놈의 처리 수단입니다. 따라서 프로그램 시작 부분에 항상 이 줄을 넣어야합니다.

#!/usr/bin/gjs

그 다음 우리가 사용할 라이브러리 버전을 설정해야합니다.

imports.gi.versions.Gtk = '3.0'; imports.gi.versions.WebKit2 = '4.0';

그 다음 우리가 가져올 라이브러리를 그놈에게 알려야겠죠.

const GLib = imports.gi.GLib; const Gtk = imports.gi.Gtk; const Webkit = imports.gi.WebKit2;

jQuery가 JavaScript으로 할 수 있는 추가 행동을 우리에게 알려주도록 라이브러리를 추가하는 방식처럼, 이 라이브러리는 그놈 앱에서 처리할 수 있는 새 기능을 제공해줍니다:

Gtk는 그놈 프로그램의 기본적인 부분이며, 창과 위젯을 만들어 한데 묶어둘 수 있습니다.

GLib는 우리가 만든 hellognome.html 파일에서 그놈에서 처리할 수 있는 동작이 가능하게 하는 보조 라이브러리입니다.

그리고 Webkit은 HTML 파일을 여는 브라우저 창을 만들 때 사용하는 웹 렌더링 엔진입니다.

이제 프로그램 그 자체를 만들어보죠:

class HelloGNOME {

이 코드는 이전에 다루어 보았다면 객체 지향 자바스크립트와 비슷해보일겝니다. 맞습니다. 이 전체 프로그램은 HelloGNOME 클래스입니다.

// Create the application itself constructor() { this.application = new Gtk.Application();

// Connect 'activate' and 'startup' signals to the callback functions this.application.connect('activate', this._onActivate.bind(this)); this.application.connect('startup', this._onStartup.bind(this)); }

// Callback function for 'activate' signal presents windows when active _onActivate() { this._window.present(); }

// Callback function for 'startup' signal builds the UI _onStartup() { this._buildUI(); }

여러분이 빌드한 모든 JavaScript 프로그램을 덜 또는 덜 복사하야 붙여넣을 코드 일부입니다. 이 코드로 새 프로그램을 만들고, activate 시그널과 startup 시그널을 함수에 바인딩하여 창을 나타내고 사용자 인터페이스를 구성합니다.

무슨 얘길까요? 그놈 프로그램의 모든 부분에서는 어떤 중요한 동작이 일어날 때 시그널을 내보냅니다. 예컨대, 단추를 누르면 clicked 시그널을 내보냅니다. 우리는 시그널을 처리할 함수와 연결하고 어떤 동작을 취할 코드를 만들겠습니다. 각각 두 인자를 가진 객체의 연결 메서드를 활용하겠습니다. 우리가 처리하고자 하는 시그널, 그리고 우리가 처리하고자 하는 시그널을 어떤 함수와 연결할 지 지시할 때 사용하는 Lang.bind 함수를 인자로 전달합니다.

이 경우 activate 시그널을 처리할 때 _onActivate 함수를, startup 시그널을 처리할 때 _onStartup을 사용하겠습니다. _onActivate는 창 자체를 나타내러고 지시합니다. 그래서 기본적으로는 Alt Tab 키를 누를 때마다 예상하던 대로 프로그램이 나타납니다. _onStartup 함수에서 사용자 인터페이스를 만들며 다음에 우리가 살펴볼 _buildUI를 호출합니다.

위 코드를 프로그램에 복사하여 붙여넣을 때마다, 바꿀 클래스 이름이 유일한 이름인지 확인하십시오.

# 창 UI 디자인

_buildUI 함수에서 그놈에게 창과 창에 있는 내용을 한번에 하나씩 언급하고 있습니다. 그 다음 개별 요소를 함께 연결하고 화면에 한번에 넣습니다.

// Build the application's UI _buildUI() {

// Create the application window this._window = new Gtk.ApplicationWindow ({ application: this.application, title: "Welcome to GNOME", default_height: 200, default_width: 400, window_position: Gtk.WindowPosition.CENTER });

우리가 만들 첫 객체는 ApplicationWindow입니다. 제목 표시줄에 들어갈 제목, 우리가 위에서 만든 프로그램에 필요한 application 속성이 필요합니다. 모양새를 바꾸는 방법에는 여러가지가 있지만 ApplicationWindow 참고 페이지의 내용에서 자세한 내막을 설명해줍니다. 여기서 보시듯, (픽셀 단위) 기본 너비, 높이 값을 설정하고 그놈에게 화면 한가운데에 창을 나타내고 싶음을 지시합니다.

// Create a webview to show the web app this._webView = new Webkit.WebView ();

// Put the web app into the webview this._webView.load_uri (GLib.filename_to_uri (GLib.get_current_dir() + "/hellognome.html", null));

시작 부분에서 Webkit을 어떻게 가져왔는지 기억하시죠? 여기서는 앱을 안에다 넣고 실행할 수 있는 더도 덜도 아닌 웹 브라우저, WebView라고 하는 Webkit 클래스의 새 인스턴스를 만들겠습니다. 그 다음 프로그램을 시작할 때 우리가 불러올 URI를 설정하겠습니다.

http://gnome.org와 같은 웹 URI를 그냥 설정 할 수 있습니다. 대신 우리가 작성한 hellognome.html 파일이 어디에 있는지 WebView에 알려줄 GLib 보조 함수 몇가지를 활용하겠습니다. GLib.get_current_dir에서는 앱을 실행할 디렉터리를 반환하고 GLib.filename_to_uri에서는 WebView의 load_uri 함수가 이해할 수 있도록 파일의 경로와 파일 이름을 URI 형식으로 반환합니다(filename_to_uri의 두번째 매개변수는 용도와 값을 바꿔야 할 이유를 정확하게 알기 전까지는 null 값이어야 합니다).

// Put the webview into the window this._window.add (this._webView);

// Show the window and all child widgets this._window.show_all(); },

});

각 창은 하나 그리고 오직 하나의 위젯만을 소유할 수 있습니다. 보통 여러 위젯을 넣을 때 Grid와 같은 컨테이너 위젯을 활용하고 창의 추가 함수로 Grid 안에 넣습니다. 우리는 WebView만 필요하기 때문에, WebView를 창에 넣기만 하면 됩니다. 그 다음 창을 만드는 _buildUI 함수의 마지막 부분으로 창에게 자신과 창의 내용을 보여주도록 지시하겠습니다.

// Run the application let app = new HelloGNOME (); app.application.run (ARGV);

마지막으로 HelloGNOME 클래스의 새 인스턴스를 만들고 그놈에게 이 코드를 실행하라고 지시하겠습니다.

# 그놈 프로그램 실행

이제 우리는 첫 그놈 프로그램을 만들었으니 시험해볼 떄가 왔습니다. 만드신 프로그램을 컴파일하거나 특별한 프로그램 마냥 설치할 필요가 없습니다. 그놈에는 그놈 셸을 실행하게 하는 gjs를 자체적으로 보유하고 있습니다. 그냥 터미널 상에서 접근할 수 있는 그 어떤 디렉터리에든 hellognome.html 파일과 실제 프로그램 hellognome.js파일을 저장하십시오(보통 사용자 이름이 붙은 '내 폴더'를 엽니다). 그 후 터미널을 열고 다음 명령을 입력하십시오:

     $ gjs hellognome.js

앞서 보신바와 같이 간단한 메시지를 띄우는 단추가 나타나는, 더 혹은 덜 유사한 화면을 볼 수 있어야합니다.

터미널 명령을 사용핧 수 있습니다.

     $ cd (디렉터리 이름)

터미널에서 저장한 파일이 어디에있는지 찾을 때 여러 디렉터리를 탐색하는 명령입니다. 그놈 파일 관리자 노틸러스에는 파일 탐색 창 어디에서든 마우스 오른쪽 단추를 누른 후 해당 위치에서 터미널을 여는 확장 기능도 있습니다. 새 프로그램을 설치할 때 사용하는 앱(프로그램 추가/제거 또는 소프트웨어 센터)을 확인해보십시오.

# 다음은요?

HTML 코드와 웹 뷰 코드 대신, 다른 프로그램 같이 "자체" 그놈 프로그램을 빌드하는 방법을 알아보려면 다음 따라하기 지침서로 계속 진행하십시오. 아니면 Gtk 위젯 예제 코드를 보고 싶으시면 일부 코드 예제를 살펴보십시오.

마지막으로 웹용으로 만든 JavaScript 라이브러리로 그놈 프로그램을 만들어보고 싶다면, 그냥 여기서 멈추고 계속 진행하실 수 있습니다. 다른 앱처럼 데스크톱의 현재 활동 메뉴에 프로그램이 나타나도록 .desktop 파일을 만드는 방법을 알아보려면 다음 따라하기 지침서를 확인해보십시오.

# 완전한 코드 예제

#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0'; imports.gi.versions.WebKit2 = '4.0';

const GLib = imports.gi.GLib; const Gtk = imports.gi.Gtk; const Webkit = imports.gi.WebKit2;

class HelloGNOME {

// Create the application itself constructor() { this.application = new Gtk.Application ();

// Connect 'activate' and 'startup' signals to the callback functions this.application.connect('activate', this._onActivate.bind(this)); this.application.connect('startup', this._onStartup.bind(this)); }

// Callback function for 'activate' signal presents windows when active _onActivate() { this._window.present(); }

// Callback function for 'startup' signal builds the UI _onStartup() { this._buildUI(); }

// Build the application's UI _buildUI() {

// Create the application window this._window = new Gtk.ApplicationWindow ({ application: this.application, title: "Welcome to GNOME", default_height: 200, default_width: 400, window_position: Gtk.WindowPosition.CENTER });

// Create a webview to show the web app this._webView = new Webkit.WebView ();

// Put the web app into the webview this._webView.load_uri (GLib.filename_to_uri (GLib.get_current_dir() + "/hellognome.html", null));

// Put the webview into the window this._window.add (this._webView);

// Show the window and all child widgets this._window.show_all(); }

};

// Run the application let app = new HelloGNOME (); app.application.run (ARGV);