Share via


연결된 Windows 스토어 앱 만들기

우리 곁에는 항상 네트워크에 연결할 수 있는 장치가 있습니다. 최신형 냉장고와 세탁기에도 인터넷과 홈 네트워크에 연결하는 기능이 있습니다. 따라서 최종 사용자들은 앱을 연결하는 기능도 당연히 기대하게 될 것입니다. 이렇게 "연결된 앱"에서는 소셜 미디어, 디지털 미디어, 블로그 등 웹의 최신 콘텐츠를 사용합니다. 연결된 앱 개발은 표준이 되었지만 네트워크 연결 끊김, 네트워크 요금제 비용 또는 성능 문제와 같은 일반적인 문제를 처리해야 하는 숙제가 여전히 남아 있습니다. Windows 8에서는 연결된 앱을 예전보다 훨씬 더 쉽게 작성할 수 있습니다.

이 글에서는 Windows 스토어 앱 사용자에게 빠르고 유연하며 번거롭지 않은 연결된 환경을 제공하는 데 도움이 되는 유용한 팁 몇 가지를 살펴봅니다.

  • 시나리오에 적합한 API 선택
  • 적합한 네트워크 기능 선택
  • 네트워크 요금제에 맞게 앱 동작 조정
  • 네트워크 상태 변경에 대응
  • 유연성을 위한 콘텐츠 캐시

각 팁을 자세히 알아보겠습니다.

적합한 API 선택

집을 지으려면 적절한 공구가 필요합니다. 못을 박으려면 망치가 필요하고, 나무판을 자르려면 톱이 필요하고, 나사를 고정하려면 드라이버가 필요합니다. 마찬가지로 연결된 Windows 스토어 앱을 개발할 때도 적절한 네트워킹 API를 사용해야 합니다. Windows 8에서는 앱이 인터넷이나 사설 네트워크를 통해 다른 컴퓨터나 장치와 통신하는 데 사용할 수 있는 다양한 네트워킹 API를 제공합니다. 따라서 앱에 필요한 네트워킹 기능을 파악하는 것이 첫 단계입니다.

가장 일반적인 네트워킹 시나리오는 웹 사이트에 액세스하여 정보를 검색하거나 저장하는 것입니다. 간단한 예로 웹 사이트를 사용하여 사용자 정보와 게임 점수를 저장하는 게임이 있습니다. 이보다 복잡한 예로는 REST 기반 웹 서비스에 연결하여 웹 서비스에서 제공하는 라이브러리를 통해 정보에 액세스하거나 정보를 저장하는 앱이 있습니다. Windows 8에는 웹 서비스 및 웹 사이트에 연결하는 API가 몇 가지 있습니다. 앱은 이러한 API를 통해 REST를 지원하거나 기본 HTTP 프로토콜 명령(예: GET 및 POST)을 웹 서버로 보내는 웹 서비스에 액세스할 수 있습니다. 웹 액세스의 경우 앱을 개발할 때 사용한 언어에 따라 다른 API를 사용해야 합니다.

다음 코드는 REST 기반 웹 서비스를 사용하여 기본 요청 및 응답을 수행하는 방법을 보여줍니다. 이 경우 웹 서비스가 웹 서버에서 ASP.NET 스크립트를 실행할 수 있습니다.

JavaScript

 function makeXHRCall() {
    WinJS.xhr({ uri: "https://www.microsoft.com/en-us/default.aspx” }).done(
 function onComplete(result) {
 print(result.responseText);
 },
 function onError(err) {
 print("Error: " + err.responseText);
        });
}

C#

 private async void MakeHttpCall()
{
    HttpClient httpClient = new HttpClient();
    try {
        string response = await httpClient.GetStringAsync("https://www.microsoft.com/en-us/default.aspx");
    }
    catch (Exception) {
        // Handle exception.
    }
}

WinJS.xhr에 대한 자세한 내용은 웹 서비스에 연결(JavaScript 및 HTML을 사용하는 Windows 스토어 앱)을 참조하십시오. HttpClient에 대한 자세한 내용은 빠른 시작: HttpClient를 사용하여 연결(C#/VB/C++ 및 XAML을 사용하는 Windows 스토어 앱)HttpClient 샘플을 참조하십시오.

또 다른 일반적인 네트워킹 시나리오는 파일 전송 시간이 오래 걸릴 수 있는 파일을 다운로드하거나 업로드하는 경우입니다. 예를 들어 웹 서비스의 사진이나 사진 앨범을 업로드하거나 다운로드해야 하는 카메라 또는 사진 갤러리 앱이 있습니다. 이 경우 전송 시간이 오래 걸릴 수 있으므로 전송이 완료될 때까지 사용자를 기다리게 하는 것은 부적절합니다. Windows.Networking.BackgroundTransfer API는 앱을 실행하고 있지 않을 때에도 파일을 다운로드 또는 업로드할 수 있는 기능을 제공합니다. 앱이 포그라운드에서 실행 중이고 포커스가 있을 때 전송을 시작하면 앱을 종료하더라도 백그라운드에서 전송이 계속 진행됩니다.

좀 더 구체적인 다른 시나리오는 신디케이티드 콘텐츠에 액세스하는 경우입니다. Windows.Web.Syndication API는 RSS 또는 Atom 형식의 피드를 검색할 수 있습니다. 또한 Windows.Web.AtomPub API는 앱이 다양한 AtomPub 형식의 데이터를 게시하도록 지원합니다.

또한 API에서 상위 수준의 특정 네트워킹 프로토콜을 지원하지 않을 경우를 대비해 Windows 런타임에서 멀티캐스팅과 함께 TCP 및 UDP 소켓도 지원합니다. Windows.Networking.Sockets API는 다른 상위 계층의 프로토콜을 구현할 수 있는 StreamSocket(TCP) 및 DatagramSocket(UDP)을 제공합니다.

참고: Windows 8에는 WebSocket이라는 새로운 유형의 소켓이 도입되었습니다. WebSocket이란 무엇이고 어떤 앱에 적합한지 자세히 알아보려면 WebSocket을 사용하여 연결을 참조하십시오.

다음 표에는 지원되는 네트워킹 기능의 전체 목록과 추가 정보 링크가 나와 있습니다.

 

API

기능

 

 

 

 

RSS 또는 Atom 형식의 피드를 버전에 관계없이 검색합니다. OData와 같은 최신 형식에 대한 지원 기능을 쉽게 구현할 수 있는 API입니다. 또한 Windows 런타임은 Atom 컬렉션을 게시하는 데 사용되는 Atom Publishing Protocol도 지원합니다. 자세한 내용은 신디케이티드 콘텐츠 액세스 및 관리를 참조하십시오.

 

 

 

 

 

    • RSS 판독기

 

 

 

Windows.Networking.BackgroundTransfer

 

 

호출 앱이 포그라운드에 있지 않을 때도 사용 요금을 인식하며 콘텐츠 업로드 및 다운로드가 계속 진행되고 다시 시작할 수 있습니다. 이 API는 HTTP, HTTPS 및 FTP 프로토콜을 사용한 콘텐츠 전송을 지원합니다. 자세한 내용은 백그라운드로 데이터 전송을 참조하십시오.

 

 

 

 

    • SkyDrive

 

    • Xbox 동영상

 

 

 

 

 

 

 

 

 

 

REST 기반 웹 서비스 및 다른 HTTP 기반 프로토콜과 상호 작용합니다. 자세한 내용은 웹 서비스에 연결을 참조하십시오.

 

 

 

 

 

    • Bing 지도

 

 

 

Windows.Networking.Proximity

 

 

앱이 아주 가까이 있는 두 장치를 탐지한 후 소켓 API를 사용하여 두 장치 간에 네트워크 통신을 실행할 수 있습니다. 자세한 내용은 근접 연결 및 탭 지원을 참조하십시오.

 

 

 

 

    • 게임

 

    • 공동 작업 앱

 

 

 

Windows.Storage.Pickers

 

 

원격 파일 공유와 통신합니다. 자세한 내용은 데이터 및 파일에 액세스를 참조하십시오.

 

 

 

 

    • Xbox 음악

 

    • 사진

 

 

 

Windows.Networking.Sockets

 

 

앞서 언급한 SMTP, MAPI 또는 텔넷과 같은 API에서 지원하지 않는 프로토콜을 사용하는 서비스에 연결하거나 동일한 로컬 네트워크의 다른 장치에 연결합니다. HTTP 프록시를 포함한 웹을 통해 새 서비스에 연결하기 위해 소켓과 유사한 의미 체계(비동기, 양방향)가 필요한 앱에도 사용됩니다. 자세한 내용은 소켓을 사용하여 연결을 참조하십시오.

 

 

 

 

 

 

 

    • Lync, 공동 작업 화이트보드 또는 주식 투자

 

 

 

Windows.Storage.ApplicationData

 

 

Windows 8은 사용자 장치 간 특정 응용 프로그램 데이터를 자동으로 전환합니다. 사무실에서 PC를 사용하고 집에서 태블릿을 사용하는 등 둘 이상의 장치를 활용하고 있는 사용자가 여러 장치에 앱을 설치한 경우 응용 프로그램 데이터 로밍이 매우 유용합니다. 자세한 내용은 응용 프로그램 데이터 로밍에 대한 지침을 참조하십시오.

 

 

 

적합한 네트워크 기능 선택

네트워크 격리는 Windows 8에서 사용하는 앱 보안 모델의 일부입니다. Windows는 네트워크 경계를 적극적으로 검색하여 네트워크 격리에 대한 네트워크 액세스 제한을 적용합니다. 이러한 기능을 올바르게 배포하면 사용자와 앱을 악의적인 공격으로부터 보호하는 데 도움이 됩니다.

네트워크 액세스 범위를 정의하려면 앱이 네트워크 격리 기능을 선언해야 합니다. 이러한 기능을 선언하지 않으면 앱이 네트워크 리소스에 액세스할 수 없습니다. Windows에서 앱에 네트워크 격리를 적용하는 방법에 대해 자세히 알아보려면 네트워크 기능을 설정하는 방법을 참조하십시오.

동일한 장치에서 Windows 스토어 앱과 데스크톱 앱 간에 프로세스 간 통신 메커니즘으로 네트워킹을 사용할 수는 없습니다. 따라서 Windows 스토어 앱에는 IP 루프백 주소를 사용할 수 없습니다. Visual Studio 디버거를 사용할 경우 일부 개발 목적에 한해 IP 루프백 주소를 사용할 수 있는 예외가 적용됩니다. 자세한 내용은 루프백을 사용하도록 설정하고 네트워크 격리 문제를 해결하는 방법을 참조하십시오.

네트워크 액세스 요청은 두 가지 범주로 분류됩니다.

  1. 클라이언트에서 시작되는 아웃바운드 요청: 앱이 클라이언트 역할을 하며, 원격 컴퓨터(일반적으로 서버)에 초기 네트워크 요청을 보내 네트워크 액세스를 시작합니다. 앱이 하나 이상의 요청을 서버에 보내고, 서버가 단일 응답 또는 여러 응답을 다시 보냅니다. 예를 들어 웹 클라이언트 앱에서 웹 서버로의 모든 트래픽이 이 범주에 속합니다.
  2. 자발적 인바운드 요청: 앱이 네트워크 서버 역할을 하고, 원격 컴퓨터에서 들어오는 인바운드 네트워크 요청을 수신합니다. 원격 컴퓨터가 서버 역할을 하는 앱으로 초기 요청을 보내 네트워크 액세스를 시작합니다. 원격 컴퓨터가 하나 이상의 요청을 앱으로 보내고, 앱이 하나 이상의 응답을 원격 컴퓨터로 다시 보냅니다. 예를 들어 미디어 서버 역할을 하는 앱이 이 범주에 속합니다.

최소 권한의 원칙을 따라 앱에 필요한 기능만 추가하십시오. 앱은 클라이언트에서 시작하는 아웃바운드 요청만 필요할 수도 있지만 원치 않는 인바운드 요청을 수신해야 할 수도 있습니다. 네트워크를 통해 인증할 때 사용자 자격 증명 및 인증서에 액세스해야 하는 앱도 있습니다.

다음 표에는 연결된 앱에 주로 필요한 네트워크 격리 기능 및 기타 관련 기능이 자세히 설명되어 있습니다. 처음 3개는 연결된 앱에서 사용하는 주요 네트워크 격리 기능입니다. 실제로 연결된 앱은 이러한 기능 중 하나 이상을 사용해야 합니다. 나머지 기능은 일부 연결된 앱에 필요한 추가 기능입니다.

 

네트워크 기능

설명

앱의 예

인터넷(클라이언트)

 

 

공항이나 카페 등 공공 장소에서의 인터넷과 네트워크에 아웃바운드 액세스합니다. 인터넷 액세스가 필요한 대부분의 앱은 이 기능을 선언해야 합니다.

 

       

    • RSS 판독기

 

    • 소셜 네트워크

 

    • 게임

 

 

 

인터넷(클라이언트 및 서버)

 

 

공항이나 카페 등 공공 장소에서의 인터넷과 네트워크에 인바운드 및 아웃바운드 액세스합니다. 중요한 포트로의 인바운드 액세스는 항상 차단되어 있습니다. 이 기능은 인터넷(클라이언트) 기능의 상위 집합입니다. 둘 다 선언할 필요는 없습니다.

 

 

 

    • P2P 앱

 

    • 멀티캐스트를 사용하여 플레이어를 검색하는 멀티 플레이 게임

 

 

 

사설 네트워크(클라이언트 및 서버)

 

 

사용자가 신뢰하는 전용 공간에서의 네트워크에 인바운드 및 아웃바운드 액세스합니다. 일반적으로 집이나 직장의 네트워크입니다. 중요한 포트로의 인바운드 액세스는 항상 차단되어 있습니다.

 

 

 

    • NAS(Network Attached Storage) 콘텐츠에 액세스하는 앱

 

    • LOB(기간 업무) 앱

 

    • 사설(집 또는 직장) 네트워크에서 멀티캐스트를 사용하여 플레이어를 검색하는 멀티 플레이 게임

 

 

 

근접 연결

 

 

장치와의 필드 근접 통신에 필요합니다. 사용자가 초대장을 보내거나 수락하면 앱이 네트워크에 액세스하여 아주 가까이 있는 장치에 연결할 수 있습니다.

 

 

 

    • 아주 가까이 있는 사람과 멀티 플레이 게임

 

 

 

엔터프라이즈 인증

 

 

도메인 자격 증명이 필요한 기업 인트라넷 리소스에 연결하도록 접근 권한을 줍니다.

 

 

 

    • LOB(기간 업무) 앱

 

 

 

공유 사용자 인증서

 

 

사용자 ID를 인증하기 위해 스마트카드 인증과 같은 소프트웨어 및 하드웨어 인증에 액세스하도록 접근 권한을 줍니다. 런타임에 관련 API가 호출될 때 사용자가 조치를 취해야 합니다(예: 카드 삽입 또는 인증서 선택 등).

 

 

 

    • 가상 사설 네트워크 앱

 

  • LOB(기간 업무) 앱

이 검사 목록을 사용하여 앱에 네트워크 격리를 구성하십시오.

  • 앱에 필요한 네트워크 액세스 방향을 결정합니다(클라이언트에서 시작하는 아웃바운드 요청, 자발적 인바운드 요청 또는 둘 다).
  • 앱이 통신할 네트워크 리소스 유형을 결정합니다(집 또는 직장 네트워크의 리소스, 인터넷의 액세스 또는 둘 다).
  • 앱 매니페스트에 필요한 최소 네트워크 격리 기능을 구성합니다. 이 기능은 Microsoft Visual Studio 2012의 앱 매니페스트 디자이너를 사용하여 구성하거나 수동으로 추가할 수 있습니다.
  • 문제 해결용으로 제공된 네트워크 격리 도구로 앱을 배포 및 실행하여 테스트해 보십시오. 자세한 내용은 루프백을 사용하도록 설정하고 네트워크 격리 문제를 해결하는 방법을 참조하십시오.

다음은 Microsoft Visual Studio 2012의 앱 매니페스트 디자이너를 사용하여 네트워크 기능을 사용하도록 설정하는 방법을 보여주는 스크린샷입니다.

Visual Studio 2012에서 앱의 package.appxmanifest의 네트워크 기능 선택

Visual Studio 2012에서 앱의 package.appxmanifest의 네트워크 기능 선택

네트워크 요금제에 맞게 앱 동작 조정

가장 최근에 월 데이터 한도에 도달하거나 해외 여행을 한 적이 언제인지 생각해 보십시오. 이러한 경우에는 일반적으로 불필요한 네트워크 요금이 부과되지 않도록 장치와 앱을 주의해서 사용하게 됩니다.

Windows 8에서는 앱이 사용 가능한 네트워크 리소스를 모니터링하고 네트워크 요금제에 맞게 작동하도록 지원함으로써 이러한 사용자 문제를 해결합니다. 앱에 대한 사용자의 신뢰도를 높이려면 연결 요금이 부과될 수 있는 경우에 앱에서 이를 알려줄 수 있게 만들고 요금 발생을 피하거나 줄이도록 동작을 조정해야 합니다.

Windows.Networking.Connectivity API는 네트워크 연결 유형과 금액에 대한 정보를 제공합니다. 이를 통해 앱에서 네트워크 리소스를 평소대로 사용하는 시기, 아껴서 사용해야 하는 시기, 사용자에게 물어봐야 하는 시기를 결정할 수 있습니다.

ConnectionProfile은 네트워크 연결을 나타냅니다. ConnectionProfileConnectionCost를 사용하여 동작을 조정할지 여부를 결정할 수 있습니다. NetworkCostType 속성은 네트워크 연결 유형을 알려줍니다. 이 속성에는 다음 4개 값 중 하나가 올 수 있습니다.

  • Unrestricted - 무제한 이용 가능한 네트워크 연결입니다. 사용 요금이 부과되지 않고 사용량에 제한이 없습니다.
  • Fixed - 특정 한도까지 무제한 이용 가능한 네트워크 연결입니다.
  • Variable - 사용량이 바이트 단위로 측정되는 네트워크 연결입니다.
  • Unknown - 요금 관련 정보가 없는 네트워크 연결입니다.

ConnectionCost의 다른 여러 부울 속성도 자세한 정보를 제공합니다.

  • Roaming - 홈 제공자 외부 네트워크에 연결되어 있습니다.
  • ApproachingDataLimit - 데이터 요금제에 명시된 사용 한도에 도달했습니다.
  • OverDataLimit- 데이터 요금제에 명시된 사용 한도를 초과했습니다.

이러한 속성이 나타내는 상황을 앱에서 대응하게 하십시오. 연결이 Roaming일 때는 네트워크 사용 관련 데이터 요금이 비쌉니다. NetworkCostTypeVariable일 때는 사용자가 네트워크에서 주고받은 데이터 양에 대해 요금을 지불하는 네트워크 요금제를 이용하고 있는 것입니다. NetworkCostTypeFixed일 때는 사용자가 이미 데이터 한도를 초과했거나 데이터 한도에 도달한 경우 우려할 만한 원인이 있는 것입니다.

앱은 이러한 정보를 참조하여 다음과 같은 지침을 따라 네트워크 리소스를 가장 잘 사용하는 방법을 결정할 수 있습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

동작

연결 요금

앱 지침

일반

 

 

NetworkCostTypeUnrestricted 또는 Unknown이고 ConnectionCostRoaming이 아닙니다.

 

 

앱이 제한 사항을 구현하지 않습니다. 앱이 연결 요금을 Unlimited로 처리하고 사용 요금 및 사용량 제한의 적용을 받지 않습니다.

 

 

 

    • 미디어 플레이어 앱이 전체 HD 영화를 재생할 수 있습니다.

 

    • 앱이 제한 사항이나 프롬프트 없이 대용량 파일을 다운로드할 수 있습니다.

 

 

 

절약

 

 

NetworkCostTypeFixed 또는 Variable이고 ConnectionCostRoaming 또는 OverDataLimit이 아닙니다.

 

 

앱이 네트워크 사용량을 최적화하기 위한 제한 사항을 구현하여 네트워크 요금제에 대한 작업을 처리합니다.

 

 

 

    • 미디어 플레이어 앱이 저해상도로 영화를 재생할 수 있습니다.

 

    • 앱이 중요하지 않은 다운로드를 연기할 수 있습니다.

 

 

 

옵트인

 

 

ConnectionCostRoaming 또는 OverDataLimit입니다.

 

 

네트워크 액세스 요금이 요금제 금액을 훨씬 초과한 예외적인 경우를 앱에서 처리합니다.

 

 

 

    • 앱이 사용자에게 네트워크에 액세스할지 묻습니다.

 

  • 앱이 모든 백그라운드 데이터 네트워크 작업을 일시 중지합니다.

다음은 연결 요금을 확인하고 적절한 앱 동작에 대한 제안 사항을 반환하는 코드입니다.

JavaScript

 var CostGuidance = { Normal: 0, Conservative: 1, OptIn: 2 };
// GetCostGuidance returns an object with a Cost (with value of CostGuidance), 
// CostName (a string) and Reason, which says why the cost is what it is.
function GetCostGuidance() 
{
    var connectionCost = Windows.Networking.Connectivity.NetworkInformation.getInternetConnectionProfile().getConnectionCost();
    var networkCostConstants = Windows.Networking.Connectivity.NetworkCostType;
    var Retval = new Object();
    if (connectionCost.roaming || connectionCost.overDataLimit)
    {
        Retval.Cost = CostGuidance.OptIn;
        Retval.CostName = "OptIn";
        Retval.Reason = connectionCost.roaming
            ? "Connection is roaming; using the connection may result in additional charge."
            : "Connection has exceeded the usage cap limit.";
    }
    else if (connectionCost.networkCostType == networkCostConstants.fixed
        || connectionCost.networkCostType == networkCostConstants.variable)
    {
        Retval.Cost = CostGuidance.conservative;
        Retval.CostName = "Conservative";
        Retval.Reason = connectionCost.networkCostType == NetworkCostType.fixed
            ? "Connection has limited allowed usage."
            : "Connection is charged based on usage. ";
    }
    else
    {
        Retval.Cost = CostGuidance.Normal;
        Retval.CostName = "Normal";
        Retval.Reason = connectionCost.networkCostType == networkCostConstants.unknown
            ? "Connection is unknown."
            : "Connection cost is unrestricted.";
    }

    return Retval;
}

C#

 public enum NetworkCost { Normal, Conservative, OptIn };
public class CostGuidance
{
    public CostGuidance()
    {
        var connectionCost = NetworkInformation.GetInternetConnectionProfile().GetConnectionCost();
        Init(connectionCost);
    }
    public NetworkCost Cost { get; private set; }
    public String Reason { get; private set; }


    public void Init(ConnectionCost connectionCost)
    {
        if (connectionCost == null) return;
        if (connectionCost.Roaming || connectionCost.OverDataLimit)
        {
            Cost = NetworkCost.OptIn;
            Reason = connectionCost.Roaming
                ? "Connection is roaming; using the connection may result in additional charge."
                : "Connection has exceeded the usage cap limit.";
        }
        else if (connectionCost.NetworkCostType == NetworkCostType.Fixed
            || connectionCost.NetworkCostType == NetworkCostType.Variable)
        {
            Cost = NetworkCost.Conservative;
            Reason = connectionCost.NetworkCostType == NetworkCostType.Fixed
                ? "Connection has limited allowed usage."
                : "Connection is charged based on usage. ";
        }
        else
        {
            Cost = NetworkCost.Normal;
            Reason = connectionCost.NetworkCostType == NetworkCostType.Unknown
                ? "Connection is unknown."
                : "Connection cost is unrestricted.";
        }
    }
}

네트워크 요금제에 맞게 앱 동작을 조정하는 방법에 대해 자세히 알아보려면 네트워크 정보 샘플을 사용하십시오.

사용자는 또한 작업 관리자를 실행하여 각 앱이 사용하고 있는 네트워크 데이터의 양을 볼 수 있습니다. 다음은 예를 보여주는 스크린샷입니다.

앱별 CPU 및 네트워크 사용량을 볼 수 있는 작업 관리자의 앱 기록 탭

앱별 CPU 및 네트워크 사용량을 볼 수 있는 작업 관리자의 앱 기록 탭

네트워크 상태 변경에 대응

모바일 장치의 경우 네트워크 연결이 불안정할 수 있습니다. 모바일 3G 또는 4G 광대역 네트워크는 사용자의 집이나 창고 안에서 연결이 끊길 수 있지만 Wi-Fi는 계속 사용할 수 있습니다. 마찬가지로 사용자가 집 밖으로 나가면 Wi-Fi 연결이 끊길 수 있습니다. 네트워크를 아예 사용할 수 없을 때도 있습니다. Wi-Fi와 모바일 광대역 네트워크의 보급으로 이러한 네트워크 변경은 자주 일어날 수 있습니다.

NetworkStatusChanged 이벤트는 적용 요금 또는 연결 옵션이 변경되었다는 의미입니다. 네트워크 상태 변경에 대응하고 변경이 생겼을 때 원활한 고객 경험을 제공하려면 연결된 앱에서 이러한 시나리오 지침을 따라야 합니다.

오류로 인한 연결 끊김

대부분의 경우 네트워크 작업을 다시 시도하면 연결을 다시 설정할 수 있습니다. 실패할 경우 NetworkStatusChanged 이벤트를 기다리십시오. 연결이 계속 실패할 경우 50밀리초 값부터 기하급수적으로 늘어나는 백오프 재시도 간격을 앱에 사용하는 것이 좋습니다.

네트워크 연결 끊김

사용자에게 연결이 끊겼음을 알려주고 등록 후 NetworkStatusChanged 이벤트를 기다리십시오.

새 네트워크 사용 가능성

장치가 여러 네트워크에 연결되는 경우가 있습니다. 예를 들어 사용자가 집 밖에서 모바일 광대역에 연결하고 Windows 8 메시지 앱을 사용하여 친구들과 채팅한 후 집에 돌아와서 무제한 네트워크에 연결하는 경우가 있습니다. Windows 8의 기본 정책은 네트워크 요금제보다는 무제한 네트워크로, 느린 네트워크보다는 빠른 네트워크로 설정하는 것입니다. 그러나 앱에 의해 설정된 기존 연결은 새 네트워크로 자동 전환되지 않습니다. 새 네트워크로 전환할지 여부는 앱만 결정할 수 있으므로 앱이 관여해야 합니다.

예를 들어 동영상 스트림이 거의 완료된 경우 새 네트워크로 전환하는 것은 부적절합니다. 그러나 현재 네트워크가 패킷을 삭제하고 있거나, 너무 느리거나, 스트림이 완료될 때까지 추가 시간이 필요할 경우 새 네트워크로 전환하는 것이 가장 좋습니다.

네트워크 전환이 앱 시나리오에 적절한 것으로 판단되면 새 네트워크가 탐지되었을 때 다음 지침을 따르십시오.

  1. 기존 네트워크와 새 네트워크의 네트워크 요금을 확인합니다. 새 네트워크로 전환하는 것이 적절할 경우 방금 말한 지침에 따라 새 네트워크 연결을 설정하고 네트워크 작업을 다시 시도하십시오. Windows는 자동으로 네트워크 요금제보다 무제한 네트워크를, 느린 네트워크보다 빠른 네트워크를 우선적으로 선택합니다.
  2. 새 네트워크 연결이 완료되면 앱의 새 네트워크 연결을 사용하고 기존의 연결이 있을 경우 이전 네트워크에 대한 원래 네트워크 작업을 취소하십시오.

네트워크 비용 변경

NetworkCostTypeFixed이고 사용량이 데이터 한도에 도달했거나 초과한 경우 네트워크 요금이 변경될 수 있습니다. NetworkCostTypeVariable이 되거나 Roaming이 true로 변경될 경우에도 네트워크 요금이 변경될 수 있습니다. 이러한 경우 이전 팁의 지침을 따라 앱 동작을 조정하십시오.

다음은 NetworkStatusChanged 이벤트를 사용하여 다양한 네트워크 상태 변경에도 원활한 앱 경험을 제공하는 코드 예입니다. 두 예는 모두 registeredNetworkStatusNotification이라는 전역 부울 변수를 사용하며, 이 변수는 처음에 false로 설정되어 있습니다.

JavaScript

 // Register for NetworkStatusChanged notifications, and display new 
// Internet ConnectionProfile info upon network status change.
function registerForNetworkStatusChange() {
    try {

        // Register for network status change notifications.
        if (!registeredNetworkStatusNotification) {
            var networkInfo.addEventListener("networkstatuschanged", onNetworkStatusChange);
            registeredNetworkStatusNotification = true;
        }
    }
    catch (e) {
        print("An unexpected exception occurred: " + e.name + ": " + e.message);
    }
}

// Event handler for NetworkStatusChanged event
function onNetworkStatusChange(sender) {
    try {
        // Get the ConnectionProfile that is currently used to connect 
        // to the Internet.
        var internetProfile = networkInfo.getInternetConnectionProfile();
        if (internetProfile === null) {
            print("Not connected to Internet\n\r");
        }
        else {
            internetProfileInfo += getConnectionProfileInfo(internetProfile) + "\n\r";
            print(internetProfileInfo);
        }
        internetProfileInfo = "";
    }
    catch (e) {
        print("An unexpected exception occurred: " + e.name + ": " + e.message);
    }
}

C#

 // Register for NetworkStatusChanged notifications, and display new 
// Internet ConnectionProfile info upon network status change.
void NetworkStatusChange()
{
    // Register for network status change notifications.
    try
    {
        var networkStatusCallback = new NetworkStatusChangedEventHandler(OnNetworkStatusChange);
        if (!registeredNetworkStatusNotification)
        {
            NetworkInformation.NetworkStatusChanged += networkStatusCallback;
            registeredNetworkStatusNotification = true;
        }
    }
    catch (Exception ex)
    {
        rootPage.NotifyUser("Unexpected exception occurred: " + ex.ToString(), NotifyType.ErrorMessage);
    }
}

// Event handler for NetworkStatusChanged event
async void OnNetworkStatusChange(object sender)
{
    try
    {
        // Get the ConnectionProfile that is currently used to connect 
        // to the Internet 
        ConnectionProfile InternetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();

        if (InternetConnectionProfile == null)
        {
            await _cd.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                rootPage.NotifyUser("Not connected to Internet\n", NotifyType.StatusMessage);
            });
        }
        else
        {
            connectionProfileInfo = GetConnectionProfile(InternetConnectionProfile);
            await _cd.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                rootPage.NotifyUser(connectionProfileInfo, NotifyType.StatusMessage);
            });
        }
        internetProfileInfo = "";
    }
    catch (Exception ex)
    {
        rootPage.NotifyUser("Unexpected exception occurred: " + ex.ToString(), NotifyType.ErrorMessage);
    }
}

NetworkStatusChanged 이벤트에 대해 자세히 알아보려면 빠른 시작: 연결 이벤트 및 가용성 변경 관리네트워크 정보 샘플을 참조하십시오.

유연성을 위한 콘텐츠 캐시

콘텐츠를 디스크에 캐시하면 앱이 빠르고 유연하게 동작합니다. 예를 들어 RSS 피드 판독기 앱은 이전 세션에서 디스크에 캐시된 피드를 즉시 표시할 수 있습니다. 최신 피드가 공개되자 마자 앱의 콘텐츠가 업데이트됩니다. 캐싱은 앱을 시작하는 즉시 사용자가 콘텐츠를 읽고 앱에서 새 콘텐츠를 가져오도록 해줍니다.

Windows 8에서는 Windows.Storage 네임스페이스에 ApplicationData 클래스를 제공합니다. 이 클래스는 앱 데이터 저장소에 대한 액세스를 제공합니다. 이 데이터 저장소는 장치의 로컬에 있거나, 여러 장치 간에 로밍되거나, 임시로 저장된 파일 및 설정으로 구성되어 있습니다.

파일은 일반 파일 형식의 대용량 데이터 집합, 데이터베이스 또는 데이터를 저장하는 데 적합합니다. 파일은 Roaming, Local 또는 Temporary 폴더에 있을 수 있습니다. 자세한 의미는 다음과 같습니다.

  • 로밍 파일은 사용자가 연결된 계정을 사용하여 로그인한 여러 시스템 및 장치 간에 동기화됩니다. 파일 로밍은 즉시 이루어지지 않습니다. 시스템에서 여러 요인을 평가하여 데이터를 보낼 시기를 결정합니다. 로밍 데이터 사용량은 할당량(RoamingStorageQuota 속성을 통해 사용 가능) 미만으로 유지하십시오. 할당량을 초과할 경우 데이터 로밍이 일시 중단됩니다. 앱이 파일에 데이터를 쓰고 있을 때는 파일을 로밍할 수 없으므로 더 이상 필요 없는 앱의 파일 개체를 닫으십시오.
  • 로컬 파일은 시스템 간에 동기화되지 않습니다. 파일이 처음으로 작성된 시스템에 남아 있습니다.
  • 임시 파일은 사용되지 않을 때 삭제될 수 있습니다. 시스템에서는 임시 파일을 삭제할 시기 또는 삭제할지 여부를 결정할 때 사용 가능한 디스크 용량이나 파일 저장 기간 같은 요소를 고려합니다.

다음은 디스크에 콘텐츠를 캐시하는 코드 예입니다. 서버 응답을 캐시하면 앱을 종료했다가 다시 시작하는 즉시 사용자에게 콘텐츠가 표시됩니다. 이러한 예에는 편의상 앱 데이터 저장소에 설정을 기록하는 방법이나 로밍 이벤트에 대응하는 방법 등은 나와 있지 않습니다. 자세한 내용은 응용 프로그램 데이터 샘플을 참조하십시오.

JavaScript

 var roamingFolder = Windows.Storage.ApplicationData.current.roamingFolder;
var filename = "serverResponse.txt";

function cacheResponse(strResponse) {
    roamingFolder.createFileAsync(filename, Windows.Storage.CreationCollisionOption.replaceExisting)
        .done(function (file) {
            return Windows.Storage.FileIO.writeTextAsync(file, strResponse);
        });
}

function getCachedResponse() {
    roamingFolder.getFileAsync(filename)
        .then(function (file) {
            return Windows.Storage.FileIO.readTextAsync(file);
        }).done(function (response) {
            print(response);
        }, function () {
            // getFileAsync or readTextAsync failed. 
            // No cached response.
        });
}

C#

 MainPage rootPage = MainPage.Current;
StorageFolder roamingFolder = null;
const string filename = "serverResponse.txt";

async void cacheResponse(string strResponse)
{
    StorageFile file = await roamingFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
    await FileIO.WriteTextAsync(file, strResponse);
}

async void getCachedResponse()
{
    try
    {
        StorageFile file = await roamingFolder.GetFileAsync(filename);
        string response = await FileIO.ReadTextAsync(file);
    }
    catch (Exception)
    {
        // getFileAsync or readTextAsync failed.
        // No cached response.
    }
}

앱 데이터 저장소에 대한 자세한 내용을 알아보려면 앱 데이터 로밍 게시물을 참조하고 응용 프로그램 데이터 샘플을 사용해 보십시오.

결론

Windows 스토어 앱을 계획할 때는 이 글의 지침에 따라 유용하고 번거롭지 않으며 연결된 환경을 제공하십시오. 이러한 팁은 개발 프로세스를 단축할 뿐만 아니라 앱의 유연성을 유지하고 사용자 신뢰도를 높여줄 수 있습니다.

- Windows 프로그램 관리자 II, Suhail Khalid

도움을 주신 분: Steven Baker와 Peter Smith