SQL、サーバ、フロントで出来る処理は、どこにやらせるべきなのか

![15743358488980752.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330109/f3382b1b-ad63-a9cf-8772-e1e5b55e5d55.png)

[ここ](https://nippori30.herokuapp.com/hanabi/post)で作成しました。
~~あ、ボクはやりたいことをやれたので満足です。フロントごめん~~

## まえおき
> SQLが最速なんだから、可能な限り処理はSQLにやらせるべきだよね！

というツイート(ネタかガチか分からない)を読んだ。この業界に**銀の弾丸**は存在しないはずだが……。

では、SQL、サーバサイド、フロントエンドで書ける処理はどこに書くべきなのだろうか？
それを判断する材料を考えてみた。

## 例題

| DBの値 | 画面に出したい値 |
| :--- | :--- |
|10|￥10|
|999|￥999|
|5000|￥5,000|
|10500|￥10,500|
|21000|￥21,000|


上記のDBの値をブラウザ上に表示させるという仕様があり、既に値自体は画面に表示できているが、三桁区切りと通貨記号(￥)を実装しなければらない！とする。

## 実装例

※一応書いたけど、そんなに重要じゃない

### ①SQL

下記はOracleの例だが、`TO_CHAR関数`を付けるだけで出来る。
サーバサイドのEntityをstring型に変更することになった。

``` sql
-- Oracle (※DBに通貨記号の設定をする必要がある)
SELECT TO_CHAR(カラム名, 'FML999,999,999') FROM テーブル名;
```

### ②サーバサイド

下記はなんとなくC#だが、扱う金額によってはintで済まない。
処理はC#特有であるが、普通に先頭に通過記号つけて、三桁ごとに文字連結とかでもいいんだけどネ。

```C# 
using System;
using System.Collections.Generic;
using System.Globalization;
public class Money{
    public static void Main(){
        
        // paiza.ioで試したんだが
        // デフォルトだとドルになっちまうんだナ
        CultureInfo jpn = new CultureInfo("ja-JP", false);

        // DBから取ってきたテイのList
        List<int> moneyList = new List<int>();
        moneyList.Add(10);
        moneyList.Add(999);
        moneyList.Add(5000);
        moneyList.Add(10500);
        moneyList.Add(21000);

        // 画面に表示させる値を入れるリスト
        List<string> moneyDisplay = new List<string>();

        // 3桁区切りで通貨記号をつける
        foreach(int money in moneyList)
        {
            moneyDisplay.Add(money.ToString("C", jpn));
        }
        
        // 出力
        foreach(string result in moneyDisplay)
        {
            // マジレスすると俺C#書けないわ。よくがんばった
            Console.WriteLine(result);
        }
    }
}
```

### ③フロントエンド

このAPIは[対応していないブラウザもあるらしい](https://qiita.com/shisama/items/661c33fef5cbe3bb8335)
ブラウザ対応の都合を考えて、一般的には正規表現でやる。

```JavaScript
const money = [10, 999, 5000, 10500, 21000];

// 便利なAPIで日本円にしてくれる
const formatter = new Intl.NumberFormat('ja-JP', {
    style: 'currency',
    currency: 'JPY'
});

const displayMoney = money.map(value => formatter.format(value))

// 配列を出力
console.log(displayMoney);
```

## 判断基準

①処理時間
この場合、レコードは5件しかないので、SQL、サーバサイド、フロントエンドのいずれでやっても`人間にとっては些細な時間`であろう。**もしも千件、万件を画面に出そうとしているならSQLが圧倒的に早そう**……だけど、少し思いとどまったほうがいいかもしれない。その仕様は本当に大丈夫？

②値の汎用性
もしも`出力した値を計算に使う場合`はDBでやってしまうと、サーバは文字列型として受け取ってしまうので、サーバ、フロント側で計算処理を書きづらくなる。したがって、SQL以外で処理した方が後で値を使いまわしやすい

③負荷
今回はほぼ影響ないが、処理をサーバ側でやると`サーバに負荷がかかる`ので、フロントのほうが良い。特に大量にアクセスされるページとかは、なるべくフロントにしたいところ。ブラウザ側で処理が遅くならないようにバランスは調整したい

④役割
この処理は「画面に表示させる処理」ではないので、サーバサイドで行う。「JavaScriptはサーバとの通信とDOM操作だけに徹底する！計算とかはしない！」ルールがあるなら、それもアリ。フロントとサーバの役割をぎっちり分ける会社、現場も一応見たことはある

⑤改修
あんまり気にすることはないかもしれないが、10年、20年後に改修するときにDBがOracleからPostgreSQLに変わるかもしれない。そうなったときに、SQLで関数を多用していたりすると書き直しになる可能性が高い。「SQL YYYY構文」(YYYYには年数が入る)以外の使用は可能な限り避けた方が良いだろう。
サーバサイドは言語のバージョンアップがあるかもしれない。言語の変更もあり得なくはない。フロントエンドはどうなんだろう(JSの改修案件とかみたことない)

※上記の判断基準は一例だが、SQLはオススメできない……。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330109/ee214d51-d2ea-dc7a-9503-2e29383ca253.png)

## まとめ
- (基本的に)SQLの処理って早いと思うよ
- 自分だったらこの処理をフロントエンドでやりそう
- 銀の弾丸はない。現場のルールやいろいろな判断基準を元にどこで書くのが良いかしっかり検討しよう。最速だから何でもかんでもSQLにすればいい！ってもんじゃない

#### 最後に
「いいね」ボタンを押して頂けると、うれしくなって記事を書けます。
あと、一緒に記事を書くIT芸人会の仲間を探しています。