기본 앱 코딩

기본 앱 코딩(HTML)

[ 이 문서는 Windows 런타임 앱을 작성하는 Windows에서 8.x 및 Windows Phone 8.x 개발자를 대상으로 합니다. Windows 10용으로 개발하는 경우에는 최신 설명서를 참조하세요.]

이 항목에서는 기본 앱의 구조를 보여 주고 JavaScript를 사용하는 Windows 스토어 앱 코딩 규칙을 소개합니다.

사전 요구 사항

JavaScript를 사용하여 첫 Windows 런타임 앱 만들기에 설명된 대로 JavaScript로 작성한 기본 Windows 런타임 앱을 만들 수 있다고 가정합니다.

기본 앱의 내용

Microsoft Visual Studio에서 새 응용 프로그램 템플릿을 사용하는 새 프로젝트를 만들면 다음과 같은 몇 개의 파일이 포함된 앱이 만들어집니다.

  • default.html

    앱의 시작 페이지입니다. 앱을 시작하면 표시되는 페이지입니다. 이 파일에는 JavaScript용 Windows 라이브러리 파일 및 스타일시트인 default.js와 앱 자체 스타일시트인 default.css에 대한 참조가 포함됩니다.

  • /js/default.js

    앱이 시작될 때의 동작을 지정하는 JavaScript 코드입니다. 이 파일에는 앱의 수명 주기를 처리하는 코드가 포함됩니다. 템플릿에서 생성되는 default.js가 앱 활성화를 처리하지만 일반적은 앱은 일시 중단 및 다시 시작 이벤트도 처리합니다.

  • /css/default.css

    앱의 CSS 스타일시트입니다. 여기에서 자체의 스타일을 정의하거나 WinJS에서 제공한 기존 스타일을 재정의할 수 있습니다.

  • /References/WinJS SDK

    WinJS: 앱을 만들기 위한 스타일, 컨트롤 및 유틸리티의 집합입니다.

  • package.appmanifest

    앱 매니페스트입니다. 이 파일은 앱의 콘텐츠를 나열하고 앱의 접근 권한 값을 설명합니다. 앱의 시작 페이지로 사용할 페이지도 지정합니다. Visual Studio를 사용하여 앱에 파일을 추가하면 앱 매니페스트가 자동으로 업데이트됩니다.

  • /images

    또한 이 템플릿에는 시작 화면 이미지에 사용되는 splashscreen.png, Windows 스토어에 사용되는 storelogo.png 등 여러 개의 이미지 파일이 들어 있습니다.

default.html 및 default.js 파일

JavaScript로 작성한 Windows 런타임 앱을 만들 때 어떤 Visual Studio 템플릿을 사용하든 관계없이 default.html 및 default.js 파일은 항상 포함됩니다.

다음은 새 응용 프로그램 템플릿을 사용하여 새 프로젝트를 만들 때 생성되는 default.html의 태그입니다.

Windows 앱용 default.html


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>BasicSampleApp</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>

    <!-- BasicSampleApp references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body>
    <p>Content goes here</p>
</body>
</html>

Windows Phone 앱용 default.html


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>BasicSampleApp</title>

    <!-- WinJS references -->
    <link href="/css/ui-themed.css" rel="stylesheet" />
    <script src="//Microsoft.Phone.WinJS.2.1/js/base.js"></script>
    <script src="//Microsoft.Phone.WinJS.2.1/js/ui.js"></script>

    <!-- BasicSampleApp references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body>
    <p>Content goes here</p>
</body>
</html>

다음은 새 프로젝트를 만들 때 자동으로 생성되는 default.js 파일의 코드입니다.



(function () {
    "use strict";

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll());
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // args.setPromise().
    };

    app.start();
})();


앱 수명 주기

default.js 파일에 있는 대부분의 코드는 앱 수명 주기를 처리합니다. 앱 수명 주기는 앱이 시작될 때 시작하고 앱이 종료될 때 끝납니다. 프로젝트 템플릿에는 앱 수명 주기를 관리하기 위한 일반 패턴이 포함되어 있습니다.

템플릿에서 제공하는 코드는 앱이 시작 화면에서 시작되었는지 여부를 확인하고 WinJS.UI.processAll을 호출합니다. WinJS.UI.processAll은 HTML 파일에서 선언한 WinJS 컨트롤을 모두 로드합니다. 앱에서 초기 상태를 설정할 때 실행해야 하는 코드가 있는 경우 activated 이벤트 처리기에 해당 코드를 포함해야 합니다.

참고  활성화 동안 많은 작업을 수행하면 앱이 응답하지 않는 것처럼 보일 수 있습니다. 가능하면 부담이 큰 작업은 앱이 로드된 후로 미루세요.
 

템플릿에는 앱 일시 중단, 다시 시작 또는 종료를 처리하는 코드가 없습니다. 이러한 상태 처리에 대한 자세한 내용은 응용 프로그램 수명 주기를 참조하세요.

익명 함수 및 strict 모드

웹 사이트 프로그래밍에 익숙한 경우 코드에서 특이한 몇몇 부분을 발견할 수 있을 것입니다. 이를테면 다음과 같이 전체 파일을 익명 함수로 묶었습니다.


(function () {
    ...
})();

이유가 무엇일까요? JavaScript에는 전역과 지역이라는 두 개의 범위가 있습니다. 함수 정의 외부에서 변수를 선언하면 전역 변수가 되고 해당 값은 프로그램 전체에서 액세스하고 수정할 수 있습니다. 함수 정의 내부에서 변수를 선언하면 지역 변수가 되며 함수 외부에서 액세스할 수 없습니다.

코드를 익명 함수로 묶으면 비공개 코드가 됩니다. 코드를 익명 함수로 묶는 것은 좋은 코딩 습관으로, 코드 범위를 제한하여 전역 네임스페이스를 오염시키지 않습니다. 또한 이름 충돌이나 의도하지 않은 값을 실수로 수정하는 일은 예방하기도 용이합니다.

기본적으로 JavaScript에서는 익명 함수를 사용하여 비공개 멤버를 만들 수 있습니다. 이 언어에서 이 작업을 지원하는 다른 방법은 없습니다.

아래와 같이 함수 선언 끝에 있는 추가 괄호는 익명 함수를 호출합니다.


(function () {
    ...
})(); // Makes the function self-invoking.

또한 default.js 파일에서는 함수가 strict 모드로 실행되도록 선언합니다.


(function () {
    "use strict"; // Declares strict mode. 

    ...

})();

Strict 모드는 JavaScript 코드의 오류 검사를 향상합니다. strict 모드를 사용하면 JavaScript에서 일반적으로 허용되는 것보다 엄격한 일련의 제한이 코드에 적용됩니다. 예를 들어 선언하지 않은 변수를 사용할 수 없거나, 읽기 전용 속성에 쓸 수 없거나, with 문을 사용할 수 없습니다. 이러한 제한을 통해 더 나은 코드를 작성하고 앱에 오류가 유입될 가능성을 줄일 수 있습니다.

strict 모드에 대한 자세한 내용은 JavaScript 언어 참조의 Strict 모드를 참조하세요.

이벤트 처리기 추가

코드를 익명 함수로 묶으면 여러 이점이 있는 것과 동시에 코드 작성 방법도 변경해야 합니다. 예를 들어 이벤트를 처리하는 방법을 변경해야 합니다.

default.html 페이지에 단추를 추가한다고 가정합니다. 사용자가 단추를 클릭할 때 클릭한 점의 x 및 -y 좌표를 표시하려는 경우 해당 정보를 표시하는 paragraph 요소를 추가합니다. 다음 예제에서는 이러한 요소를 default.html 파일의 BODY 태그에 추가하고 이 요소를 포함하는 div 요소를 추가합니다.



<body>
    <div>
        <button id="button1">An HTML button</button>
        <p id="button1Output"></p>
    </div>
</body>


이제 단추의 click 이벤트에 대한 이벤트 처리기를 default.js 파일에 정의합니다. 대부분의 이벤트 처리기는 이벤트에 대한 정보를 포함하는 Event 개체를 단일 인수로 사용합니다. 다른 이벤트는 해당 이벤트와 관련된 정보를 제공하는 다른 유형의 이벤트 정보 개체를 반환할 수 있습니다.

click 이벤트는 누른 마우스 단추, 이벤트를 발생시킨 개체 등과 같은 이벤트에 대한 정보를 포함하는 MouseEvent 개체를 제공합니다. 다음 예제에서는 MouseEvent 개체를 사용하여 사용자가 클릭한 점의 x 및 y 좌표를 가져오는 click 이벤트 처리기를 만듭니다.

click 이벤트는 터치 및 키보드 상호 작용에도 응답하지만, 이 항목의 예제에서는 사용자가 마우스로 클릭한다고 가정합니다. )


(function () {
    "use strict";

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll());
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // args.setPromise().
    };

    // The click event handler for button1
    function button1Click(mouseEvent) {
        var button1Output = document.getElementById("button1Output");
        button1Output.innerText =
            mouseEvent.type
            + ": (" + mouseEvent.clientX + "," + mouseEvent.clientY + ")";

    }

    app.start();
})();

이제 이벤트 처리기를 단추에 등록하기만 하면 됩니다. 단추의 onclick 특성을 설정하여 처리기를 등록할 수 있습니다.


        <button id="button1" onclick="button1Click(event)">An HTML button</button>

그런데 코드가 작동하지 않습니다. 앱을 실행하고 단추를 클릭하면 다음 예외가 표시됩니다.

ms-appx://77d9a962-d259-45b1-9f04-3abf289aff57-6mtxa77c2r4nt/default.html의 21행, 39열에서 처리되지 않은 예외가 발생했습니다.

0x800a1391 - JavaScript 런타임 오류: 'button1Click'이 정의되지 않았습니다.

하지만 default.js 파일에는 button1Click에 대한 정의가 들어 있습니다. 그런데 작동하지 않는 이유는 무엇일까요?

default.js에서 익명 함수 안에 있는 모든 코드는 지역 또는 비공개이기 때문입니다. 따라서 default.html에서 button1Click 함수에 액세스할 수 없습니다.


(function () {
    
    // default.html can't access anything inside this function.
 
})();

이 제한을 해결하는 방법에는 두 가지가 있습니다. button1Click을 공개적으로 액세스할 수 있게 만들거나 코드에서 이벤트 처리기를 연결할 수 있습니다. 권장하는 방법은 코드에서 이벤트 처리기를 연결하는 것이지만 여기서는 두 방법 모두 설명하겠습니다. 권장되는 방법에 대한 설명으로 바로 점프하려면 코드에서 이벤트 처리기 연결을 참조하세요.

멤버를 공개적으로 액세스할 수 있게 만들기

JavaScript를 사용하는 Windows 런타임 앱에는 항상 WinJS가 포함되어 있습니다. WinJS가 제공하는 유용한 기능 중 하나는 네임스페이스와 클래스를 정의하는 방법입니다. WinJS.Namespace.define 함수는 공개 네임스페이스를 만듭니다. 이 함수는 두 개의 매개 변수 즉, 만들 네임스페이스 이름과 하나 이상의 속성/값 쌍을 포함하는 개체를 사용합니다. 각 속성은 멤버의 공개 이름이고 각 값은 노출할 변수, 속성 또는 함수입니다.

다음 예제에서는 단일 멤버 clickEventHandler를 포함하는 startPage라는 네임스페이스를 만듭니다. clickEventHandler의 값은 앞에서 정의한 button1Click 함수입니다.


    var namespacePublicMembers = { clickEventHandler: button1Click };
    WinJS.Namespace.define("startPage", namespacePublicMembers);

다음의 전체 default.js 파일에서 네임스페이스 선언이 파일의 나머지 부분에 어떻게 적용되는지 볼 수 있습니다.


(function () {
    "use strict";

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll());
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // args.setPromise().
    };

    // The click event handler for button1
    function button1Click(mouseEvent) {
        var button1Output = document.getElementById("button1Output");
        button1Output.innerText =
            mouseEvent.type
            + ": (" + mouseEvent.clientX + "," + mouseEvent.clientY + ")";

    }

    var namespacePublicMembers = { clickEventHandler: button1Click };
    WinJS.Namespace.define("startPage", namespacePublicMembers);

    app.start();
})();

이벤트 처리기가 startPage.clickEventHandler로 공개적으로 노출되므로 이를 사용하여 단추의 onclick 특성을 설정할 수 있습니다.


      <button id="button1" onclick="startPage.clickEventHandler(event)">An HTML button</button>

이제 앱을 실행하면 이벤트 처리기가 제대로 작동합니다.

지금까지 이벤트 처리기를 연결하는 한 가지 방법을 살펴보았습니다. 이제 다른 방법인 코드에서 이벤트 처리기를 연결하는 방법을 살펴보겠습니다.

코드에서 이벤트 처리기 연결

이벤트 처리기를 연결하는 다른 방법(권장되는 방법)은 JavaScript를 사용하여 컨트롤을 검색한 다음 addEventListener 메서드를 사용하여 이벤트를 등록하는 것입니다. 문제는 '컨트롤을 검색해야 하는 시기'입니다. 컨트롤을 JavaScript 코드의 아무 곳에나 추가해도 되지만, 그러면 컨트롤이 있는 위치보다 더 앞에서 호출될 수도 있습니다.

대부분의 HTML 파일은 WinJS.UI.processAll 메서드에서 반환된 Promise에 대한 then 또는 done 함수를 제공한다는 것에 답이 있습니다. 페이지 컨트롤의 경우 대신 ready 함수를 사용할 수 있습니다.

Promise란 무엇입니까? 응답이 빠른 사용자 환경을 제공하기 위해 WinJS 및 Windows 런타임 함수는 대부분 비동기적으로 실행됩니다. 이렇게 하면 백그라운드에서 작업을 수행하는 동안 앱이 계속해서 사용자 조작에 응답할 수 있습니다. 비동기 함수는 직접 값을 반환하는 대신 Promise 개체를 값으로 반환합니다. 비동기 프로그래밍에 대한 자세한 내용은 JavaScript의 비동기 프로그래밍을 참조하세요.


            args.setPromise(WinJS.UI.processAll().then(function () {
                var button1 = document.getElementById("button1");
                button1.addEventListener("click", button1Click, false);
                })
            );


다음은 default.html 및 default.js의 전체 코드입니다.

Windows 앱용 default.html


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>BasicSampleApp</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>

    <!-- BasicSampleApp references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body>
    <p>Content goes here</p>
</body>
</html>

Windows Phone 앱용 default.html


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>BasicSampleApp</title>

    <!-- WinJS references -->
    <link href="/css/ui-themed.css" rel="stylesheet" />
    <script src="//Microsoft.Phone.WinJS.2.1/js/base.js"></script>
    <script src="//Microsoft.Phone.WinJS.2.1/js/ui.js"></script>

    <!-- BasicSampleApp references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body>
    <p>Content goes here</p>
</body>
</html>


(function () {
    "use strict";

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll().then(function () {
                var button1 = document.getElementById("button1");
                button1.addEventListener("click", button1Click, false);
                })
            );
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // args.setPromise().
    };

    // The click event handler for button1
    function button1Click(mouseEvent) {
        var button1Output = document.getElementById("button1Output");
        button1Output.innerText =
            mouseEvent.type
            + ": (" + mouseEvent.clientX + "," + mouseEvent.clientY + ")";

    }

    // You don't need the following code if you don't define the 
    // onclick attribute in the HTML markup of the button.
    //var namespacePublicMembers = { clickEventHandler: button1Click };
    //WinJS.Namespace.define("startPage", namespacePublicMembers);

    app.start();
})();

페이지 추가 및 페이지 탐색

새 응용 프로그램 템플릿은 아주 간단한 앱에는 적합하지만 좀더 복잡한 앱을 작성할 때는 콘텐츠를 여러 파일로 나누어야 할 수 있습니다.

일반적인 웹 사이트는 일련의 페이지를 포함할 수 있고, 이들 페이지를 하이퍼링크를 사용하여 탐색합니다. 각 페이지에는 고유한 JavaScript 함수 및 데이터 집합, 표시할 새 HTML 집합, 스타일 정보 등이 있습니다. 이러한 탐색 모델을 다중 페이지 탐색이라고 합니다.

일반적인 웹 사이트와 달리 JavaScript를 사용하는 Windows 런타임 앱은 단일 페이지 탐색 모델을 사용할 경우 가장 효과적입니다. 이 모델에서는 앱에 단일 페이지를 사용하고 필요에 따라 해당 페이지에 추가 데이터('조각')를 로드합니다.

따라서 앱이 default.html 페이지를 벗어나지 않습니다. 항상 default.html 및 default.js 파일을 앱의 시작 페이지로 만듭니다. 이 파일은 앱의 가장 바깥쪽 UI(예: AppBar)를 정의하고 응용 프로그램 수명 주기를 처리합니다.

default.html 외의 다른 페이지를 탐색하지 않는다면 다른 페이지의 콘텐츠를 어떻게 가져옵니까? 여러 가지 방법이 있습니다.

  • HtmlControl을 사용하여 대화형 작업이 들어 있지 않은 다른 페이지의 HTML을 표시할 수 있습니다(HtmlControl은 JavaScript 로드를 지원하지 않음).
  • PageControl을 만들어 기본 페이지에 표시할 수 있습니다. PageControl은 다른 컨트롤처럼 HTML 페이지 내에 표시할 수 있는 HTML, JavaScript 및 CSS의 집합입니다. 페이지 컨트롤을 만드는 방법에 대한 자세한 내용은 페이지 컨트롤 추가를 참조하세요.
  • WebView 컨트롤을 사용하여 앱에 웹 기반 콘텐츠를 표시할 수 있습니다. WebView 컨트롤은 외부 페이지에서 대부분의 HTML5 기능에 액세스할 수 있습니다. 또한 고유한 기록 스택을 유지 관리하며 앞/뒤로 이동 또는 페이지 다시 로드를 허용합니다.
  • DOM 메서드를 사용하여 다른 페이지의 콘텐츠를 포함할 수도 있습니다.

탐색에 대한 자세한 내용은 탐색 지원을 참조하세요.

가장 적합한 템플릿 선택

새 응용 프로그램 템플릿에는 JavaScript로 작성한 Windows 런타임 앱을 만드는 데 필요한 최소한의 코드가 포함되어 있습니다. Visual Studio에는 앱으로 수행하려는 작업에 따라 더 나은 시작점을 제공하는 여러 템플릿이 있습니다. 이러한 템플릿에 대한 자세한 내용은 Windows 런타임 앱용 JavaScript 프로젝트 템플릿을 참조하세요.

요약 및 다음 단계

기본 앱의 구성 요소와 JavaScript를 사용하는 Windows 런타임 앱 코딩 규칙에 대해 알아보았습니다. 다음 항목 HTML, CSS 및 JavaScript 기능 및 차이점에서는 JavaScript를 사용하는 Windows 런타임 앱의 코딩과 웹 사이트 코딩 간의 차이점에 대해 자세히 설명합니다.

관련 항목

Windows 런타임 앱용 JavaScript 프로젝트 템플릿
응용 프로그램 수명 주기
빠른 시작: HTML 컨트롤 추가 및 이벤트 처리
빠른 시작: WinJS 컨트롤 및 스타일 추가
탐색 지원

 

 

표시:
© 2018 Microsoft