ロゴに隠された面倒なあれこれ〜誰でも目指せるロゴマスターへの道のり〜

こんにちは!こんばんは! トラストバンクデザイナーの脇川です。

突然ですが、みなさんは自社や他社のロゴガイドラインを穴が開くまで見つめたことはありますか?僕が予想するに大抵の方はまだ穴が開いてない思います。そして、一部にはガイドラインは知ってるけど見たことないよなんていう方もいるかと思います。そんな方には許されざる呪文を。。。

というのは冗談で、実際にまじまじと見る人が少ないのも現状なのですが、デザイナーとしては制作したからには理解してほしい!という微かなエゴがあるわけなのです。
今回は誰でも理解できるように我らがトラストバンクのサービスである「ふるさとチョイス」のロゴガイドラインを見ながら説明していきたいと思います。
これで明日からあなたもロゴマスターです。


そもそもガイドラインってなんであるのよ

これはとーーーーっても重要なお話です。ブランドを守るためです。

会社には企業活動を行うために自らの存在価値や理念、行動指針を定めたCI(コーポレートアイデンティティなるものが存在し、またその中にブランド全体の見栄えを左右する様々なデザイン要素について規定しているVI(ビジュアルアイデンティティがあるわけなのですが、その一部がロゴガイドラインな訳です。

既にめまいを起こしている方がいるかもしれませんね。

簡単に言うと弊社で言えばふるさとチョイスのロゴが黄色や緑になったらイメージ変わっちゃうよね!
小さすぎて見えなかったら意味ないよね!
大切なブランドなんだから大事にしてよ!ってことなわけですね


では実際に見ていきましょう

おいおい、待ってくれよ
早速よくわからない言葉が出てきたじゃないか

そんな言葉が聞こえてきそうですね〜



プライマリーロゴとセカンダリーロゴ

プライマリー?? セカンダリー????

ワシは英語圏の民ではないのでわからないのじゃ
というある種極めに極めた方々に説明すると

プライマリーロゴ

とりあえず迷ったらこれ使って!ロゴです。

雑に説明しましたが、優先的に使ってほしいロゴですね。
弊社のプライマリーロゴはこんな感じです↓

セカンダリーロゴ

優先度は低いけど全然使っていいからね!ロゴです。

伝え方が下手だとブログに向いていないということが今わかりました。
つまりプライマリーロゴが使いにくい場合はセカンダリーロゴになるわけですね。
こんな感じ↓

じゃあ1番ロゴ2番ロゴにすればよくないですか?
というある種極めに極めた方々から横やりが飛んできそうですがこれはアレですあの〜
かっこいいからです。
ほら、国境を越えて世界中の方々が見るかもしれないじゃないですね、ね
さてと、続いては



アイソレーション

先ほどの資料に「A」やら「0.25A」やらの数字とアルファベットが並んだパスワードが並んでいましたが、実はこれ脱出ゲームではありません。
これですね↓

これはロゴの周りに少しは余白欲しいよ!アピールです。

皆さんにもパーソナルスペースがあるようにロゴにもちょっと近づきすぎるとソワソワするよという距離感があるわけです。なるほど、となるとこれは尊重しなければなりません。あまり近くに要素を置きすぎないように気を付けてあげましょう。

続いては



ミニマムサイズ

先ほどの資料には小さいロゴも載っていましたね。
これです↓

見て分かる通りこれ以上小さいとハズキルーペなんだけどのスレスレがこのサイズです。
このロゴでいえば紙で印刷する場合は24mm以下にならないように、画面で見る場合には120px以下にならないようにしましょうということです。
国民全員がハズキルーペを持っているわけではないのでしっかりと守りましょう。



カラースキーム

どんな色が使われているんだろう?

ふるさとチョイスでは日本の伝統色を使用しており、メインカラーは「ふるさと色」というオリジナルカラーを採用しています。なんとも素敵な色です。

ん?待てよ?
なんか書いてあるな、、、

CMYKとRGB?HEX?

みなさん来ましたよ、短めのパスワード(じゃなくて専門用語)
と言いつつ聞いたことあるけどよくわからないという方も多いかと思います。
実際にイチから手取り足取り説明したい気持ちはやまやまなのですが、説明してくれている方が既にいらっしゃるのでこちらをぜひ(僕も時々お世話になるDigitalMarketingblog様ですね)

digitalidentity.co.jp

それでもめんどくさいよ!という方には要約しますとRGBHEXは画面で見るとき!CMYKは印刷するとき!これに尽きます。

RGB光の3原色(なんか聞いたことある)でCMYK印刷の4原色(なんか聞いたことない)なわけなのですが、RGBの方が多くの色を再現できます。CMYKは明度の高い色の再現が難しい上、色がぼやけたりくすんだりすることもあります。

じゃあ全部RGBで印刷もすればいいじゃないか
というある種極めに極めた方々からまたまた横やりが飛んできそうですが、ぜひモニターで見たものを家のプリンターで印刷して見比べてみてください。色の違いに涙が流れます。どうしても気になる方はおもむろに家や会社のコピー機を解体してみてください。きっとマゼンタやシアンといった名前のインクが漏れ出てくることでしょう。それが真実なのです。
そんなこんなで次がラスト



禁止事項

変形させたり装飾したらダメ!

要約すると大切に扱ってほしいよということです。
アイソレーションのお話ミニマムサイズのお話と同じように勝手に装飾したりフォントを変更したり、潰したり、煮たり、焼いたりしちゃだめだよということです。


コントラストに気をつけて!

こちらも端的に言えば、存在感薄くしちゃダメということです。せっかくなのでぜひ目立たせてあげてください。あなたの選択でロゴは陽にも陰にもなり得るということです。何お話しでしょうか。ではお次。


背景がつくときも注意!

ふるさとチョイスのロゴは写真の上に載せることが可能なのですが、あまりにも背景に溶け込んでしまうのは良くないよということです。これはロゴですか?フォトグラフですか?とデザイナーの後輩に質問されたらたまったものじゃありません。加えて、こちら会社によってはそもそも写真素材の上にロゴを載せること自体NGなこともあるので、とーーーっても注意が必要です。



まとめ

ということで長々と読んでいただいたロゴブログもこの辺でまとめです。
ここまでこんなことをお話ししました。

  • ガイドラインって何(ロゴはとても大事だよ大切にしてね)
  • プライマリーロゴ(優先して使ってね)
  • セカンダリーロゴ(これでもいいよ)
  • アイソレーション(余白とってね)
  • ミニマムサイズ(小さすぎると見えないよ)
  • カラースキーム(こんな色を使ってるよ)
  • 禁止事項(これだけはマジでやめてね!)

といった感じです。

雑ですね!最後にちょっとだけ真面目に話すと弊社では外部のデザイナーさんから、弊社のロゴを使用したデザインが上がって来ることがあります。その際は、我々社内のデザイナーが確認するのですが(ロゴのガイドラインに沿っているかどうかも含め)やはり怪しいなというところがたま〜〜〜にあったりするわけなんです。
弊社パイセン「これデザインきた!見といて!よろしく!」
ペーペーデザイナーワシ「はい!」
という感じでもちろん確認するわけなのですが、少しでもロゴについて詳しくなるとどうでしょう
弊社素敵パイセン「なんかちょっとロゴの周りがパツパツに見えるのですがこれはガイドラインに反してたりしますかね」
ペーペー素敵デザイナーワシ「はい!」
となるわけです。

つまりロゴについて社内のみんなが詳しくなることで、ダブルチェックにもなるわけですね。これがとても重要でかつデザイナーにとってはものすごくありがたいのです。
ということで普段「あまりロゴのガイドラインって見たことないな〜」という方はぜひ自社のガイドラインを穴が開くまで見つめてみてください。

以上、トラストバンクデザイナーの脇川でした。



最後に

弊社トラストバンクでは様々な職種で絶賛採用中です! 気になった方、是非お気軽にご連絡ください!

www.wantedly.com

エンティティの属性を公開せずにリポジトリで永続化する

前置き

こんにちは。うしおです。
前回の記事の続きになります。
今回の話は、エンティティとリポジトリの実装についてです。
ソースコードこちらに置いています。

やりたいこと

下記のようにユースケースを書けることを目指します。

<?php
// 注文受付のユースケース
final class Interactor
{
    public function __construct(
        private readonly OrderRepository $orderRepository,
    )
    {

    }

    public function execute(string $id): void
    {
        $order = $this->orderRepository->findById($id);
        $order->accept();
        $this->orderRepository->save($order);
    }
}

問題点

リポジトリ側の処理を雑に書いてみます。

<?php
final class OrderRepository
{
    public function save(Order $order): void
    {
        // Eloquentを使う想定
        \App\Models\Order::findOrFail($order->id)
            ->fill([
                'id' => $order->id,
                'accepted' => $order->accepted,
            ])->saveOrFail();
    }
}

これでユースケースの様に書けそうです。
しかし、困った問題が出てしまいました。
Orderクラスでidやacceptedなどのプロパティを公開しなければいけません。
エンティティがプロパティやゲッターで属性を公開すると、ドメインロジックがエンティティ外に流出しやすくなります。
下記のようなエンティティを永続化するためにはどうすれば良いでしょうか。

<?php
final class Order
{
    private string $id; // ゲッターも用意しない
    private bool $accepted; // ゲッターも用意しない

    public function __construct(...)
    {
        // ...
    }

    // エンティティ操作を行うメソッドのみがpublic
    public function accept(): void
    {
        $this->accepted = true;
    }
}

改良版のリポジトリ

Closure::bindを使います。

<?php
final class OrderRepository
{
    public function save(Order $order): void
    {
        Closure::bind(function() use ($order) {
            \App\Models\Order::findOrFail($order->id)
                ->fill([
                    'id' => $order->id,
                    'accepted' => $order->accepted,
                ])->saveOrFail();
        }, null, Order::class)();
    }
}

これで属性を公開していないエンティティを永続化できました。
エンティティのカプセル化をすり抜けているのでハック寄りなコードですが、リポジトリだけにエンティティの属性を公開する正攻法は今のところPHPにはありません。
とはいえ、アプリケーションのリポジトリ実装でこのコードが頻出するのは好ましくありませんね。
処理を切り出しましょう。

<?php
class EntityRepository
{
    protected function __construct(
        protected readonly string $entity,
    )
    {
        if ($entity === '') {
            throw new InvalidArgumentException('entity name is required');
        }
    }

    final protected function getAttributes(mixed $entity): array
    {
        return Closure::bind(function() use ($entity) {
            return get_object_vars($entity);
        }, null, $this->entity)();
    }
}

こうしておけば、リポジトリ実装は下記でいけそうです。

<?php
final class OrderRepository extends EntityRepository
{
    public function __construct()
    {
        parent::__construct(Order::class);
    }

    public function save(Order $order): void
    {
        $attr = $this->getAttributes($order);
        \App\Models\Order::findOrFail($attr['id'])
                ->fill($attr)
                ->saveOrFail();
    }
}

これなら良いでしょう。
実際のソースコードでは、今回の内容をライブラリ化するとともに、エンティティの生成部分もファクトリとリポジトリでのみ行うようにしています。
生成と永続化を隠蔽し、安全なエンティティクラスが出来上がりました。

最後に

今回の内容の他にもドメインイベント実装やLaravelの導入などを行っています。
Livewireも利用しているので、次回はその内容について書きたいですね。
それではまた次回に。

CSS擬似クラス関数 :is()が便利で使いやすい!

トラストバンク開発部・フロントエンドチームの君田(きみた)です。

本日はCSS擬似クラス関数である:is()について気になったので記載していきます!

CSSの擬似クラス関数:is()とは?

CSSの擬似クラス関数:is()とは、引数にCSSセレクタを渡すと、その条件に一致した要素を選択することができる便利なCSS擬似クラス関数です。 今まで1つ1つ記述していたCSSをまとめて記載できるようになるので、かなりスッキリ記載することができてハッピーになれそうですね。 基本的に現在使用されている主流なブラウザでは対応しているので、問題なく使用できそうです。

developer.mozilla.org

ただし、古いバージョンのブラウザの場合は対応していないものがあるので、互換性を保つためにも以下のように指定しておくと間違いないです。(ほんとは書きたくないけど仕方ない)

  • :-webkit-any() ⇨ 古いバージョンのChrome/Safariなどに対応するため
  • :-moz-any() ⇨ 古いバージョンのFirefoxに対応するため
  • :matches():is()の前の名前、以前は:matches()という名前で使用されていたため

余談ですが、:is()の名前を変更するときのやりとりが見れて面白いです github.com

:is()の使用例

分かりやすい使用例を記載してみます。

  • 未使用の場合
header p:hover,
main p:hover,
footer p:hover {
  color: red;
  cursor: pointer;
}
  • 使用した場合
:is(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}

どちらも同じ結果になりますが、かなりスッキリと記述できるようになりました。

同じような機能を持つ擬似クラス:where()とは?違いは?

基本的には行っていることは同じです。なので以下のコードは全く同じ動きをします

:is(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}

:where(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}

違いは詳細度に影響を与えるかどうかです。 詳細度とは、CSSで指定されたスタイルの重みづけをする値です。詳細度が高ければ高いほどスタイルが優先されて適用されるようになります。 一番高い詳細度を指定できるのはIDで指定することです。 なので、例えば以下のように記述した場合は、IDで指定したスタイルが優先されて適用されます。

<div id="app">何かしらを表示させる要素</div>
#app {
  background-color: green;
}

div {
  background-color: red;
}

:where()で指定した要素は詳細度が常に0になり、:is()で指定した場合は詳細度の計算が適用されます。 また、:where()で指定した要素はどのような要素であれ、詳細度を上げることができません。 例えば1つの要素を:where():is()で同じ要素を指定した場合は:is() で指定したスタイルが適用されます。

<header>
  <p>詳細度は:is()で指定しなければ適用されない</p>
</header>
:where(header) p {
  color: blue;
}

:is(header) p {
  color: red;
}

上記の記述をした場合、テキストの色はredになります。

どちらを使用するのか良いのか?

基本的には:is()を使用した方が良いと思いました。 ある要素の中に存在する要素を:where()で指定しスタイルを記述していたとしても、その他の方法で指定されていた場合はそちらが優先されてしまうためです。 では:where()はいつ使うのでしょうか?

CSS を編集するアクセス権を持たない開発者が使用するサードパーティ CSS保有する場合、可能な限り詳細度の低い CSS を作成することは良い習慣と考えられています。 developer.mozilla.org

テーマなどを作成し、第三者へ提供する場合は使用するユーザー側で簡単にスタイルを上書きできるため、スタイルは:where()で指定するといいかもねという感じです。

最後に

弊社トラストバンクでは様々な職種で絶賛採用中です! 気になった方、是非お気軽にご連絡ください!

www.wantedly.com

inputタグに正規表現を適用させる!pattern属性とは?

トラストバンク開発部・フロントエンドチームの君田(きみた)です。

本日はinputタグのpattern属性について書いていこうと思います。 フロントエンド開発をしていると、入力値の検証はどこかで実装する機会がある機能です。 そんなときに少しでも役に立てれば嬉しいです。

patern属性について

pattern属性とはinput要素に正規表現を適用させることができる便利な属性です。 どんなinput要素にも指定できるわけではなく、以下のtype属性を指定した場合に有効になります。

  1. text
  2. tel.
  3. email
  4. url
  5. password
  6. search

正規表現を設定することによって、入力欄が空文字でない場合を除いて、設定した正規表現と一致しない場合はpatternMissmatchtureになり、対象のinput要素の擬似クラス:invalidが有効になります。

patternMissmatchとは?

値の入力値検証に関しての状態を表すValidityStateオブジェクトの読み取り専用プロパティです。

developer.mozilla.org

input要素のtype属性に text, tel, email, url, password, searchのいづれかが設定されてる状態で、pattern属性に正規表現が設定されているかつ、それに反する入力をした場合patternMismatchプロパティが trueになります。これがtrueになることで擬似クラス:invalid が有効になります。

擬似クラス:invalidを利用してみる

実際の動作を確認してみます。

<form>
  <div>
    <label for="uname">メールアドレス</label>
    <input
      type="email"
      name="email"
      pattern="[a-zA-Z0-9_+&*-]+(?:\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}]"
    />
  </div>
  <div>
    <button>送信</button>
  </div>
</form>
input:invalid {
  border: red solid 3px;
}

JavaScriptなしで入力値を検証し、:invalid 擬似クラスを利用してスタイルを変更することができます。

ユーザビリティに関して

pattern属性を付与したinput要素はユーザビリティの観点からtitle属性を設定することを推奨されています。 例えば、「4文字以上、8文字以下で入力してください」などの文言を設定します。 こちらも実際にやってみます。

<form>
  <div>
    <label for="uname">ユーザー名:</label>
    <input
      type="text"
      id="uname"
      name="name"
      required
      size="45"
      pattern="[a-z]{4,8}"
      title="英語小文字で4文字以上、8文字以下で入力してください"
    />
  </div>
  <div>
    <button>送信</button>
  </div>
</form>
input:invalid {
  border: red solid 3px;
}

pattern属性の検証中にパターンに一致しないことをtitle属性に設定した値を通してユーザーに伝えることができます。

アクセシビリティに関して

titile属性に値を設定した場合、マウスカーソルを合わせたときにテキスト表示されてしまうことがあります。 ですので、「入力が間違っています、見直してください」「エラーが発生しました、再度入力してください」などエラーが発生しているかのような文言を設定しないように注意が必要です。

最後に

弊社トラストバンクでは様々な職種で絶賛採用中です! 気になった方、是非お気軽にご連絡ください!

www.wantedly.com

fetchでは正確なエラーハンドリングができない? 〜 JavaScriptのFetch APIでより安全にデータを取得する方法 〜

トラストバンク開発部・フロントエンドチームの君田(きみた)です。

先日以下のような記事を目にして、とても気になったので記事にしようと思いました。

www.builder.io

自分もフロントエンドの開発時によく使用したり、見かけたりするFetch APIです。 このFetch APIのエラーハンドリングについて言及されていた記事で、書かれていた内容を実際に試してみたので書いていきます。

Fetch APIステータスコード200以外の場合でもエラーをスローしない

任意のステータスコードを返却してくれるサービスを使用して記載していきます。

httpbin.org

例えば以下のようなコードがあったとします。

const fetchSample = async () => {
  try {
    // ステータスコード404を返すリクエスト
    const response = await fetch('https://httpbin.org/status/404');
  } catch (err) {
    console.log(err, 'error')
  }
}

この場合、存在しないURLへデータを取得しに行っていますが、fetchSampleを実行してもcatch句に書かれているconsole.logが実行されません。 実際に実行するとFetch APIステータスコード200以外の場合でもエラーをスローしないことがわかります。 これを以下のように書き換えることで、エラーをスローしcatch句に書かれているconsole.logが実行されるようになります。 これは取得したデータのjsonメソッドのエラーによりcatch句の処理が実行されています。

const fetchSample = async () => {
  try {
    // ステータスコード404を返すリクエスト
    const response = await fetch('https://httpbin.org/status/404');
    const data = await response.json();
  } catch (err) {
    console.log(err, 'error')
  }
}

ステータスコードによって処理を分岐させ、適切なハンドリングができるようにしよう!

レスポンスのステータスコードごとにエラーハンドリングすることで、どのようなことが原因でエラーになっているのかをユーザーに明確に示すことができます。 以下は受け取ったレスポンスのステータスコードを判別し、適切な処理を行うサンプルコードです。

const fetchSample = async () => {
  try {
    const res = await fetch("https://httpbin.org/status/404");
    if (!res.ok) {
      switch (res.status) {
        case 400:
          throw new Error('400 error');
        case 401:
          throw new Error('401 error');
        case 404:
          throw new Error('404 error');
        case 500:
          throw new Error('500 error');
        default:
          throw new Error('something error');
      }
    }
  } catch (err) {
    console.log(err, "error");
  }
};

これでもステータスコードを判別し、各エラーごとに適切な処理を実行することができます。 ただ、可読性を上げるためにもエラーハンドリングはcatch句に記載したいところです。

そこで、Errorクラスを継承したクラスを作成し、catch句で判別できるようにします。

class ResponseError extends Error {
  constructor(message, res) {
    super(message);
    this.response = res;
  }
}

const fetchSample = async () => {
  try {
    const res = await fetch("https://httpbin.org/status/404");
    if (!res.ok) {
      throw new ResponseError("fetch did not work properly", res);
    }
  } catch (err) {
    switch (err.response.status) {
      case 400:
        // 400エラーだった時の処理
        break;
      case 401:
        // エラーだった時の処理
        break;
      case 404:
        // エラーだった時の処理
        break;
      case 500:
        // エラーだった時の処理
        break;
      default:
        // エラーだった時の処理
        break;
    }
  }
};

これでステータスコードごとのエラーハンドリングが可能になりました。 ただ、Fetch APIの登場回数は結構多く、あらゆる箇所で使用されると思います。 ですので、毎回この実装をするのは少し面倒です。 そこで、一連の処理をラップして独自の関数を作成したらかなり使い勝手の良いものになると思います。 例えば

class ResponseError extends Error {
  constructor(message, res) {
    super(message);
    this.response = res;
  }
}

export async function myFetch(...options) {
  const res = await fetch(...options)
  if (!res.ok) {
    throw new ResponseError('Bad fetch response', res)
  }
  return res
}

Fetch APIを利用するときは上記の例でいうmyFetch関数を呼び出し、レスポンスが成功した場合(ステータスが200-299)はレスポンスデータを返し、 そうでない場合はエラーと共に、レスポンスデータを返すようにします。 これを今までのtry...catch句で使用すると、

const dataFetch = async () => {
  try {
    const res = await myFetch('https://httpbin.org/status/404')
    const user = await res.json()
  } catch (error) {
    // Errorクラスを拡張したクラスを使用しているので
    // errorオブジェクトにレスポンスデータが格納されており、
    // その中のステータスコードにより適切なハンドリングをすることができるようになる
  }
}

と実装することができかなりスッキリします。

axiosを使えばさっきのラッパー関数使わなくてもステータスコードごとにエラーハンドリング可能.....

github.com

行っていることはFetch APIとほぼ同じですが、

実際に以下のコードを試して、コンソールを確認してみてください。

const fetchSample = async () => {
  try {
    const { data } = await axios.get('https://httpbin.org/status/404')
  } catch (err) {
    console.log("err", err.response);
  }
};

fetchSample();

そうすると以下のようなjsonデータが返却されていることがわかります。

{
  data: "",
  status: 404,
  statusText: "",
  headers: AxiosHeaders,
  config: Object,
  request: XMLHttpRequest,
}

元々エラーが発生した時にステータスコードのみならず、そのほかの情報も確認することができます。

さいごに

JavaScriptのデータ取得におけるエラーハンドリングについて記載しました。 Fetch APIaxiosどちらを使用しても同じ処理が実現できますが、使用する場面やプロダクトによって適切な選択をし、 それぞれで正しくエラーを処理できるようにしたいと思いました。

弊社トラストバンクでは様々な職種で絶賛採用中です! 気になった方、是非お気軽にご連絡ください!

www.wantedly.com

iOSのinputとtextareaクリック時にズームされてしまうのを防ぐ

トラストバンク開発部・フロントエンドチームの君田(きみた)です。

本日はiOSにて入力フィールドをクリックした時に自動でズームされてしまう挙動を防ぐ方法を書いていこうと思います。

iOSでは入力フィールドの文字サイズ(font-size)が16px以下だとズームされる

iOSの挙動では入力フィールドの文字サイズによって、少し画面がズームされます。 見出しにもあるとおり、具体的には16px以下の文字サイズを設定しているとクリック時にズームされます。

実際の挙動はこんな感じです。 (現状のふるさとチョイスでは以下の挙動は起こりません。疑似的にズームされるようにしています。) ズームの挙動

この挙動をそのまま保持したい場合はなんの問題もないですが、「ズームされたくないけど、文字サイズは小さくしたい!」 というような要望があった場合、ズームされるのを防がなければなりません。

ズームされるのを防ぐ解決策

metaタグのviewport設定を以下のように記述することで入力フィールドの文字サイズを16px以下にした場合でもズームされることを防ぐことができます。

   <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/>

maximum-scale=1.0を設定することによりズームされるのを防ぐことができます。 ピンチインによるズームは使用可能な状態のままのですので、ご安心ください。

そのほかのviewport設定に関しては以下で紹介されています。

developer.mozilla.org

また、各モバイルデバイスのviewport一覧は以下で紹介されています。

experienceleague.adobe.com

最後に

弊社トラストバンクでは様々な職種で絶賛採用中です! 気になった方、是非お気軽にご連絡ください!

www.wantedly.com

トラストバンクのSREとしてこの1年やってきたこと

この記事は、トラストバンク Advent Calendar 2022の23日目です。

こんにちは!CTO室でSREやっている@Tocyukiです!

夜はまさに大クリスマス時代、という感じで気づいたら年の瀬で明日はクリスマスイヴで明後日はクリスマスでグランドライン目指してWe are !!という感じですね!

というわけでアドベントカレンダー書いていきたいと思います!

ふるさとチョイスのではなくトラストバンクのSREとして

昨年のアドベントカレンダーではこんな記事を書かせていただきました。

qiita.com

ありがたいことにたくさんの人に読んで頂けて、一時はIT関連のはてブランキングにも登場するなど「我、ふるさとチョイスのSRE也」ということを世に知らしめることができたとかできないとかそんな記事になったとかならないとかしました(してない

そんな(?)様々な改善活動が評価されたのかどうかは知る由もありませんが、今年の4月に組織編成が行われ、元々ふるさとチョイス事業本部開発部付のSREチームだったのが全社組織であるCTO室が爆誕し、それに伴いCTO室付のSREチームとして事業部を横断する形に活動の場を広げることになりました。

さらに個人としてもフルリモート環境下におけるコーポレート全体のコミュニケーション改善をミッションとしたインターナルコミュニケーションチームも兼務することになり、Gatherの導入やNotionの全社導入などSRE領域とはまた違ったチャレンジもしてきました。

今回アドベントカレンダーを書くにあたりこの一年を振り返ってみたのですが、活動の幅が広がったことも有り、個人としてもチームとしても思った以上に色々とやってきてて完全に記憶から消去されているなぁと思ったのでこの1年でどんなことをやってきたのかという部分を記憶とチケットを掘り起こしながら以下のテーマを中心に振り返っていきたいと思います!

  • 採用活動
  • 改善活動
  • 新規サービスリリース

採用活動

自分がトラストバンク一人目のSREとして入社してから2年が経過しました。現在SREチームは3名いて来月から4名体制になる予定で去年に比べるとかなり順調な感じなのですが、改めて振り返ると以下のような感じでした。

名前 入社時期 採用要因
1人目SREニキ Tocyuki 2020/12 1人目のSREとして裁量もってできる場所を求めてたどり着いた。
2人目SREニキ budatora 2021/07 プロダクトとフェーズに共感してくれた。正直採用できたのは幸運以外のなにものでもない。
3人目SREニキ iwatea 2022/06 リファラルでマイメンとして来てくれた。正直採用できたのは幸運以外のなにものでもない。
4人目SREニキ Mr.Y 2023/01 唯一採用戦略がハマり採用できた。(はず)シャスシャス!!

上記の通り、今年の中頃まで採用活動に関してはかなり苦戦していて振り返ってみると採用活動の成果と言えるのは4人目のみでした。

今年の6月までは2名体制でひーこら言いながら通常の業務と平行して採用活動を頑張っていたのですが、募集要項やスカウト文面の見直しに終始してしまい中々思うような成果に結びつかず、スカウトを打っても返信が返ってくることは稀でカジュアル面談に辿り着くことさえ困難な状況が続いていました。

これは流石にやばいなぁと思い、今年度の個人目標としてもSRE採用にコミットすることにして以下のことにチャレンジをしました。

  • 伝家の宝刀リファラ
  • テックブログ開設
  • コミュニティ活動
  • 登壇

伝家の宝刀リファラ

前述の通り、2人目のSREである@butadoraが入社してくれて以降、採用活動は非常に厳しい状況だったにも関わらず、SRE全社化による他事業部の改善や他サービスのAWS移行などもやることになり、新規サービスリリースも計画されていき、SREの採用が急務となる中、前職の同僚であり、マイメンでもあり、転職後もちょこちょこ連絡を取り合っていた@iwateaリファラルで入社してくれるということになりました。

今回のアドベントカレンダーで入社エントリを書いてくれたのでこちらも是非見てみてください。 tech.trustbank.co.jp

上記入社エントリにも書いてありますが、前職で出会いとても仲良くなって話はよくしていたのですが結局直接一緒に仕事をする機会は訪れることなく自分が先に転職してしまったのでどこかで仕事も一緒にできれば良いなとずっと思っていました。

また@iwateaPHPでのバックエンド開発をメインにやってきていることやTerraformやAnsible、AWSも問題なく扱えるので弊社技術スタックとの親和性も非常に高く、SREとして普通に採用するのは無理ゲーなレベルの人材だったので、様々なタイミングや条件も合う形でリファラルが実現が出来たのは最高にラッキー、もはやディスティニーだったなと思います。

持つべきものは友ですね。

テックブログ開設

採用活動ではテックブログの有無も影響を及ぼしてきますよね。

弊社には元々テックブログはなかったのですが、そんな中、昨年末に弊社初となるアドベントカレンダーが実施されました。

qiita.com

そしてアドベントカレンダーを行ったことでアウトプットの機運も高まったので、すかさずテックブログの開設を行いました。

tech.trustbank.co.jp

アウトプット文化を醸成するためには恒常的にアウトプットできる場所が必要ということと採用面へのポジティブな効果を期待して開設したのですが、テックブログ開設後はカジュアル面談に来てくれる方や面接に来てくれる候補者の方々が高い確率でテックブログを見てくれていてトラストバンクのエンジニア組織にはどういう人がいてどんなことがアウトプットされているのかという情報を提供する役割を担ってもらえるものになってきているのかなと思います。

当初は自発的に書いてくれる人は少なかったのですが、ここ数ヶ月は自ら書いてくれるという人も出始めてとても良い流れになってきているなと感じているのでアウトプット文化の醸成とともに、候補者の方への情報提供をより高い解像度で行うことができるものになっていければなと思っております。

今回のアドベントカレンダーでもテックブログに書いてくれる人が増えてきており、それもまた良き流れかなと思うので、今後はきちんとした運用体制を敷いてより活発に様々なアウトプットができる組織になっていければ良いなと考えております。

コミュニティ活動

採用活動を行う上である一定の認知や露出はやはり大事だし、個人のキャリアとしても社外のエンジニアとの繋がりは大事だよねということで、今まであまりしてこなかったコミュニティ活動にもチャレンジしようと決心しました。

するとグッドタイミングで昨年の12月にNRUG SRE支部が立ち上がり、そこの運営メンバーとして参加してイベントの運営および登壇を行ってきました。

NRUG SRE支部運営に参加した経緯や初回イベントの感想や関連リンクがあるので興味のある方は以下の記事を見てみてください。 tech.trustbank.co.jp

この初回のイベントは運営3名ががっつり登壇するという内容だったのですが、イベント終了後から今まで無風状態に近かったスカウトに返信が来るようになったり、カジュアル面談を実施できることも増え、さらにはイベントを見てくれた方が興味を持って話しを聞きに来てくれたりして「これが、登壇の、効果か・・・!」と感動したことをつい昨日の事のように覚えています。

個人としてもこのコミュニティ活動を通じて様々な方とつながることもできてエンジニアの友人が少ない手前にとって、勇気を出して運営メンバーに立候補してユーザーグループの運営に携わることができたことは本当に良い決断、経験だったなと思っています。

「感謝するぜ、お前と出会えたこれまでの全てに」というビヨンド・ネテロの気持ちが今ならとてもわかります。 ハンターハンターを再開してくれた富樫大先生には感謝しかありません。

登壇

コミュニティ活動だけではなく、個人のキャリアへの影響はもちろん、トラストバンクのエンジニア組織のプレゼンス向上および採用活動に繋げるべく今年はイベントやカンファレンスへの登壇にもチャレンジしてみました!

コミュニティ活動も本当にやってみて良かったなと思いましたが、このイベントやカンファレンスへの登壇も資料の準備などはとても大変でしたが本当にやってみて良かったなと思いました。

来年以降も外部へ発表できるように様々な改善活動を進めていき、色々な場所で発表をしていければなと思います!

JAWSDAYS2022への登壇

まずJAWSDAYS2022への登壇にチャレンジしました。

jawsdays2022.jaws-ug.jp

JAWSDAYSはJAWS-UG最大のイベントで毎年イベントへの参加はしていましたが、いつか登壇してみたいなぁと思っていたイベントの一つでもありました。

jaws-ug.jp

今回のJAWSDAYS登壇による採用的な狙いとしては「SRE採用におけるペルソナへの情報提供」でした。

弊社は現在ふるさとチョイスをはじめとしたサービスインフラのAWS移行を進めています。 移行後もEC2ベースのVM基盤となっていますが、TerraformやAnsible、Packerを活用してフルIaCでこの移行プロジェクトを進めているということもありSRE採用のペルソナとして「EC2環境の改善が進まなかったり、IaCの導入がうまくいかなかったりしてもやもやしている」みたいな部分も要素として盛り込んでいました。

そのため現職での改善活動やIaC導入などのチャレンジが組織的な課題等でうまく進められないことに対して自身のキャリアに課題を感じて転職を検討している人に対して、トラストバンクでは現在このようなフェーズで、移行に関してはこのように進めているというのを届けて弊社へ興味を持ってもらえるようにするために具体的な事例として発表させてもらいました。

JAWSDAYSという特性上、AWSを利用しているそのようなペルソナのSREへ情報を届けるにはうってつけのイベントだったのでそういった内容で登壇にチャレンジしてみたのですが、その後のカジュアル面談等でこの発表の内容について話を聞きたいということも何度か有り、採用に関しての狙いとしては十分以上に達成できたのかなと思いました。

参加の経緯や発表内容などもレポートとして記事にまとめていますので是非見てみてください。

tech.trustbank.co.jp

Cloud Native Days Tokyo 2022

またJAWSDAYSから間を開けずにCloud Native Days Tokyo 2022への登壇にもチャレンジをしてみました。

event.cloudnativedays.jp

このカンファレンスも毎年参加はしていたものの、いつか登壇したいと思っていたカンファレンスです。

event.cloudnativedays.jp

これまでの外部発信での内容では主に既存環境の移行や改善活動に伴う内容が主で、新しいチャレンジや新サービス、システムのアーキテクチャについてあまり発信出来ていなかったのでCfP提出を行い、無事採択され発表することができました。

既存サービスのAWS移行に伴い、AWSの本格利用が進み、新しいサービス、システムは基本的にすべてAWSを利用し、コンテナ基盤としてはECSを利用しています。

新サービス、システムへのAWS利用は今年から本格的にスタートし、多くの新規サービス、システムの新規構築に加え、複数の既存サービスのAWS移行も進めながら普段の運用業務も行っていたので、中々大変だったなぁと振り返りながら思い出してきましたw

今年新規構築したサービスについては後半に軽く触れていきたいと思います。

そんなこんなで新規のサービス、システムなどはPHP8系にLaravel9を基本としてコンテナ基盤としてはECSを採用するなどCloudNativeな開発もされるようになってきたので、そういうこともやれるようになってきましたYO、ということを伝えるべく今回のCloud Native Days Tokyo 2022での発表にチャレンジしましたが、こちらもとてもポジティブな反応を頂けてチャレンジして良かったなと思います。

参加レポート書き忘れていたので発表資料を置いておきます。

speakerdeck.com

改善活動

今年も色々な改善活動をしてきました。

AWS移行

ふるさとチョイスだけではなく、SREチームの全社化に伴い、地域通貨事業であるchiicaのAWS移行も行うことになりました。

chiica.jp

ふるさとチョイスでのIaC資産を活用し、スピーディーに開発環境の移行を行うことができ、ローカル開発環境も整備し、ステージング環境も新設しました。

LPのCloudflarePages移行

弊社には数多くのLPが存在するのですが、静的サイトにも関わらず、サーバーを用意してホスティングするという運用がスタンダードだった部分を自分が入社してからはCloudflarePagesをスタンダードにするように推進してきました。

www.cloudflare.com

すでに独立したLPや新規のLPについてはCloudflarePagesの活用を進めていたのですが、ふるさとチョイスに組み込まれているLPがあり、開発が活発なプロダクトにイベントのLPが組み込まれていることで外部の制作会社を利用しづらかったり、リリースもふるさとチョイス本体同様の開発フローで進める必要があるためスピーディーに変更できなかったりと様々な問題があったサイトもついにCloudflarePagesへ移行することができました。

award.furusato-tax.jp

New Relicの本格導入

自分が入社した時点では一部のサーバーにAPMが導入されているぐらいでまったく活用は出来ていなかった状況だったのですが、監視運用の内製化、DevOpsの実装に伴い、New Relicをo11y基盤として活用すべく様々な取り組みを行いました。

詳細については明日公開予定のNew Relicアドベントカレンダー24日目の記事を御覧ください。

qiita.com

新規サービスリリース

以下、今年新規に構築を行い(or している)、リリースが公表されているサービスたちです。 実際にはもっと数多くのシステムを今年に入ってから構築、リリースしています。 ものによっては外部の開発リソースを利用したりしていますが、インフラやCI/CDの実装周り、全体のアーキテクチャ設計は基本的にSREが行っています。

OEM API

www.trustbank.co.jp

www.trustbank.co.jp

www.trustbank.co.jp

このOEM APIの実装まわりについてもアドベントカレンダーで記事が上がっているので是非見てみてください! tech.trustbank.co.jp

読むふるさとチョイス

yomu.furusato-tax.jp

www.trustbank.co.jp

こちらについては以前テックブログに記事を書きました。

tech.trustbank.co.jp

めいぶつチョイス

www.trustbank.co.jp

おわりに

まだまだ色々とやったことや振り返りたいことはあるのですが、まだNew Relicアドベントカレンダーの記事も書けていないので一旦ここまでにしたいと思いますw

改めて振り返ってみると今年は個人としても本当に飛躍できた年と なりました。 きっかけとしてはやはりコミュニティ活動や外部登壇などのアウトプットなのかなと思いますが、前提としてしっかりと日々エンジニアリングに向き合い、インプットを継続し、その上でアウトプットするというバランスとサイクルが大事なんだなと感じました。

コミュニティ活動や色々なイベントでの様々な事例を見ると自分のエンジニアとしての実力、経験はまだまだだなと痛感する日々ですが、まわりと比べすぎて自分を下げることはせず、しっかりインプット、アウトプットを継続して来年以降も個人としてもチームとしても様々なことにチャレンジし、エンジニアリングを楽しみ、事業に貢献をしていくことができる自分、チーム、開発組織にしていきたいなと思っていますのでよろしくお願いします!

そんなトラストバンクではSREをはじめとした様々な職種で絶賛採用中なので気になった方は是非お気軽にご連絡くださいー!

www.wantedly.com