LINE Front-end Framework
LINE Front-end Framework(LIFF)は、LINEが提供するウェブアプリのプラットフォームです。このプラットフォームで動作するウェブアプリを、LIFFアプリと呼びます。 ...
https://developers.line.biz/ja/docs/liff/overview/
こんにちは。エンジニアの佐々木です。最近アイスの実ばかり食べています。
Linc’wellは医療・ヘルスケアに関する複数のプロダクトを開発しており、その中で最近リリースしたのが「sai+ダイアリー」と呼ばれるプロダクトです。
sai+ダイアリーは、Linc’wellが持つ女性向けD2Cブランドの「sai+」を補完するためのプロダクトで、現在は女性の生理管理のための機能を提供しています。今後はピルの服用記録機能や医師との連絡機能を追加し、将来的には女性の健康をトータルサポートするプロダクトを目指しています。
sai+ダイアリーは、フロントエンドがTypeScriptとNext.jsを利用したSPAとなっており、Apollo ClientでGraphQLのAPIを呼んでいます。APIサーバーはRuby on Railsで作成しています。シンプルな構成のSPAですが、ターゲット層のユーザーのほとんどがLINEを利用することを考慮してLIFFと呼ばれる技術を採用しています。
恥ずかしながら最近までLIFFの存在を知りませんでしたが、実際に使ってみると容易にLINE上で動くアプリケーションを作成でき、またユーザーの体験も向上させることができました。本記事では、LIFFの概要やメリット、具体的な利用例を紹介します。
LIFFはLINE Front-end Frameworkの略で、LINE社が提供するウェブアプリのプラットフォームです。このプラットフォームで動作するウェブアプリを、LIFFアプリと呼びます。
アプリと聞くと身構える方もいるかもしれませんが、既存のウェブサイトのURLをLINE Developersコンソール画面で登録するだけでLIFFアプリになります。LINEでLIFFアプリのURLを開くことで、LIFFブラウザと呼ばれるWebViewを利用したブラウザでアプリケーションが開かれます。LIFFアプリはLIFF SDKが提供するAPIを利用でき、そのAPIを通じてLINEに登録したユーザーの情報やデバイスの情報の取得、LINEのアクション(投稿、カメラ起動、シェア等)を実行できます。
sai+ダイアリーでLIFFを利用する最大の目的は、シームレスな認証のためです。ユーザー登録やログインにおけるユーザーの離脱をなるべく避けるために、体験の良い認証を実現する必要がありました。LIFFを利用することで、ユーザーから見るとLINEログインすら必要がなくなり、アプリケーションを立ち上げると自動でログインしているように見えます。
LIFFは起動時にSDKがLINEログインを自動で行い、アクセストークンやIDトークンを取得します。sai+ダイアリーではここで取得したIDトークンを利用し、API認証を行っています。LIFFのIDトークンは有効期限が1時間であり、有効期限が切れた際にはAPI認証が通らなくなります。そのため、sai+ダイアリーではIDトークンの有効期限が切れたタイミングでアプリケーションを一度閉じて、再度開いてもらうようにユーザーに促しています。アプリを1時間開きっぱなしというユースケースが想定されなかったため、上記の解決策でも問題ないと判断しました。
以下はLIFFアプリを開いてから実際にサーバーで認証するまでのシーケンス図で、このフローに沿って認証を行っています。
LIFFのAPIでできることの例として以下のようなものがあります。
クライアント側で以下のような情報を取得できます。
LINEでLIFFアプリを開く場合は、LIFFの初期化時に自動でログイン処理が実行されますが、他の起動方法、例えばPCのブラウザから開く場合には別途ログイン処理を実装する必要があります。
login APIを利用すれば、処理実行時にLINEログインのダイアログが表示でき、PCのブラウザであっても容易にログイン処理を実装することができます。
shareTargetPicker APIを利用することで、開発者が作成したメッセージを、ユーザーが選択したグループ・友だちに対して、ユーザーが送信したかのように投稿することができます。これにより、最小限のユーザーの手間で情報のシェア、拡散を促すことができます。
その他提供されているAPIは以下に記載されています。
以下では、フロントエンド側でどのようなLIFFの使い方をしているかを説明していきます。導入が非常に簡単であることがわかると思います。
まず、複数のコンポーネントからLIFFのAPIを呼べるようにProviderとHooksを作成します。
なお、今回IDトークンをAPI認証に利用していて、IDトークンの有効期限切れを把握したかったためisExpire関数を定義しています。
// src/contexts/liff/index.tsx
import React, { createContext, useContext, useEffect, useState } from 'react';
import type Liff from '@line/liff';
type UseLiff = {
idToken?: string;
initialized: boolean;
isInClient: boolean;
loggedIn: boolean;
closeWindow?: () => void;
isExpire: () => boolean;
login?: () => void;
logout?: () => void;
};
const LiffContext = createContext<typeof Liff>(undefined);
export const LiffProvider: React.FC = ({ children }) => {
const [liff, setLiff] = useState<typeof Liff>(undefined);
useEffect(() => {
(async () => {
const liff = (await import('@line/liff')).default;
await liff.init({ liffId: process.env.NEXT_PUBLIC_LIFF_ID });
setLiff(liff);
})();
}, []);
return <LiffContext.Provider value={liff}>{children}</LiffContext.Provider>;
};
export const useLiff = (): UseLiff => {
const liff = useContext(LiffContext);
if (!liff) {
return {
initialized: false,
isInClient: false,
loggedIn: false,
isExpire: () => false,
};
}
const isExpire = (): boolean => {
if (!liff.isLoggedIn()) {
return false;
}
const expirationTime = liff.getDecodedIDToken().exp;
return expirationTime < Date.now() / 1000;
};
return {
idToken: liff.getIDToken(),
initialized: true,
isInClient: liff.isInClient(),
loggedIn: liff.isLoggedIn(),
closeWindow: liff.closeWindow,
isExpire: isExpire,
login: liff.login,
logout: liff.logout,
};
};
これだけです。
あとは、LIFFのAPIを呼び出したいコンポーネントでuseLiff()を記述し、LIFFの情報を取得したりAPIを呼び出すことができます。
const { idToken, initialized, closeWindow, isExpire } = useLiff();
現在は利用していないのですが、今後体験を良くしていくにあたり、LIFF間遷移と呼ばれる仕組みに注目しています。LIFF間遷移というのは、LIFFアプリから異なるLIFFアプリと行き来できるという仕組みです。
Linc’wellは、リモートで予約から受診まですべてが完結するオンライン診療サービスも開発しています。sai+ダイアリーとオンライン診療がLIFF間遷移できるようにすることで、ユーザーがsai+ダイアリー利用時にオンライン診療の予約が必要になった場合に、シングルサインオンしているような感覚でオンライン診療の予約ができるという体験を提供できるのではないかと感じています。
LIFFの概要、できること、利用例を紹介させていただきました。LIFFはフレームワークと言いつつも、少ないコードの変更で部分的に導入できます。サービスがLINE上で利用されることを前提とするのであれば、ユーザーの体験を向上させる手段の一つとしてLIFFが有効だと感じています。今回はLIFFの紹介でしたが、ユーザーの体験を突き詰めて技術を適用し、少しずつプロダクトを改善していきたいと思います。