UWP 점프 리스트(JumpList) 사용자화하기

Steam 애플리케이션의 드롭다운 메뉴에 나타나는 점프 리스트

점프 리스트란?

Windows의 상태 표시줄이나 시작 메뉴에 있는 애플리케이션의 아이콘을 우클릭하면 나오는 메뉴에서, 애플리케이션의 작업을 빠르게 실행할 수 있는 기능입니다. 주로 애플리케이션을 통해 최근에(또는 자주) 열은 파일이 나열되거나, 앱의 주요 기능 바로가기를 표시하는 데 쓰입니다. 이곳에서 점프 리스트에 대해 더 자세히 알아보실 수 있습니다.

이 기능은 Windows 7에서 추가되었습니다. Win32 애플리케이션에서는 당연히 사용할 수 있고, 오늘날 Windows 10의 UWP 애플리케이션도 이 기능을 사용할 수 있습니다. 이번 포스트에서는 WinRT API 중 하나인 Windows.UI.StartScreen.JumpList로 UWP 애플리케이션에서의 점프 리스트를 만드는 방법을 알아 봅니다.

⚠️ 잠깐, 개발자가 아니신가요?

이 글에서는 개발자가 애플리케이션을 개발하면서 직접 메뉴를 추가 및 수정하는 방법에 대한 설명이며, 일반 사용자를 위한 설명이 아닙니다. 사용하시는 애플리케이션에서 메뉴를 직접 사용자화할 수 있는 기능을 제공하지 않으면 일반 사용자가 직접 점프 리스트를 관리할 수 없습니다. 사용하시는 앱에 점프 리스트를 사용하고 싶으실 경우, 해당 앱 개발자에게 기능을 제안하시길 바랍니다.

 

점프 리스트에서 관리할 수 있는 메뉴 종류

점프 리스트에 표시되는 메뉴는 '시스템 그룹'과 '사용자 그룹' 두 가지로 분류할 수 있습니다.

점프 리스트의 시스템 그룹에 있는 메뉴. DC Door에 연결된 패턴(.ddptn) 파일이 최근에 열은 항목으로 자동으로 추가되어 있습니다.

점프 리스트의 시스템 그룹에 있는 메뉴. DC Door에 연결된 패턴(.ddptn) 파일이 최근에 열은 항목으로 자동으로 추가되어 있습니다.

시스템 그룹에서는 그 앱으로 열은 파일이 자동으로 나열됩니다. 여기에 표시되는 목록을 마음대로 관리할 수는 없지만, 어떻게 목록을 표시할 지 세 가지 모드가 제공됩니다. 최근 항목(Recent)으로 나열하거나, 자주 사용하는 항목(Frequent)으로 나열하거나, 아예 숨기는(None) 모드가 있습니다.

테스트 앱에서 사용자 메뉴를 점프 리스트에 추가한 모습입니다.

테스트 앱에서 사용자 메뉴를 점프 리스트에 추가한 모습입니다.

사용자 그룹에서 원하는 메뉴를 추가하고 관리할 수 있습니다. 여기에서 메뉴를 추가할 때 서로 다른 두 가지 특성으로 메뉴를 추가할 수 있는데 추가하려 하는 목적에 맞게 사용해야 합니다. 이 두 특성은 어떻게 다른 걸까요?

Quick Menu A를 우클릭한 모습

Quick Menu A를 우클릭한 모습

Quick Menu C를 우클릭한 모습. 그룹 'Quick Menu' 아래에 있던 Quick Menu A를 우클릭했을때와 다르게 '열기' 메뉴만 있고 삭제는 할 수 없습니다.

Quick Menu C를 우클릭한 모습. 그룹 'Quick Menu' 아래에 있던 Quick Menu A를 우클릭했을때와 다르게 '열기' 메뉴만 있고 삭제는 할 수 없습니다.

테스트 앱애서 4가지 메뉴를 추가해 봤습니다. Quick Menu A와 Quick Menu B는 'Quick Menu'란 그룹 아래에 있고, Quick Menu C와 Quick Menu D는 '작업'이란 그룹 아래에 있습니다. Quick Menu A를 우클릭하니 사용자가 이 메뉴를 마음대로 지울 수 있게 되어 있습니다. 반면에 Quick Menu C를 우클릭하니 A와는 다르게 지울 수는 없고 열기만 가능합니다.

점프 리스트에 메뉴를 추가하는 방법은 아래에서 더 자세하게 다루겠지만, 추가하는 메뉴에는 앱 내부에서 점프 리스트 메뉴들을 분류하기 위한 값 argument, 목록에 표시되는 이름 displayName, 마우스를 갖다댔을 때 툴팁으로 뜰 설명 description, 그룹으로 분류할 이름 groupName, 앱 내 리소스로 포함된 아이콘 이미지의 주소 logo 이렇게 5가지 특성을 지정할 수 있습니다. 여기서 이름으로 사용할 어떤 String을 그룹 이름에 적용시키면 위 이미지의 Quick Menu처럼 그 String으로 메뉴가 분류됩니다. 이 메뉴들은 사용자가 삭제할 수 있습니다. 반면 그룹 이름으로 빈 String("")을 할당시키면 '작업' 그룹에 분류됩니다(영어 환경에서는 'Tasks'라고 뜸). 여기서는 사용자가 마음대로 메뉴 항목을 삭제할 수 없습니다.

인스타그램 앱의 점프 메뉴. 제공된 메뉴들의 제거가 가능합니다.

인스타그램 앱의 점프 메뉴. 제공된 메뉴들의 제거가 가능합니다.

그러면 어떻게 점프 리스트에 메뉴를 추가해야 잘 추가했다고 소문이 날까요? 앱 기능 바로가기와 같은 메뉴들은 groupName에 아무 것도 지정하지 않고 점프 리스트에 추가해서 '작업' 그룹 아래에 추가되도록 하여 사용자가 함부로 삭제하지 못하도록 해야 겠습니다. 이렇게 하면 바로가기 메뉴들에 대한 그룹 이름을 지정할 수 없지만, 사용자가 실수로(또는 고의로) 바로가기 메뉴를 삭제하는 불상사를 막을 수 있습니다. 삭제된 메뉴를 다시 원상태로 복구할 수 있는 옵션을 제공하는게 아니라면 말이죠. 앱 기능 바로가기가 아닌, 사용자가 추가한 즐겨찾기나 최근 방문 목록과 같은 항목은 추가할 때 특별히 그룹 이름을 지정하여 사용자가 편집할 권한을 받을 수 있도록 하여야 합니다.

인스타그램 앱의 점프 메뉴를 보면 '메뉴'라는 그룹 아래에 기능 바로가기들이 있습니다. 사용자가 이 바로가기를 제거할 수는 있지만 앱을 초기화하기 전까지는 삭제한 메뉴를 다시 가져다놓을 수 없으므로 인스타그램 앱이 이 API를 잘못 사용하고 있음을 알 수 있습니다.

 

점프 리스트에 접근하기

점프 리스트는 바로 접근할 수 없고 비동기식으로 현재 점프 리스트를 로드해야 관리할 수 있습니다. 모든 것을 관리하기 전에, 접근을 해 봅시다.

Windows.UI.StartScreen.JumpList.loadCurrentAsync로 현재 앱의 점프 리스트를 불러옵니다. 이 메소드는 비동기식입니다.

JavaScript
var JumpList = Windows.UI.StartScreen.JumpList;
// 점프 리스트를 불러옵니다.
JumpList.loadCurrentAsync().then(function (loadedJumpList) {
    // loadedJumpList는 로드된 점프 리스트입니다.

}).done();

이제 loadedJumpList를 argument로 한 function 안에서 대로 점프 리스트를 관리할 수 있습니다.

 

점프 리스트에 표시할 시스템 그룹 유형 변경하기

앞서 설명했듯이 앱으로 열은 파일들이 나열되는 시스템 그룹은 최근 항목, 자주 사용하는 항목을 표시하거나 숨길 수 있습니다. 접근한 점프 리스트에서 표시할 모드를 지정해 봅시다.

Windows.UI.StartScreen.JumpListSystemGroupKind에 세 가지 모드가 정의되어 있습니다. 위에서 접근한 점프 리스트에 적용을 하려면 접근한 점프 리스트 아래의 systemGroupKind에 원하는(상황에 맞는) 모드를 할당시키면 됩니다.

☝️ 참고

  • 앱에 연결된 파일을 해당 앱에서 열은 적이 없을 경우, 시스템 그룹 표시 모드를 최근 사용 항목이나 자주 사용하는 항목으로 바꿔도 표시되지 않습니다.
  • 시스템 그룹을 숨겨도 사용자 그룹의 메뉴들은 표시됩니다.
JavaScript
var JumpList = Windows.UI.StartScreen.JumpList;
// 점프 리스트를 불러옵니다.
JumpList.loadCurrentAsync().then(function (loadedJumpList) {
    // loadedJumpList는 로드된 점프 리스트입니다.
    // 시스템 그룹으로 표시할 모드를 지정합니다. 여기에서는 frequent(자주 사용하는 항목)으로 설정합니다.
    loadedJumpList.systemGroupKind = Windows.UI.StartScreen.JumpListSystemGroupKind.frequent;
    
}).done();
 

점프 리스트에 바로가기 메뉴 추가하기

위에서 '사용자 그룹'을 설명하면서 예시로 만들었던 Quick Menu A, B, C, D를 만들어 봅시다.

Windows.UI.StartScreen.JumpListItem.createWithArguments function으로 메뉴 아이템을 만듭니다. 첫 번째 argument는 앱 내에서 각 메뉴들을 구분할 값 String, 두 번째 argument는 메뉴 리스트에 표시될 이름 String입니다. 툴팁으로 띄울 설명과 그룹 이름은 새 변수에 새로 만든 이 아이템을 지정한 후에 조작할 수 있습니다.

로드한 점프 리스트(아래 코드에서는 loadedJumpList)의 items.append function으로 목록에 새로 만든 아이템을 밀어넣습니다.

JavaScript
var JumpList = Windows.UI.StartScreen.JumpList,
    JumpListItem = Windows.UI.StartScreen.JumpListItem;
// 점프 리스트를 불러옵니다.
JumpList.loadCurrentAsync().then(function (loadedJumpList) {
    // loadedJumpList는 로드된 점프 리스트입니다.
    // 시스템 그룹으로 표시할 모드를 지정합니다. 여기에서는 frequent(자주 사용하는 항목)으로 설정합니다.
    loadedJumpList.systemGroupKind = Windows.UI.StartScreen.JumpListSystemGroupKind.frequent;
    // Quick Menu A와 Quick Menu B는 그룹 'Quick Menu'아래에 포함되도록 합니다.
    var itemA = JumpListItem.createWithArguments("quickMenuA", "Quick Menu A");
    itemA.description = "Description of Quick Menu A";
    itemA.groupName = "Quick Menu";
    var itemB = JumpListItem.createWithArguments("quickMenuB", "Quick Menu B");
    itemB.description = "Description of Quick Menu B";
    itemB.groupName = "Quick Menu";
    // Quick Menu C와 Quick Menu D는 어떤 그룹에도 포함시키지 않아 '작업' 목록에 오도록 합니다.
    var itemC = JumpListItem.createWithArguments("quickMenuC", "Quick Menu C");
    itemC.description = "Description of Quick Menu C";
    var itemD = JumpListItem.createWithArguments("quickMenuD", "Quick Menu D");
    itemD.description = "Description of Quick Menu D";
    // 새로 만든 4개의 아이템을 로드한 loadedJumpList에 추가합니다.
    loadedJumpList.items.append(itemA);
    loadedJumpList.items.append(itemB);
    loadedJumpList.items.append(itemC);
    loadedJumpList.items.append(itemD);

}).done();
빈 점프 리스트에서 위 코드와 같이 추가하면 이렇게 됩니다.

빈 점프 리스트에서 위 코드와 같이 추가하면 이렇게 됩니다.

바로가기 메뉴 외에도 구분선을 추가할 수 있습니다. Windows.UI.StartScreen.JumpListItem.createSeparator function으로 구분선 아이템을 새 변수에 만든 후, 바로가기 메뉴를 추가하는 것처럼 추가하면 됩니다. 그룹 내 다른 메뉴들 간 구분선 역할을 합니다.

JavaScript
var JumpList = Windows.UI.StartScreen.JumpList,
    JumpListItem = Windows.UI.StartScreen.JumpListItem;
// 점프 리스트를 불러옵니다.
JumpList.loadCurrentAsync().then(function (loadedJumpList) {
    // loadedJumpList는 로드된 점프 리스트입니다.
    // 시스템 그룹으로 표시할 모드를 지정합니다. 여기에서는 frequent(자주 사용하는 항목)으로 설정합니다.
    loadedJumpList.systemGroupKind = Windows.UI.StartScreen.JumpListSystemGroupKind.frequent;
    // Quick Menu A와 Quick Menu B는 그룹 'Quick Menu'아래에 포함되도록 합니다.
    var itemA = JumpListItem.createWithArguments("quickMenuA", "Quick Menu A");
    itemA.description = "Description of Quick Menu A";
    itemA.groupName = "Quick Menu";
    var itemB = JumpListItem.createWithArguments("quickMenuB", "Quick Menu B");
    itemB.description = "Description of Quick Menu B";
    itemB.groupName = "Quick Menu";
    // Quick Menu C와 Quick Menu D는 어떤 그룹에도 포함시키지 않아 '작업' 목록에 오도록 합니다.
    var itemC = JumpListItem.createWithArguments("quickMenuC", "Quick Menu C");
    itemC.description = "Description of Quick Menu C";
    var itemD = JumpListItem.createWithArguments("quickMenuD", "Quick Menu D");
    itemD.description = "Description of Quick Menu D";
    // 구분선 하나를 새로 만듭니다.
    var itemSep1 = JumpListItem.createSeparator();
    // 새로 만든 4개의 아이템을 로드한 loadedJumpList에 추가합니다.
    loadedJumpList.items.append(itemA);
    loadedJumpList.items.append(itemB);
    loadedJumpList.items.append(itemC);
    // 구분선을 C와 D 메뉴 사이에 추가합니다.
    loadedJumpList.items.append(itemSep1);
    loadedJumpList.items.append(itemD);

}).done();
Quick Menu C와 D 사이에 구분선을 추가한 모습

Quick Menu C와 D 사이에 구분선을 추가한 모습

 

점프 리스트 편집 내용 저장하기

처음에 비동기식으로 점프 리스트의 사본을 가져온 것이므로, 편집한 점프 리스트를 직접 저장해줘야 합니다. 비동기식 function인 saveAsync로 저장을 합니다.

JavaScript
var JumpList = Windows.UI.StartScreen.JumpList,
    JumpListItem = Windows.UI.StartScreen.JumpListItem;
// 점프 리스트를 불러옵니다.
JumpList.loadCurrentAsync().then(function (loadedJumpList) {
    // loadedJumpList는 로드된 점프 리스트입니다.
    // 시스템 그룹으로 표시할 모드를 지정합니다. 여기에서는 frequent(자주 사용하는 항목)으로 설정합니다.
    loadedJumpList.systemGroupKind = Windows.UI.StartScreen.JumpListSystemGroupKind.frequent;
    // Quick Menu A와 Quick Menu B는 그룹 'Quick Menu'아래에 포함되도록 합니다.
    var itemA = JumpListItem.createWithArguments("quickMenuA", "Quick Menu A");
    itemA.description = "Description of Quick Menu A";
    itemA.groupName = "Quick Menu";
    var itemB = JumpListItem.createWithArguments("quickMenuB", "Quick Menu B");
    itemB.description = "Description of Quick Menu B";
    itemB.groupName = "Quick Menu";
    // Quick Menu C와 Quick Menu D는 어떤 그룹에도 포함시키지 않아 '작업' 목록에 오도록 합니다.
    var itemC = JumpListItem.createWithArguments("quickMenuC", "Quick Menu C");
    itemC.description = "Description of Quick Menu C";
    var itemD = JumpListItem.createWithArguments("quickMenuD", "Quick Menu D");
    itemD.description = "Description of Quick Menu D";
    // 구분선 하나를 새로 만듭니다.
    var itemSep1 = JumpListItem.createSeparator();
    // 새로 만든 4개의 아이템을 로드한 loadedJumpList에 추가합니다.
    loadedJumpList.items.append(itemA);
    loadedJumpList.items.append(itemB);
    loadedJumpList.items.append(itemC);
    // 구분선을 C와 D 메뉴 사이에 추가합니다.
    loadedJumpList.items.append(itemSep1);
    loadedJumpList.items.append(itemD);
    // 편집을 다 했으면, 저장합니다.
    return loadedJummpList.saveAsync();
}).done();
 

점프 리스트에서 일부 항목 또는 전체 항목 삭제

JumpList.loadCurrentAsync()에서 비동기식으로 반환되는 점프 리스트는 자바스크립트의 Array와 유사한 IList입니다. 앱의 점프 리스트를 싹 비울 경우엔 items.clear();를 통해 현재 점프 리스트의 모든 아이템을 삭제할 수 있으며(시스템 그룹의 리스트는 영향을 받지 않음), 일부 아이템만 삭제할 경우엔 items.splice(index, amount)로 일부만 삭제할 수 있습니다.

JavaScript
var JumpList = Windows.UI.StartScreen.JumpList;
JumpList.loadCurrentAsync().then(function (loadedJumpList) {
    // 점프 리스트의 2번째 아이템부터 1개를 삭제합니다.
    loadedJumpList.items.splice(1, 1);
    // 현재 앱의 모든 점프 리스트 아이템을 삭제합니다.
    // 시스템 그룹의 목록은 영향을 받지 않습니다.
    loadedJumpList.items.clear();
    // 편집을 다 했으면 저장을 합니다.
    return loadedJumpList.saveAsync();
}).done();
 

점프 리스트에서 앱이 실행(호출)되었는지 판단하기

웹 기술 기반 UWP에서 앱이 실행된 방법을 확인하는 방법은 Windows.UI.WebUI.WebUIApplication.onactivated 이벤트(또는 WinJS 사용 시 WinJS.Application.onActivated 이벤트)의 두 번째 argument 아래에 있는 activationKind를 확인하면 됩니다. 여기에 나오는 모든 앱 실행(호출) 원인은 Windows.ApplicationModel.Activation.ActivationKind에 나와 있어 앱이 어떻게 켜졌는지를 확인하려면 여기에서 대조하면 됩니다. 점프 리스트에서 클릭되어 앱이 실행(호출)되었을 경우 일반적으로 아이콘을 클릭해서 실행했을 때(ActivationKind.launch)와 똑같이 분류되는데, 일반적인 실행과는 다르게 위에서 점프 리스트를 새로 만들면서 별도로 지정한 argument를 확인하면 어떤 메뉴를 통해 사용자가 들어왔는지 알 수 있습니다. 이 값은 위 이벤트의 두 번째 argument 아래에 있는 activatedEventArgs의 첫 번쨰 항목 안의 arguments 속성으로 확인할 수 있습니다.

JavaScript
function activatedEvt (element, options) {
    var ActivationKind = Windows.ApplicationModel.Activation.ActivationKind;
    //
    if (options && options.activationKind === ActivationKind.launch &&
        options.activatedEventArgs.length > 0) {
        if (options.activatedEventArgs[0].arguments != "") {
            // 점프 리스트에서 앱이 실행(호출)되었습니다. 점프 리스트를 생성할 때 만든 argument로 특정 메뉴를 확인합니다.

        } else {
            // 일반적으로 아이콘이 클릭되어 앱이 실행(호출)되었습니다.

        }
    } else {
        // 기타 특수한 방법으로 앱이 실행(호출)되었습니다. 어떻게 실행되었는지 ActivationKind로 확인합니다.

    };
};

Windows.UI.WebUI.WebUIApplication.addEventListener("activated", activatedEvt);
////////// 또는 WinJS를 사용할 경우 //////////
WinJS.Application.addEventListener("activated", activatedEvt);