GDPR対象国のiOSアプリ側での判定を考える

##はじめに

###背景
2018年5月25日より個人情報保護に関わる規則として、[EEA加盟国](https://ja.wikipedia.org/wiki/%E6%AC%A7%E5%B7%9E%E7%B5%8C%E6%B8%88%E9%A0%98%E5%9F%9F)を対象に[GDPR - EU 一般データ保護規則](https://www.jetro.go.jp/ext_images/_Reports/01/dcfcebc8265a8943/20160084.pdf)が施行されました。各種のアプリからのお知らせ等でご存知の方も多いかと思います。（プライバシーポリシーの改定などで直近多くの連絡が行われていました）
本保護規則の施行に際しまして、サーバ側、DB側など各レイヤーで対応が必要かと思われますが、本記事ではiOSアプリ内で保護対象国に現在いるかどうかの判定をいかに行うのが良いかを考察してみます。

###前提
* 本記事の見解は筆者の個人的なものであり、筆者の所属する組織の公式見解は一切含みません
* 筆者は法律は専門としていないため、法的解釈に関して誤りを含む可能性があります

法的な解釈や具体的な対応内容に関しては以下の参考資料を当たるのが良いかと思われます。

* [Jetroでの特集 - EU 一般データ保護規則（GDPR）について](https://www.jetro.go.jp/world/europe/eu/gdpr/?guid=ON)
* [個人情報保護委員会 - GDPR](https://www.ppc.go.jp/enforcement/cooperation/cooperation/GDPR/)
* [欧州連合](http://eur-lex.europa.eu/eli/reg/2016/679/oj)

##使用環境
以下の環境を使用しています。

* Xcode9.3
* Firebase iOS SDK 4.9.0
* Firebase RemoteConfig

##達成目標
以下を本記事での達成目標とします。

* GDPR対象国の判定をアプリ内で行う

具体的には以下の対応になります。
 GDPR対象国（EEA加盟国31ヶ国）にアプリ使用時に滞在しているかどうかを判定する。「アプリ使用時に」としているのはGDPRの規則内に以下の記載があるためです。

>GDPRの対象となる個人データは、EU加盟国など31か国の欧州経済領域（EEA）域内に存在する個人に関する個人データです（GDPR第２条）。国籍や居住地を問わず、EEA域内に短期滞在する出張者や旅行者の情報も対象となります。

そのため、日本国籍を所持しているユーザーであったとしても、EEA加盟国に旅行に行った場合は、旅行期間中の情報はGDPRの対象となり得ます。


##方法１ TimeZoneの使用

アプリのTimeZoneを使用して判定する方法です。iOSの設定アプリ内で固有の国にしておらず、自動設定となっていた場合は、現在地から適切なTimeZoneが取得できるため、タイムラグなく、判定することができます。問題点としては、TimeZoneをユーザーが固定していた場合に現在地の情報が正常に反映されないことです。

![日付と時刻.png](https://qiita-image-store.s3.amazonaws.com/0/154099/aa1b919d-11c6-6c21-c1e2-87725c53c262.png)


現在のTimeZoneは下記の方法で取得できます。

```Swift
let currentTimeZone = TimeZone.current.identifier
```


対象国が今後追加・削減されることを考慮し、対象国のリストはアプリ内部でのみ持つのではなく、外部から追加・削除できるようにするのが良いのではないかと思われます。例えば、FirebaseのRemoteConfigで対象国のTimeZoneのリストを作成し、アプリで配列化、現在のTimeZoneが該当のTimeZoneに含まれるかで判別するというのが良いのではないでしょうか。
例えば、以下のようなメソッドを作成すれば判定できそうです。

```Swift
// RemoteConfigから対象国のTimeZoneのStringを取得し、配列化します
// 例えば、該当国のTimeZoneを ','区切りで設定していた場合
// なおRemoteConfigからの値取得処理は割愛します、参考文献をご参照ください
let targetCountryTineZones = targetCountryTineZonesString.components(separatedBy: ",")

if isGDPRTargetCountry(targetCountryTimeZones: targetCountryTineZones) {
    // GDPR対象国用の処理
}

func isGDPRTargetCountry(targetCountryTimeZones: [String]) -> Bool {
    let currentTimeZone = TimeZone.current.identifier
    return targetCountryTimeZones.contains(currentTimeZone)
}
```

なお、補足ですが、iOSで規定されているTimeZoneの一覧は以下のメソッドで取得可能です。

```Swift
TimeZone.knownTimeZoneIdentifiers
```

##方法2 GeoCoderの使用
アプリで緯度・経度を取得している場合に使用できる方法です。
緯度・経度が取得できている場合は、iOSのCLGeoCoderを使用して以下のように国コードが取得可能です。
※サンプルで取得しているコードは２桁の国コードです。（例：日本 - JS）
しかし、国コードの取得が非同期であることから、取得タイミングや方法は検討が必要です。
例えばですが、アプリ起動時などに国コードを取得、UserDefaultsに保存、判定時にはUserDefaultsの保存情報を使用、という方法が良いのではないでしょうか。

```Swift
final class GeoCoderWrapper {
    static private var countryCode: String? {
        get { return UserDefaults.standard.string(forKey: #function) }
        set { UserDefaults.standard.set(newValue, forKey: #function) }
    }
    
    // 緯度・経度情報からCountryコードを取得し、UserDefaultsに保存
    // locationはCLLocationManagerで取得済みとする
    static func updateCountryCode(location: CLLocation) {
        let geoCoder = CLGeocoder()
        geoCoder.reverseGeocodeLocation(location) { (placeMarks, error) in
            // placeMarkは複数返却されるため、１番目を取得
            GeoCoderWrapper.lastISOCountryCode = placeMarks?.first?.isoCountryCode
        }
    }
}
```

先ほどのTimeZoneの場合と同じく、Firebaseやサーバ側で対象国のリストを生成しておき、該当の国コードが対象国に含まれるかどうかを持って、判定を行います。

```Swift
func isGDPRTargetCountry(targetCountryCodes: [String]) -> Bool {
    guard let currentCountryCode = GeoCoderWrapper.countryCode else { return true }
    return targetCountryCodes.contains(currentCountryCode)
}
```

なお、対象国31ヶ国の国コードのリストは下記になりそうです。
```
LI,IS,NO,AT,BE,BG,HR,CY,CZ,DK,EE,FI,FR,DE,GR,HU,IE,IT,LV,LT,LU,MT,NL,PL,PT,RO,SK,SI,ES,SE,GB
```

##番外編

###Firebaseの条件（地域、言語）
FirebaseのRemoteConfigを設定する際に該当のプロパティに対し、条件を設定し条件毎に返却値を分けることができます。ただ、Firebaseの該当プロパティは設定アプリの地域や言語を見て判定を行っていました。地域や言語設定はユーザーが明示的に変更しない限り変更されません。そのため、日本からEU圏に移動していたとしても、地域・言語は変更されないため、GDPRの対応の対象としては認識できず、要件を満たすことができません。
Firebaseのコンソール上で直感的に対象を絞り込めるため、良いなと考えていましたが、この方法は使用できなさそうです。

![言語と地域.png](https://qiita-image-store.s3.amazonaws.com/0/154099/86314614-8ccb-1047-e8ff-fa53df647d59.png)

![国:地域.png](https://qiita-image-store.s3.amazonaws.com/0/154099/3cb33f04-12b0-32da-cb5c-6460822bfea7.png)


##最後に
GDPRは罰則が年間売上の4%か2000万ユーロのいずれか高い方と大変厳しく、ユーロ圏を対象にサービスを提供しているアプリでは対応が必須だと考えています。本情報がどなたかのお役に立てましたら幸いです。こういった方法があるのではないか、といった情報がありましたら、コメントいただけますと幸いです。

##参考資料

### iOS
* [Firebase iOS RemoteConfig](https://firebase.google.com/docs/remote-config/use-config-ios?hl=ja)
* [GeoCoderについて](https://developer.apple.com/jp/documentation/UserExperience/Conceptual/LocationAwarenessPG/UsingGeocoders/UsingGeocoders.html) 
* [GeoCoder - Apple公式ドキュメント](https://developer.apple.com/documentation/corelocation/clgeocoder)

### iPhone
* [TimeZoneの設定](https://support.apple.com/ja-jp/HT203483)
* [言語の設定 - apple document](https://support.apple.com/ja-jp/HT204031)

### 国コード
* [国名と国コードの対応表 MicroSoft](https://msdn.microsoft.com/ja-jp/library/ee783931%28v=cs.10%29.aspx?f=255&MSPPError=-2147217396)
* [ISO-3166-1　国コード - Wikipedia](https://ja.wikipedia.org/wiki/ISO_3166-1)

### GDPR
* [Jetroでの特集 - EU 一般データ保護規則（GDPR）について](https://www.jetro.go.jp/world/europe/eu/gdpr/?guid=ON)
* [個人情報保護委員会 - GDPR](https://www.ppc.go.jp/enforcement/cooperation/cooperation/GDPR/)
* [欧州連合](http://eur-lex.europa.eu/eli/reg/2016/679/oj)