OS 통합

웹 앱은 도달 범위가 넓습니다. 여러 플랫폼에서 실행됩니다. 링크를 통해 쉽게 공유할 수 있습니다. 그러나 전통적으로 운영 체제와의 통합이 없었습니다. 얼마 전까지만 해도 설치가 불가능했습니다. 다행히 이 점은 변경되었으며 이제 이러한 통합을 활용하여 PWA에 유용한 기능을 추가할 수 있습니다. 이러한 옵션 중 일부를 살펴보겠습니다.

파일 시스템 작업

파일을 사용하는 일반적인 사용자 워크플로는 다음과 같습니다.

  • 기기에서 파일이나 폴더를 선택하여 직접 엽니다.
  • 해당 파일이나 폴더를 변경하고 변경사항을 다시 직접 저장합니다.
  • 새 파일 및 폴더를 만듭니다.

File System Access API 전에는 웹 앱에서 이러한 작업을 할 수 없었습니다. 파일을 열려면 파일 업로드가 필요했고 변경사항을 저장하려면 사용자가 다운로드해야 했으며 웹은 사용자의 파일 시스템에 새 파일과 폴더를 만들 수 있는 액세스 권한이 전혀 없었습니다.

파일 열기

파일을 열려면 window.showOpenFilePicker() 메서드를 사용합니다. 이 메서드에는 버튼 클릭과 같은 사용자 동작이 필요합니다. 파일을 열기 위한 나머지 설정은 다음과 같습니다.

  1. 파일 시스템 액세스의 파일 선택 도구 API에서 파일 핸들을 캡처합니다. 이렇게 하면 파일에 대한 기본 정보가 표시됩니다.
  2. 핸들의 getFile() 메서드를 사용하면 파일에 관한 추가 읽기 전용 속성 (예: 이름, 최종 수정일)이 포함된 특별한 종류의 BlobFile를 가져올 수 있습니다. Blob이므로 Blob 메서드(예: text())를 호출하여 콘텐츠를 가져올 수 있습니다.
// Have the user select a file.
const [ handle ] = await window.showOpenFilePicker();
// Get the File object from the handle.
const file = await handle.getFile();
// Get the file content.
// Also available, slice(), stream(), arrayBuffer()
const content = await file.text();

변경사항 저장

파일에 변경사항을 저장하려면 사용자 동작도 필요합니다.

  1. 파일 핸들을 사용하여 FileSystemWritableFileStream을 만듭니다.
  2. 스트림을 수정합니다. 이렇게 해도 파일이 제자리에 업데이트되지 않으며, 대신 임시 파일이 생성됩니다.
  3. 마지막으로 변경을 완료하면 스트림을 닫으면 변경사항이 일시적에서 영구적으로 적용됩니다.

코드를 통해 확인해 보겠습니다.

// Make a writable stream from the handle.
const writable = await handle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();

파일 처리

File System Access API를 사용하면 앱 내에서 파일을 열 수 있지만 그 반대의 경우는 어떨까요? 사용자는 자주 사용하는 앱을 기본 앱으로 설정하여 파일을 열고 싶어 합니다. 파일 처리 API는 설치된 PWA를 허용하는 실험용 API입니다. 사용자 기기에서 파일 핸들러로 등록하고 PWA가 웹 앱 매니페스트에서 지원하는 MIME 유형 및 파일 확장자를 지정합니다. 지원되는 확장 프로그램에 맞춤 파일 아이콘을 지정할 수 있습니다.

등록이 완료되면 설치된 PWA가 사용자의 파일 시스템에 옵션으로 표시되어 사용자가 파일을 직접 열 수 있습니다. 다음은 PWA가 텍스트 파일을 읽기 위한 매니페스트 설정의 예입니다.

...
"file_handlers": [
     {
         "action": "/open-file",
         "accept": {
             "text/*": [".txt"]
         }
     }
]
...

URL 처리

URL 처리를 통해 PWA는 운영체제에서 범위에 속하는 링크를 캡처하여 기본 브라우저 탭이 아닌 PWA 창 내에서 렌더링할 수 있습니다. 예를 들어 PWA로 연결되는 메시지를 수신하거나 PWA에서 딥 링크 (특정 콘텐츠를 가리키는 URL)를 클릭하면 콘텐츠가 독립형 창에서 열립니다.

이 동작은 WebAPK가 사용될 때(예: 사용자가 Chrome으로 PWA를 설치할 때) Android에서 자동으로 적용됩니다. Safari에서는 iOS 및 iPadOS에 설치된 PWA의 URL을 캡처할 수 없습니다.

데스크톱 브라우저의 경우 웹브라우저 커뮤니티에서 새로운 사양을 만들었습니다. 이 사양은 현재 실험용이며 새로운 매니페스트 파일 멤버인 url_handlers이 추가됩니다. 이 속성에는 PWA에서 캡처하려는 출처의 배열이 필요합니다. PWA의 출처는 자동으로 부여되며, 다른 각 출처는 web-app-origin-association라는 파일을 통한 처리 작업을 수락해야 합니다. 예를 들어 PWA의 매니페스트가 web.dev에서 호스팅되고 app.web.dev 출처를 추가하려는 경우 다음과 같이 표시됩니다.

"url_handlers": [
    {"origin": "https://app.web.dev"},
]

이 경우 브라우저는 파일이 app.web.dev/.well-known/web-app-origin-association에 있는지 확인하여 PWA 범위 URL에서 URL 처리를 수락합니다. 개발자가 이 파일을 만들어야 합니다. 다음 예에서 파일은 다음과 같습니다.

{
    "web_apps": [
        {
            "manifest": "/mypwa/app.webmanifest",
            "details": {
                "paths": [ "/*" ]
            }
        }
    ]
}

URL 프로토콜 처리

URL 처리는 표준 https 프로토콜 URL에서 작동하지만 pwa://와 같은 커스텀 URI 스키마를 사용할 수도 있습니다. 여러 운영체제에서 설치된 앱은 스키마를 등록하여 이 기능을 사용할 수 있습니다.

PWA의 경우 이 기능은 데스크톱 기기에서만 사용할 수 있는 URL 프로토콜 핸들러 API를 통해 사용 설정됩니다. PWA를 앱 스토어에 배포해야 휴대기기의 맞춤 프로토콜을 허용할 수 있습니다.

등록하려면 registerProtocolHandler() 메서드를 사용하거나 매니페스트에서 다음과 같이 원하는 스키마 및 PWA 컨텍스트에서 로드할 URL과 함께 protocol_handlers 멤버를 사용합니다.

...
{
  "protocol_handlers": [
    {
      "protocol": "web+pwa",
      "url": "/from-protocol?value=%s"
    },
  ]
}
...

URL from-protocol를 올바른 핸들러로 라우팅하고 PWA에서 쿼리 문자열 value을 가져올 수 있습니다. %s는 작업을 트리거한 이스케이프된 URL의 자리표시자이므로 <a href="web+pwa://testing">와 같은 어딘가에 링크가 있다면 PWA에서 /from-protocol?value=testing이 열립니다.

다른 앱에 전화 걸기

URI 스키마를 사용하여 모든 플랫폼의 사용자 기기에 설치된 다른 모든 앱 (PWA 여부와 관계없이)에 연결할 수 있습니다. 링크를 만들거나 navigator.href를 사용하고 원하는 URI 스키마를 가리켜 URL 이스케이프 처리된 형식으로 인수를 전달하기만 하면 됩니다.

전화 통화에는 tel:, 이메일 전송에는 mailto:, 문자 메시지에는 sms:와 같이 잘 알려진 표준 스키마를 사용할 수 있습니다. 또는 잘 알려진 메시지, 지도, 내비게이션, 온라인 회의, 소셜 네트워크, 앱 스토어 등 다른 앱의 URL 스키마에 관해 알아볼 수도 있습니다.

웹 공유

브라우저 지원

  • 89
  • 93
  • 12.1

소스

Web Share API를 사용하면 PWA가 공유 채널을 통해 기기에 설치된 다른 앱으로 콘텐츠를 전송할 수 있습니다.

이 API는 Android, iOS, iPadOS, Windows, ChromeOS 등 share 메커니즘이 있는 운영체제에서만 사용할 수 있습니다. 다음을 포함하는 객체를 공유할 수 있습니다.

  • 텍스트 (titletext 속성)
  • URL (url 속성)
  • 파일 (속성 files개)

현재 기기에서 텍스트와 같은 간단한 데이터의 경우 navigator.share() 메서드가 있는지 확인하고 navigator.canShare() 메서드가 있는지 확인하는 파일을 공유할 수 있는지 확인합니다.

navigator.share(objectToShare)를 호출하여 공유 작업을 요청합니다. 이 호출은 undefined로 확인되거나 예외와 함께 거부되는 프로미스를 반환합니다.

Android의 Chrome과 iOS의 Safari에서 웹 공유 덕분에 공유 시트를 열고 있습니다.

웹 공유 타겟

Web Share Target API를 사용하면 PWA가 PWA 여부에 관계없이 해당 기기의 다른 앱에서 공유 작업의 대상이 될 수 있습니다. PWA는 다른 앱에서 공유한 데이터를 수신합니다.

이 기능은 현재 WebAPK 및 ChromeOS가 설치된 Android에서 사용할 수 있으며, 사용자가 PWA를 설치한 후에만 작동합니다. 앱이 설치되면 브라우저가 운영체제 내에 공유 타겟을 등록합니다.

웹 공유 타겟 초안 사양에 정의된 share_target 멤버로 매니페스트에서 웹 공유 타겟을 설정합니다. share_target는 다음과 같은 일부 속성이 있는 객체로 설정됩니다.

action
공유 데이터를 수신할 것으로 예상되는 PWA 창에 로드될 URL입니다.
method
HTTP 동사 메서드(예: GET, POST, PUT)가 작업에 사용됩니다.
enctype
(선택사항) 매개변수의 인코딩 유형. 기본값은 application/x-www-form-urlencoded이지만 POST과 같은 메서드의 multipart/form-data로 설정할 수도 있습니다.
params
웹 공유의 title, text, url, files 키의 공유 데이터를 URL(method: 'GET') 또는 선택한 인코딩을 사용하여 요청 본문에 전달하는 인수로 매핑하는 객체입니다.

예를 들어 매니페스트에 추가하여 공유 데이터 (제목 및 URL만)를 수신할 PWA를 정의할 수 있습니다.

...
"share_target": {
   "action": "/receive-share/",
   "method": "GET",
   "params": {
      "title": "shared_title",
      "url": "shared_url"
   }
}
...

이전 샘플에서 시스템의 앱이 제목이 있는 URL을 공유하고 사용자가 대화상자에서 PWA를 선택하면 브라우저는 출처의 /receive-share/?shared_title=AAA&shared_url=BBB로 이동하는 새 탐색을 만듭니다. 여기서 AAA는 공유 제목이고 BBB는 공유 URL입니다. JavaScript를 사용하면 URL 생성자로 파싱하여 window.location 문자열에서 이 데이터를 읽을 수 있습니다.

브라우저는 매니페스트의 PWA 이름과 아이콘을 사용하여 운영체제의 공유 항목을 제공합니다. 이러한 목적에는 다른 세트를 선택할 수 없습니다.

자세한 예와 파일 수신 방법은 Web Share Target API로 공유 데이터 수신을 참고하세요.

연락처 선택도구

브라우저 지원

  • x
  • x
  • x
  • x

소스

Contact Picker API를 사용하면 사용자가 하나 이상의 연락처를 선택할 수 있도록 사용자의 모든 연락처가 포함된 네이티브 대화상자를 렌더링하도록 기기에 요청할 수 있습니다. 그러면 PWA가 이러한 연락처로부터 원하는 데이터를 수신할 수 있습니다.

Contact Picker API는 주로 휴대기기에서 사용할 수 있으며 호환되는 플랫폼에서 navigator.contacts 인터페이스를 통해 모두 사용할 수 있습니다.

navigator.contacts.getProperties()로 쿼리할 수 있는 속성을 요청하고 원하는 속성 목록과 함께 단일 또는 여러 연락처 선택을 요청할 수 있습니다.

샘플 속성은 name, email, address, tel입니다. 사용자에게 연락처를 하나 이상 선택하라고 요청하는 경우 navigator.contacts.select(properties)를 호출하여 반환받고자 하는 속성의 배열을 전달할 수 있습니다.

다음 샘플은 선택 도구에 의해 수신된 연락처를 나열합니다.

async function getContacts() {
   const properties = ['name', 'email', 'tel'];
   const options = { multiple: true };
   try {
     const contacts = await navigator.contacts.select(properties, options);
     console.log(contacts);
   } catch (ex) {
     // Handle any errors here.
   }
}

자료