SREチーム発足と今期の取り組みについて

はじめに

皆様、はじめまして。Findyでプロダクト開発部/SREとしてジョインしました安達(@adachin0817)と申します。今年の6月に入社し、ちょうど3ヶ月が経ちました。本日は、SREチームの立ち上げに関する0から1のプロセスと、今期の取り組みについてご紹介させていただきたいと思います。

SREチーム発足

2023年までは、バックエンドチームがインフラを担当していました。しかし、サービスの拡大に伴い、バックエンドチームのリソースが不足し、SRE的な改善が十分に行えない状況が続いていました。そこで、昨年からSREの大矢とチームリーダーの下司(@gessy0129)がジョインし、現在は3名体制で活動しております。

SREチームの位置づけとミッション

SREチームは横断的なSRE活動をしており、これを「横断SRE」と指しています。一方で、各プロダクトにおいてSRE的な役割を担っていたメンバーは「Embedded SRE」と呼ばれ、引き続き改善活動を担当しています。

SREチームは現在、チームを作り上げていく段階にあり、まだまだやることが多く残されています。こうした背景を踏まえ、SREチームの短期および中期におけるミッションを設定しました。

  • 短期ミッション
    • 「ファインディの事業成長を支えるための、SRE組織のあり方の確立」
  • 中期ミッション
    • 「社員全員が事業成長に集中できような仕組みを構築し、提供する」
  • SREの存在意義
    • SREは道を作るために存在する
    • リスクを受け入れ、管理する
    • SLOを計測する
    • トイルの削減
    • モニタリングする
    • 自動化する
    • 他プロダクトの支援

SREチームの業務の進め方

アジャイル開発手法を採用しており、各メンバーにはそれぞれIssue(タスク)が割り当てられます。一週間イテレーションで管理し、Issueのクローズを目指しています。毎朝、GitHubのProjectsを使用してカンバンボードを確認し、今日のタスクや困っていることを共有や、雑談をしています。また、毎週金曜日にはチーム全体で振り返りを行い、Findy Team+を活用しながら内容をKibelaに記録し、全員が閲覧できるようにしています。さらに、隔週でEmbedded SREチームとのお茶会も実施しており、取り組みたいことを共有する場を設けています。

  • カンバン/ステータス
ステータス 内容
To Do Issueを作成した状態、未着手
Parent In Progress 親子関係のあるIssueの親
In Progress 進行中のIssue
Done 対応が完了したIssue

では、今期SREチームの取り組みについてご紹介していきたいと思います。

今期の取り組みについて

全環境のTerraform import化

これまで全ての環境がTerraformで完全にコード管理されていない状態でしたが、現在は全リソースをコード化することで一元管理を実現し、環境間での設定の整合性が保たれるようになりました。まずは既存の設定を棚卸しし、リソースをインポートすることで、今後の変更や拡張がより容易になっています。さらに、Terraform Cloudを活用しながら、今後はmodule化を進めて、効率的でスケーラブルなインフラ管理を目指しています。

Findy Toolsのインフラ改善

私が入社してからFindy Toolsのインフラ改善として、いくつか対応していきました。まずは、RDSのSSL/TLS証明書更新とAuroraのマイナーバージョンアップを開発環境から本番環境まで3日で実施しました。次に監視とオブザーバビリティの強化では、元々はインフラリソースをモニタリングしておらず、SentryのエラートラッキングとAPMのみでした。そこでDatadogでのインフラリソース(ECS、外形監視、CloudFront、RDS、イベントログ、WAF)、APMなどを対象に、アラートをTerraformで管理し、ダッシュボードを手動で運用するようになりました。普段見えていなかった部分がオブザーバビリティの向上によって可視化されていきました。

また、SLI/SLOの策定を進め、ページ表示速度やリクエスト成功率の目標を設定し、エラーバジェットとバーンレートの管理を進めていきました。SLOの振り返りは隔週で実施しており、アラートが発生した際に、開発メンバーと改善案を話し合えることは非常に重要だと感じています。

最後に、Rails serverやNode.js、MySQL8の開発環境の構築を改善し、Justfileを活用して自動化を進めました。JustはMakefileと比較すると、シンプルで直感的な構文で、シェルスクリプトに似ています。また、依存関係の管理が簡単なため、学習コストも低いです。これにより、開発メンバーはスピーディーに構築できるようになりました。以下フロントエンドのJustfileになります。

  • Frontend Justfile
# Justfile for setting up development environment

# Install Homebrew and essential packages
install_homebrew:
    @echo "Installing Homebrew if not already installed..."
    @if ! command -v brew >/dev/null 2>&1; then \
        /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"; \
    else \
        echo "Homebrew is already installed."; \
    fi

install_essential_packages:
    @echo "Installing essential packages..."
    brew install coreutils curl git

# Configure Git
configure_git:
    @echo "Configuring Git..."
    git config core.ignorecase false

# Install asdf and Node.js
install_asdf:
    @echo "Installing asdf if not already installed..."
    @if ! command -v asdf >/dev/null 2>&1; then \
        brew install asdf; \
        echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc; \
    else \
        echo "asdf is already installed."; \
    fi

install_nodejs:
    @echo "Installing Node.js..."
    @if ! asdf plugin list | grep -q 'nodejs'; then \
        asdf plugin add nodejs; \
    else \
        echo "Node.js plugin is already added."; \
    fi
    asdf install nodejs
    asdf reshim nodejs

# Install mkcert and create certificates
install_mkcert:
    @echo "Installing mkcert if not already installed..."
    @if ! command -v mkcert >/dev/null 2>&1; then \
        brew install mkcert; \
        mkcert -install; \
    else \
        echo "mkcert is already installed."; \
    fi

create_certificates:
    @echo "Creating local certificates..."
    mkcert -cert-file localhost.pem -key-file localhost-key.pem localhost 0.0.0.0 hoge-web

# Install npm packages
install_npm_packages:
    @echo "Installing npm packages..."
    npm ci

# Run all tasks
all: install_homebrew install_essential_packages configure_git install_asdf install_nodejs install_mkcert create_certificates install_npm_packages

これらの改善については、7月の弊社DevRelイベントでLTを行いましたので、まだご覧になっていない方はぜひスライドをご確認ください。

findy.connpass.com

speakerdeck.com

AWSセキュリティ周り向上

AWSセキュリティの強化策として、Security Hubの実装を検討しましたが、予想以上の導入工数と既存ダッシュボード機能の現状を考慮した結果、我々の要件により適した別のアプローチを模索することにしました。複数のSaaSセキュリティサービスを検討し、最終的にShisho Cloudを選定しました。Shisho Cloudは使いやすさとコスト面で現在のファインディ社の課題にマッチしており、現在はAWSセキュリティポリシーガイドラインを作成し、Embedded SREチームと協力して対応を進めています。

「Findy Team+」オブザーバビリティ周り強化

Findy Toolsで培ったオブザーバビリティやSLOの経験を活かし、Findy Team+のSRE支援も行いました。元々設定されていたDatadogのアラートはTerraformで管理されていなかったため、まず棚卸しをし、全てをTerraformでimport化しました。しきい値などは次のように環境変数で管理し、テンプレート化することで他のプロジェクトにも適用可能にしました。SLOの策定にはまだ改善の余地がありますが、今後はミッションクリティカルな領域にも取り組んでいき、開発メンバーと振り返りを実施していく予定です。

  • rds.alert.tf
resource "datadog_monitor" "rds_cpu_alert" {
  name               = "[${var.service_name}]rds_cpu_alert"
  type               = "metric alert"
  query              = "avg(last_5m):avg:aws.rds.cpuutilization{rds:${var.service_name}-${var.environment}} by {dbinstanceidentifier} > ${var.rds_cpu_critical_threshold}"
  escalation_message = "RDS CPU usage for ${var.service_name}_${var.environment} instance has exceeded ${var.rds_cpu_critical_threshold}%"
  notify_no_data     = false
  notify_audit       = false
  timeout_h          = 1
  include_tags       = true

  monitor_thresholds {
    critical = var.rds_cpu_critical_threshold
  }

  message = <<-EOT
    @${var.slack_channel}
  EOT

  tags = local.combined_tags
}

今期まだやりきれていないタスク

  • DevSecOpsの推進に向けたセキュリティ基盤のさらなる整備
  • AWSコスト最適化
  • 開発メンバー生産性の向上
    • 開発環境 完全Docker化とJustfile化
    • ECS Arm化
    • Stg複数環境 自動化
    • デプロイ高速化

後半では、AWSコスト最適化や開発メンバーの生産性向上のために、さらなる効率化とやりやすさを追求し、インフラ管理や開発プロセスの改善を進めています。

まとめ

SREチームの発足と今期の取り組みについて、簡単にご紹介させていただきました。チームの立ち上げからインフラの改善、セキュリティ対策まで、多岐にわたる課題に取り組んできましたが、まだやるべきことがたくさんあります。(Issueが100個以上あります)

今後も引き続き、SREチームとしてサービスの信頼性向上に努めていくのと同時にSREに興味のある方は、ぜひ一緒に働きましょう!カジュアル面談お待ちしております🙏

herp.careers

findy-code.io

findy-code.io

EmotionからCSS Modulesへの移行!React Server ComponentsのCSS対応

こんにちは。エンジニアの佐藤(@t0m0h1r0x)です。

今回は、弊社で現在進めているEmotionからCSS Modulesへの移行について紹介します。
移行の背景、検討した代替ライブラリ、そして最終的な決定について話していきます。

移行の検討理由

弊社では現在、CSS-in-JSライブラリとしてEmotionを使用しています。ピュアなCSS記法を好むメンバーが多いので、EmotionのTagged Template Literal記法がチーム文化との相性も良く、これまで活用してきました。
一方で、フロントエンド開発フレームワークにNext.jsを採用しており、そちらではApp Routerへの移行を進めています。
App RouterのメリットはやはりReact Server Components(RSC)の活用だと思います。RSCはユーザー体験と開発者体験の向上につながる重要な機能ですが、2024年9月現在、その仕様上EmotionでRSCをスタイリングできません。

このような背景から、RSCに対応できる新たなCSSライブラリの検討を始めました。

代替ライブラリの検討

代替ライブラリの選定にあたっては、パフォーマンスやAPIの使い勝手といった要素も大切ですが、チームとの相性も重要な要件としました。特に、Tagged Template Literalをサポートしていて、Emotionとの書き心地に互換性があることをポイントとしました。

Panda CSS

Panda CSSChakra UIのチームが開発しています。CSSの記法としてObject LiteralかTagged Template Literalを選択できますが、後者には機能制限があるようです。 詳細については 公式ドキュメントを参照してください。

Pigment CSS

Pigment CSSMaterial UIのチームが開発しています。 こちらも要件と合致しそうなのですが、開発初期段階のためプロダクション利用には検討が必要です。 ちなみにPigment CSSは、最近リリースされたMaterial UI v6に、experimentalなopt-inとして組み込まれました。さらなる開発が期待できそうです。

CSS Modulesへの移行

上記の検討を踏まえ、弊社では一時的に信頼と実績があるCSS Modulesへの移行を決定しました。その理由は次の通りです。

  • プロダクトとチームの要件に合致
  • 他ライブラリへの将来的な移行が比較的容易

一方でCSS Modulesの採用にあたっては、特に次の点に留意しています。

  • TypeScriptによる型定義
  • 動的スタイリングの実装
  • 仕様がメンテナンスモード

型定義にはHappy CSS Modulesを使用して、自動生成することで対応しています。

動的スタイリングについては、コード中にpropsベースのスタイリング実装が多くなかったことや、コンポーネントのルールを整備していたことで不要なcomponent targetingを予め減らせていたため、現時点では大きな支障は出ていません。

仕様についてはメンテナンスモードであるものの、長らくこの状態が続いていながら今の所大きな問題は起きていないため安定しているのではないかと思っています。
参考:

今後の展望

CSSを取り巻く環境は日々進化しています。例えば、React v19からは<style>のホイスティングがサポートされる予定であり、それを活かしたRESTYLEというライブラリも登場しています。 このような状況を踏まえ、当面はCSS Modulesへの移行を進めつつ、新たなライブラリの登場にも注目していきたいと思います。

まとめ

EmotionからCSS Modulesへの移行は、弊社のフロントエンド開発環境を大きく変える重要な取り組みでした。 RSCとの互換性という課題はありましたが、暫定的な解決策を見つけつつ、より良い選択肢を模索し続けていきたいと思います。

弊社では一緒に働いてくれるメンバーを募集中です。興味を持っていただいた方は是非こちらのページからご応募お願いします。

herp.careers

Cloud DLPを使ってBigQuery上の個人情報をマスキング

はじめに

Findyでデータエンジニアとして働いている開(hiracky16)です。 この記事ではGoogle Cloudの製品であるCloud DLPを中心に弊社で取り組んでいるデータマスキングについて紹介します。

弊社はFindyやFindy Freelanceなど人材に関する事業を取り扱っているため個人データがより集まりやすい環境にあります。 ファインディの組織が日々拡大しサービス拡張していく中で、利用者の安全性を担保し、データにおけるリスクを低くするためのデータ基盤づくりが求められてきました。 データ基盤には事業部のデータを集約しているため、利用者にすべてを公開してしまうと運用を誤り、思わぬ事故につながる可能性が上がります。 ただ、閲覧できないと困る業務もあり、データの閲覧権限を絞りすぎてもリスクがあります。

今回は、個人データなどのセンシティブなデータを自動で検出・マスキングを行い、業務に必要な場合にのみ閲覧できる状態にする取り組みについてご紹介します。

権限周りの基本設計

マスキングの前に権限周りの基本設計を説明します。 データセットにはレイヤーを設けており、それぞれ次のようになっています。

  • source ... ローデータが入っているテーブル
  • staging ... ローデータをBigQuery用に加工したテーブル
  • intermediate ... CTEなどのテーブル
  • mart ... 利用用途ごとに用意したテーブル

まずはデータ基盤を利用するにあたり用途ごとにロールを定義しようと考えました。 用途以外のことができてしまうと誤操作によってデータを書き換えたり、消してしまったりするおそれがあるためです。 データの用途は大きく3つに分けることができ、特定のデータを定期的に見ることやBigQueryコンソールやDataformで自分のほしいデータを作ること、外部ツールにデータを連携することになります。

これらの利用用途ごとに権限を付与するためのロールを作りました。 また1ユーザーごとにロールを付与するのは大変なので、Googleグループを用意しあらかじめ付与しています。 こうすることでグループへの追加・削除によりロールの管理が比較的簡単な操作で可能になります。 更にデータマートに相当するデータセットは用途ごとに作りGoogleグループのメールアドレスをデータセットのIAMメンバーとして追加しておきます。

ロール できること Google Cloudプロジェクト上のIAMロール 対応するGoogleグループ
管理者 全てのデータセットに対して編集 プロジェクトレベルのオーナー -
編集者 source以外のデータセットへの編集、またDataformなどの周辺サービスの利用 プロジェクトレベルの「BigQueryユーザー」と「BigQueryデータ編集者」 editor
(各データセットの)閲覧者 特定のmart_で始まるデータセットの閲覧 プロジェクトレベルの「BigQueryユーザー」とデータセットレベルの「BigQueryデータ閲覧者」 mart_sales, mart_external_system

上記のようにデータセットごとにIAMロールを付与するためのTerraform Moduleを公開しているのでよかったらお使いください。 registry.terraform.io

ポリシータグによる動的マスキング

基本的に個人データはsourceからstagingへの伝搬時にセンシティブなデータを省いています。 また上記の通り権限が絞れているので一見問題なさそうに見えますが、martデータセットの中には業務システムに使うものもあり個人データが含まれます。 そういったデータをグループに属する全員が閲覧できる状態というのは望ましくありません。

このような場合には、カラムレベルでポリシータグを付与し、許可されたユーザーには通常のデータを、許可されていないユーザーにはマスキングされたデータを表示させています。

タグの付与はDataformのconfigで行っています。 次のように書くとテーブルが作られる際にタグを付与してくれます。

config {
    type: "table",
    "schema": "stg_hoge",
    "description": "ユーザーテーブル",
    "columns": {
        "id": "ユーザーのID",
        "email": {
            description: "メールアドレス",
            bigqueryPolicyTags: ["projects/project-hoge/locations/asia-northeast1/taxonomies/fuga/policyTags/piyo"]
        },
        "tel": {
            description: "電話番号",
            bigqueryPolicyTags: ["projects/project-hoge/locations/asia-northeast1/taxonomies/fuga/policyTags/piyo"]
        }
    },
}
...

マスキングのルールもいろいろなものがあります。 なお今回は試していませんが、BigQuery UDFをルールに追加できます。

cloud.google.com

動的マスキングの方法はわかりました。 ただ、個人データに対して曖昧な理解のまま運用してしまうと付与忘れや、付与しすぎて情報量が落ちてしまうおそれがあります。 そこで役立つのがCloud DLPです。

Cloud DLPによる個人データ検出

Cloud DLP(Data Loss Prevention)は、機密性の高いデータを検出、分類、保護するために設計されたGoogle Cloudのサービスです。

Cloud DLPにはBigQueryのデータをスキャンして個人データに該当するテーブル、カラムを検出してくれる機能が備わっています。

この検出を定期的に実行することによりポリシータグを付与する候補となるカラムを特定できます。 テーブルはサンプルですが、検査するとデータリスクが中程度〜高のカラムに個人データが含まれていそうなことが一目でわかるようになります。

以下は公式ドキュメントに載っていたイメージになります。

cloud.google.com

DLP APIを用いてテキスト内の情報をマスキング

ポリシータグを使ったマスキングは値全体をマスクしてしまいますが、ロングテキストの場合一部だけマスクしたいといったニーズが存在します。 例えば、商品レビューのテキストデータをポジネガ判定したい場合、テキスト全てをマスクしてしまうとポジネガ判定に使う情報が落ちてしまいます。

DLP APIを使うとテキスト中の個人情報をマスクできます。 DLP APIによるマスクの手順は「個人データの検出」と「データの匿名化」の2ステップがあります。

「個人データの検出」では事前に用意された検出器(INFO TYPE)を使い検出できます。 INFO TYPEは特定したい情報、例えば名前や電話番号、住所など情報の種類ごとに違います。 INFO TYPEはGCSに置いた辞書から自作でき、固有名詞にも対応できます。 下記が事前に用意されたINFO TYPEのリファレンスです。

cloud.google.com

「データの匿名化」は検出したINFO TYPEごとにどのように情報をマスクするかを定義します。

DLP APIにはPython ClientがあるのでこれをCloud RunにデプロイしてBigQueryからリモート関数で呼び出せるようにしています。

declare text string;
set text = """
私は山田太郎です。
本日はよろしくお願いします。
山田
090-0000-0000
tensyoku.taro@gmail.com
""";

select text, `function_dataset.dlp_api`(text) as masked_text;

まとめ

Cloud DLPの機能を使うことでマスキングする術をまとめてみました。 データ利活用が増えることは喜ばしいことですが、常にデータの扱いを気にしながらデータ抽出や分析するのにも限界があります。 これからもデータエンジニアとして安全に意思決定をサポートするデータ基盤を作っていきたいと思っています。

弊社ではデータ基盤を共に育てていくメンバーを募集しています。少しでも興味が湧いた方はカジュアル面談お待ちしております🙏

herp.careers

herp.careers

コントリビューション・オブ・ザ・イヤー あの名物企画の仕組みと裏側を大公開!

Findyでエンジニアをしている栁沢(@nipe0324)です。

今回は、Findyの名物企画である「コントリビューション・オブ・ザ・イヤー2024中間発表」の裏側を公開します。裏側を知り、キャンペーンをより楽しんでもらえたら嬉しいです。

キャンペーン期間中にXでシェア後にフォームから応募することで「Anker充電器(Findyオリジナルデザイン入り)」が抽選で当たるかも!?

ぜひお申し込みください。

👇👇👇

コントリビューション・オブ・ザ・イヤー2024中間発表を試してみる

続きを読む

フルリモート第1号の自分が、働く上で大切にしている5つのこと

こんにちは。

Findy で Tech Lead をやらせてもらってる戸田です。

弊社では遠隔地フルリモートで働いているメンバーが多数おり、北は北海道から南は福岡まで、全国各地に点在しています。

本社は東京にあって関東在住のエンジニアも多数おり、遠隔地フルリモートの人数の比率で言うと半々くらいでしょうか。

実を言うと、弊社のフルタイム勤務でのエンジニアの遠隔地フルリモート勤務の第一号は私なのです。

2020年7月にJOINしてから4年以上、ずっと福岡から遠隔地フルリモートで働いていますが、第一号の私が結果を出すことで「出社・フルリモート関係なく成果が出るよね」と思ってもらうために、当初は本当に頑張りましたw

結果として弊社では、「ハイスキルなエンジニアであればフルリモートでも問題ない」という認識になり、遠隔地フルリモートで働くエンジニアが増えていきました。

そこで今回は、私がフルリモート勤務をする上で心がけていることを公開しようと思います。

それでは見ていきましょう!

心がけてることリスト

とりあえず自分のtimesになんか書く

弊社ではエンジニアを中心にSlackで自分自身のtimesチャンネルを持つようにしています。

timesチャンネルは一般的に使われている運用方法ですが、「開始します」「終了します」だけの書き込みになってしまっている人はいませんか?

このtimesチャンネルの使い方というのが重要で、とりあえず自分のtimesになんか書く ということを心がけています。

つぶやく内容は何でもいいです。無言よりは数万倍マシです。

フルリモート勤務だと出社メンバーの顔も、他のフルリモートメンバー同士の顔も見えないので、お互いに存在感を出すことが重要です。

そのため、自分自身に割り当てられたtimesチャンネルで好きなようにつぶやくことが、フルリモート勤務でのコミュニケーションの1つの形だと思っています。

作業ログ的に自分の作業をtimesに記録することもオススメです。作業途中に詰まった時などに、timesを見てくれた他のメンバーが助け舟を出してくれることがあります。

timesが無言なのはダメゼッタイ。

わからないこと。上手くいったことは全力でアピールする

自分が何に困ってるのか、何に苦しんでいるのかは、自分から発信します。

先ほど紹介した自分のtimesチャンネルに書いてもいいですし、そこから直接メンションして誰かに助けを求めるのもいいでしょう。

作業に詰まって1人でずっと悩んで結果的に1日潰しました。はオフィス出社でもそうですが、フルリモート勤務においては特に信頼を大きく失ってしまいます。

わからないことだけじゃなくて、解決したこと、上手くいったことは特に全力でアピールします。

嬉しいことは形に残ったほうがいいので、timesにガンガン書き込みます。

周りのみんなも全力で祝福しましょう。

わからないこと、上手くいったことといったような作業の進捗に関わる発信は都度行うようにしています。

メンションには最優先で反応する

何かしらの作業をしていても、自分へのメンションを優先してチェックします。

今の作業に集中したいなら、「あとで確認する」旨を相手に伝えたり、リアクションアイコンを付けます。

「メンション送ったのに反応が何もない」ということは、相手からしたら「無視されてる」のか「忙しくて見れてない」のかが分かりません。

まずは「あなたのメンションを見てますよ」ということを伝えます。

テキストと通話の使い分け

テキスト、通話でのコミュニケーションを適切に使い分けることを心がけています。

テキストでのコミュニケーションだけではどこかしらで必ず限界がきますが、テキストにも形に残る、非同期でコミュニケーションできるといったメリットもあります。

これは誰が相手でも、自分がどれほどテキストコミュニケーションが上手いと思ってても、必ず限界があります。

あ、これ伝わってないなと察したり、認識が一致していないと感じたらハドルやZoomで繋いで通話をします。

その際、議事録的なものを書いて対面で話した内容のサマリを議事録として形に残します。その議事録を後で相手に送り、認識が合ってるかどうかを確認します。

議事録は必要があれば他メンバーが見える場所にも共有します。そうすることで何の話をしていたのか、何で困っていたのかを他のメンバーが把握できるようになります。

また、テキストは後々まで形に残るので、相手への感謝や称賛はテキスト、リアクションで送ります。

逆に文脈を口頭で伝えたほうがよい話、ネガティブな話は対面で、ハドルやZoomを使います。自分が言及されているのを他の人に見られたり、後々まで形に残るのは良い気分ではないです。

あと自分の場合は、不定期に自分のtimesチャンネルのハドルを開いて雑談をする「お茶会」を開いています。

なんか話したい、雑談したい、相談したいことがあるなど、動機は何でもOKです。エンジニア以外の職種の子が参加してくれることもあります。

とはいえ出社も大事だよね?

ここまでフルリモート勤務での話を書いていましたが、やはり出社しての対面コミュニケーションに勝るものはありません。

遠隔地フルリモートで勤務していたとしても、1年に数回は出社して対面コミュニケーションを取るようにしています。

自分の場合は4ヶ月に1回程度、費用は会社持ちで1週間程度出社しています。

その期間は自分の作業よりも出社メンバーとの対面コミュニケーションを重視しています。

この期間での対面コミュニケーションにより、帰宅後のお互いのコミュニケーションのハードルが下がり、結果的に意思疎通がスムーズになります。

まとめ

いかがでしたでしょうか?

今回の記事が、フルリモート勤務での悩み事に少しでも役に立てれば幸いです。

現在、ファインディでは一緒に働くメンバーを募集中です。

興味がある方はこちらから ↓ herp.careers

【2024年上半期】Findy Tech Blogの人気記事まとめ

こんにちは。

Findy で Tech Lead をやらせてもらってる戸田です。

2024年の2月末に弊社テックブログを開設してから半年が過ぎようとしています。

今年は上半期だけで31個の記事を投稿しており、テックブログを開設してから6月いっぱいまでで週に1~2記事のペースで投稿できています。

また総PV数は10万PV、はてブ数は1200を超え、多くの方に読んでいただいているようです。いつもありがとうございます!

イベントでお会いした方や、弊社に応募していただき面接でお会いした方からも「テックブログ読んでます!」と言っていただけることが増えてきており、改めて技術広報の重要性を感じています。

そこで今回は、2024年上半期の弊社テックブログの振り返りと称しまして、2024年上半期の人気記事達を紹介します。

それでは見ていきましょう!

2024年上半期の人気記事

【エンジニアの日常】エンジニア達の自慢の作業環境を大公開シリーズ

tech.findy.co.jp

弊社テックブログの最初のターニングポイントとなった記事です。おそらくこのシリーズが出ていなかったら、総PV数が10万を超えることはなかったでしょう。

2月末にテックブログを開設してから1ヶ月程度が経った頃にPart1が公開され、想定以上の反響があったため、Part2、Part3と続けてシリーズ化された人気シリーズの1つです。

もともとテックブログを開設した理由の1つに、エンジニア採用を強化したいという狙いがありました。

採用を強化する上で技術的な発信は重要ですが、それと同じくらい文化の発信も重要だと考えており、まずはどんなエンジニア達が働いているのかを知ってもらいたいという思いからこのシリーズを企画しました。

おかげさまで多くの方に読んでいただき、上半期のPV数の3割はこのシリーズが占めています。

内容としましては、弊社エンジニアたちの自宅での作業環境を写真付きで紹介しており、ガジェットやキーボード、デスク周りのアイテムなどが紹介されています。

ちなみに記事のタイトルですが、タイトルを考えるのに行き詰まった私がChatGPTにタイトル案をいくつか生成してもらい、その中から選んだものですw いや〜生成AIって便利ですね!

開発生産性指標を向上させるためにやってはいけないアンチパターン

tech.findy.co.jp

記事単体のPV数としては上半期1位の記事です。

開発生産性を向上するためにやったほうがいいことは多くの記事が発信していますが、こちらはその逆でアンチパターンを紹介しています。

一見、「そんなの当たり前やろ」と思うかもしれませんが、その当たり前をきちんと明記したことに価値があると思います。

やってはいけないことを理由付きできちんと説明できるからこそ、正しい方法を理解、実行できるのです。

開発生産性に興味関心がある方には是非一読していただきたい記事となっています。

開発生産性を上げるために開発をする前に考えていること

tech.findy.co.jp

記事単体のはてブ数としては上半期1位の記事です。

こちらも開発生産性に関する記事で、実際にコードを書く前にやるべきこと、準備すること、考えることを紹介しています。

いかに速く、シンプルに、効率よくリリースしてユーザーに価値提供をするか、という視点で書かれており、開発において重要なポイントがまとめられています。

Findyの爆速開発を支えるテクニック

tech.findy.co.jp

弊社は開発生産性、とりわけ開発スピードには非常に拘っています。

この開発スピードを継続し、更に速くするために弊社で実践しているテクニックをいくつか紹介しているのがこの記事です。

タスクの分解の仕方やPull requestの粒度、テストコードの考え方などをシンプルにまとめている記事となっています。

開発生産性の向上に着手したいけど何から着手したらいいのかわからない。という方には是非読んでいただきたい記事です。

Findyの爆速開発を支える「システムを守るテストコード」の実例3選

tech.findy.co.jp

先ほど紹介した「Findyの爆速開発を支えるテクニック」の記事で紹介したテストコードに関する内容を更に掘り下げた記事となっています。

実際のテストコードを交えて、具体的にどのようなテストコードでシステムを守るのかを説明しています。

実際に読んでみると、抜け落ちていた視点などもあるかと思いますので、ジュニアエンジニアの方にもシニアエンジニアの方にも是非1度読んでいただきたい記事です。

Wallaby.jsを使ってフロントエンド開発のテストを効率化しよう

tech.findy.co.jp

Wallaby.jsはフロントエンド開発において非常に便利なツールです。

多数のIDEに対応しており、ほぼリアルタイムに修正内容を反映しつつテストコードの実行結果を表示してくます。

この記事では、Wallaby.jsの使い方や設定方法、実際にどのように活用しているかを紹介しています。

フロントエンドのテストコードを書くのが苦手だったり、テストコードをもっと効率的に書きたい!と思ってる方にオススメの記事です。

ファインディにエンジニアとして入社していいなと思ったこと3選

tech.findy.co.jp

実際に弊社にJOINしてくれたエンジニアが、入社して1ヶ月程度経ってから感じたことをまとめた記事です。

JOIN直後のエンジニアが弊社の開発環境をどのように感じているのか、どのような点が良かったのかなど、長年弊社に在籍している自分からは気づかない視点もありました。

弊社に興味を持ってくれている方には是非読んでいただきたい記事となってます。

まとめ

いかがでしたでしょうか?

ここでは紹介しきれなかった記事も多数ありますので、それらも是非読んでみてください。

全体的に見て、開発生産性やフロントエンド関連の記事に対しての反響が大きかったように感じます。

下半期も引き続き、これらのトレンドを追いつつも技術的な挑戦を続け、社内の文化、雰囲気なども含めてテックブログを通じて発信できればと思います。

今後とも弊社テックブログをよろしくお願いします。

現在、ファインディでは一緒に働くメンバーを募集中です。

興味がある方はこちらから ↓ herp.careers

ファインディの爆速開発を支えるモノレポ管理ツール「Nx」について

ファインディ株式会社でフロントエンドのリードをしております 新福(@puku0x)です。

この記事では、ファインディで導入しているモノレポ管理ツール「 Nx 」について紹介します。

モノレポとは

モノレポは全てのコードベースを単一のリポジトリで管理する手法です。

monorepo.tools

コードの共通化や可視化、ツール・ライブラリの標準化、一貫性のあるCI/CDパイプラインを構築できるといったメリットがあります。また、マイクロサービスと相性が良いとも言われています。

circleci.com

ファインディでは主にフロントエンド系のリポジトリをモノレポとして運用しています。

アプリケーションとそれに関連するフィーチャー、UIライブラリがひとつにまとまっているため、複数のリポジトリを移動することなくコードを参照できます。

Nxとは

Nxはモノレポ管理やアプリケーションのビルド、テストの実行、コード生成などの機能を備えた統合的なツールです。

nx.dev

モノレポ管理ツールは他にもLernaTurborepoなどがあります。アプリケーション開発において有用な機能が多くあることや、コミュニティが活発で継続的なメンテナンスが見込めること、前職で導入実績があったことなどがNxを選んだ理由です。

後述する「変更検知」や「キャッシュ機構」といった機能は、Pull Requestの粒度を細かくするファインディの開発スタイルと高い親和性があり、導入当初から私達の開発を支える頼もしいツールとなっています。

大手企業でも採用事例が増えており、Nxはモノレポ管理ツールとして有力な選択肢といえるでしょう。

https://npmtrends.com/lerna-vs-nx-vs-turbo

(個人的に推していたOSSがここまで有名になったことには感慨深いものがありますね!)

Nxワークスペースの作成

create-nx-workspace を実行するとワークスペースを作成できます。

Reactをはじめ、メジャーなフレームワーク用のプリセットもあるためすぐに開発を始められます。

npx create-nx-workspace@latest <ワークスペース名> --preset=react-monorepo --appName=<アプリケーション名> --bundler=webpack --e2eTestRunner=playwright --style=scss --nxCloud=skip

詳細は公式のチュートリアルをぜひご覧ください。

nx.dev

Nxの機能

コード生成

nx generate コマンドでプロジェクト(アプリケーションやライブラリ)を作成できます。

npx nx generate @nx/react:application --name=<アプリケーション名> --directory=<ディレクトリ> --routing=false --e2eTestRunner=playwright --projectNameAndRootFormat=as-provided
npx nx generate @nx/react:library --name=<ライブラリ名> --directory=<ディレクトリ> --bundler=rollup --unitTestRunner=jest --projectNameAndRootFormat=as-provided

nx generate で実行できるGeneratorは自分で作ることもできます。

nx.dev

ファインディではフィーチャー用のファイル一式を生成するGeneratorを作って開発を効率化しているチームもあります。また別の機会に紹介できればと思います。

変更検知

Nxはプロジェクト間の依存関係を自動的に算出する機能を備えています。

npx nx affected --graph を実行すると次のように依存関係を可視化できます。

npx nx affected --target=build のように指定すると、変更のあったプロジェクトとそれに依存する他のプロジェクトを全てビルドしてくれます。

nx affected は変更されたコードに関するプロジェクトのみ実行する

個人的なおすすめは、npm-scriptsやCI上で実行するコマンドを nx affected ベースにすることです。

"scripts": {
  "build": "nx affected --target=build",
  "test": "nx affected --target=test",
  "lint": "nx affected --target=lint",
  ...
},

必要なタスクのみ実行されるためスピーディーに開発できます。

依存関係の管理

Nxが持つプロジェクト間の依存関係はLintルールにも応用されます。

ファインディでは、@nx/enforce-module-boundaries ルールを適用し、意図しない依存関係の逆転が起こらないように制御しています。

nx.dev

具体的には、各プロジェクトに次のようなタグを設定し、

{
  "name": "utils",
  "sourceRoot": "libs/utils/src",
  "projectType": "library",
  "tags": ["scope:shared", "type:util"],
  ...
}
- apps/
  - app1                (scope:app1)
  - app2                (scope:app2)
- libs/
  - app1/
    - feature-dashboard (scope:app1, type:feature)
    - ui                (scope:app1, type:ui)
  - app2/
    - feature-user      (scope:app2, type:feature)
    - ui                (scope:app2, type:ui)
  - utils               (scope:shared, type:util)

.eslintrc.json に対応するルールを設定しています。

"@nx/enforce-module-boundaries": [
  "error",
  {
    "allow": [],
    "depConstraints": [
      {
        "sourceTag": "scope:shared",
        "onlyDependOnLibsWithTags": ["scope:shared"]
      },
      {
        "sourceTag": "scope:app1",
        "onlyDependOnLibsWithTags": ["scope:shared", "scope:app1"]
      },
      {
        "sourceTag": "scope:app2",
        "onlyDependOnLibsWithTags": ["scope:shared", "scope:app2"]
      },
      {
        "sourceTag": "type:feature",
        "onlyDependOnLibsWithTags": ["type:ui", "type:util"]
      },
      {
        "sourceTag": "type:ui",
        "onlyDependOnLibsWithTags": ["type:ui", "type:util"]
      },
      {
        "sourceTag": "type:util",
        "onlyDependOnLibsWithTags": ["type:util"]
      }
    ]
  }
]

設定したルールを図にするとこのようになります。scope がプロジェクト間の依存関係、type が内部のレイヤーの依存関係を表します。

@nx/enforce-module-boundaries ルールが設定されたプロジェクトでは依存してはいけないモジュールに対してエラーが表示されます。

大規模なコードベースの管理においては、モジュール同士の依存関係の制御が非常に重要であり、こういった「かゆいところに手が届く」機能を持っていることがNxの魅力でもあります。

キャッシュ機構

Nxは一度実行されたコマンドのキャッシュを保持しており、同じコマンドが実行された場合にキャッシュから結果を再現する機能を持っています。

nx.dev

また、関連サービスである「 Nx Cloud」のリモートキャッシュ機能を有効にすると大幅なCI高速化が可能です。

実際にファインディでは、キャッシュの活用で毎月1,000時間以上のCI時間を削減できました。

自動マイグレーション

NxにはCodemodAngular CLIng update と似たコマンドが備わっています。

nx.dev

npx nx migrate latest
npx nx migrate --run-migrations

nx migrate を実行すると、Nx本体と各種プラグイン、reacteslinttypescript などの依存ライブラリ・ツールがまとめて更新されます。

バージョンアップに伴うマイグレーションは手動で対応すると大変ですが、Nxでは自動化されています。メンテナンスの手間が省けると同時に属人化も抑えられるため重宝しています。

まとめ

この記事では、Nxの概要と基本的な機能について紹介しました。

Nxは単なるモノレポ管理ツールに留まらず、「開発者体験の改善」や「開発生産性の向上」といったポテンシャルを秘めています。

✨✨✨ Nxはいいぞ! ✨✨✨

Nxはいいぞおじさんから伝えたいことは以上です。

より詳細な活用法やNx Cloudの高度な機能については、今後の記事で取り上げる予定ですのでご期待ください。

ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。

herp.careers