TECH PLAY

株式会社ラクス

株式会社ラクス の技術ブログ

927

こんにちは。株式会社 ラク スで先行技術検証や非エンジニアの方向けへの勉強会を実施している技術推進課のt_okkanです。 今回は非エンジニアの方向けの勉強会で、 IPv4 と IPv6 についてまとめる機会があったため記事にしました。 エンジニアでない方でも理解できるようにまとめましたので、 IPアドレス枯渇 問題を調べる際の事前知識としてもらえればと思います。 IPとは IPv4とネットワーク IPv4アドレス枯渇問題 NATを使用した対策 グローバルIPアドレスとプライベートIPアドレス NAT IPv4アドレスの確保 IPv6への移行 IPv6への移行の現状 IPv6へ移行するメリット IPv6へ移行するデメリット IPv6が普及していない理由 まとめ 参考 IPとは IPとは、Internet Protocolの略でコンピュータとコンピュータを繋ぐための通信規格の1つです。 複数のネットワークを相互に接続して、データを中継・伝達しながら1つの巨大なネットワーク「インターネット」を構成する役割を担っています。 IPによって接続されたインターネットでは、個々のネットワークとコンピュータを識別するために IPアドレス を割り当て、 送信先 と送信元を指定して通信を行っています。 IPv4 とネットワーク IPアドレス とは、インターネットに接続されたコンピュータ1台ごとへ割り振られる番号で、コンピュータのインターネット上での住所のようなものです。 そのため、ネットワーク上に接続されているコンピュータの IPアドレス は基本的に重複することはありません。 コンピュータがインターネット上でデータの送受信を行う場合、この IPアドレス を用いてデータの 送信先 と送信元を指定して通信を行っています。 この IPアドレス にはバージョン4とバージョン6が存在し、現在広く使用されているのがバージョン4の IPv4 になります。 IPv4 の IPアドレス は2進数の32桁で8桁ごとの4つに区切られており、それぞれ10進数にした形で表現されています。 2進数の1桁は0と1の2通りで、8桁の場合は256通りを表現できます。 IPv4 アドレスはその8桁の数字を4つ組み合わせているため、約43億通り表現できます。 よって IPv4 アドレスは約43億台のコンピュータを識別できます。 IPv4 アドレス枯渇問題 IPv4 アドレスを使用すると、約43億個のコンピュータを識別できます。しかし、2020年の世界の人口は約77億人と言われており、一人がPCと スマートフォン などの複数のコンピュータを所持する世の中になっています。 IPv4 アドレスでは、43億個以上のコンピュータに IPアドレス を割り当てることができなくなってしまいます。このように、インターネットに接続するコンピュータに割り振る IPv4 アドレスがなくなることを、 IPv4 アドレス枯渇問題と呼んでいます。 実際に、2019年に欧州地域で IPアドレス を管理しているRIPE NCC は IPv4 アドレスが完全に枯渇したと報告しています。 1 また、日本を含むアジア太平洋地域の IPアドレス を管理している組織であるAPNICは、2021年に IPv4 アドレスが完全に枯渇するのではないかと予想しています。 2 この問題を解決するための対策として、 IPv4 を利用して対策を行う延命策と、別の仕組みを利用して解決を行う恒久的な対策があります。延命策としてはNATを利用した対策などが、恒久的な対策として IPv6 への移行が主な対策として挙げられます。 NATを使用した対策 IPv4 アドレスの枯渇問題に対する IPv4 を利用した延命策の一つとして、NATを利用した対応があります。 NATの説明の前に、 グローバルIPアドレス とプライベート IPアドレス の説明をします。 グローバルIPアドレス とプライベート IPアドレス グローバルIPアドレス とは、インターネットに接続しているコンピュータに割り当てられる IPアドレス で、これまで扱ってきた IPアドレス を指します。 一方のプライベート IPアドレス は、企業のネットワークや家庭用のネットワーク内で使用される IPアドレス です。インターネット上では使用できず、同じネットワーク内でのみ使用できる IPアドレス になります。プライベート IPアドレス は、同じ IPアドレス でもネットワークが異なる場合は重複してもよいです。 IPv4 アドレスの枯渇が懸念されすべてのコンピュータに IPv4 アドレスを割り当てできなくなるため、ルータや公開サーバーなどインターネットに直接接続するコンピュータにのみ グローバルIPアドレス を割り当て、ルータ内の閉じられたネットワークに接続されているコンピュータにはプライベート IPアドレス を割り当てるようにしています。こうすることで IPv4 アドレスを効率的に使用できます。 ではどのようにして、 グローバルIPアドレス とプライベート IPアドレス を結び付けているのでしょうか。この IPアドレス の変換を行うのがNATです。 NAT NAT(Network Adress Translation)とは、 グローバルIPアドレス をプライベート IPアドレス に、またはその逆の変換を行う技術のことです。最近は IPアドレス とポート番号を組み合わせたNAPT(Network Address and Port Translation)が主流になっています。主に ルーター にこのNATの機能が組み込まれています。この技術を利用することで、プライベート IPアドレス が割り当てられた複数のコンピュータを1つの グローバルIPアドレス で管理できます。 このように、一つの IPv4 アドレスで複数のコンピュータを効率的に管理でき グローバルIPアドレス を節約できるため、 IPv4 の延命策としてNATが利用されています。 IPv4 アドレスの確保 もう一つの IPv4 アドレス枯渇問題の対策として、未使用の IPv4 アドレスの確保が挙げられます。 IPv4 アドレスが枯渇する前にプロバイダーから事前に未使用の IPv4 アドレスを割り当てを受けて確保しておくことや、未使用の IPv4 アドレスを 保有 している企業や組織から IPアドレス を購入して確保することが挙げられます。 しかし、2014年以降から IPv4 アドレスの消費ペースは上がっており最終的には IPv4 アドレス数の限界があるため、時間が進むにつれ IPv4 アドレスの確保が困難になります。 IPv6 への移行 IPv4 アドレスの枯渇を背景に恒久的な対応策として開発されたのが、 IPv6 です。 IPv4 は2進数の32桁で表現されましたが、 IPv6 は2進数の128桁で16桁ごとに区切り表現できます。また、それぞれ16進数にした形で表現されます。 2進数で16桁の場合は65536通りを表現できます。 IPv6 アドレスはその16桁を8つ組み合わせているため、約340潤個の IPアドレス を管理できます。1潤は1兆の3乗ですのでほぼ無限であることがわかります。 そのため、全世界のコンピュータに対して IPアドレス を割り当てることができ、NATを介さずに直接コンピュータ同士で通信を行えるようになります。 IPv4 アドレスから IPv6 アドレスへ移行することで、 IPv4 アドレス枯渇問題を根本的に解決することができます。 IPv6 への移行の現状 IPv4 アドレスの恒久的な対策である IPv6 への移行ですが、現状は IPv6 が普及しているとは言い難い状況です。 3 IPv6 へ移行するメリットとデメリットを紹介し、 IPv6 が普及しない原因を考察していきます。 IPv6 へ移行するメリット サービスを提供する企業において、 IPv4 アドレスの枯渇問題の制限を受けることなく、サービスの拡大や新規サービスの展開を行うことが挙げられます。 4 IPv4 アドレスが枯渇することで、新たにサービスを拡大する際に必要なネットワーク機器やサーバーに IPアドレス を割り当てることが困難になります。 また今後は IPv4 アドレスの市場価値が高まり値段が高騰する可能性もあり、サービスを拡大するために莫大なコストを投下する必要があるかもしれません。 5 IPv6 に移行することで、ほぼ無限に IPアドレス を付与することができるため、このような制限を気にすることなくサービスの拡大を行うことができます。 逆に IPv6 への対応が遅れると IPv4 アドレスの制限を受け、サービスの拡大や新サービスの展開ができなくなる可能性もあります。 IPv6 へ移行するデメリット IPv6 へ移行することのデメリットとして、 IPv4 との互換性がないことが挙げられます。 IPv4 と IPv6 は同じIPという プロトコル であっても互換性がなく、 IPv4 アドレスのコンピュータと IPv6 アドレスのコンピュータは直接通信することができません。 そのため IPv4 から IPv6 へ移行するために、 IPv6 に対応したルータやソフトウェアの開発・導入するコストが必要になります。 6 また、 IPv4 と IPv6 の通信のどちらにも対応する必要があることも挙げられます。今後も IPv4 を利用し続けるサービスやユーザーが存在することになります。 IPv4 のインターネットと IPv6 のインターネットが同時に存在することになり、 IPv4 の通信と IPv6 の通信のどちらにも対応する必要があります。 デュアルスタックやトンネリングなど IPv4 と IPv6 を共存させる技術があるため、そのための機器の導入や環境を構築するコストが必要になります。 IPv6 が普及していない理由 IPv4 アドレスの枯渇を解消するために開発された IPv6 ですが、今だに主流となっているのは IPv4 になっており、 IPv6 が普及しているとは言い難い状況です。 Google が「 IPv6 の採用状況」という統計で、 IPv6 アドレスを利用して Google サービスにアクセスしているユーザーの割合のデータを公開しています。 7 この統計によると、 IPv6 アドレスを利用している全世界のユーザーの割合は約35%で、日本国内のユーザーの割合は約40%となっています。 IPv6 が普及していない理由としては、以下の記事でも紹介されているようにこのような理由が考えられます。 cloud.watch.impress.co.jp 対応、運用コストがかかる IPv6 のデメリットでも紹介した、 IPv4 から IPv6 へ移行するためのコストや、 IPv4 と IPv6 の通信を共存するための運用コストが高いことが原因で、 IPv6 の普及が進んでいないと考えられます。 新たな利益を獲得できる訳ではなく、優先度が低い また IPv4 と IPv6 を共存させる技術があり、今後も IPv4 を利用できます。 IPv6 に移行しても、新たなユーザーを獲得したり新たな利益を得ることができる訳ではないため、優先度が低く対応が遅れていると考えられます。 また 総務省 の IPv6 についての調査結果によると、データセンター事業者とコンテンツ事業者で IPv6 への移行を検討していない理由として「自社だけで検討しても意味がない」ことや、「同業他社の動向を見てから検討する」ことが挙げれれています。 8 IPv6 に移行する必要性はあるものの、移行にかかるコストを回収できるわけでもないため、他の誰か(他社)が IPv6 に移行するのを待っている状態なのかもしれません。 まとめ IPアドレス のバージョンである IPv4 と IPv6 と、 IPv6 への移行について、簡単に説明してきました。 サービスを提供する企業にとって、 IPv6 に移行しても新たに利益がでない可能性があるものの、移行しないとサービスの拡大の障壁になるかもしれません。 IPv4 枯渇問題や IPv6 対応についての記事を見る前の、事前知識としてもらえたらと思います。 参考 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com The RIPE NCC has run out of IPv4 Addresses ↩ IPv4アドレスはもう残っていないのか、枯渇問題の現状 ↩ 日本におけるIPv6の普及とIPv4 over IPv6 ↩ IPv6@APNIC ↩ IPv4アドレスのお値段について考える ↩ Professional IPv6(無料版) ↩ IPv6の採用状況 ↩ IPv6 によるインターネットの利用高度化に関する研究会 最終報告書 ↩
アバター
こんにちは。 株式会社 ラク スで先行技術検証を行っている「技術推進課」の堀内( id:yhoriuchi )です。 今回、先行技術検証の取り組みである「技術推進プロジェクト」で調査を行なったメッセージキュー(MQ)について紹介します。 調査項目としてMQを選定した理由とゴール よくある話として、画面操作からのバッチ実行制御(実行順序制御、リトライ制御、エラー制御など)は非同期に動作するため実装が複雑化しやすいという問題を抱えています。 この「非同期な実行制御」をメッセージキュー製品で解決し、コードベースの簡素化が可能かの結論を出すことをゴールとして進めました。 MQとは何か 非同期型の通信方式のことです。システム間で通信を行う際、キューを挟んでメッセージをやり取りすることで非同期通信を実現します。 技技術的には1980年代から利用されており、歴史がある技術領域となっています。 近年ではマイクロサービス アーキテクチャ や分散処理システムの非同期通信において利用されることが多いため、このコンテキストでは聞いたこと・使ったことのある方もいるかもしれません。 下記にMQを使わない場合、使った場合の違いを簡単な絵で説明します。 MQを使わない場合のイメージ AさんからBさんへの作業依頼を直接行うことがイメージとして近いです。 Bさんが不在だったり、忙しい場合は作業依頼を受け付けてもらうことができないため、依頼できるようになるまでAさんは待ち続ける必要があります。 MQを使った場合のイメージ AさんとBさんとの間に「机」を設置して作業依頼を行うようなイメージです。Aさんは作業依頼を机に置いておくことでBさんに依頼を出すことができます。 Bさんは都合の良いタイミングで依頼を受け取れば良いですし、AさんはBさんの都合に合わせて待つ必要も無くなります。 このように送信側(Aさん)と受信側(Bさん)はMQ(机)を挟むことでお互いが好きなタイミングで処理を行うことができるようになります。 さらには受信側に障害が発生していたとしても、送信側はそれを意識することなく作業依頼を送ることができるため、障害に強いシステムにすることができます。 MQが無い場合のシステム 画面から CSV をアップロードする場合を想定し、手っ取り早く実現することを考えると下記のようになります。 ①ファイルをアップロードする ②Webアプリケーションがリク エス トを受け取り、 バッチ処理 を起動する ③ バッチ処理 の中でDBへの書き込みを行う ④一連の処理が終わった後、ユーザーに結果を返す この場合、リク エス トを受けてバッチが実行されるため、ユーザーはリク エス トを行うとすぐに処理が開始し、処理が終わればすぐに結果を受け取ることができます。また、特別な制御を行わないので実装量も少なくなります。 しかし、リク エス トのたびに バッチ処理 が実行されるため、たくさんのリク エス トを同時に受け付けるとサーバーが高負荷になりやすいというデメリットもあります。 これを回避するために取られる手段としてDBを用いた実行制御が考えられます。 次のようなイメージです。 このようにWebアプリとバッチの間にジョブ管理用のテーブルを用意し、cronや自作の常駐プロセスでジョブ管理テーブルを常に監視しながらバッチ実行を行うことになります。 DBを使ったジョブ管理も悪くはないのですが、1サーバーを複数の顧客で共有する(マルチテナント)場合は途端に考えないといけないことが増えます。 例えば、A社、B社、C社...と複数ある顧客で バッチ処理 が同時に起動しても問題ないのか、サーバーリソースを考えると何社まで同時起動が許容されるか、シーケンシャルに全テナントを処理した方がよいのか、などなど。システム要件にもよるので、どれが良い悪いではありませんが、考えることが増えると実装にも跳ね返ってくるのが世の常ですよね。 MQを導入した場合 先ほどの画面からの CSV アップロードは下記のような構成になります。 ①ファイルをアップロードする ②Webアプリケーションがリク エス トを受け取り、キューに登録する(このタイミングでユーザーにレスポンスを返す) ③ワー カープ ロセスがキューからメッセージを1つずつ取り出す ④DBへの書き込みを行う ⑤一連の処理が終わった後、ユーザーに結果を通知する キューを介してWebアプリと バッチ処理 であるワー カープ ロセスを分離することが可能となり、非同期処理を実現できるようになります。 さらにキューからメッセージを1つずつ取り出して処理するため、同時アクセスによる多重起動を気にする必要はありません。 下記のようなイメージです。 こうなってくると バッチ処理 部分をスケールしたい場合にどうするのか気になるところですが、この場合はキューに接続するバッチをスケールしたい分だけ単純に増やしてあげれば実現できます。基本的にキューのメッセージは 排他制御 されるため、別のプロセスが同じメッセージを取り合うことはありません。 セマフォ のような制御を意識する必要もありません。 さらに、メッセージを取り出すとメッセージは削除されます。何らかの理由でリトライが必要な場合はメッセージをキューに戻す(リキューと呼ぶ)ことも簡単に実現できます。 通常DBでジョブ管理を行うとテーブルをロックしてステータスを「処理中」に更新する、完了したら完了ステータスに更新する、一定の期間が経過したらジョブ管理テーブルから履歴を消す、といったことが必要になってくると思いますが、MQを利用するとこれらの実装は不要となります。 結論 ここまで調べてきた結果、下記の理由から複雑な箇所をMQに任せることができるため、実装が減りコードベースを簡素化できることが分かりました。 MQでリク エス トを1列に整列できるため、多重起動制御の実装が不要になる。 MQのメッセージ登録、取得がジョブのステータス管理に相当するため、ステータス管理を実装する必要がない。 メッセージは重複なくキューから受信側に配信されるため、 排他制御 を意識する必要がない。 利用できる ユースケース CSV ファイルアップロードを例に考えてきましたが、MQの利用が向いていると思われる ユースケース を考えてみました。 下記のような瞬間的に大量リソースを要求するケースや、機能間の 疎結合 を実現したい場合に有効となります。 大量のデータ登録/出力など、長時間リソースを消費するケース CSV アップロード/ CSV ダウンロードなど 画像変換等、瞬間的に大量リソースを使うケース 画像のリサイズ、加工をユーザーリク エス トに応じて実施するなど サービスとサービスを分離したいケース マイクロサービス アーキテクチャ のような構成で、サービス間にMQを挟むことで分離する 最後に MQを調べ始めた頃、基本的な用語が分からず変に時間がかかってしまったので、基本用語の説明と検証した結果からの所管を書いて締めくくろうと思います。 基本用語 MQ製品を調べていると プロデューサー/コンシューマー 、 パブリッシャー/サブス クライバー (略してパブサブとも呼ばれる)が説明として出てくることがありますが、この用語を理解しておくと製品理解がスムーズなのでここで説明しておきます。 プロデューサー/コンシューマー 1つのメッセージが1つの受信者だけに配信されるケースでは、送信側を「プロデューサー」、受信側を「コンシューマー」と呼びます。 1対1通信となる設計で使われる用語で、このページで紹介した内容がまさにプロデューサー/コンシューマーの関係で成り立っています。 多くのWebアプリでは直感的に理解しやすい構成だと思います。 パブリッシャー/サブス クライバー MQでは1つのメッセージを2つ以上の受信者にブロードキャストする仕組みがあり、その場合は送信側と受信側の呼び方が上記と変わります。 送信側が「パブリッシャー」、受信側が「サブス クライバー 」となります。さらにキューは「トピック」と呼ばれるようになります。(調べ始めの頃はトピックが何かが分かっておらず、ドキュメントを読むのに苦労していました...) 検証した結果からの所感 今回の検証でMQを使えば、リク エス ト毎にプロセスを起動する実装のデメリットを解消しつつ、DBでジョブ管理を行う際の煩わしさから解放されることが分かりました。 サーバーのリソースコン トロール が必要な際には是非とも導入しておきたい技術だと思います。 一方で、すでにDBによるジョブ管理を行なっており、実装が複雑になってしまっている場合、MQに置き換えるべきかについてはどうでしょうか。 個人的な結論となりますが、このケースでは無理に置き換えなくて良い考えています。実装が複雑になっていたとしても、それで保守・運用が回っているのであればMQに置き換えるだけのコストメリットはないでしょう。 もしかしたらジョブを追加、変更する頻度が多くて、その都度バグが発生するようなケースがあるかもしれませんが、この場合は作り直しが候補に上がってくると思います。作り直すのであればMQの導入も検討に含めるのが良いでしょう。
アバター
はじめに みなさんこんにちは。フジサワです。 「フロントエンド」や「フロントエンドエンジニア」という単語を耳にするようになって久しいですが、自他共に認めるバックエンドエンジニアを出自に持つ私にとって フロントエンド界隈の移り変わりは激しく、追いかけるのもなかなか大変です。 そこで今回は、改めてフロントエンドとは、またフロントエンドエンジニアに必要なスキルとは、といったあたりを整理してみたいと思います。 フロントエンドエンジニアに興味を持ったものの、あまりよくわかっていないと言う方の参考になれば幸いです。 はじめに フロントエンドとは フロントエンドエンジニアとは バックエンドとは バックエンドエンジニアとは フロントエンドエンジニアが押さえておいた方が良い技術要素 フロントエンド基本三要素 パッケージマネージャ ビルドツール群 JavaScriptフレームワーク SPAと状態管理 WebComponents Modern CSS テスト 型システム サーバーサイドレンダリング(SSR) GraphQL おわりに 参考 フロントエンドとは まずはフロントエンドとは何なのか、その定義から確認してみましょう。 Web開発業界におけるフロントエンドとは、システムの利用者が直 接触 れる・見ることができる領域、つまり Webブラウザ 上で動作する領域をさします。 一昔前は、「クライアントサイド」と呼ばれることが多かったですが、最近は「フロントエンド」という呼び方をすることが多い印象です。 実際に、 Google トレンドなどで調べてみると、2014年ごろを境に「フロントエンド」の呼称が増えているようです。 ※「クライアントサイド」の比較対象を「フロントエンドエンジニア」という単語にしているのは、「フロントエンド」という単語がアプリケーション開発以外でも 用いられる単語のためです。厳密には比較する対象の次元が異なっていますが、呼称の移り変わり程度は、上記画像からでも読み取れると思います。 フロントエンドエンジニアとは 主にHTML, CSS , JavaScript を用いて、前述のフロントエンド領域、すなわち Webブラウザ 上のUI部分を開発するエンジニアを指すことが多いです。 利用者からの操作を受け付け、後述のバックエンドに対して情報の取得・検索や更新などのリク エス トを行い、得られた結果を加工・表示する部分を担います。 以前は、 Webデザイナー が兼務をすることも多かったですが、フロントエンド領域の複雑化・大規模化によって求められる範囲が広くなるに従い、分業されるようになっています。 ただし、これはあくまでそういうケースもある、ということで、チームの体制、人員、プロダクトの規模によってはこの限りではありません。 バックエンドとは フロントエンドに対して、バックエンドとは、利用者が直 接触 れない領域、つまりサーバー上で動作する領域を指します。 このため、クライアントサイドの対義語として、サーバーサイドと呼ばれることも多いです。 バックエンドエンジニアとは Java や PHP 、 Python 、 Ruby などの言語を用いて、サーバー上で実行される処理を開発するエンジニアです。 フロントエンドからのリク エス トを受け付け、計算処理やデータベースに対して情報の取得・検索や更新の処理を実行し、処理結果をフロントエンドにレスポンスする部分を担います。 Webデザイナー とフロントエンドエンジニアの線引きがときに存在しないように、フロントエンドエンジニアとバックエンドエンジニアの線引きも、状況によっては存在しない場合もあります。 一人のエンジニアが、フロントエンド領域とバックエンド領域、双方を担うというケースも少なくありません。 大規模な開発においてはフロントエンド、バックエンド、あるいは、デザイナーやインフラエンジニアといった分業が行われることが多いと思いますが、 前述の通り、プロダクトの状況によっては一人のエンジニアが多くの領域を担うことも十分にありえます。 おそらくこの記事を読まれている方の中には、これからエンジニアを目指そうとされている方も多いかと思いますが、 私見 として、どのような領域を目指すにせよ、それはあくまでその領域に対する専門性が突出して高い・強みである、という状態であって、 「フロントエンドエンジニアなのでバックエンドのことは全くわからない」よりは、「フロントエンドエンジニアだけどバックエンドもある程度分かる」という状態を 目指すのが良いのではないでしょうか。(もちろん、その逆も然り) フロントエンドエンジニアが押さえておいた方が良い技術要素 それでは、フロントエンドエンジニアはどのような技術要素を押さえておけば良いかを見ていきましょう。 「これが正解」というものはないと思いますが、筆者が参考にしている下記のWebサイトを元に簡単にそれぞれの技術要素について抜粋する形で補足をします。 また、ここで紹介する技術要素が全て必要、というわけではありませんので、その点もご留意ください。 Developer Roadmaps(のFrontend Developerの項) https://roadmap.sh/frontend フロントエンド基本三要素 HTML CSS JavaScript パッケージマネージャ アプリケーションを開発する際に用いる フレームワーク やライブラリなどのインストール、バージョン、依存関係のある関連パッケージの管理などを行うもの。 パッケージマネージャと呼ばれるもの自体は数多く存在しますが、フロントエンド領域においては、 npm ・ yarn が主に用いられます。 ビルドツール群 タ スクラン ナー 開発の際に実行する様々なタスクを自動化するためのもの。 フロントエンドで開発をする際、 コンパイル する、テストを実行する、ソースを難読化する…など様々なタスクを実行することが多くなりますが、自動化することで、省力化したり、ミスを防いだり、あるいは自動化の設定をチーム内で共有することで属人化を解消することができるようになります。 以前はGulpやGruntをよく耳にしましたが、パッケージマネージャのnpmに備わっている npm-scripts がRoadmapでは推奨されています。 モジュールバンドラー JavaScript や CSS 、画像ファイルを一つにまとめるためのもの。 複数のファイルに分割した JavaScript の依存関係を整理する、Webサイトにアクセスした際のブラウザからのアクセスの回数を減らすことなどを目的に使用されます。 特に、大規模なプロダクトのフロントエンド開発においては、 JavaScript を細かく分割し、可読性や保守性・拡張性の向上を行うことが必要になるため、モジュールバンドラーを用いない場合はこの管理がとても大変になります。 Roadmapでは webpack が推奨。なお、Webpackにはタ スクラン ナーとしての機能も有しているため、タ スクラン ナーの一種として紹介されることもあるので混乱しないように注意してください。 Linter/Formatter ソースコード の整形や記述ルール、構文のチェックを行うためのもの。 ESLint (Linter)や、 Prettier (Formatter)など。 複数のエンジニアでプロダクトを開発する際には、 ソースコード を読みやすくするために、書式を統一することが一般的です。この際に用いられるのがFormatterです。 また、 ソースコード の解析で検出できるレベルの記法ミス・バグを見つけるために用いられるのがLinterです。 なお、両者は ソースコード の静的解析を行うという点で同じ領域を守備範囲に持つため、双方がルールに沿った ソースコード の自動整形や補正機能を持っていることがあり、同時に語られたり、併用する/しないといったケースがあります。 JavaScript フレームワーク 開発の生産性を高めるために、一定の枠組み・ルールに沿って実装を行うための基盤となるソフトウェア。 フロントエンド開発においてもっとも注目されている領域の一つがが JavaScript フレームワーク ではないでしょうか。 メジャーな JavaScript フレームワーク としては React.js 、 Vue.js 、 Anglar など。RoadmapではReact.jsが推奨されていますが、弊社では、React.jsとVue.jsを採用しています。個人的な意見としては、フロントエンドエンジニアでも、バックエンドエンジニアでも、少なくともメジャーな JavaScript フレームワーク のうち、一つだけでも押さえておくと良いのではないかと思います。 厳密には JavaScript フレームワーク ではないのですが、小規模な開発においては古くから活用されている jQuery を採用するケースもあります。 「脱・ jQuery 」という文脈で JavaScript フレームワーク が代替手段として語られることがありますが、完全な代替手段というわけではなく、小規模なフロントエンド開発において、まだ jQuery の活用範囲はあるかなと思っています。 Svelt など、新しい フレームワーク もどんどん出てきており、今後の JavaScript フレームワーク の盛衰に注目です。 SPAと状態管理 JavaScript フレームワーク の進歩と共に、従来の Webブラウザ の画面を全て書き換えて画面遷移を行うスタイルのアプリケーションから、よりリッチな操作性や表現を実現するために、一つの画面だけを用意し、その画面内の一部分だけを更新するというアプローチをとるSPA(SinglePageApplication)という手法がメジャーになっています。 SPAの流れの中で、画面に表示されているUI要素の状態(読み込み中、とか現在選択されている、など)を管理する量、複雑さが増すことになりました。 これらを解決する手段として用いられるのが状態管理ライブラリです。( Redux や Vuex など) WebComponents フロントエンド開発が大規模化すると、画面を構成するHTML要素を意味のあるカタマリ、役割でまとめ、他の要素の影響を受けなくしたり( カプセル化 )、部品として再利用できるようにする必要が生じました。 これを可能にするのがWebComponentsの考え方で、 HTML Templates 、 Custom Elements 、 Shadow DOM 、といった3つの技術要素がベースになっています。 Chrome 、 FireFox 、 Safari やEdgeといった主要なブラウザ全てでWebCompotentsがサポートされています。 なお、HTML要素を部品化する、 カプセル化 するというアプローチは、ReactやVueなどの JavaScript フレームワーク でも行われており、それらも「 コンポーネント 」と呼ばれています。 いずれにせよ、HTMLの要素とその振る舞い、デザイン、これらを意味のあるカタマリでまとめるというアプローチが、現在のフロントエンド開発では重要な考え方となります。 Modern CSS JavaScript は ES Modules によって、HTMLは WebComponents というアプローチによって適切に カプセル化 することができるようになりました。 CSS も、JSやHTMLと同様に適切に意味や責務によって カプセル化 をしたくなります。これを実現するのが Styled Components や CSS Modules といった技術要素になります。 テスト バックエンド開発においては、テストコードを書いてテストするというのは一昔前からスタンダードな開発手法になっていますが、フロントエンド開発の大規模化により、フロントエンドでも同様にテストコードを書くようになりました。Roadmapでは Jest や Cypress などが推奨されています。 型システム JavaScript は実行時に初めてデータの種類(型)が評価される言語であるため、数値を格納するための変数に文字列を代入できてしまうなどの不具合があったとしても、実行時までそれを十分に検出することができません。そこで、 JavaScript に対して型の概念を導入し、安全な実装ができるようにしたいというニーズが生じました。 型の導入により、より安全な実装ができるようになった他、 ソースコード の実装者の意図や処理、部品の役割を表現しやすくなることで、可読性や保守性の向上も実現できるようになりました。 この領域においては、現在ではほぼ TypeScript の採用一択なのではないかと思います。 サーバーサイド レンダリング ( SSR ) SPAで実現されたアプリケーションは、 JavaScript などの読み込みファイルが大きくなったり、ブラウザ上で動的に レンダリング を行うため、従来のWebアプリケーションに比べ、初回アクセス時の表示が遅くなりがちという課題が生じました。 これを解決するためにサーバー側でHTMLを生成してしまおうというアプローチが SSR です。React.jsの場合は Next.js 、Vue.jsの場合は Nuxtjs で実現することができます。 GraphQL SPAでは、フロントエンドとバックエンドの通信を REST API の呼び出しで行うことが一般的です。 REST API の仕様はシンプルである一方、柔軟なリク エス トに対して柔軟なレスポンスを返すことを実現するのが難しく、専用の API を大量に実装したり、あるいは不要なパラメータをフロントエンド側で取捨選択するといった方法が取られていました。また、 REST API では API の仕様を理解する必要があり、フロントエンドのエンジニアがバックエンドの仕様を理解するオーバーヘッドが発生していました。 GraphQLでは、 API のデータ構造の表現方法( スキーマ )と問い合わせ方法(クエリ)を規格化することで、バックエンドの内部実装に依らず、フロントエンドで必要な情報を柔軟にリク エス トすることができるようになります。 おわりに さて、本項では、フロントエンドとバックエンドの定義から、現在フロントエンドで主流となっていると思われる各種技術要素について整理して解説させて頂きました。 今回改めて整理してみると、フロントエンド領域の変化はとても激しく、情報をキャッチアップするのにとても苦労しました。 自分自身の知識整理もかねて、今回の記事を書かせて頂きましたが、これがみなさまのキャッチアップのお役にも立てれば幸いです。 解説に誤りなどありましたら、ご指摘いただけると幸いです! 参考 Developer Roadmaps - https://roadmap.sh/ エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
こんにちは ラク ス開発エンジニアのUKoniです。 社会人になって PHP 開発するようになったら、配列の機能がいろいろあることを知りました。 「あれってどうするんだっけ?」といちいち調べるのもあれなんで、ここにまとめます。 PHP の配列の機能を忘れてしまったときに活用してもらえるとうれしいです。 配列とは PHPでの配列の変数作成 多次元配列 PHPの配列と繰り返し PHPでの配列の操作 追加 式で追加 1つ以上の値の追加(array_push関数) 削除 特定の値の削除(unset関数) 重複した値の削除(array_unique関数) 並び替え 検索 配列内の値の全取得(array_values関数) 指定した値が配列内にあるか(in_array関数) 配列内の添字の取得(array_keys関数) 指定した添字が配列内にあるか(array_key_exists関数) 配列の要素数の取得(count関数) 変更 式で変更 配列同士の値の置き換え(array_replace関数) 変換 配列から文字列へ変換(implode関数) 文字列から配列へ変換(explode関数) 結合 配列同士の結合(同一の文字列添字の値を上書き)(array_merge関数) 配列同士の結合(同一の文字列添字の値をまとめる)(array_merge_recursive関数) まとめ 配列とは 配列とは、複数の値を格納できる変数のことです。配列は値ごとに添字を持ちます。 PHP での配列の変数作成 PHP で配列では、 array() 、または [] (角括弧)で作成することができます。 [] (角括弧)での配列の作成は、PHP5.4以降で使用できます。 この記事では [] (角括弧)の書き方で進めていきます。 では、実際に作成します。 <?php $ country = [ 'Japan' , 'USA' ] ; print_r ( $ country ) ; 実行すると以下のようになります。 Array ( [0] => Japan [1] => USA ) 配列に値を格納することで添字に番号が付けられます。 番号は配列内で使用されている整数の添字の最大値+1が次に追加される値の添字になります。 また、添字に番号の代わりに好きな文字列をつけることができます。 このような、文字列を添字にもつ配列を「 連想配列 」と呼びます。 <?php $ capital = [ 'Japan' => 'Tokyo' , 'USA' => 'Washington D.C.' ] ; echo $ capital [ 'Japan' ] ; 結果: Tokyo PHP では配列と 連想配列 に差はなく、1つの配列で番号の添字と文字列の添字を同時に使うことができます。 多次元配列 多次元配列とは、配列の中に配列を格納している配列です。 PHP では多次元配列を以下のように生成します。 <?php $ numbers = [ 'odd' => [ 'one' , 'three' , 'five' ] , 'even' => [ 'two' , 'four' , 'six' ] ] ; echo $ numbers [ 'even' ][ 0 ] ; 結果: two 配列と繰り返し 条件を満たすまで同じ処理をくり返します。 foreach文の場合 PHP の配列をforeach文で処理するときは、以下のように実装します。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' , 'Kyoto' , 'Fukuoka' , 'Aichi' , 'Kanagawa' ] ; foreach ( $ prefectures as $ value ) { echo $ value . '<br>' ; } 上記のプログラムでは、foreach文の条件式内の $value に配列の値が入ります。 そして、foreach文内の処理が完了すると、 $value の値は配列の次の値に変わります。 これを配列の最後の値の処理が終わるまで繰り返します。 実行結果は以下になります。 Tokyo Osaka Kyoto Fukuoka Aichi Kanagawa また、 連想配列 では添字と値を同時に取得することができます。 <?php $ prefectures = [ 'Tokyo' => '東京' , 'Osaka' => '大阪' , 'Kyoto' => '京都' , 'Fukuoka' => '福岡' , 'Aichi' => '愛知' , 'Kanagawa' => '神奈川' ] ; foreach ( $ prefectures as $ key => $ value ) { echo $ key . ' : ' . $ value . '<br>' ; } foreach文の条件式内の $key に $value と紐づいた添字が入ります。 実行結果は以下になります。 Tokyo : 東京 Osaka : 大阪 Kyoto : 京都 Fukuoka : 福岡 Aichi : 愛知 Kanagawa : 神奈川 for文の場合 先ほどはforeach文での実装を紹介しましたが、for文でも実装は可能です。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' , 'Kyoto' , 'Fukuoka' , 'Aichi' , 'Kanagawa' ] ; for ( $ i = 0 ; $ i < count ( $ prefectures ) ; $ i ++ ) { echo $ prefectures [ $ i ] . '<br>' ; } 実行結果は以下のようになります。 Tokyo Osaka Kyoto Fukuoka Aichi Kanagawa PHP での配列の操作 ここには PHP で配列の操作の方法をまとめています。 追加 PHP の配列に新たな値を追加します。 1. 式で追加する PHP で配列に値を追加する式は以下の通りです。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' ] ; $ prefectures [] = 'Aichi' ; //連想配列の場合 $ prefectures [ 'Kyoto' ] = 'Kyoto' ; print_r ( $ prefectures ) ; 結果: Array ( [0] => Tokyo [1] => Osaka [2] => Aichi [Kyoto] => Kyoto ) 2. 1つ以上の値の追加(array_push関数) 1つ以上の値を配列の最後に追加します。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' ] ; array_push ( $ prefectures , 'Kyoto' , 'Fukuoka' , 'Aichi' ) ; print_r ( $ prefectures ) ; 結果: Array ( [0] => Tokyo [1] => Osaka [2] => Kyoto [3] => Fukuoka [4] => Aichi ) 削除 PHP の配列の値を削除します。 1. 特定の値の削除(unset関数) 配列から指定した添字と紐づいている値を削除します。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' , 'Kyoto' ] ; unset ( $ prefectures [ 0 ]) ; print_r ( $ prefectures ) ; 結果: Array ( [1] => Osaka [2] => Kyoto ) 2. 重複した値の削除(array_unique関数) 配列内で重複している値を削除します。 配列の先頭から最初に当たった値を残して、それ以降同じ値があると削除します。 <?php $ number = [ 'A' => 10 , 0 => 15 , 1 => 10 , 'B' => 13 , 'C' => 15 ] ; $ result = array_unique ( $ number ) ; print_r ( $ result ) ; 結果: Array ( [A] => 10 [0] => 15 [B] => 13 ) 並び替え PHP で配列内のデータの並び替えを行う関数は以下の表の通りです。 関数 説明 sort関数 値の昇順に並び替える。並び替え後の値に新しく番号の添字を割り当てる。 rsort関数 値の降順に並び替える。並び替え後の値に新しく番号の添字を割り当てる。 asort関数 値と添字を紐づけたまま、値の昇順に並び替える。 arsort関数 値と添字を紐づけたまま、値の降順に並び替える。 ksort関数 値と添字を紐づけたまま、添字の昇順に並び替える。 krsort関数 値と添字を紐づけたまま、添字の降順に並び替える。 では実際に使ってみましょう。 商品名を添字にし、値を値段にした $menu という配列を用意します。 この配列にsort関数を使うとこのようになる。 <?php $ menu = [ 'pasta' => 800 , 'hamburger' => 1000 , 'sashimi' => 2000 , 'sarada' => 500 , 'juice' => 300 ] ; sort ( $ menu ) ; print_r ( $ menu ) ; 結果: Array ( [0] => 300 [1] => 500 [2] => 800 [3] => 1000 [4] => 2000 ) このように値段の安い順になりますが、商品名が番号に変わっています。 ではこれをasort関数にするとどうなるでしょうか。 <?php $ menu = [ 'pasta' => 800 , 'hamburger' => 1000 , 'sashimi' => 2000 , 'sarada' => 500 , 'juice' => 300 ] ; asort ( $ menu ) ; print_r ( $ menu ) ; 結果: Array ( [juice] => 300 [sarada] => 500 [pasta] => 800 [hamburger] => 1000 [sashimi] => 2000 ) このように商品名を添字にもったまま、値段の安い順にはなります。 最後にksort関数を使います。 <?php $ menu = [ 'pasta' => 800 , 'hamburger' => 1000 , 'sashimi' => 2000 , 'sarada' => 500 , 'juice' => 300 ] ; ksort ( $ menu ) ; print_r ( $ menu ) ; 結果: Array ( [hamburger] => 1000 [juice] => 300 [pasta] => 800 [sarada] => 500 [sashimi] => 2000 ) このように商品名の昇順に並びます。 検索 PHP の配列内の値や添字、配列の要素の数などを調べます。 1. 配列内の値の全取得(array_values関数) PHP の配列内のすべての値を取得します。 ただし、添字は一緒に取得はできません。 <?php $ prefectures = [ 'Tokyo' => 'Shinjuku' , 'Osaka' => 'Osaka' , [ f : id : UKoni : 20201223191948p : plain ] 'Kyoto' => 'Kyoto' , 'Fukuoka' => 'Fukuoka' , 'Aichi' => 'Nagoya' , 'Kanagawa' => 'Yokohama' ] ; $ result = array_values ( $ prefectures ) ; print_r ( $ result ) ; 結果: Array ( [0] => Shinjuku [1] => Osaka [2] => Kyoto [3] => Fukuoka [4] => Nagoya [5] => Yokohama ) 2. 指定した値が配列内にあるか(in_array関数) PHP の配列内に指定した値があるかを調べます。 array_values関数とは違い、値を取得はしません。 <?php $ productList = [ 'banana' , 'orange' , 'mellon' , 'lemon' ] ; if ( in_array ( 'banana' , $ productList )) { echo 'バナナは取り扱っています。' ; } else { echo 'バナナは取り扱っていません。' ; } 結果: バナナは取り扱っています。 3. 配列内の添字の取得(array_keys関数) PHP の配列の中のすべての添字を取得します。 <?php $ fruits = [ 'banana' => 'yellow' , 'orange' => 'orange' , 'mellon' => 'green' , 'lemon' => 'yellow' ] ; print_r ( array_keys ( $ fruits )) ; 結果: Array ( [0] => banana [1] => orange [2] => mellon [3] => lemon ) また、指定した値を持つ添字を調べることもできます。 <?php $ fruits = [ 'banana' => 'yellow' , 'orange' => 'orange' , 'mellon' => 'green' , 'lemon' => 'yellow' ] ; print_r ( array_keys ( $ fruits , 'yellow' )) ; 結果: Array ( [0] => banana [1] => lemon ) 4. 指定した添字が配列内にあるか(array_key_exists関数) PHP の配列内に特定の添字があるか調べるときに使います。 array_keys関数とは違い、添字を取得はしません。 <?php $ kantou = [ 'Tokyo' => 'Shinjuku' , 'Kanagawa' => 'Yokohama' ] ; $ kansai = [ 'Osaka' => 'Osaka' , 'Kyoto' => 'Kyoto' , 'Hyogo' => 'Kobe' ] ; if ( array_key_exists ( 'Tokyo' , $ kantou )) { echo '東京は関東にあります。' ; } if ( array_key_exists ( 'Tokyo' , $ kansai )) { echo '東京は関西にあります。' ; } 結果: 東京は関東にあります。 5. 配列の要 素数 の取得(count関数) PHP の配列の要 素数 を数えます。 <?php $ fruits = [ 'banana' => 'yellow' , 'orange' => 'orange' , 'mellon' => 'green' , 'lemon' => 'yellow' ] ; echo count ( $ fruits ) ; 結果: 4 変更 PHP の配列内の値をほかの値に変更します。 1. 式で変更 既に配列内にある添字で値を呼び出し、別の値に変更します。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' , 'Kyoto' ] ; $ prefectures [ 2 ] = 'Aichi' ; print_r ( $ prefectures ) ; 結果: Array ( [0] => Tokyo [1] => Kanagawa [2] => Aichi ) 2. 配列同士の値の置き換え(array_replace関数) 配列の値をほかの配列の値に置き換えます。 この時、最初の配列にない添字が置き換える配列にある場合は、最初の配列に追加されます。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' , 'Kyoto' ] ; $ replace = array_replace ( $ prefectures , [ 1 => 'Kanagawa' , 2 => 'Chiba' , 3 => 'Saitama' ]) ; print_r ( $ replace ) ; 結果: Array ( [0] => Tokyo [1] => Kanagawa [2] => Chiba [3] => Saitama ) 変換 PHP の配列を別の型に変換したり、別の型の変数を配列に変換します。 1. 配列から文字列へ変換(implode関数) 配列を文字列に変換します。 <?php $ array = [ 'Tokyo' , 'Osaka' , 'Kyoto' ] ; $ string = implode ( ',' , $ array ) ; echo $ string ; 結果: Tokyo,Osaka,Kyoto 2. 文字列から配列へ変換(explode関数) 文字列を配列に変換します。 <?php $ string = 'Tokyo, Osaka, Kyoto' ; $ array = explode ( ',' , $ string ) ; print_r ( $ array ) ; 結果: Array ( [0] => Tokyo [1] => Osaka [2] => Kyoto ) 結合 PHP の配列同士をつなげます。 1. 配列同士の結合(同一の文字列添字の値を上書き)(array_merge関数) 配列を結合します。そのとき添字が重複した場合は、文字列だと後の配列の値に上書きし、番号だと追記します。 <?php $ car1 = [ 'color' => 'silver' , 'price' => 5000000 , 0 => 'car navigation' ] ; $ car2 = [ 'color' => 'black' , 'price' => 10000000 , 'max_speed' => '200km' , 0 => 'sports car' ] ; $ result = array_merge ( $ car1 , $ car2 ) ; print_r ( $ result ) ; 結果: Array ( [color] => black [price] => 10000000 [0] => car navigation [max_speed] => 200km [1] => sports car ) 2. 配列同士の結合(同一の文字列添字の値をまとめる)(array_merge_recursive関数) 結合するのはarray_merge関数と同じです。 この関数の特徴は、添字が重複した場合は、文字列だとその添字の値同士で配列を作り、番号だと追記します。 <?php $ car1 = [ 'color' => 'silver' , 'price' => 5000000 , 0 => 'car navigation' ] ; $ car2 = [ 'color' => 'black' , 'price' => 10000000 , 'max_speed' => '200km' , 0 => 'sports car' ] ; $ result = array_merge_recursive ( $ car1 , $ car2 ) ; print_r ( $ result ) ; 結果: Array ( [color] => Array ( [0] => silver [1] => black ) [price] => Array ( [0] => 5000000 [1] => 10000000 ) [0] => car navigation [max_speed] => 200km [1] => sports car ) まとめ 今回は PHP での配列機能をまとめました。 まとめたものだけでも、 PHP には配列の操作や関数が多くありました。 ただし、ここでまとめたものは PHP の配列の操作の一部分で、ここで書いたもの以外にも配列の操作や関数はあります。 PHP の配列を活用して、より良いプログラムを作成しましょう。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
技術広報の syoneshin です。 今回は当社の開発組織メンバー達に 『2020年の気になったニュース』 と 気になった理由やポイントを聞きました。 質問:皆さんの「2020年の気になったニュース」 を教えてください。 【目次】 『2020年の気になったニュース』ランキング 『WSL2 正式版リリース』 『Apple、MacのAppleシリコンへの移行』 『PHP8リリース』 『東証システム障害』 『Zen3アーキテクチャ』 『オープンソースで作る東京都新型コロナウイルス対策サイト』 『KubernatesがDockerランタイムを非推奨に』 『Centos8 EOL』 『Flash終了』 『Google 障害』 『PostgreSQL13 リリース』 『5G』 『NAVERまとめ終了』 『東芝が量子暗号通信を事業化』 『GitHubのデフォルトブランチ名』 まとめ 『2020年の気になったニュース』ランキング 以下は当社の開発組織メンバーが選んだ「2020年の気になったニュース」ランキングです。 調査概要 調査手法:任意アンケート( ヒアリ ングシート)※複数回答可 調査対象:当社開発組織メンバー(テッ クリード ・開発マネージャー含む) 調査項目:2020年12月18日迄のニュース 有効回答数:60名 ランキング内容:得票数2票以上の2020年の気になったニュース Rank ニュースタイトル(概要) 得票数 1 WSL2 正式版リリース 9 2 Apple 、 Mac の Apple シリコンへの移行を発表 8 3 PHP8リリース 6 4 東証 システム障害 5 5 Zen3 アーキテクチャ 4 6 オープンソース で作る東京都 新型コロナウイルス 対策サイト 3 6 KubernatesがDockerランタイムを非推奨に 3 6 Centos8 EOL 3 6 Flash 終了 3 10 Google 障害 2 10 postgreSQL13 リリース 2 10 5G 2 10 NAVER まとめ終了 2 10 東芝 が量子暗号通信を事業化 2 10 GitHub のデフォルトブランチ名 2 当社で得票数1位の2020年の気になったニュースは 『WSL2 正式版リリース』 forest.watch.impress.co.jp 以下は気になった理由やポイント Windows で気軽に Linux 環境を動かせるようになって良かったです。 windows マシンで手軽に本物の Linux を動かせるようになるということで、ずっと楽しみにしていました。特に Docker Desktop はぐっと使いやすくなったと思います。 最近の Mac OS につらみを感じていて、脱却する手段の一つとしてウォッチしていました。 Windows Terminalも併せてMSの方向性を知ることができたのも良かったです。 業務で使っている Mac を修理に出した時、大した苦労もなく Windows 上に開発環境を構築し、手が止まる時間を最小限にできた。 etc 次いで、得票数2位の2020年の気になったニュースは 『 Apple 、 Mac の Apple シリコンへの移行』 www.apple.com 以下は気になった理由やポイント スマホ で活躍している ARMアーキテクチャ が x86 が主流だった昨今のPCに搭載されるということで注目を浴びています。 アプリ開発 でも ARMアーキテクチャ へのネイティブ対応するなど、大きな変化をもたらしているかと思います。 比較サイトを見ると格段に性能が上がっているらしく、独自開発でこういった結果を残せる Apple はさすがだなと感じた。 スマホ 用途で急速に性能向上してきた ARMアーキテクチャ が、 x86 アーキテクチャ とスペック的に遜色なくなってきて、 x86 に比較して強みだった省電力と GPU 性能を引っさげてデスクトップ用途に入ってきたこと。ARM版Windows10やARM搭載ノートは既にあったのでそこまで不思議はなかったが、一定のシェアをもつ Apple がシフトしたことで、デスクトップ用途のARMが市民権を得た印象。 etc 得票数3位の2020年の気になったニュースは 『PHP8リリース』 www.php.net 以下は気になった理由やポイント 議論がしばらく続いていたので、期待していました。 PHP らしい新機能・非推奨の廃止が見れて楽しい。 JIT 導入によって PHP の活用範囲の幅が広がった。 etc 次いで得票数4位の2020年の気になったニュースは 『 東証 システム障害』 www.itmedia.co.jp 以下は気になった理由やポイント 金融系は ステークホルダー の数が非常に多いため、意思決定の難しさや、普段から備えることの大切さを改めて思い起こさせてくれる出来事でした。 原因解明のスピード感がすごかった。判明している問題をすべて提示して、調査中などのコメントもなく「市場運営者としての責任は私共に全面的にある」の回答など、完璧な記者会見だと思った。 原因自体はマニュアル把握不備(ヒューマンエラー)という部分で、規模や事業の垣根を越えたITにおける根源的で極めて大きな課題を感じた。 etc 次いで得票数5位の2020年の気になったニュースは 『Zen3 アーキテクチャ 』 pc.watch.impress.co.jp 以下は気になった理由やポイント AMD のCPUが高い処理性能のCPUとして認知されるようになったことは、元 AMD 信者として感慨深いものがあります。最近は GPU も nvidia と バチバチ やってますね。 AMD のCPUがシングルスレッドで Intel を超えた。 etc 次いで得票数同率6位の2020年の気になったニュース3つは 『 オープンソース で作る東京都 新型コロナウイルス 対策サイト』 www.itmedia.co.jp 以下は気になった理由やポイント 政府主導ではなくエンジニア・デザイナー主導で公共性のあるサイトが作られて素晴らしい。 COCOA と似ていますが、 自治 体(しかも東京都)の公式サイトが オープンソース で開発されるというのが興味深く感じました。 etc 『KubernatesがDockerランタイムを非推奨に』 www.publickey1.jp 以下は気になった理由やポイント Kubernetes がDockerを経由しなくてもcontainerdを操作できるようになった。コンテナ業界がちゃんと規格化されて発展しているいい話だなあ、と思いました。 コンテナ=Dockerという印象を改めないといけない気になった。Dockersim使っている人は構成変更もあってお祭りになってました。 etc 『Centos8 EOL』 gigazine.net 以下は気になった理由やポイント OSS の商用利用を考えさせられ、ただただ辛いな…と思ったニュースでした。 唐突に「来年末終わって商用に切り替えます」となり、コミュニティから反発があった後、「やっぱ後続続けます」となった経緯が面白かった。 etc 『 Flash 終了』 www.adobe.com 以下は気になった理由やポイント 昔、ネットに大きな影響を与えた Flash がとうとう終了しました。最近では使うこともなくなってきましたが少しさびしい気がしますね。 昔よく見たサイトが Flash だったりして時代の隆盛を実感する一方、製品にも影響するので対応が大変な今日この頃です。 etc 次いで得票数同率10位の2020年の気になったニュース6つは 『 Google 障害』 www.itmedia.co.jp 以下は気になった理由やポイント 障害そのものよりも、ストレージ不足という原因の判明と解消までを45分で乗り切った Google の技術力に驚嘆しました。 影響範囲を考えると日常でどれだけ Google 頼りになっているのかが見えたようで、笑えないけど興味深いと思いました。 『PostgreSQL13 リリース』 www.postgresql.jp 以下は気になった理由やポイント PostgreSQL12からどういうバージョンアップがあったか気になった。 毎年のお約束ですが、変更ポイントは抑えておきたい。 『5G』 www.softbank.jp 以下は気になった理由やポイント キャリアサービス開始とか、みんなが騒ぎ出して5G普及したらどうなる?というのが盛り上がった気がっていました。 「今後の生活にどう影響してくるのか」が楽しみというところで気になっていました。 『 NAVER まとめ終了』 www.itmedia.co.jp 以下は気になった理由やポイント 雑学からグルメから何からものすごくお世話になりました。 なくなっていくのは時代ですね。。。 技術ネタだけでなく、 ウィキペディア よりも オタッキー なネタたちに、たくさんお世話になっていました。大きなサービスが突如終わる切なさ…あります。 『 東芝 が量子暗号通信を事業化』 www.toshiba.co.jp 以下は気になった理由やポイント 中国など競争相手も多いが、ぜひ世界をリードする分野に育ってほしい。 論理的に破られない暗号というのがポイントで、暗号解読される心配がなくなる。まさに最強の暗号技術という点で気になりました。 『 GitHub のデフォルトブランチ名』 [ www.publickey1.jp 以下は気になった理由やポイント OSS 文化も社会情勢を考慮するようになったのだなと思いました。 センシティブな話だとは思いますが、ずっと「master」と呼んでた身からすれば違和感があります…。 その他 『 SpaceX の有人宇宙飛行成功』 jp.techcrunch.com 『 接触 確認アプリ「 COCOA 」、 ソースコード を GitHub 上に公開』 k-tai.watch.impress.co.jp 『Vue3リリース』 news.vuejs.org 『シン・テレワークシステムの開発』 www.itmedia.co.jp 『Zoom』 www.nikkei.com などなど 110件の「2020年の気になったニュース」が当社内で共有されました。 まとめ 以上、いかがだったでしょうか。 改めて、2020年は本当に大変な一年だったと振り返っております。 当社開発組織では 重要な技術ニュースの クリッピング と見解を メンバー達が日常的にチャット共有し 最新の技術動向をチェックしております。 また最新の技術動向をプロダクトに導入するか を検証する社内勉強会も実施しており 検証で得られた知見も今後の主催イベントで発信していきます。 もし、当社活動に少しでもご興味をお持ちいただけましたら 当社イベントにも是非ご参加下さい。 主催イベント一覧 rakus.connpass.com 本記事でご紹介した 2020年の気になったニュース が皆さまの情報探索の一助となれば幸いです。 私たちは一緒に働く仲間を募集しています。 ご興味を持たれましたら以下のサイトからお問い合わせください。 career-recruit.rakus.co.jp
アバター
初めに 皆さん初めましてmosyoryです。 画像処理に興味はあるがどうやってやるのかわからない、そんな方もいるのではないでしょうか。 本記事では Windows ・ Mac の環境で Python と OpenCV を使ってちょっとした画像処理の方法を紹介したいと思います。関数等の詳細な解説は行っていないので予めご了承ください。 初めに OpenCVとは OpenCVのインストール Windows Mac pipでインストールできない 基本操作 読み込み 表示 保存 画像処理 色空間の変換 二値化処理 輪郭検出 輪郭描画 終わりに 参考サイト OpenCV とは OpenCV (Open Source Computer Vision Library)とは オープンソース コンピュータ・ビジョン・ライブラリです。 画像処理や汎用的な数学処理、 機械学習 に関する アルゴリズム が多数含まれています。 C+、 Python 、 Java でサポートされており Windows 、 Linux 、 OS X 、 Android 、 iOS などの様々なプラットフォームに対応しています。 BSD 3-Clauseラインセンスでリリースされているので商用利用も可能です。 opencv.org OpenCV のインストール まずは OpenCV のインストールから行います。 Windows と Mac での方法を紹介しますのでお持ちのパソコンに合わせて行ってください。 Python はすでにインストールされている前提で進めますのでまだの方は Python 公式サイトからPython3.xのバージョンをインストールしてください。本記事ではPython3.9で進めています。 www.python.org Windows コマンドプロンプト からpipを使用してインストールします。pipは Python のパッケージ管理ツールでPython3.4以上なら標準で付属していますので別途インストールする必要はありません。 Python の OpenCV はNumpyというライブラリを使用しますのでこちらもインストールします。 OpenCV をインストールするとNumpyの最新バージョンも自動でインストールしてくれるのですがブログ作成時はWindows10 2004とNumpy1.19.4の組み合わせだと Python プログラムを実行した際にエラーになります。 なのでバージョン1.19.3を指定してインストールしましょう。 pip install numpy==1.19.3 pip install opencv-python Mac ターミナルからpipでインストールします。以前はHomeBrewから OpenCV を入れていましたが今はpipだけでインストールできるようになりました。 Mac はNumpy1.19.4でも問題なく動くので OpenCV のインストール時にNumpyも自動でインストールしてもらいましょう。 pip install opencv-python pipでインストールできない pipで OpenCV をインストールしようとするとこんなエラーが出る時があります。 WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))': /simple/opencv-python/ WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))': /simple/opencv-python/ WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))': /simple/opencv-python/ WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))': /simple/opencv-python/ WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))': /simple/opencv-python/ Could not fetch URL https://pypi.org/simple/opencv-python/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/opencv-python/ (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))) - skipping ERROR: Could not find a version that satisfies the requirement opencv-python ERROR: No matching distribution found for opencv-python どうやら Python パッケージを管理している PyPI との通信で SSL に問題があるらしく接続先を指定する必要があるそうです。 なのでpipを使う時にオプションを設定してインストールしましょう。 pip install opencv-python --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --trusted-host pypi.org 基本操作 ここでは画像処理を行うための基本操作を紹介します。画像はお好きなものを用意してください。 今回は OpenCV のア イコン画 像を使って例をお見せします。 まず最初に OpenCV を Python のプログラム内で使えるようにインポートしましょう。 import cv2 読み込み 画像の読み込みではcv2.imread()を使います。引数は画像のファイル名です。 異なる ディレクト リにファイルがある場合は 絶対パス か 相対パス で指定してください。 パスが間違っていてもエラーにならず処理は継続されるので注意しましょう。 img = cv2.imread( 'OpenCV.png' ) 表示 画像をウィンドウに表示するにはcv2.imshow()を使います。 引数にウィンドウの名前、表示したい画像を指定してください。 表示する際にはcv2.waitKey()とcv2.destroyAllWindows()も一緒に書きましょう。 この2つはキーボード入力を受け付ける関数と作成したすべてのウィンドウを閉じる関数です。 cv2.imshow()だけではウィンドウは表示された後すぐに消えてしまいますが、続けて2つの関数を書くことでキーボード入力が行われるまでウィンドウが表示され続けます。 画像は左が Windows 、右が Mac で表示した際のウィンドウになります。 cv2.imshow( 'OpenCV' , img) cv2.waitKey( 0 ) cv2.destroyAllWindows() 保存 保存はcv2.imwrite()を使います。引数に保存する画像のファイル名、保存したい画像を指定します。 cv2.imwrite( 'save.png' , img) 画像処理 それでは画像処理を行っていきます。 今回は色空間の変更、二値化処理、輪郭検出・描画の方法を Python プログラムと結果画像と併せて紹介します。 色空間の変換 色空間(カラースペース)とは特定の色を数値などのパラメーターで表したものです。RGBや HSV のことですね。 OpenCV では画像はBGRで読み込まれますが画像処理の内容によっては別の方が適している場合があります。 そんな時はcv2.cvtColor()を使いましょう。引数に色空間を変更したい画像、色変換のフラグを指定してください。 よく使用する変換フラグはcv2.COLOR_△△2○○という形式で用意されており△△が変更前、○○が変換後の色空間の名前になります。 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #BGR → グレースケール 二値化処理 二値化処理とはグレースケール画像に対し 閾値 を設け白黒画像に変換することです。 二値化処理にはcv2.threshold()を使います。引数にグレースケール画像、 閾値 、 閾値 以上(フラグによっては値以下)の画素に割り当てる値、 閾値 処理を行うフラグを指定することで 閾値 と二値化画像を返します。 下の Python コードは画素が127以上なら白に、以下なら黒に変換しています。 ret, thresh = cv2.threshold(gray, 127 , 255 , cv2.THRESH_BINARY_INV) OpenCV の緑のマークが映らなくなりましたね。 輪郭検出 輪郭検出はcv2.findContours()を使います。引数に二値化画像、輪郭を検索するモード、輪郭検出方法のフラグを指定し実行することで輪郭と輪郭の階層情報を返します。 OpenCV は黒の背景から白の物体の輪郭を探すことを前提としているので使用する二値化画像に気を付けましょう。 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contoursに検出された全輪郭がlistで格納されています。 輪郭描画 描画にはcv2.drawContours()を使います。 引数に画像、listに格納された輪郭、描画したい輪郭のインデックス、描画する色と線の太さを指定します。 下の Python コードは全ての輪郭を線の太さ3の紫色で描画しています。 cv2.drawContours(img, contours, - 1 , ( 255 , 0 , 255 ), 3 ) OpenCV の文字と赤、青のマークに紫色の輪郭線が描画されましたね。 終わりに Python と OpenCV を使った画像処理の例を紹介しました。 今回は色の変換や描画となりましたが、 OpenCV では人の顔の検出や 機械学習 など多くのことができるようになっています。 公式のドキュメントにも Python のサンプルコード付きで説明がありますので詳しい処理内容を知りたい方はそちらをご覧になってください。 参考サイト OpenCV: OpenCV-Python Tutorials Pythonによる画像処理に利用するライブラリを現役エンジニアが解説【初心者向け】 | TechAcademyマガジン 画像処理をマスターしよう!PythonでOpenCVを使う方法を紹介! | TechTeacher Blog Pythonで画像処理をするならOpenCVがオススメ! | 侍エンジニアブログ エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
この記事は アーキテクチャテスト Advent Calendar 2020 - Qiita の 25 日目のエントリです。 qiita.com こんにちわ。株式会社 ラク スで「楽楽 労務 」を開発している @kawanamiyuu です。遅くなりましたが、先月開催された JJUG CCC 2020 Fall の登壇レポートです。 イベント概要 プロポーザル 登壇資料 登壇に対する反応 登壇を終えて イベント概要 日時 2020 年 11 月 7 日 (土) 開催形式 オンライン(事前録画放送+リアルタイムQ&A) 公式サイト https://ccc2020fall.java-users.jp/ タイムテーブル https://confengine.com/jjug-ccc-2020-fall/schedule タイムライン #jjug_ccc since:2020-11-07_00:00:00_JST until:2020-11-08_00:00:00_JST - Twitter Search 発表動画リスト 2020-11-07 JJUG CCC 2020 Fall - YouTube プロポーザル jjug-ccc-2020-fall - マイクロサービスアーキテクチャをあきらめないための、モノリスで始めるアーキテクチャテスト | ConfEngine - Conference Platform マイクロサービス アーキテクチャ にチャレンジしたい!しかし、プロダクト立ち上げ時においては、 業務 ドメイン に対する知識の少なさから、適切な粒度のサービス分割が難しい そもそも売れるか分からない、仮説検証を高速にまわしていかなければいけない段階で、MSAで開発・運用するオーバーヘッドが大きい 手段が目的化している感 といった理由から、モノリシックなアプリケーションとして開発を開始するケースは少なくないと思います。一方で、あとから分割すればよいと開発を始めた モノリス で、いざ分割を検討する段階でアプリケーション内の依存関係が複雑に絡み合い、分割したくとも解きほぐすのが困難になってしまっているケースも少なくないはずです。 モノリス で適切なモジュール分割を実現するために ドメイン 駆動設計や、具体的な設計パターンとしてクリーン アーキテクチャ やレイヤード アーキテクチャ などの方法をとることが多い最近のソフトウェア開発において、モノリシックなアプリケーションを構成するレイヤーや ドメイン 、各パッケージ・クラスの依存関係をいかに適切に維持し続け、将来 アーキテクチャ を発展させる可能性を残すか。 この発表ではその1つの有力な方法としての「 アーキテクチャ テスト」についてお話します。 登壇資料 speakerdeck.com 登壇資料のサマリー 登壇に対する反応 (jjug_ccc_b OR archunit) since:2020-11-07_17:00:00_JST until:2020-11-07_18:00:00_JST - Twitter Search 依存関係を適切に設計したいだけ いい言葉だ #jjug_ccc #jjug_ccc_b — Kei Kondoh (@kei_kondoh) 2020年11月7日 私のところは今は人数が少ないので アーキテクチャ に対するレビューもできるし直してももらえるけど人が増えてきたりすると アーキテクチャ の維持って厳しいよなー #jjug_ccc_b — uuuu.kt (@yushi_koga) 2020年11月7日 ここでも ArchUnit ! #jjug_ccc #jjug_ccc_b — YujiSoftware ☕ (@YujiSoftware) 2020年11月7日 派手さはないけど落ち着いた議論でいいっすな #jjug_ccc #jjug_ccc_b — kabao (@kabao) 2020年11月7日 「ソフトウェアが「ソフト」であるための選択肢を残す」 いいメッセージ! #jjug_ccc #jjug_ccc_b https://t.co/O7zYARquNL — YujiSoftware ☕ (@YujiSoftware) 2020年11月7日 ハンズオン モデラー がいないと アーキテクチャ の維持は難しいっていう印象があったけど、 アーキテクチャ テストがあれば、少しはそれがマシになりそう #jjug_ccc_b — uuuu.kt (@yushi_koga) 2020年11月7日 今日は arch unit のことを初めて知った。たしかに正しくない依存の記述を、コードレビューで目で見るのは大変なので、自動テストの中でテストできるのは便利&品質の維持に繋がりますね #jjug_ccc #jjug_ccc_b — Yuusuke Masaki (@makky55makky55) 2020年11月7日 ArchUnit、使ってみたい #jjug_ccc #jjug_ccc_b — lethe2211 / Shuhei Shogen (@lethe2211) 2020年11月7日 登壇を終えて まず今回、当日参加された方、タイムテーブルをご覧になった方はお気づきになったかと思いますが、まさかの アーキテクチャ テストネタかぶり でした! (もう一つの発表は こちら ) アーキテクチャ テストをテーマにした登壇は、過去に 2 回( ArchUnit で Java アプリケーションのアーキテクチャを CI する - JJUG CCC 2019 Spring 、 ドメイン駆動設計を支えるアーキテクチャテスト - Object-Oriented Conference 2020 )行っていて、今回はそれらの内容も整理しながら、「マイクロサービス アーキテクチャ をあきらめないための、 モノリス で始める アーキテクチャ テスト」という主題で登壇内容をまとめました。 私のこれまでのカンファレンス規模のイベント登壇経験としては、最長でも 20 分枠の発表だったため、今回初めて 40 分という枠を満足させるボリュームと質の発表内容を作り上げることできるか不安でした。しかし、資料を作り始めてみると なんだかんだで なんとか、30 分程度の発表に仕上がりました。資料としては 100 ページを超えていたため、もしかすると時間が足りないかも?と一時は思いましたが、事前録画方式だったので淡々としゃべってしまい余裕で時間枠内に収まりました。コロナ禍で無聴衆(オンライン)での発表は何度か経験していますが、目の前に聴衆がいないと、発表中の間のとり方が難しいです。 さて、今回で アーキテクチャ テスト 3 部作 (?) の完結編として、いったん今時点で私が アーキテクチャ というものに対して考えていることは 言語化 できました。今後も アーキテクチャ テストを実際のプロダクト開発の中で実践的に取り組んでいきたいと思っているのと、この手の話は、 プログラミング言語 に関係なく通じるもので 他の言語でのアーキテクチャテスト も試してみて、別の言語コミュニティでも アーキテクチャ テストを布教していきたいと思っています。 それでは、また。 今回はオンラインかつ事前録画だったからかなりましだったけど、登壇する当日までは一定のマインドシェアを持って行かれるので登壇終わったらしばらく何も考えずゆっくりしたいと思うんだけど、終わったら終わったで何か物足りなくて次の機会を探してしまう現象に名前付けたい。(文字数まであとちょっ — ゆう (@kawanamiyuu) 2020年11月7日
アバター
こんにちは。新卒の id:w1p と申します。 今回業務でTypeScriptを導入するということで、いい機会なのでTypeScriptについていろいろ調べました。 目次 環境構築 TypeScriptの基本的な文法 型アノテーションの書き方 基本の型 number型 bigint型 string型 boolean型 symbol型 null型 undefined型 型エイリアスで型に別名をつける リテラル型 複合型 object型 array型 tuple型 enum 数値型enumの注意点 class Union型 Intersection型 その他の型 Function型 Index Signitures 特殊な型 any unknown void never インターフェースと型エイリアス インターフェース 2つの違い 宣言のマージ プリミティブ型とUnion型 その他 ジェネリクス ジェネリクスを導入できる場所 関数型 型エイリアス インターフェース tsconfig.json 型を操作する 型のキーワード typeof keyof Lookup Types in extends infer Utility Types Partial / Required / Readonly Pick<T, K> Record<K, T> Exclude<T, ExcludedUnion> Union Distribution Extract<T, Union> Omit<Type, Keys> NonNullable Parameters ConstructorParameters ReturnType InstanceType ThisParameterType OmitThisParameter ThisType Uppercase / Lowercase Capitalize / Uncapitalize まとめ 参考 環境構築 Microsoft 公式がブラウザ上で実行できる サンドボックス を提供しており、これを使用すると手軽にTypeScriptを試すことができます。 TypeScriptから JavaScript への変換結果や、型定義ファイル生成の結果まで見れます。 この記事で出てくるサンプルコードはすべてTS Playground v4.1.2上で行っています。 Playground Link Visual Studio Code や Intellij IDEAなど手元のエディタで書いてローカルで実行したい場合には以下の手順を踏む必要があります。 npm or yarnがインストールされていることが前提です。 Step1. TypeScriptをインストールする $ mkdir ts && cd ts $ npm init -y # yarn init -y $ npm i -D typescript # yarn add -D typescript Step2. .ts拡張子のファイルを作成する $ echo ' console.log("Hello, TypeScript!"); ' > ./hello.ts Step3. TypeScriptを実行する ここでは手軽にTypeScriptを実行する方法として、 tsc を使用する方法と、 ts-node というパッケージを使用する方法を紹介します。 tsc を使用する場合 tsc はTypeScriptを JavaScript へトランスパイルするための公式ツールです。 tsc の挙動は tsc 実行時にオプションとして渡したり、 tsconfig.json というファイルで変更することができます。 hello.ts のあるフォルダで以下を実行します。 $ npx tsc ./hello.ts # yarn run tsc ./hello.ts tsc はトランスパイルした結果を指定された ディレクト リに出力します。 今回は特に指定していませんのでカレント ディレクト リに出力されます。 あとは通常のjsファイルと同様に実行できます。 $ node hello.js Hello, TypeScript! ts-nodeを使用する場合 ts-node を使用すると、 tsc → node という2度手間を省略できます。 $ npm i -D ts-node # yarn add -D ts-node 実行は以下のように行えます。 $ npx ts-node ./hello.ts # yarn run ts-node ./hello.ts TypeScriptの基本的な文法 ここまではどのようにTypeScriptファイルを実行するのかについて見てきました。 ここからは基本的なTypescriptの文法について見ていきます。 型 アノテーション の書き方 型 アノテーション とは、変数や関数の戻り値などの型が何であるかを明示的に指定することです。 基本的には : type の形式で書くことができます。 // 変数nの型をnumberに let n: number = 123 n = 'string' // Type 'string' is not assignable to type 'number'. // argをstring, fの戻り値はvoidに function f ( arg: string ) : void { /* */ } f ( 123 ) // Argument of type 'number' is not assignable to parameter of type 'string'. TypeScriptは 型推論 (型をコンテクストから推論すること)により、全ての場所に型 アノテーション を必要としない仕組みになっています。 // nはnumber型と推論される let n = 123 // tはboolean型と推論される let t = true ; 基本の型 早速ですが、TypeScriptの核となる型についてみていきます。 ここで紹介する型はプリミティブ型と呼ばれる基本的な型です。 number型 number型は実数に加え、無限を表す Infinity , 非数を表す NaN が含まれます。 const n1: number = 123 ; const n2: number = -0 . 1 ; const n3: number = Infinity ; const n4: number = NaN ; bigint型 ES2020で導入されたbigint型は Number.MAX_SAFE_INTEGER(2^53 - 1) よりも大きな整数を扱うことができます。 精度が落ちる可能性があるためnumber型変数へ直接代入することはできず、明示的な変換が必要になります。 let big = 123n ; let num = 123 ; num = big ; // Type 'bigint' is not assignable to type 'number'. big = num ; // Type 'number' is not assignable to type 'bigint'. num = Number ( big ); big = BigInt ( num ); string型 文字列全般をとりうる型です。 const s1: string = "Hello, World!" ; const s2: string = s1.slice ( 0 , 5 ); boolean型 true と false の2つの値をとり得る型です。 let b: boolean ; b = true ; b = false ; b = !!1 ; b = 1 ; // Type 'number' is not assignable to type 'boolean'. symbol型 ES2015から取り入れられた、一意の値を生成するための仕組みです。 const s1: unique symbol = Symbol ( 'abc' ); // typeof s1 let s2 = Symbol ( 'abc' ); // symbol let s3 = Symbol . for( 'abc' ); // symbol const s4 = Symbol . for( 'abc' ) // symbol console .log ( s1 === s2 ); // false console .log ( s2 === s3 ); // false console .log ( s3 === s4 ); // true null型 nullもしくはany型のみを受け付ける型です。 const n1: null = null ; const n2: null = 123 as any ; const n3: null = undefined ; // Type 'undefined' is not assignable to type 'null'. const n4: null = 123 as unknown ; // Type 'unknown' is not assignable to type 'null'. undefined型 undefinedとany型のみを受け付けます。 const u1: undefined = undefined ; const u2: undefined = 123 as any ; const u3: undefined = null ; // Type 'null' is not assignable to type 'undefined'. const u4: undefined = 123 as unknown ; // // Type 'unknown' is not assignable to type 'null'. 型 エイリアス で型に別名をつける 型 エイリアス と呼ばれる機能により、任意の型に別名をつけることができます。 型 エイリアス は type キーワードで作成できます。 type ID = number ; type Name = string ; type Cond = boolean ; リテラル 型 TypeScriptの面白い特徴として リテラル 型があります。 リテラル 型とは、プリミティブ型に含まれる一部の値のみをとりうるような型です。 const で変数を定義する際に、TypeScriptはその値はもう変化しないだろうと考え リテラル 型で推論します。 // numberのリテラル型 let num1 = 123 ; // number型 const num2 = 123 ; // 123型 // stringのリテラル型 let str1 = "abc" ; // string型 const str2 = "abc" ; // "abc"型 // booleanのリテラル型 let bool1 = true ; // boolean型 const bool2 = false ; // false型 後述するUnion型とよく組み合わせて使われます。 // 許容するHTTPメソッドの一覧 type AllowedHttpMethods = "GET" | "HEAD" | "POST" | "PUT" ; let method: AllowedHttpMethods = "GET" ; // OK method = "PUT" ; // OK method = "DELETE" ; // Type '"DELETE"' is not assignable to type 'AllowedHttpMethods'. 複合型 object型 プリミティブ型以外の値をとりうる型です。 オブジェクトの構造を指定することはできません。 const o1: object = { a: 123 , b: "abc" } ; const o2: object = {} const o3: object = 123 ; // Type 'number' is not assignable to type 'object'. const o4: object = null ; // Type 'null' is not assignable to type 'object'. array型 配列を表す型です。 型 アノテーション の方法として T[] と Array<T> の2パターンありますが、前者の方が多く使われています。 const arr1: number [] = [ 1 , 2 , 3 ] ; const arr2: Array < string > = [ "a" , "b" , "c" ] ; tuple型 TypeScriptではタプル型を宣言できます。 タプルは複数の要素からなる組み合わせのような型です。 配列と違うのは、異なる型の要素が共存できる点です。 const tup1: [ number , string ] = [ 1 , "str" ] ; const tup2: [ number , number , number ] = [ 1 , 2 , 3 ] ; const arr: number [] = tup2 ; // number型の要素しかないため配列に割り当て可能 enum tuple同様、TypeScriptは独自に enum を使用できます。 enum は プログラマ が事前に定義した特定の値のみをとりうるような型です。 enum Suits { Diamonds , Clubs , Hearts , Spades } console .log ( Suits.Diamonds === 0 ) // true それぞれの列挙子には値を割り当てることができます。 上の Suits には値を割り当てていませんが、そのような場合TypeScriptは0から数値を割り当てます。 数値型 enum の注意点 「TypeScriptの Enum は使わない方が良い」という意見を聞いたことがある方もいらっしゃるかと思いますが、 1番の問題としては数値型の enum にはすべての数値を割り当てることができてしまう点かと思います。 const suit: Suits = 10000 ; // OK これを回避するためには文字列型の enum を使用するか、もしくはUnion型を使用する方法があります。 enum Suits { Diamonds = "Diamonds" , Clubs = "Clubs" , Hearts = "Hearts" , Spades = "Spades" } const suit: Suits = Suits.Diamonds ; type Suits = "Diamonds" | "Clubs" | "Hearts" | "Spades" ; const suit: Suits = "Diamonds" ; class ES2015から導入されたclass宣言はもちろんTypeScriptでも利用できます。 class Animal { // TypeScriptではprivate / protected / publicが使用できる private species?: string ; constructor( species: string ) { this .species = species ; } } const animal = new Animal ( 'dog' ); animal.species = 'cat' ; // Property 'species' is private and only accessible within class 'Animal'. speciesフィールドはprivateなため、クラス外部から触ることはできずエラーになっています。 Union型 TypeScriptの大きな特徴としてよく挙げられるのがこのUnion型です。型同士を | でつなぐことで作成できます。 Unionの名前通り、Union型は構成する型がとる値それぞれの和集合になります。 type StrOrNum = string | number ; let val: StrOrNum = "str" ; val = 123 ; val = true ; // Type 'boolean' is not assignable to type 'string | number'. この例の StrOrNum はstringがとりうる値とnumber型がとりうる値の両方をとります。 Intersection型 Intersection型はそれぞれの型いずれにも割り当てられる型を作り出します。 Union型を和集合とみるなら、Intersection型は積集合を作り出すイメージです。 type StrOrNum = string | number ; type BoolOrNum = boolean | number ; type I = StrOrNum & BoolOrNum ; let val: I = 123 ; // valはnumber型になる val = 'str' ; // Type 'string' is not assignable to type 'number'. val = true ; // Type 'boolean' is not assignable to type 'number'. その他の型 Function型 Function型は全ての関数を受け付ける型です。 引数の型や数、戻り値の型などは指定できないため、object型と同じく使用頻度は高くありません。 let fun: Function = ( arg: string ) => console .log ( `Hello, ${ arg } !!` ); fun ( 'TypeScript' ); // "Hello, TypeScript!!" fun () // "Hello, undefined!!" let fun2: ( arg: string ) => void = ( arg: string ) => console .log ( `Hello, ${ arg } !!` ); fun2 (); // Expected 1 arguments, but got 0. fun は arg という引数が必要ですが、 Function 型で宣言しているためにTypeScriptは警告を出しません。 基本的には上の例で使用した (arg: type) => returnType という形式で アノテーション します。 Index Signitures キーの型、値の型を指定してプロパティの個数は指定しないようなオブジェクトも定義できます。 type T = { [ key: number ] : string } const t: T = { 1 : 'one' , 2 : 'two' , 3 : 'three' } ; // このコードはエラーにならないので注意 console .log ( t [ 0 ] .length ); // Cannot read property 'length' of undefined 特殊な型 any anyは何でもありの型です。どのような型でも受け付け、どのような型にも割り当てられます。 let any : any ; any = 123 ; any = { a: 123 , b: 'string' } ; any = null ; any = 123 as unknown ; const s: undefined = any ; any型は実際の値がどのような型か全くわからないため、TypeScriptのメリットを享受しづらくなってしまいます。 プロジェクトを JavaScript からTypeScriptに置き換える際に、とりあえずanyとして型をつけておくのは便利ですが、 できるなら使用は避けるべきです。 型が実行時までわからないような場合には、unknown型の使用をまずは検討しましょう。 unknown TypeScript 3.0から導入されました。 unknown型の変数はどのような値も代入可能な点でanyと同様ですが、変数を利用するときには その変数の値の型が実際は何であるかが判明するまで利用することができません。 let unknown : unknown ; unknown = 123 ; unknown = { a: 123 , b: 'string' } ; // 比較は可能 if ( !! unknown ) { console .log ( 'truthy' ); } unknown = 'Hello unknown' ; if (typeof unknown === 'string' ) { console .log ( unknown .substring ( 0 , 5 )); } 上の例では typeof 演算子 を使用し、変数 unknown の実際の型が何であるかをチェックしてから String.substring メソッドを使用しています。 型をチェックしなければ変数を使用できないという面で any 型の変数よりも安全です。 void return文で値を返さない関数の戻り値はvoid型として推論されます。 function f () {} type R = typeof f ; // () => void // undefinedはvoid型に代入可能 let r = f (); r = undefined ; never never型はとりうる値が一つもない型です。 never型の変数にはanyすら代入できません。 let never : never ; never = {} ; // Type '{}' is not assignable to type 'never'. never = 123 as any ; // Type 'any' is not assignable to type 'never'. とりうる値が一つもないため、never型とその他の型のUnion型においてnever型は無視されます。 type T = string | number | never ; // Tは string | number 型 使い所としては、実行したら2度と呼び出し元の関数に処理が戻らないような関数の戻り値があります。 以下はNodeの Process.exit 関数の型です。 NodeJS.Process.exit ( code?: number | undefined ) : never exitを呼び出した時点で指定された ステータスコード でプロセスを終了するため、呼び出し元に処理が戻ることはありません。 その他、後述するConditional Typesにおいても使用されています。 インターフェースと型 エイリアス インターフェース TypeScriptにはインターフェースという仕組みがあり、オブジェクトの構造を指定することができます。 interface User { name: string , id: number , registeredDate: Date } const user: User = { name: 'Guest' , id: 0 , registeredDate: new Date ( '1900-01-01' ) } Classに実装することもできます。 class UserClass implements User { constructor( public name: string , public id: number , public registeredDate: Date ) { } } 型 エイリアス もしくは他のインターフェースを継承できます。 type Animal = { name: string , age: number } interface Cat extends Animal { mew () : void } const tama: Cat = { name: 'tama' , age: 2 , mew () { console .log ( "mew" ) } } 2つの違い TypeScriptには型 エイリアス とインターフェースが存在し、共にオブジェクトの構造を定義することができます。 この2つは何が違うのでしょうか? 宣言のマージ インターフェースは同名のインターフェースを重複して宣言できます。 その場合はインターフェースの定義をTypeScriptが自動的にマージします。 interface User { id: number } interface User { // 同一のプロパティは同じ型でなければならない // id: string, name: string , } const user: User = { id: 0 , name: "Guest" } ; 外部ライブラリの型を拡張したい場合インターフェースで宣言されていれば、 同名のインターフェースを再度宣言するだけで拡張が可能です。 対して、同名の型 エイリアス はエラーになります。 // Duplicate identifier 'User'. type User = { id: number } type User = { name: string } プリミティブ型とUnion型 インターフェースでは型 エイリアス で表現できる以下のような型を表現できません。 // プリミティブ型 type ID = number ; // Union型 type NumOrStr = number | string ; その他 インデックス シグネチャ を型のプロパティとして持つ際に違いがあるようです。 assignabiltity between interfaces and types · Issue #14736 · microsoft/TypeScript · GitHub ジェネリクス ジェネリクス はTypeScriptに限らず様々な言語で導入されている、型を抽象化するための仕組みです。 配列のそれぞれの要素に関数を適用する map 関数は ジェネリクス を使用して以下のように定義できます。 // <T>によって型変数Tを導入できる function map < T >( arr: T [] , f: ( element: T ) => T ) : T [] { const result = [] ; for ( const e of arr ) { result.push ( f ( e )) } return result ; } console .log ( map ( [ 1 , 2 , 3 ] , elm => elm * 2 )) ジェネリクス を導入できる場所 関数型 上のmap型のような書き方も可能ですが、アロー関数でももちろん ジェネリクス を使用できます。 const map = < T >( arr: T [] , f: ( e: T ) => T ) : T [] => { /* ... */ } 型 エイリアス type F < T , R > = ( arg: T ) => R ; const f: F < number , string > = arg => arg.toString (); インターフェース interface F < T , R > { ( arg: T ) : R ; } const f: F < number , string > = arg => arg.toString (); tsconfig. json tsconfig.json はTypeScript コンパイラ の挙動を指定するための設定ファイルです。 以下のコマンドを実行するとカレント ディレクト リ上にデフォルトの tsconfig.json が作成されます。 $ tsc -- init tsconfigで設定可能なオプションの一覧は以下で確認できます。 TypeScript: TSConfig Reference - Docs on every TSConfig option 型を操作する 型のキーワード ここではTypeScriptの型にまつわるキーワードについて紹介します。 typeof typeof val でvalの値の型を取得できます。 const n = 123 ; const s = 'str' ; const o = { n , s } ; const u = undefined ; // T1 = 123 type T1 = typeof n ; // T2 = "str" type T2 = typeof s ; // T3 = {s: string, n: number} type T3 = typeof o ; // T4 = undefined type T4 = typeof u ; keyof keyof は keyof Type とすることで、 Type が持つプロパティをUnion型として得ることができる 演算子 です。 type User = { id: number ; name: string ; age: number ; } // type UserKey = "id" | "name" | "age" type UserKey = keyof User ; Lookup Types Lookup Typesは特別なキーワードがあるわけではありませんが、 keyof と組み合わせて使われることが 多いためここで紹介します。 ある型TのプロパティKの型を T[K] として参照できる機能です。 type User = { id: number ; name: string ; age: number ; } // type UserIdType = number type UserIdType = User [ 'id' ] ; in for..in 構文でも使用されるinですが、TypeScriptでは Mapped Types と呼ばれる構文のためのキーワードとしても用いられます。 // type U = {A: any, B: any, C: any} type U = { [ K in "A" | "B" | "C" ] : any } inの後ろにある要素(Union型の場合には1つずつ取り出すイメージ)をキーとしたプロパティを作成します。 extends classやinterface,typeなどを継承する際に用いられる extends キーワードですが、 Conditional Types と呼ばれる機能でも使用されています。 // T1 = true type T1 = number extends number | string ? true : false ; // T2 = false type T2 = number extends null ? true : false ; T extends U ? X : Y となっている箇所が Conditional Types です。TypeScript 2.8から導入されました。 TがUに割り当て可能であればX、割り当て不可であればYを返します。 上の例では number 型は number | string 型にもちろん割り当てられますので、T1は true 型になります。 しかし null 型には割り当てられませんので、T2は false 型になります。 infer inferは推論した型を型変数として使用するための仕組みです。Conditional Types内で使用できます。 例としてこの後紹介するUtility Typesから ReturnType という型を見てみます。 type ReturnType < T extends ( ...args: any ) => any > = T extends ( ...args: any ) => infer R ? R : any ; ジェネリクス T extends (...args: any) => any の部分はTに割り当てられる型を関数型に制限しています。 右辺の T extends (...args: any) => infer R はTが関数型かどうかをextendsで判定するとともに、 関数の戻り値の型を R という新たな型変数にバインドしています。 当然Tが関数型でない場合にはRに値がバインドされないので、Rが使用できるのはTが関数型の場合のみです。 その他の場合にはany型になります。 Utility Types 最後にTypeScript組み込みの、いくつかの便利な型について紹介します。 上のkeyofやextendsなどの使用例が盛り沢山です。 Partial / Required / Readonly この3つは似たような定義なのでまとめて紹介します。 type Partial < T > = { [ P in keyof T ] ?: T [ P ] ; } ; type Required < T > = { [ P in keyof T ] -?: T [ P ] ; } ; type Readonly < T > = { readonly [ P in keyof T ] : T [ P ] ; } ; Partialはオブジェクトのプロパティを省略可能( key?: value の構文)にします。 Mapped Type を用いて T のプロパティを列挙して、プロパティに ? をつけることで全てのプロパティを省略可能にしています。 T[P] の箇所は Lookup Types で、各プロパティの値の型を参照しています。 Requiredは全てのプロパティを省略不可に、Readonlyは変更不可にする型です。 補足: readonlyについて readonly はプロパティを変更不可にするキーワードです。 type U = { a: string , b: number } type T = Readonly < U > const t: T = { a: "str" , b: 123 , } t.a = "modified" ; // Attempt to assign to const or readonly variable readonly も ? と同様に -readonly とすることで、各プロパティから readonly を取り除くことができます。 Pick<T, K> Pickはオブジェクトの型から指定したプロパティのみを持つオブジェクトを作る型です。 type Pick < T , K extends keyof T > = { [ P in K ] : T [ P ] ; } // T = { a: string, b: number } type T = Pick < { a: string , b: number , c: boolean } , "a" | "b" > K extends keyof T の部分は、Kが指定できるプロパティをTが持つプロパティのみに制限しています。 Record<K, T> Recordは2つの型K, Tを受け取り、Kの各プロパティに対してTを値としたオブジェクトの型を作る型です。 type Record < K extends keyof any , T > = { [ P in K ] : T ; } ; keyof any は確認してみるとわかりますが、 string | number | symbol というUnion型です。 type K = string | number | symbol つまり K extends keyof any はキーとする型Tを、キーとして指定できる型に制約しているということになります。 Exclude<T, ExcludedUnion> Excludeは型TからExcludedUnionの各要素を除いたものを作る型です。 type Exclude < T , U > = T extends U ? never : T ; // type E = 123 | "str" type E = Exclude < 123 | "str" | (() => any ), Function > 123 | "str" | (() => any) というUnion型から、Function型に割り当て可能な型のみを取り除いています。 never 型を返却する理由は、先の方でも述べましたが、以下のようにUnion型における never はないものとして扱えるためです。 // U1 = string | number type U1 = string | number | never ; // U2 = void type U2 = null | void | never ; Union Distribution 上の例のように、 T extends U のT が型変数かつUnion型の場合、TypeScriptは Union Distribution という特殊な挙動になります。 type Exclude < T , U > = T extends U ? never : T ; // type E = 123 | "str" type E1 = Exclude < 123 | "str" | (() => any ), Function > // E1はこんな感じに分配されるイメージ type E2 = 123 extends Function ? never : 123 | "str" extends Function ? never : "str" | (() => any ) extends Function ? never : (() => any ); 参考: TypeScript: Documentation - Advanced Types#Distributive conditional types Extract<T, Union> Excludeの逆です。 type Extract < T , Union > = T extends Union ? T : never ; Omit<Type, Keys> TypeScript 3.5から導入されました。 Pickとは対照的に、プロパティをKeysとしてUnion型で指定しTypeから取り除きます。 type Omit < T , K extends keyof any > = Pick < T , Exclude <keyof T , K >>; // T = { c: boolean } type T = Omit < { a: string , b: number , c: boolean } , "a" | "b" > 既出のUtility TypesであるPickとExcludeを使用しています。 ExcludeでTのプロパティからKを除き、残ったプロパティのみの型をPickで作成しています。 NonNullable 型Tを受け取り、名前通りnullはもちろん、undefinedもTから取り除きます。 type NonNullable < T > = T extends null | undefined ? never : T ; // U = string | (() => any) type U = NonNullable < string | null | undefined | (() => any )> Parameters 関数型を受け取り、引数の型をタプル型として返却します。 type Parameters < T extends ( ...args: any ) => any > = T extends ( ...args: infer Arg ) => any ? Arg : never ; // P1 = [a: number, b: string] type P1 = Parameters <( a: number , b: string ) => void > // P2 = type P2 = [a: { b: number, c: boolean }] type P2 = Parameters <( a: { b: number , c: boolean } ) => string > // P3 = unknown[] type P3 = Parameters < any > infer を使用して引数の型を推論し、結果をArgという新たな型変数にバインドしています。 ConstructorParameters Parameterのコンスト ラク タ版です。 type ConstructorParameters < T extends new ( ...args: any ) => any > = T extends new ( ...args: infer Arg ) => any ? Arg : never ; class A { constructor( private id: number , private name: string , ) {} } // U = [id: number, name: string] type U = ConstructorParameters <typeof A > T extends new (...args: any) => any でTの取りうる型をコンスト ラク タに制限しています。 ReturnType Parametersの戻り値版です。 type ReturnType < T extends ( ...args: any ) => any > = T extends ( ...args: any ) => infer R ? R : any ; // U1 = void type U1 = ReturnType <() => void > function f () { return Math .random () < 0.5 ? "OK" : "NG" } // U2 = "OK" | "NG" type U2 = ReturnType <typeof f > infer で今度は戻り値の型を推論しています。 InstanceType constructorの戻り値の型を取得します。 ReturnTypeのコンスト ラク タ版です。 type InstanceType < T extends new ( ...args: any ) => any > = T extends new ( ...args: any ) => infer Class ? Class : any ; class C { constructor( private name: string = "Guest" , private id: number = 0 ) {} } // U1 = C type U1 = InstanceType <typeof C > // U2 = any type U2 = InstanceType < any > ThisParameterType Tが関数型で this をパラメータとして持つ場合にその型を返却します。 type ThisParameterType < T > = T extends ( this : infer This , ...args: any ) => any ? This : unknown ; function f1 ( this : number ) {} function f2 ( arg: number ) {} // F1 = number type F1 = ThisParameterType <typeof f1 > // F2 = unknown type F2 = ThisParameterType <typeof f2 > this パラメータは必ず引数の先頭である必要があるため、それを利用してthisの型を推論しています。 OmitThisParameter 関数型Tを受け取り、Tが this パラメータを含んでいればそれを除いた関数型を返します。 type OmitThisParameter < T > = unknown extends ThisParameterType < T > ? T : T extends ( ...args: infer A ) => infer R ? ( ...args: A ) => R : T ; // F1 = (a: string) => any type F1 = OmitThisParameter <( this : number , a: string ) => any > // F2 = 123 type F2 = OmitThisParameter < 123 > unknown extends ThisParameterType<T> でTがthisパラメータを含むかどうか確認しています。 thisは可変長引数のパラメータに含まれないようなので、関数型であれば可変長引数の型を推論して返します。 ThisType この型を利用するためには --noImplicitThis を有効にする必要があります。 公式の例を引用して説明します。 TypeScript: Documentation - Utility Types#ThisType type ObjectDescriptor < D , M > = { data?: D ; methods?: M & ThisType < D & M >; // Type of 'this' in methods is D & M } ; function makeObject < D , M >( desc: ObjectDescriptor < D , M >) : D & M { let data: object = desc.data || {} ; let methods: object = desc.methods || {} ; return { ...data , ...methods } as D & M ; } let obj = makeObject ( { data: { x: 0 , y: 0 } , methods: { moveBy ( dx: number , dy: number ) { this .x += dx ; // Strongly typed this this .y += dy ; // Strongly typed this } , } , } ); obj.x = 10 ; obj.y = 20 ; obj.moveBy ( 5 , 5 ); ObjectDescriptor 内の methods?: M & ThisType<D & M> は、methods内で使用される this の型をobjの型である D & M 型に アノテーション します。 D & M 型はdataの型とmethodsの型の交差型なので、今回は以下のような型になります。 { x: number ; y: number ; moveBy ( dx: number , dy: number ) : void ; } makeObjectの引数が ObjectDescriptor 型なので、method内の this が上のような型に推論されるため this.x の形式でxにアクセスできる、ということだと思われます。 ちなみにThisTypeで アノテーション しない場合には関数内のthisは以下の型になりますので、TypeScriptはエラーを出します。 moveBy ( dx: number , dy: number ) { // Property 'x' does not exist on type '{ moveBy(dx: number, dy: number): void; }' this .x += dx ; // Property 'y' does not exist on type '{ moveBy(dx: number, dy: number): void; }' this .y += dy ; } Uppercase / Lowercase ここから紹介する4つの型はTypeScript 4.1から導入された新しめの型です。せっかくですので紹介します。 いずれも文字列型を操作できます。 // U1 = "FOO" type U1 = Uppercase < "foo" >; // U2 = "bar" type U2 = Lowercase < "BAR" > Capitalize / Uncapitalize // C1 = "Foo" type C1 = Capitalize < "foo" >; // C2 = "bar" type C2 = Uncapitalize < "Bar" > これらは単体で使うというよりかは、同じく4.1から導入された仕組みである Template literal types の補助として使われるのではと思います。 Template literal types の説明は流石に入門記事の範囲外のため割愛します。詳しく知りたい方はこちらをご覧ください。 TypeScript: Documentation - Template Literal Types まとめ 入門記事ということで長めになってしまいましたが、これをきっかけに少しでもTypeScriptに興味を持っていただけたなら嬉しい限りです。 紹介していないTypeScriptの機能もまだまだあるようですので、また機会があれば書かせていただきたいと思います。 参考 O'Reilly Japan - プログラミングTypeScript 実践TypeScript | マイナビブックス TypeScript: Handbook - The TypeScript Handbook TypeScript: TSConfig Reference - Docs on every TSConfig option TypeScript: Documentation - Utility Types TypeScript Ninja TypeScriptの型入門 - Qiita TypeScriptの型初級 - Qiita さようなら、TypeScript enum | Kabuku Developers Blog TypeScriptのenumを使わないほうがいい理由を、Tree-shakingの観点で紹介します - LINE ENGINEERING TypeScriptのInterfaceとTypeの比較 - Qiita TypeScriptにヤバい機能が入りそうなのでひとしきり遊んでみる|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社 TypeScript: Interfaces vs Types - Stack Overflow assignabiltity between interfaces and types · Issue #14736 · microsoft/TypeScript · GitHub エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
はじめに こんにちは、Engawaです。 ここ最近業務でReactについて触れる機会があり、Reactの学習を行ったので、 環境構築からreact-router-domを使用した簡単なSPAの作成方法についてザックリ紹介していこうと思います。 はじめに Reactとは 環境構築 起動 SPAの作成 react-router-domのインストール サンプルコード 実行 おわりに 参考資料 Reactとは React は FaceBook 社が開発した、UIを作るための JavaScript 用ライブラリです。 アプリに特化したReactNativeもあります。 そちらについては こちら で紹介していますのでご覧いただけれと思います。 環境構築 私が学習をした際の環境は以下になります。 node: v10.19.0 OS : macOS Catalina 使用したエディタ: VSCode こちらで記載する環境構築方法は macOS のみになります。 windowsでnodeをインストールする時はこちらを参考にしてください。 次の5つのコマンドを順番にターミナルで実行してください。 Homebrewのインストール (nodeをインストールする際に使用します) /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" nodeのインストール brew install node nのインストール npm -g i n nodeのバージョン確認 node -v 上記コマンドを実行してバージョンが表示されていればnodeのインストールは完了です。 $ node -v vバージョン 続いてファイル等の作成を行います。 が、1から設定ファイル等の作成は面倒なのでcreate-react-appを使用します。 create-reeact-appは環境構築ツールで一度インストールしてしまえば、コマンド1つでReactに必要な環境を構築することができます。 まずは下記コマンドでcreate-react-appをインストールします。 npm install create-react-app インストールが完了したらプロジェクトを作成したいフォルダ上で、下記コマンドでcreate-react-appを実行してReactプロジェクトを作成します。 create-react-app 作成したいプロジェクト名 上記コマンド実行後、プロジェクトフォルダの中に以下のフォルダおよびファイルが作成されていたら作成完了です。 プロジェクト名 ├── node_modules/ ├── package. json ├── public/ ├── README.md ├── src/ └── yarn.lock 起動 作成したプロジェクトフォルダに移動して、 cd プロジェクト名 下記コマンドで起動します。 npm install ↓ npm start 実行後下記画面が表示されれば問題なく起動できています。 SPAの作成 react-router-domのインストール Reactで画面遷移させるため、react-router-domを使用します。 プロジェクト名のフォルダ直下で下記コマンドを実行してreact-router-domをインストールしてください。 npm install react-router-dom package. json にreact-router-domのライブラリが追加されていたらインストール完了です。 サンプルコード src/index.js <BrowserRouter> でrouterの導入を行います。 react-router関連の処理はすべて <BrowserRouter> 内で使用しなくてはいけないかつ、1プロジェクトにつき1つしか使用できないため、 <BrowserRouter> は上位層で使用することになります。 import React from 'react' ; import ReactDOM from 'react-dom' ; import { BrowserRouter } from 'react-router-dom' ; import './index.css' ; import App from './App' ; import reportWebVitals from './reportWebVitals' ; ReactDOM.render( <BrowserRouter> <App /> </BrowserRouter>, document .getElementById( 'root' ) ); reportWebVitals(); src/App.js <Route> にはルーティング先のURLと コンポーネント の切り替えを行います。 今回はroutes.jsにパスを記載して、routesからそれぞれの値を呼び出し、 <Switch> でURLが一致した時に コンポーネント を表示させます。 import React from 'react' ; import { Route, Switch, withRouter } from 'react-router-dom' ; import routes from './routes' ; const App = () => { return ( <Switch> { routes.map((route, idx) => ( <Route path= { route.path } exact= { route.exact } component= { route.component } key= { idx } /> )) } </Switch> ); } ; export default withRouter(App); src/routes.js(新規で作成) import One from './page/one' ; import Two from './page/two' ; const routes = [ { path: '/' , component: One, exact : true } , { path: '/two' , component: Two, } , ] ; export default routes; src/page/one.js(新規で作成) 画面遷移をするために <link> を使用しています。 やっていることはaタグと同じで、to属性でリンク先のURLを指定しています。 import React from 'react' ; import { Link } from 'react-router-dom' ; import Two from './two' ; class One extends React.Component { render() { return ( <div> test_one<br/> <Link to= '/two' >twoへ</Link> </div> ) } } export default One; src/page/two.js(新規で作成) import React from 'react' ; import { Link } from 'react-router-dom' ; import One from './one' ; class Two extends React.Component { render() { return ( <div> test_two<br/> <Link to= '/' >oneへ</Link> </div> ) } } export default Two; 実行 実行するとこんな感じで画面遷移することができます。 おわりに 今回はReactの触りについて学習を行ったので、環境構築から簡単な画面遷移のやり方について紹介させていただきました。 何かしら学習を行う際は大体環境構築あたりで躓いて投げ出すことが多いので、今回みたいにcreate-reeact-appを実行するだけで簡単に環境構築ができるのは大変助かりました。 参考資料 https://qiita.com/ShinKano/items/541050c36e08e78a5176 https://dezanari.com/react-react-router/ https://code-ship-blog.wemotion.co.jp/technology/react-js%E3%81%A7%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%82%92%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AEreact-router%E3%81%AE%E7%B4%B9%E4%BB%8B/ エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
はじめに 初めましてこんにちは!matsutairaです! 今回は、普段何気なく利用している DNS サーバーというものにフォーカスし、実際にWebサーバー・ DNS サーバーの構築を通して DNS サーバーとは何なのかをざっくり学べる内容となっております。「 DNS サーバーってどんなもの?」「自分で DNS サーバーを構築してみたい!」という方々の力になれればと思います。 今回は初めて触る方向けの内容になっていますので、「 DNS サーバーの構築方法だけ知りたい!」という方は目次からジャンプしていただければと思います。 手順の大まかな流れとしては、「 ドメイン 取得」 → 「各種サーバー構築」 → 「動作確認」です。 ドメイン の取得は通常それなりのコストがかかりますが、お名前ドットコムであれば初回1年間は1円で利用することができる「.work」 ドメイン があるため、最小限のコストに抑えることができます。また、 ドメイン の取得は個人・法人問わず、ホームページやメールアドレス、個人ブログで利用することができ、世界に一つだけのオリジナルであるという証明にもなります。 各種サーバーの構築は今回 AWS を利用して作成していきます。 AWS を利用するメリットとしては、初回1年間のみ無料で試すことができ、今回利用する範囲内であれば1年間無料で利用できます。(BDやRoute53を利用する場合は別途料金がかかります)また、 AWS 上でサーバーを一括管理できることや グローバルIPアドレス の取得が容易であること、 GUI での操作が可能であることもメリットになります。 通常お金のかかる ドメイン の取得と AWS の利用ですが、今回は合計1円のみで DNS サーバーについて学ぶことができるため、初めての方でも取り組みやすい内容になっているかと思います。 目次 はじめに DNSサーバーとは 環境準備 ドメイン取得 AWS登録 インスタンス作成 ネットワーク設定 Webサーバー構築 Apacheのインストール HTMLの作成と配置 セキュリティグループの変更(Webサーバー) DNSサーバー構築 プライマリDNSサーバーの構築 セカンダリDNSサーバーの構築 セキュリティグループの変更(DNSサーバー) DNSサーバー登録 動作確認 おわりに DNS サーバーとは DNS ( D omain N ame S ystem)とは、 ドメイン 名や完全修飾 ドメイン 名( FQDN )に対応する IPアドレス の情報を管理・運用するシステムです。 簡単に言えば、例えば ドメイン 名「 google .com」を「172.217.175.14」という IPアドレス に変換してくれるシステムです。 もう少し詳しく言うと、インターネット上でコンピュータ同士が通信を行うためには IPアドレス と呼ばれるインターネット上の住所のようなものを使って通信します。 しかし私たち人間が IPアドレス 「172.217.175.14」を見ただけでは、それが「 google .com」のサーバーだとはわかりません。 同様にコンピュータが ドメイン 名「 google .com」を見ても、コンピュータは IPアドレス でしか読み取ることができないため、人間とコンピュータにわかるようにするための相互変換が必要になり、 DNS というシステムが使用されています。 DNS サーバーはその機能を実装しているサーバーということになります。 例えば、検索バーに「 google .com」と入力します。先ほども説明したようにコンピュータには「 google .com」という文字列からサーバーの住所はわかりませんが、 DNS サーバーに「 google .comの IPアドレス (住所)を教えて下さい」と問い合わせを行うことで DNS サーバーは「 google .comの IPアドレス (住所)は172.217.175.14ですよ」とコンピュータに教えてくれます。これによりコンピュータは受け取った IPアドレス にアクセスすることで google .comのページが表示されるということになります。 簡単に DNS サーバーの動きを説明しましたが、 DNS サーバーは世界中にある無数の DNS サーバーが階層構造になって存在しています。そのため、一口に「 google .comの IPアドレス は何?」と言っても、「ルート DNS サーバー」→「.comを管理している DNS サーバー」→「 google .comのIPを管理している DNS サーバー」を経由して IPアドレス をコンピュータに教えてくれます。この動作は世界中にある無数の DNS サーバーが連携し一瞬で完了するため、私たちは普段意識することはありません。また、 DNS サーバーにはキャッシュ DNS サーバーと権威 DNS サーバーというものが存在しています。キャッシュ DNS サーバーは、自身で ドメイン 名と IPアドレス の情報を管理しているわけではなく、他の DNS サーバーに問い合わせを行ったり、自身で保持しているキャッシュから IPアドレス などを返したりする DNS サーバーです。逆に権威 DNS サーバーは、自身で ドメイン 名と IPアドレス の情報を管理している DNS サーバーになります。今回は、自身で ドメイン 名と IPアドレス の情報を管理するので、権威 DNS サーバーを構築します。 今回の名前解決の流れは以下のようになります。 クライアントはブラウザで「 http://web-test.dns-server-test.work 」と入力すると、Webサーバーの IPアドレス を得るためにキャッシュ DNS サーバーに問い合わせを行います。 キャッシュ DNS サーバーは、「 http://web-test.dns-server-test.work 」の IPアドレス を保持している場合はその IPアドレス をクライアントに返し、保持していない場合はルート DNS サーバーに問い合わせを行います。 ルート DNS サーバーには、「 http://web-test.dns-server-test.work 」の IPアドレス の情報はありませんが、「.work」を管理している DNS サーバーの IPアドレス を保持しているため、その IPアドレス を返します。 3で受け取った DNS サーバーの IPアドレス を元に、「.work」を管理している DNS サーバーに「 http://web-test.dns-server-test.work 」の IPアドレス を問い合わせます。 「.work」を管理している DNS サーバーには、「 http://web-test.dns-server-test.work 」の IPアドレス の情報はありませんが、「 dns -server-test.work」を管理している DNS サーバーの IPアドレス を保持しているため、その IPアドレス を返します。 5で受け取った DNS サーバーの IPアドレス を元に、「 dns -server-test.work」を管理している DNS サーバーに「 http://web-test.dns-server-test.work 」の IPアドレス を問い合わせます。 「 dns -server-test.work」を管理している DNS サーバーには、「 http://web-test.dns-server-test.work 」の IPアドレス 情報が記載されているため、その IPアドレス を返します。 受け取った「 http://web-test.dns-server-test.work 」の IPアドレス をクライアントに返します。 クライアントは「 http://web-test.dns-server-test.work 」の IPアドレス を元にWebサーバーにアクセスします。 WebサーバーのHTMLからブラウザ上にWebページが表示されます。 DNS サーバーには、 ドメイン 名と IPアドレス を紐づける情報が無数に蓄積されています。しかし、 DNS サーバーがダウンしてしまった場合、 ドメイン 名と IPアドレス の紐づけができなくなるため、 Webサービス にアクセスできなくなったり、メールを送信することができなくなってしまいます。そのため、 DNS サーバーは障害がいつ発生しても問題ないように2つ以上のサーバー群で構成されています。今回はプライマリ DNS サーバーと セカンダリ DNS サーバーの2つを構築し、片方の DNS サーバーで障害が発生しても問題ないことも確かめたいと思います。 目次へ 環境準備 実際に DNS サーバーを構築するための準備を行っていきます。 ※今回は AWS 上で作成したWebサーバーと DNS サーバーに SSH 接続するため、RLoginという SSH クライアントをインストールしておきます。 ※すでにターミナルソフトがインストールされている方はそちらを利用してください。 http://nanno.dip.jp/softlib/man/rlogin/#INSTALL nanno.dip.jp ドメイン 取得 まず、 ドメイン の取得です。今回は初回1年のみ1円/年で取得できる「.work」 ドメイン を取得します。 ※今回は dns -server-test.work ドメイン を取得しました(取得する場合は) www.onamae.com ※お名前ドットコムは1年後に ドメイン が自動更新される設定になっているため、自動更新を解除しておきましょう。 ※お名前ドットコムからは頻繁にメールが届くため、メールの配信設定を変更することをお勧めします。 AWS 登録 次に AWS ( Amazon Web Service)を利用するためアカウント登録を行います。 aws.amazon.com インスタンス 作成 AWS が利用可能になったら次は インスタンス を作成していきます。 インスタンス とは、 AWS クラウド 上にあるOSを載せた仮想サーバーのことです。 インスタンス を作成することでサーバーの環境構築を行うことができます。 以下のリンクを参考に インスタンス を作成します。 aws.amazon.com インスタンス の仕様は以下のように設定します。 AMI( Amazon マシンイメージ):CentOS8 minimal インスタンス タイプ    :t2.micro セキュリティグループ   :Webサーバー・・・ SSH (マイIP)、HTTP(80番ポート)              : DNS サーバー・・・ SSH (マイIP)、 DNS ( UDP )、 DNS ( TCP ) Nameタグ         :Webサーバー・・・web-test              :プライマリ DNS サーバー・・・dns1-test              : セカンダリ DNS サーバー・・・dns2-test Webサーバー・プライマリ DNS サーバー・ セカンダリ DNS サーバーの3つ分、 インスタンス を作成します。 ネットワーク設定 次にネットワークの設定を行っていきます。 AWS ではEIP(Elastic IP)というものが設定でき、今回作成したサーバーに固定の IPアドレス を付けることができます。 以下の リンクを参考にEIPを設定します。 docs.aws.amazon.com 今回使用するWebサーバー・プライマリ DNS サーバー・ セカンダリ DNS サーバーの3つにそれぞれ割り当てます。 EIPが重複せずに設定されていれば完了です。 目次へ Webサーバー構築 DNS サーバーの構築に入る前に、Webサーバーを作成します。 初めにWebサーバーに SSH 接続します。 今回はログインユーザ名を「 centos 」とする必要があるため注意してください。(rootユーザではログインできません) また、 インスタンス 作成時に作成したキーペアを登録します。(登録しない場合 SSH できません) SSH 接続後は、rootに切り替えてコマンドを実行していきます。 (デフォルトではrootユーザでログインできないため) ※以降サーバー内でコマンドを実行するときは必ずrootユーザに変更してから行う # sudo su - SSH 接続後は、 ミドルウェア アップデートをして 脆弱性 の排除を行います。 # dnf check-update # dnf upgrade ミドルウェア アップデートが完了したら再度確認を行い、最新の状態であることを確認します。 アップデート対象が表示されなければ完了です。 # dnf check-update Apache のインストール 次に、 Apache をインストールします。 # dnf install httpd インストールが完了したら、 Apache のバージョンを確認しておきます。 # httpd -v Server version: Apache/2.4.37 (centos) Server built: Nov 4 2020 03:20:37 Apache を 自動起動 する設定に変更しておきます。 enabledになっていれば 自動起動 される設定になったということになります。 # systemctl enable httpd.service Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service. # systemctl list-unit-files | grep httpd.service httpd.service enabled Apache を起動してステータスを確認します。 「Active: active (running)」となっていれば起動状態です。 # systemctl start httpd.service # systemctl status httpd.service ● httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled) Active: active (running) ~省略~ 無事 Apache が起動しましたので、次はHTMLの作成と配置です。 HTMLの作成と配置 クライアントからのアクセスでファイル名を指定しなかった場合( http://example.com/index.html ← この最後のファイルを指定しない場合)、/etc/ httpd /conf/ httpd .confファイル内のDirectoryIndexディレクティブからindex.htmlがデフォルトで表示されるようになっています。 ~省略~ <IfModule dir_module > DirectoryIndex index.html </IfModule> ~省略~ このようにデフォルトではindex.htmlが指定されており、 http://www.dns-server-test/ にアクセスされると、index.htmlが存在すればそのHTMLが、存在しなければ Apache のテストページが表示されます。 そのため、今回は編集する箇所を少なくしたいという意味も込めて、index.htmlファイルを作成していきます。 まず、HTMLファイルの配置場所ですが、以下のコマンドを使用することで確認することができます。 # grep "^DocumentRoot" /etc/httpd/conf/httpd.conf DocumentRoot "/var/www/html" これによりHTMLファイルは「/var/www/html」の下に配置すればよいということがわかります。 次に、HTMLの作成です。以下のコマンドでHTMLを作成します。 # vi /var/www/html/index.html 簡易的ですが、記述するHTMLを記載します。 <!DOCTYPE html> < html lang = "ja" > < head > < meta charset = "UTF-8" > < meta name = "viewport" content = "width=device-width, initial-scale=1" > < meta name = "description" content = "" > < meta http-equiv = "X-UA-Compatible" content = "IE=edge" > < title > DNS TEST </ title > </ head > < body > < h1 > Successful Access! </ h1 > </ body > </ html > HTMLの作成と配置が完了しました。 セキュリティグループの変更(Webサーバー) これにてWebサーバーの構築は完了しましたので、構築できているか確認するためにアクセスします。 Webサーバーにアクセスするためには、セキュリティグループを変更して80番ポートを解放する必要があります。 以下のように設定を追加します。 タイプ:HTTP ソース:カスタム、0.0.0.0/0 一度動作確認のため、 IPアドレス でアクセスしてみます。 成功しました。 目次へ DNS サーバー構築 前置きが長くなりましたが、いよいよ本題のプライマリ DNS サーバーと セカンダリ DNS サーバーの構築に入ります。 プライマリ DNS サーバーの構築 それでは実際に構築していきます。 まず、 AWS 上で作成したサーバーを DNS サーバーとして動作させるための設定ファイル等が入った ミドルウェア をインストールする必要があります。 今回インストールするものは、「bind」「bind- chroot 」「bind-utils」の3種類です。 bind ・・・・・・BIND9本体で各種設定ファイル等が入っているもの bind- chroot ・・・ chroot 化させるためのもの bind-utils・・・・nslookupやdigコマンドを使用するためのもの(named-checkzoneコマンドも使用できるようにするため) Step1~9で DNS サーバーの構築を行います。 Step1 Webサーバー構築時と同様にプライマリ DNS サーバー(dns1)に SSH 接続します。 ※接続方法はWebサーバーで解説していますのでそちらを参照 ※「# sudo su -」でrootユーザに変更してから実施 Step2 Webサーバー構築時と同様に ミドルウェア アップデートを行います。 # dnf check-update # dnf upgrade Step3 以下のコマンドを入力し、BIND関連の ミドルウェア をインストールします。 # dnf install bind bind-chroot bind-utils Step4 BINDのバージョンがBIND9系であることを確認します。 # named -v BIND 9.11.20-RedHat-9.11.20-5.el8 (Extended Support Version) <id:f3d1d66> Step5 namedではなくnamed- chroot というサービスを起動して利用するため、namedのステータスと設定を確認します。 ※ chroot については後述します。 # systemctl list-unit-files | grep ^named.service named.service disabled # systemctl status named ● named.service - Berkeley Internet Name Domain (DNS) Loaded: loaded (/usr/lib/systemd/system/named.service; disabled; vendor preset: disabled) Active: inactive (dead) namedが 自動起動 しない設定であることと停止していれば問題ありません。 自動起動 する設定や起動している場合には、以下のコマンドで停止させましょう。 # systemctl disable named.service # systemctl stop named.service Step6 named- chroot を 自動起動 する設定にして起動させます。先ほど説明を後回しにした chroot ですが、ルート ディレクト リを変更するというもので、namedを chroot 化させると/var/named/ chroot 以下に関連するファイルがマウントされ、 chroot より上位の ディレクト リにはアクセスをできなくなります。これによりアクセス可能な範囲が制限されセキュリティ対策となります。 # systemctl enable named-chroot.service Created symlink /etc/systemd/system/multi-user.target.wants/named-chroot.service → /usr/lib/systemd/system/named-chroot.service. # systemctl start named-chroot.service # systemctl status named-chroot.service ● named-chroot.service - Berkeley Internet Name Domain (DNS) Loaded: loaded (/usr/lib/systemd/system/named-chroot.service; enabled; vendor preset: disabled) Active: active (running) ~省略~ Step7 named.confファイルを編集して DNS サーバーの基本設定を行います。 ※ chroot 化しているため、/etc/named.confではなく/var/named/ chroot /etc/named.confを編集することに注意 # vi /var/named/chroot/etc/named.conf デフォルトのnamed.confファイルは以下になります。 // // named.conf // // // named.conf // // Provided by Red Hat bind package to configure the ISC BIND named(8) DNS // server as a caching only nameserver (as a localhost DNS resolver only). // // See /usr/share/doc/bind*/sample/ for example named configuration files. // options { listen-on port 53 { 127.0.0.1; }; listen-on-v6 port 53 { ::1; }; directory "/var/named"; dump-file "/var/named/data/cache_dump.db"; statistics-file "/var/named/data/named_stats.txt"; memstatistics-file "/var/named/data/named_mem_stats.txt"; secroots-file "/var/named/data/named.secroots"; recursing-file "/var/named/data/named.recursing"; allow-query { localhost; }; /* - If you are building an AUTHORITATIVE DNS server, do NOT enable recursion. - If you are building a RECURSIVE (caching) DNS server, you need to enable recursion. - If your recursive DNS server has a public IP address, you MUST enable access control to limit queries to your legitimate users. Failing to do so will cause your server to become part of large scale DNS amplification attacks. Implementing BCP38 within your network would greatly reduce such attack surface */ recursion yes; dnssec-enable yes; dnssec-validation yes; managed-keys-directory "/var/named/dynamic"; pid-file "/run/named/named.pid"; session-keyfile "/run/named/session.key"; /* https://fedoraproject.org/wiki/Changes/CryptoPolicy */ include "/etc/crypto-policies/back-ends/bind.config" ; }; logging { channel default_debug { file "data/named.run" ; severity dynamic; }; }; zone " . " IN { type hint ; file "named.ca" ; }; include "/etc/named.rfc1912.zones" ; include "/etc/named.root.key" ; 今回編集するのは、options ステートメント とzone ステートメント です。以下のように変更します。 options { // 1. BINDのバージョンを隠蔽 version "unknown" ; // 2. ホスト名 hostname "dns1.dns-server-test.work."; // 3. 53番ポートでの受付をすべて許可 listen-on port 53 { any; }; // 4. ipv6を使用しない listen-on-v6 { none; }; directory "/var/named"; dump-file "/var/named/data/cache_dump.db"; statistics-file "/var/named/data/named_stats.txt"; memstatistics-file "/var/named/data/named_mem_stats.txt"; secroots-file "/var/named/data/named.secroots"; recursing-file "/var/named/data/named.recursing"; // 5. すべてのクエリーを受け付ける allow-query { any; }; // 6. リゾルバとして動作しないように設定 recursion no; allow-recursion { none; }; allow-query-cache { none; }; dnssec-enable yes; dnssec-validation yes; managed-keys-directory "/var/named/dynamic"; pid-file "/run/named/named.pid"; session-keyfile "/run/named/session.key"; /* https://fedoraproject.org/wiki/Changes/CryptoPolicy */ include "/etc/crypto-policies/back-ends/bind.config" ; }; logging { channel default_debug { file "data/named.run" ; severity dynamic; }; }; // 7. ルートDNSサーバーのゾーン情報は今回必要ないのでコメントアウト /* zone "." IN { type hint; file "named.ca"; }; */ // 8. ゾーンファイルdns-server-test.workの設定 zone " dns-server-test.work " IN { // プライマリDNSサーバーであることを指定 type master ; // ゾーンファイルのファイル名を指定 file "dns-server-test.work" ; // ゾーンファイルの変更を通知する notify yes ; // ゾーンファイルの変更を通知する先を指定(セカンダリDNSサーバーのプライベートIPアドレスを指定) also-notify { xxx.xxx.xxx.xxx; }; // ゾーン転送先を指定(セカンダリDNSサーバーのプライベートIPアドレスを指定) allow-transfer { xxx.xxx.xxx.xxx; }; }; include "/etc/named.rfc1912.zones" ; include "/etc/named.root.key" ; BINDのバージョンを隠蔽 nslookupコマンド等でBINDのバージョンを表示されないようにします。バージョンが知られてしまうと、そのバージョンでの 脆弱性 を突いて攻撃される可能性があるためです。今回は入力をunknownしているため、unknownと表示されることになります。 ホスト名 DNS サーバーのホスト名を記述します。プライマリ DNS サーバーのnamed.confファイルを編集しているので、「dns1-test. dns -server-test.work」となります。 53番ポートでの受付をすべて許可 DNS サーバーは53番ポートを使用するため許可する設定にします。 IPv6 を使用しない 今回は IPv4 のみ使用するため使用しないことを明示的に記述しています。(記述しない場合も使用しない設定になります) すべてのクエリーを受け付ける どこからでも名前解決の問い合わせを受け付ける設定にします。 リ ゾル バとして動作しないように設定 recursionは 再帰 問い合わせを行う設定です。今回は権威 DNS サーバーを構築するため、設定をnoにします。 ルート DNS サーバーのゾーン情報は今回必要ないので コメントアウト キャッシュ DNS サーバーとして動作させないため コメントアウト します。 ゾーンファイル dns -server-test.workの設定 DNS サーバーがプライマリなのか セカンダリ なのかの指定や、ゾーンファイルの名前を指定、ゾーン転送先を指定等をします。 編集が完了したら記述が正しくできているかチェックを行います。 ※正しく記述できている場合には何も表示されません # named-checkconf /var/named/chroot/etc/named.conf Step8 named.confファイルの編集が終わったら次はゾーンファイルの作成です。簡単に言うとゾーンファイルは ドメイン 名と IPアドレス の対応表を記載していくファイルになります。 /var/named/ chroot /var/named以下に作成します。 # vi /var/named/chroot/var/named/dns-server-test.work ゾーンファイルの記述は以下のようになります。 $TTL 30 0 @ IN SOA dns1-test.dns-server-test.work. xxxxxxxxxx.gmail.com. ( 2020122000 ; Serial(シリアル ) 3600 ; Refresh(転送間隔 ) 900 ; Retry(再試行猶予時間 ) 21600 ; Expire(有効時間 ) 60 ; Minimum TTL(ネガティブキャッシュTTL ) ) ; DNSサーバ ー IN NS dns1-test.dns-server-test.work . IN NS dns2-test.dns-server-test.work . dns1-test IN A xxx.xxx.xxx.xx x dns2-test IN A xxx.xxx.xxx.xx x ; Webサーバ ー web-test IN A xxx.xxx.xxx.xx x ゾーンファイル内では「 ; 」はコメントとして扱われます。以下に各記述の内容を記載します。 TTL DNS サーバーがレコード情報をキャッシュする時間で、この場合最大5分間ローカルにキャッシュを保持します。 @ IN SOA ~ SOA レコートといい、@ IN SOA {MNAME} {RNAME}で記述します。 MNAMEは、 DNS サーバーの名前を記述します。 RNAMEは、この ドメイン の管理者のメールアドレスを記述します。@マークは「 . 」に置き換えて記述する必要があります。 Serial ゾーンファイルのバージョンを表し、YYYYMMDDnn形式で記述します。この場合であれば「2020年12月 20日 1回目の変更」ということになります。※変更回数は0回からカウントします。 例えば同じ日に2回目の変更をした場合はシリアルを変更して「2020122001」となります。 Refresh ゾーンの情報をリフレッシュするまでの時間です。 セカンダリ DNS サーバーはゾーン転送をした後、この時間が経過すると、ゾーンの更新がされたかを問い合わせ、必要に応じて再度データを入手しようとします。 Retry Refreshでゾーンの情報が更新できなかった場合に、指定された時間後に再度リフレッシュを試みます。 Expire ゾーン情報のリフレッシュができない状態が続いた場合に、 セカンダリ DNS サーバーが所持しているデータをどのくらいの時間利用するか記述します。 Minimum TTL ネガティブキャッシュと言われ、名前解決ができなかったという情報を保持する時間を記述します。 IN NS ~ NSレコードといい、 DNS サーバーを記述します。今回の場合はプライマリ DNS サーバーと セカンダリ DNS サーバーを指定します。 最後に「 . 」を付けます。 ~ IN A ~ Aレコードといい、ホスト名に対応する IPアドレス を記述します。 ゾーンファイルの編集が終わったら パーミッション と所有権を変更します。 # chmod 750 /var/named/chroot/var/named/dns-server-test.work # chown root:named /var/named/chroot/var/named/dns-server-test.work # ll /var/named/chroot/var/named/dns-server-test.work -rwxr-x---. 1 root named 570 Dec 20 14:01 /var/named/chroot/var/named/dns-server-test.work ゾーンファイルもnamed.confと同様、記述が正しいかチェックします。「OK」と表示されれば問題ありません。 ※構文が正しいかのみのチェックであるため、 IPアドレス が正しいかどうか等は判定されません # named-checkzone dns-server-test.work /var/named/chroot/var/named/dns-server-test.work zone dns-server-test.work/IN: loaded serial 2020122000 OK Step9 最後に設定を反映させます。rndcコマンドを使用することで、 DNS サーバーを再起動させることなくゾーンファイルを反映させることができます。 # rndc reload server reload successful プライマリ DNS サーバーの構築は完了です。 目次へ セカンダリ DNS サーバーの構築 プライマリ DNS サーバーの構築が終わったら次は セカンダリ DNS サーバーの構築です。構築はプライマリ DNS サーバーとほぼ同様です。 セカンダリ DNS サーバーに SSH 接続し、プライマリ DNS サーバーで行った Step2~6 までを行います。 Step7はプライマリ DNS サーバーと セカンダリ DNS サーバーでは変更箇所があるため、変更箇所を以下に記述します。named.confファイルを編集します。 # vi /var/named/chroot/etc/named.conf options { // BINDのバージョンを隠蔽 version "unknown" ; // ホスト名 hostname "dns2.dns-server-test.work."; // 53番ポートでの受付をすべて許可 listen-on port 53 { any; }; // ipv6を使用しない listen-on-v6 { none; }; directory "/var/named"; dump-file "/var/named/data/cache_dump.db"; statistics-file "/var/named/data/named_stats.txt"; memstatistics-file "/var/named/data/named_mem_stats.txt"; secroots-file "/var/named/data/named.secroots"; recursing-file "/var/named/data/named.recursing"; // すべてのクエリーを受け付ける allow-query { any; }; // リゾルバとして動作しないように設定 recursion no; allow-recursion { none; }; allow-query-cache { none; }; dnssec-enable yes; dnssec-validation yes; managed-keys-directory "/var/named/dynamic"; pid-file "/run/named/named.pid"; session-keyfile "/run/named/session.key"; /* https://fedoraproject.org/wiki/Changes/CryptoPolicy */ include "/etc/crypto-policies/back-ends/bind.config" ; // 1. セカンダリDNSサーバーからは通知を送信しない notify no; // 2. セカンダリDNSサーバーからはゾーン転送しない allow-transfer { none; }; }; logging { channel default_debug { file "data/named.run" ; severity dynamic; }; }; // ルートDNSサーバーのゾーン情報は今回必要ないのでコメントアウト /* zone "." IN { type hint; file "named.ca"; }; */ // 3. ゾーンファイルdns-server-test.workの設定 zone " dns-server-test.work " IN { // セカンダリDNSサーバーであることを指定 type slave ; // ゾーン転送されたファイルをバイナリ形式からテキスト形式に変換する設定 masterfile-format text; // ゾーンファイルのファイル名を指定 file "slaves/dns-server-test.work" ; // マスターDNSサーバーを指定(マスターDNSサーバーのプライベートIPアドレスを指定) masters { xxx.xxx.xxx.xxx; }; }; include "/etc/named.rfc1912.zones" ; include "/etc/named.root.key" ; セカンダリ DNS サーバーからは通知を送信しない プライマリ DNS サーバーからは通知を送信しますが、 セカンダリ DNS サーバーはバックアップのような存在であるため、通知の必要がありません。 セカンダリ DNS サーバーからはゾーン転送しない プライマリ DNS サーバーからはゾーン転送を行いますが、 セカンダリ DNS サーバーはゾーン転送を受ける側なので必要がありません。 ゾーンファイル dns -server-test.workの設定 DNS サーバーがプライマリなのか セカンダリ なのかの指定や、ゾーンファイルの名前を指定、ゾーン転送先を指定等をします。 セカンダリ DNS サーバーはゾーン転送によりゾーンファイルがプライマリ DNS サーバーから転送されてくるため、Step8は行いません。 Step9を行います。 # rndc reload server reload successful 最後にStep10として、ゾーン転送されているか確認します。 ※最初のゾーン転送が行われるまでは若干時間がかかる可能性があるため、次の「セキュリティグループの変更」や「 DNS サーバー登録」を行ってから再度確認してください。 # ll /var/named/chroot/var/named/slaves/ total 4 -rw-r--r--. 1 named named 473 Dec 20 15:20 dns-server-test.work セキュリティグループの変更( DNS サーバー) Webサーバーのセキュリティグループ変更と同様に DNS サーバーのセキュリティグループを以下のように変更します。 DNS サーバーは53番ポートで通信を行うため、 DNS ( UDP )と DNS ( TCP )を解放する必要があります。 DNS サーバーのセキュリティグループ変更は完了です。 目次へ DNS サーバー登録 先ほど構築した DNS サーバーですが、構築しただけでは DNS サーバーとしての役割、つまり名前解決を行うことはできません。 DNSサーバーとは の部分でも触れましたが、 DNS サーバーは階層構造になっているため、今回構築した DNS サーバーの一つ上の DNS サーバーに、構築した DNS サーバーの IPアドレス を登録する必要があります。 つまり今回の場合であれば「.work ドメイン を管理している DNS サーバー(お名前ドットコム)に、今回構築した DNS サーバーの IPアドレス を登録する」ということになります。 まずはお名前ドットコムにアクセスします。 画面右上の「お名前ドットコム navi ログイン」をクリックしてログイン画面に移ります。 ドメイン 取得時にお名前IDが発行されているのでそちらとパスワードを入力しログインします。 ログインが完了したら、画面上部の DNS タブにカーソルを合わせ、「 ドメイン の DNS 設定」をクリックします。 取得した ドメイン にチェックを入れ「次へ」をクリックします。 画面下部にある「ネームサーバー名としてホスト登録を行う」の「設定する」をクリックします。 作成にチェックを入れ「入力画面に進む」をクリックします。 ホスト名「dns1」とdns1の IPアドレス を入力し、「確認画面へ進む」をクリックします。 ※dns2も同様にホスト名と IPアドレス を登録します。( DNS サーバーを2つ登録しないと後の画面でエラーになります。) ホスト名の登録が完了したら次は、 DNS サーバーの変更を行います。 画面左のメニューバーから「ネームサーバーの変更」をクリックします。 ドメイン の選択で ドメイン 名にチェックを入れます。ネームサーバーの選択でその他を選択し、構築した DNS サーバーの FQDN を入力します。 今回であれば「dns1. dns -server-test.work」「dns2. dns -server-test.work」を入力します。(ここで2つ登録できないとエラーになります。) エラー時参考: 【ドメイン】ネームサーバーの変更ができません。|ヘルプサポート | ドメイン取るならお名前.com 「確認」をクリックすれば DNS サーバーの変更は完了です。 ※場合によっては、反映に時間がかかる可能性があります。 目次へ 動作確認 最後に DNS サーバーが正常に動作しているか確認します。 URL入力欄に FQDN を入力します。 成功です。 次は、 コマンドプロンプト から確認してみます。 > nslookup web-test.dns-server-test.work サーバー: ~~~~~~~~ Address: xxx.xxx.xxx.xxx ←自分のIPアドレス 権限のない回答: 名前: web-test.dns-server-test.work Address: xxx.xxx.xxx.xxx ←WebサーバーのIPアドレス Webサーバーの IPアドレス が返ってきていれば成功です。 次は DNS サーバーを直接指定して名前解決ができるか確認します。 まずは、プライマリ DNS サーバーからです。(yyy.~はプライマリ DNS サーバーの IPアドレス を指定) > nslookup web-test.dns-server-test.work yyy.yyy.yyy.yyy サーバー: UnKnown Address: xxx.xxx.xxx.xxx ←自分のIPアドレス 権限のない回答: 名前: web-test.dns-server-test.work Address: xxx.xxx.xxx.xxx ←WebサーバーのIPアドレス 次に、 セカンダリ DNS サーバーです。(zzz.~は セカンダリ DNS サーバーの IPアドレス を指定) > nslookup web-test.dns-server-test.work zzz.zzz.zzz.zzz サーバー: UnKnown Address: xxx.xxx.xxx.xxx ←自分のIPアドレス 権限のない回答: 名前: web-test.dns-server-test.work Address: xxx.xxx.xxx.xxx ←WebサーバーのIPアドレス どちらもWebサーバーの IPアドレス が返ってきていれば成功です。 最後にプライマリ DNS サーバーが停止している状態で確認します。 AWS マネジメントコンソール画面からプライマリ DNS サーバーを停止させておきます。 正常に停止したことを確認したら、次は コマンドプロンプト でコマンドを実行します。 PC内にゾーン情報が残っている可能性があるため、キャッシュを削除します。 > ipconfig /flushdns Windows IP 構成 DNS リゾルバー キャッシュは正常にフラッシュされました。 nslookupコマンドでも確認しておきます。 サーバー: ~~~~~~~~ Address: xxx.xxx.xxx.xxx ←自分のIPアドレス DNS request timed out. timeout was 2 seconds. 権限のない回答: 名前: web-test.dns-server-test.work Address: xxx.xxx.xxx.xxx ←WebサーバーのIPアドレス Webサーバーの IPアドレス が返ってきていれば準備完了です。 キャッシュを削除する以外にも、 Google Public DNS (8.8.8.8)を指定してコマンドを打つことでも確認することができます。 URL入力欄に FQDN を入力します。 成功です。 これにより、プライマリ DNS サーバーが何等かの不具合により停止したとしても、 セカンダリ DNS サーバーが稼働しているためWebページにアクセスすることが可能になっていることがわかります。 目次へ おわりに 長くなってしまいましたが、難しい手順などもなく簡単に DNS サーバーを構築できたのではないでしょうか。普段意識することの無い DNS サーバーについて少しでも知ることができていれば幸いです。 今回学んだことを応用すると、例えば「 DNS サーバーがダウンし目的のWebページにアクセスできないとなった場合( DNS サーバーが応答していません等)、 Windows や Mac の参照先 DNS サーバー( Google Public DNS :8.8.8.8 や OpenDNS:208.67.222.222 等)を変更し、その DNS サーバーを経由させ名前解決を正常に行えるようにすればWebページにアクセスできるようになる」ということが理解できるかと思います。このように、 DNS サーバーについて理解を深めることで、Webサーバーがダウンしてアクセスできないのか、 DNS サーバーがダウンしてアクセスできないのか等の原因の切り分けにも利用できるかと思います。 冒頭で一瞬出ましたが、 AWS にはRoute53という DNS サーバーを簡単に構築することができるサービスがあるので、気になる方は是非調べてみてください。 今回は触れませんでしたが、 DNS サーバーの逆引き設定についても機会があれば紹介したいと思います。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
こんにちは。 株式会社 ラク スで先行技術検証をしたり、ビジネス部門向けに技術情報を提供する取り組みを行っている「技術推進課」という部署に所属している鈴木( @moomooya )です。 ラク スでは有り難いことにサービスが順調に成長しています。今後の成長に対応できるようにするために、継続的な検討課題としてより拡大可能な アーキテクチャ の検討を行っています。 拡大成長可能な ウェブアプリケーション (のバックエンド) アーキテクチャ としてすぐに挙がるのが「 マイクロサービス アーキテクチャ 」だと思いますが、マイクロサービス アーキテクチャ が一般的に議論されるようになったのが2015年頃からだったと思います。それ以来いろいろと考え続け、従来のモノリシック アーキテクチャ 群との間にある アーキテクチャ とイメージがつながってきたのでまとめてみたいと思います。 この記事でそれぞれのバックエンド アーキテクチャ を俯瞰的に比較することで、 ウェブアプリケーション 開発時のヒントになると思います。 各アーキテクチャについて モノリシックアーキテクチャ マイクロサービスアーキテクチャ ミニサービスアーキテクチャ モジュラーモノリス 各アーキテクチャの使い分け マイクロサービスに必要なもの BtoB, BtoCの観点から まとめ 追記 各 アーキテクチャ について 今回比較する各 アーキテクチャ はどれも ウェブアプリケーション のバックエンド アーキテクチャ になります。 昔ながらのモノリシック アーキテクチャ が無秩序でつぎはぎだらけなメンテナンスしにくい ソースコード に陥りやすいという課題感は 1997 年に発表され、 1999 年に Big Ball of Mud という論文で広く認知されるようになりました(参考: 大きな泥だんご - Wikipedia )。 www.laputan.org それから15年後の 2014 年に ThoughtWorks 社の James Lewis 氏と Martin Fowler 氏が自社ブログにて『 マイクロサービス 』を発表しました。 誤解を恐れず言うのであれば発表された「マイクロサービス」の定義内容はコンセプチュアルな内容、言い換えるのであれば「 実用可能ではあるが想定が極端な アーキテクチャ コンセプト 」であったと思います。 martinfowler.com 2014年に発表されてからの数年間、 ITアーキテクト の皆さんはどうやったらプロダクトコードに落とし込むことができるのか理解と解釈を進めたと思います。 そのうち、マイクロサービス アーキテクチャ で想定されてる規模とマッチする ウェブアプリケーション に対してはマイクロサービスが適用され始めましたが、マッチする ウェブアプリケーション の範囲は ITアーキテクト たちが考えていたほど広くはありませんでした。 とはいえマイクロサービス アーキテクチャ のコンセプトは長年求められているものでした。なんとかそのコンセプトを適用することができないかと模索した結果、現実的なアプローチとして 2017 年に Cloud Elements 社の Ross Garrett 氏が自社ブログにて『 ミニサービス:実用的なマイクロサービスアーキテクチャ 』という投稿を公開しています(詳細は更にリンクされているTechTargetの記事)。 これはマイクロサービス アーキテクチャ ほど細かく分割はせずに、利用する技術要素も既存技術でまかなう考え方で、モノリシック アーキテクチャ とマイクロサービス アーキテクチャ の間にある落とし所を探す アーキテクチャ の一つとなりました。 https://blog.cloud-elements.com/pragmatic-microservices-architecture blog.cloud-elements.com といっても、ミニサービス アーキテクチャ も 複数サービスを開発・運用していく という部分では変わりなく、それよりも更に小規模であったり動的なスケールが必要ない ウェブアプリケーション にとっては導入によるデメリットが大きく、積極的に適用出来るわけではありませんでした。 モノリシック アーキテクチャ とミニサービス アーキテクチャ の間に位置づけられる アーキテクチャ として、 2018 年に Root Insurance 社の Dan Manges 氏が自身のブログで『 Railsのアーキテクチャ:モジュラーモノリス 』としてモジュラー モノリス アーキテクチャ を発表しました (2025.5.2追記)モジュラー モノリス の初出はDevNexus2016で基調講演として発表されたSimon Brownによる『 Modular monolith 』のようです 。 これはモノリシック アーキテクチャ をベースに、サービスに分割するのではなくモジュール( Rails なのでgem)に分割していき、最終的には単一の ウェブアプリケーション としてデプロイする アーキテクチャ でした。 medium.com ここまでをまとめると アーキテクチャ が生まれた順序は以下のようになります。 各 アーキテクチャ 間の関係は以下のようになります。 それぞれの アーキテクチャ についてもう少し詳細に見ていきたいと思います。 モノリシック アーキテクチャ デプロイメントラインが1つで、バックエンドサービスが1つの アーキテクチャ 。 デプロイメントラインが1つであることは利点で『 マイクロサービス 』でも立ち上げ時などの速度を重視するタイミングではモノリシックで構築することが推奨されています。 反面、アップデートを重ね規模が大きくなると開発コストが増大するとされていますし、感覚値としてもその通りであるという印象があります。 特に成功したサービスほど急速にアップデートが行われることを考えると、成功した場合にはどこかでリアーキテクトを考える必要があると言えます。ただ……開発エンジニアの想定(というか渇望)よりはモノリシックのままで対応できる範囲は広く、それが判断を難しくしている原因とも思います。 マイクロサービス アーキテクチャ 2014年に提唱されて以来、ノウハウがまとまった書籍が揃ってきました。 まずはサム・ニューマン著『マイクロサービス アーキテクチャ 』を読みましょう。 概要についてはこの本で網羅的に抑えることが出来ます。ちなみに原著の方では第2版がO'reilly Learning Centerで先行リリースされています " Building Microservices, 2nd Edition "。 ※追記 :2022/12/2に第2版の翻訳版が発刊されました 「マイクロサービス アーキテクチャ 」の流行もやや落ち着き、冷静な議論が出来るタイミングが来ていると感じていますが、忘れてはいけないのは提唱者ら自らが「『マイクロサービス アーキテクチャ から始めるべきではない』というのは合理的な議論である。 モノリス から始めて、モジュール構造を保って、 モノリス であることに問題が生じたらマイクロサービスに分割する」と語っていることを忘れてはいけません。 One reasonable argument we've heard is that you shouldn't start with a microservices architecture. Instead begin with a monolith, keep it modular, and split it into microservices once the monolith becomes a problem. " Are Microservices the Future? - Microservices " モノリス からマイクロサービスへの移行パターンについても翻訳本はまだ出ていませんが、"Building Microservices"と同じ著者で" Monolith to Microservies "という本が2019年に出版されています。 と、思ったら2020年12月26日に翻訳本が発刊されるようです! うれしい!! ミニサービス アーキテクチャ マイクロサービス アーキテクチャ は破壊的すぎるとしてミニサービス アーキテクチャ が提唱されています。大きな違いとしては以下があります。 サービス分割単位は機能単位ではなく ドメイン 単位 データストアは必ずしもサービスごとではなく、共有データストアでもOK サービス間通信はpub/subではなく、httpでもOK 調査会社のガートナー社では以下のように図解しています。 出典元: Gartner また私が以前にMicroservices Meetupで発表した資料へのリンクも置いておきます。 モジュラー モノリス マイクロサービス、ミニサービス、とサービスを分割――すなわちデプロイメントラインを複数にする――というアプローチを前提においていましたが、デプロイメントラインが複数になるということは 複数の Webサービス を開発・運用する ということになります。このコストは無視できません(なんせより大きな成功につながる かもしれない 別の Webサービス を展開するのと同等のコストです)。 この問題について1つのデプロイメントラインを維持しつつ、サービス分割をモジュール分割とすることで解決しようとしたアプローチがモジュラー モノリス になります。 2019年に Shopifyが実際に移行した取り組み で話題になりました。Shopifyでは分割後のモジュールとの依存を管理するために Wedge というツールを開発してプロジェクトを進めていたようです(このツールも OSS として公開したいとのこと)。 (2021.1.6追記) Wedge は Packwerk として公開済みとコメントにて教えていただきました。 takahashimさん、ありがとうございます。 shopify.engineering 翻訳記事も見つけました。 qiita.com モジュラー モノリス においてデータストアはどのように扱うのか、という点においてはミニサービスアキテクチャのように共有データストアを利用するケースもあれば、モジュール単位でデータストアを持つ方法も試されているようです。このあたりの話は Mnolith to Microservices(モノリスからマイクロサービスへ) の第1章「必要十分なマイクロサービス」の「 モノリス の課題」や、第4章「データベースを分割する」が参考になると思います。 モジュラー モノリス については弊社の先行技術検証の取り組みである「技術推進プロジェクト」の成果として別途記事にもしているのでご参照ください。 tech-blog.rakus.co.jp 各 アーキテクチャ の使い分け マイクロサービスに必要なもの これまでそれなりの時間をかけて検証を重ねてきましたが、マイクロサービス アーキテクチャ を採用するのは相当にハードルが高いと感じました。 最初に必要となる適切に構成された コンポーネント 群についてはサービス分割を念頭に起きながらサービスの開発・運用を一定期間続けることできれば、 ドメイン 知識の蓄積によりなんとか「適切な構成」を見出すことは出来るかもしれません(「サービス分割を念頭におく」ことが相当に難しいことはともかく)。 スキルレベルの高いエンジニアチーム、具体的には分散システムの開発・運用を実現するためのツール群や設計思想などに精通したエンジニアチームとなりますが、これも一朝一夕では厳しくとも時間をかければなんとか実現出来ると思います。 ただ、それらを揃える労力を「マイクロサービス アーキテクチャ 」を実現するコストとして投入するかというと悩ましいところです。 BtoB, BtoCの観点から ラク スはBtoBでのビジネス展開をしているわけですが、BtoBサービスにおいてはマイクロサービス アーキテクチャ の必要性はそこまで高くないと判断しています。 マイクロサービス アーキテクチャ の旨味である「オートスケールと組み合わせての予想しない負荷への自動対応」だとか「日に何十回もの小刻みな本番環境へのリリース」といったBtoCで求められることは特定多数がユーザーであるBtoBではあまり求められていないです 1 。 とはいえサービスが大きくなったときにモノリシック アーキテクチャ のままであることにもつらさがあるため、 モノリス とマイクロサービスの間のどこかを目指すことになると考えています。 直近では モノリス の状態で、問題が出始めたら"Monolith to Microservices"でも「多くの組織にとって、モジュラー モノリス は優れた選択肢である」と書かれているようにモジュラー モノリス を目指していくことになるのではないかと考えています。 コンテナ オーケストレーション だとか、分散ロギングなどの運用ノウハウが十分に貯まったころに、次いでミニサービス アーキテクチャ が選択肢に入ってくるとイメージしています。 まとめ さて、この数年間で比較されてきた モノリシック アーキテクチャ モジュラー モノリス ミニサービス アーキテクチャ マイクロサービス アーキテクチャ の4つを俯瞰して見渡してみました。 アーキテクチャ 検討の参考になればと思います。 なお、現時点では 2 先述の通り「モジュラー モノリス 」が一番現実解に近いかな……と検証を行っていますが、モノリシック アーキテクチャ に比べるとモジュールとして分離するコストが上乗せされる分高くなります。どの程度の規模で分離しはじめるべきなのか、見極めラインは今後も探っていきたいと思います。 追記 [2020.12.21追記] 今年翻訳本が発刊されたクリス・リチャードソン著『マイクロサービスパターン』もおすすめです。サービス分割に関する部分など、マイクロサービスに限らずミニサービスやモジュラー モノリス にも役に立つ内容が掲載されています。ちなみに元ネタはこの本の著者が運営するウェブサイト Microservices.io です。 microservices.io [2021.1.6追記] コメントにて takahashim さんから「 Wedge は Packwerk として公開済み」と教えていただきました。2020年9月に公開されていたようです。名前が変わっているとは盲点でした。 shopify.engineering エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 https://rakus.hubspotpagebuilder.com/visit_engineer/ rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com 契約しないと利用することが出来ないことと、契約からサービス利用開始までに一定期間があるため直近の負荷予測ができるからオートスケールはいらない。またアナウンスなしでの機能追加なども現状では考えにくく、日に何度もアナウンスされても利用者も困る。 ↩ 2年前はモジュラー モノリス の発想がなかったこともあり、ミニサービスが現実解かと思っていました。しかしデプロイメントラインが複数になるコストは無視できないものでした。 ↩
アバター
はじめに 株式会社 ラク ス 配配メール開発課の PHP エンジニア Jazumaです。 2020年12月12日(土)に PHPカンファレンス が開催されました。 phpcon.php.gr.jp 例年では「 大田区産業プラザ PiO」で開催予定でしたが、今年は 新型コロナウイルス の影響でオンライン開催となりました。個人的にはオンライン開催である分、地方のエンジニアでも気軽に参加することができたのは良かったのではないかと思います。 ラク スは PHPカンファレンス にスポンサーとして参加 させていただいている他、社内からLT枠で2名が登壇しました。 今回は PHPカンファレンス に参加した社内の PHP エンジニアがイベントをレポートしましたので、ご紹介したいと思います。 各セッションのスライドについては以下にまとめましたので、ご活用いただければ幸いです。 No タイトル 1 SPAのAPI開発の「やりづらさ」をDDDとオブジェクト指向の発想で解決する 2 PHPの今とこれから2020 3 PHP WEBアプリケーション設計入門――10年先を見据えて作る 4 レガシープロジェクトで、メタプログラミングを使ったPHPStan静的解析レベル上げ 5 長期運用を目指す『Shadowverse』におけるリファクタ事例の紹介 〜テストの導入とメンバーへの普及法〜 6 PHP on Kubernetes 7 Webサービスをセキュアに保つために必要な視点 8 Composer 2.0 って何?どう変わるの?読んでみました! 9 今こそ理解する、PHPの日時時計 10 PHP8時代のWebアプリケーションフレームワークの話をしよう 11 ウェブセキュリティのありがちな誤解を解説する 12 PHPで作るオンラインカンファレンス向け録画システム 13 静的解析ではじめる負債コード解消 14 レガシーシステムに自動テストを導入する第一歩 SPAの API 開発の「やりづらさ」をDDDと オブジェクト指向 の発想で解決する report by mrym_618 tech.quartetcom.co.jp 現代のSPAでの API 開発には様々な問題があり、その問題に対してどのような解決策があるかについてのセッションでした。 このセッションで話されていた、問題と解決策は以下の通りです。 ロジックの重複 問題:フロントエンドとバックエンドで同じロジックが現れる 解決策:バックエンド側で隠蔽する トランザクション できない 問題:サーバ側の状態が変化することを止められない 解決策:バックエンド側でロジックの隠蔽を行い、 トランザクション はサーバ内で行う この API 、他にどこで使われていたっけ?!問題 問題: API を使い回した結果、その API を削除したくても他に影響が出そうで削除できない 解決策: API もSRP(単一責任の原則)にし、フロントエンドから見て別であれば別の API にする n+1 問題:n+1回のリク エス トを発行してしまう 解決策:n+1を解決できるレイヤー( SQL )に任せる 全ての解決策に共通していることから、バックエンド側に任せられることは任せてしまい、フロントエンド側はフロントエンドのことに集中する。 そして、それぞれが連携し合って開発していくことが大切であると改めて感じる発表でした。 PHP の今とこれから2020 report by richardwagner カンファレンス冒頭を飾ったのは、 PHP がリリースされてからの25年間を俯瞰しつつ、最新のPHP8の新機能にも触れた廣川類さんの基調講演でした。 PHPの今とこれから2020 from Rui Hirokawa www.slideshare.net 前半パートは具体的な数値にふれながら、 PHP が果たしてきた性能向上と規模拡大の実例が紹介されました。 PHP4の時代からこの20年で、実に50倍の性能向上を実現 cファイルベースの総ステップ数は、Python3の40万行、Ruby2の80万行を、PHP8の120万行が大きく凌駕 後半パートではPHP8の変更/改善点と、新機能 JIT における性能向上がわかりやすくまとめられていました。 機械学習 やAIが PHP で書かれるようになる(かも)という将来は、私たちPHPerにとっても心躍る話でした。 PHP WEBアプリケーション設計入門――10年先を見据えて作る report by soachr speakerdeck.com 10年先でも使える設計についてどうあるべきか、という内容で濃い1時間のセッションでした。 冒頭に10年たったら フレームワーク ・技術が変わる というところについて実例を交えて説明されていました。 弊社も10年超えのサービスがありがたいことにいくつもあるのですが、同じように技術が変わって”レガシー”になっておりとても共感する箇所が多かったです。 「10年先を予見するのは難しいので、10年間の変化に対応しうる設計にしておく」というスタンスでお話が展開されており、 設計時に考慮する点としておっしゃっていた以下が開発言語に関わらない考えだと思い、今後の設計フェーズで意識したいと思います。 フレームワーク などの特定技術から一定の距離を保っていく 広く長く使われることを開発当時から意識する レガシープロジェクトで、 メタプログラミング を使ったPHPStan静的解析レベル上げ report by takaram speakerdeck.com 弁護士ドットコムさんで、静的解析ツールPHPStanを導入した際のお話でした。以前こちらのnoteを読み興味を持っていたため、楽しみにしていたセッションのひとつでした。 note.com すでに規模が大きくなっているプロジェクトに途中から静的解析を導入すると、既存コードで大量にエラーが出てその対応に時間が取られる、というような話も聞きます。 その点とても上手く対応されていて、導入時にはLevel 0という最も緩いチェックのみを行い、対象ファイルも無理に全ファイルを対象にはしなかったそうです。 スモールスタートで導入した後、徐々に対象ファイルの拡大・チェックレベル上げを行うために、 メタプログラミング を使って 機械的 にコードの修正を実施していったということでした。 私が担当しているプロダクトもPHPStanのような静的解析ツールは未導入で、プロジェクトの規模や技術負債の状況も今回のお話によく似ていると感じました。そのため、静的解析導入の成功事例を聞けたことはとても勇気づけられるものでした。 ちなみに、このセッションとは別にCIでの静的解析についてのセッションもあり、そちらもとても面白かったです。 speakerdeck.com 長期運用を目指す『Shadowverse』におけるリファクタ事例の紹介 〜テストの導入とメンバーへの普及法〜 report by YS https://fortee.jp/phpcon-2020/proposal/ab40d17d-37e7-42af-8a88-188a61c6745b スライドは後日、ブログにアップ予定とのこと Cygames Engineers' Blog tech.cygames.co.jp ソーシャルゲーム 「Shadowverse」を5年間アップデートしてきたことにより「コードの可読性低下」「コードの属人化」等の課題が発生し、 現状だと長期運用が厳しい状態になり安定した リファクタリング を進めるために テスト導入チームを立ち上げ、テストコード等を導入し改善を行ったという内容について語ってくださいました。 テストコード等の施策を取り入れた後、 リファクタリング を行ったことにより、 リファクタリング 後の不具合は、 デバッグ 時に1件のみ発生という素晴らしい成果を得たそうです。 メンバーへの普及方法は、「環境導入」「テスト作成」「自動テスト実行」各作業でのハードルを下げることが重要で、次の様な施策を上げてくださっておりました。 ・「環境導入」のハードル  手順書やツールの充実 ・「テスト作成」のハードル  テストコードのレビュー等による学習機会の提供 ・「自動テスト実行」のハードル  CIツールによる自動テスト実行と結果の通知等 システムの改修を安定して進めるためには、こちらのセッションで上げてくださった取り組みは とても重要な物であると認識しているため、今後の開発で参考にさせていただきます。 徳丸皆伝を狙いませんか?徳丸実務試験とPHP8上級試験の解説 report by kuwa_38 ( track2 2:25ほどから) セッション概要: 吉政さんからPHP8上級試験と徳丸実務試験の概要説明、それから特典( PHP マグ カップ と PHP 本、徳丸本)が紹介されました。 その後、徳丸さんから徳丸実務試験の例題3問とその解説が行われました。 例題の概要: 1問目:特定サイトから利用するウェブ API のテスト中にCORSのエラーがでた。どう解消すべきか(4択から1つ選択) 2問目:提示された PHP の スクリプト のうち発生する 脆弱性 を全て示せ (4択から複数回答) 3問目: XSS脆弱性 のある JSONP による API の PHP ソースコード が提示され、対策として不適切なものを1つ選択(4択から1つ選択) 視聴後の所感: 私の視聴した動機が「どんな問題が出題されるか」だったこともあり、特に例題とその解説はとても興味深かったです。また、図解や選択肢1つ1つの解説もありとても分かりやすかったと思います。 問題と解説自体は10分強なので、セキュリティに興味や関わりがある方は、ぜひ アーカイブ をご覧頂ければと思います。 PHP on Kubernetes report by Jazuma chatwork所属Kouta Ozakiさん(@k_kinzal)のセッションのレポートです。 ※このレポートで使用している画像は全てOzakiさんの発表資料 の引用です。また、資料の利用にあたってはご本人の許可を得ています。 speakerdeck.com セッション内容まとめ・感想 k8s で PHP は普通に動く PHP が他の技術と比べて特段 k8s との相性が悪いということはなく、正しく導入すれば特に問題なく稼働するようです。 k8s の学習コストは高い VM やServerlessと比較して k8s の学習コストは高いようです。そのため何のために k8s を導入するのか決めずに無計画に取り入れようとしても意味がなく、逆に 工数 をとられるだけの結果になります。他の技術と同様に k8s はあらゆる問題を立ちどころに解決する 銀の弾丸 ではないようですね。 PHP アプリケーションのコンテナ化 PHP アプリのコンテナ化にあたってはアプリの設定をどのようにコンテナに反映させるのかが問題になります。 開発環境としての k8s k8s の開発環境としてのパフォーマンスを Vagrant やdocker-composeと比較すると上記のようになるようです。 個人的には開発環境として使うのであればどれも大差はないように思いました。 k8s の学習コストをどのように支払うのか 私がOzakiさんに「chatworkさんでは k8s を使うにあたってスイッチングコストや学習コストをどのように賄ったのか」と質問したところ以下のようにお答えいただきました。 全社的に k8s の導入に前向きだった SREチーム3名が尽力した 開発チームも巻き込んで何とかした このことから k8s を導入するには次のような要素が重要だと思いました。 新技術導入に前向きな姿勢 コンテナや クラウド に精通したSREチーム 開発チームと運用チームとの連携・協力 特に開発と運用の協力についてはあらゆる企業・チームが重視すべき要素のように思います。 Webサービス をセキュアに保つために必要な視点 report by tsudachantan fortee.jp speakerdeck.com Webサービス をセキュアに保つための観点、具体的な思考法、攻撃事例、対策のための指針についての話でした。 セキュリティを学び始めたばかりの初心者にもわかりやすい内容でした。 セキュリティ初心者にもとてもわかりやすい。視点の話。 #phpcon #phpcon2020 #track3 — さりー@Webエンジニア (@Sally_42) December 12, 2020 セキュアな状態とは何か、それはユーザが安心安全だと感じる状態である。では安心安全な状態とは?逆に、安心安全でない状態とは何か? と順を追って 言語化 されていてとてもわかりやすかったです。 ユーザだけでなく、開発現場のITエンジニアに置き換えても頷けるような汎用性のある内容でした。 30分で再認証させるのは安全性を高めるけど、 ユーザーの利便性をかなり下げる気がする。 #phpcon #phpcon2020 #track3 — Fumito Mizuno 📕 #のベルズ (@ounziw) December 12, 2020 具体例を示しての掘り下げも行われ、セキュリティとユーザの利便性との兼ね合いについても触れられていました。 ユーザフレンドリーと一口に言っても、ユーザにとって「セキュアで優しい」とユーザにとって「使いやすくて優しい」を両立させることの難しさを感じました。 個人的に、セキュリティ負債の解消としてユーザの リテラシー の平均を議論するという話が、今まで無かった視点だったので興味深かったです。 フレームワーク や攻撃事例も紹介され、濃い内容の1時間でした。当日のスライドも公開されているので、ぜひご覧ください。 Composer 2.0 って何?どう変わるの?読んでみました! report by MasaKu speakerdeck.com v2 の新機能についてのお話と v1 からどのような部分が変わったのかというお話。 CakePHP のプロジェクト作成を v1 と v2 で比較して実演してくださったが、結果 v2 の場合、約半分以下の時間でプロジェクト作成が完了していたのが印象的でした。 また、メモリ使用量も劇的に削減されておりました。 メモリ削減の理由 v1 の場合は、composerの依存関係を解決する際に、packagist からパッケージの一覧を取得してメモリ上に配置する ファイルには ハッシュ値 を記録しておき、再度、composer を実行した場合は、 ハッシュ値 をもとに古くなっている場合は再取得するという流れになっている 一方、v2の場合はパッケージのリストを取得するという処理は行っていない packages, json に定義されたmetadata-url というフィールドから対象の メタデータ を取得する。 そのため、余計な処理が走らないようになっている。 この仕組みを lazy provider といって、先にリストをすべて読みこまなくても良くなったため高速化およびメモリの削減が実現できた模様。 その他にもissue や過去のリリース情報を見ると勉強になることがあるため、興味がある人はぜひ見たほうがよいとのことでした。 今まで当たり前に行っていたことを根本的に見直すことで、劇的に改善できることを体現した勇気づけられる発表だと思いました! 今こそ理解する、 PHP の日時時計 report by nr_1228 speakerdeck.com 基本的な日付関数の説明を踏まえ、DateTimeクラスとDateTimeImmutableクラスの比較など、 PHP の日付計算はどうするのがベストなのかというお話でした。 日付を取り扱うにあたってのトラップなども紹介されており、 自分がハマったことのあるトラップに関しては画面の前で大きく頷いてしまいました。 日時計 算のコードは頻繁に書くわけではないので、忘れたころにやってくることが多いです。 故にまとめる時間をなかなか取れずにいたので、今回のセッションを聞くことで考える時間を纏って取ることができてとても良かったです。 日付に関して調べたことがあるという人はぜひ アーカイブ を視聴してみてください。 PHP8時代のWebアプリケーション フレームワーク の話をしよう report by Y-Kanoh HTTPリク エス トを入力とし、HTTPレスポンスを返す仕組みである、Webフレームワークの内部の作りに、PHP8の新機能がどう利用できるかを解説したセッションでした。 Constructor Property Promotion や、Attributes など、PHP8では フレームワーク の内部で活用できそうな機能が増えて、Webアプロケーションを考えるための下地がさらに整ったと言えますので、今後はこれらの機能を用いた フレームワーク が増えることでしょう。 また、最近ではデプロイ先の選択肢も増えているため、これらの新しく開発される フレームワーク には、これらの環境へのデプロイを簡易にしてくれる機能が期待されます。 近年のフロントエンドとバックエンドを切り離す動きから、 フレームワーク にはシステムのつなぎ目をうまく作る、 API ファーストな考え方が求められており、 API 仕様から仕組みを決めてしまう方法や、サーバサイドもJS/TSで書いてしまう方法、フロントエンドもバックエンドと同じ言語で書いてしまう方法など、 システム間をスムーズにつなぐための方法も紹介されていました。 speakerdeck.com PHP8の目玉機能の一つである Attributes は、 フレームワーク やライブラリの開発に向けた機能だと考えられるため、今後どのように活用され、我々が利用することになるのかは気になるところです。 また、Webを取り巻く環境の変化やトレンドも、今後どのように フレームワーク を変えていくのか、これから開発される フレームワーク に期待が持てる発表でした。 ウェブセキュリティのありがちな誤解を解説する report by richardwagner ウェブセキュリティに関してともすれば誤解されがちな10のポイントに関する、具体的な例が満載の非常に役に立つ基調講演でした。 ウェブセキュリティのありがちな誤解を解説する from Hiroshi Tokumaru www2.slideshare.net Cookie についての誤解はエンジニアならぜひとも押さえておきたい内容でしたが、 それに加えてクレジットカードをサイト保存せず都度入力することのリスクや、 Google 検索上位サイトへの盲目的信頼への警鐘など、 エンジニアに限らず一般の方々にもぜひ参考にしていただきたい内容が目白押しでした。 個人的にも、非エンジニアの家族や友人にも紹介しようと思ったスライドでした。 そして書籍でいつもお世話になっている徳丸浩さんの、落ち着いた大学講義のような語り口はとても聞きやすく、あっという間の1時間でした。 PHP で作るオンラインカンファレンス向け録画システム report by id:radiocat speakerdeck.com 今回の PHPカンファレンス はTrack1だけが ライブ配信 でそれ以外は録画配信となっていますが、この録画配信システムは PHP (CakePHP3)で構築されいるとのことです。もともとはiOSDC Japan 2020で構築した仕組みを今回も取り入れているようです。iOSDCでのエピソードは Podcast の PHP の現場でも話されていました。 php-genba.shin1x1.com 録画はZoomと Youtube Liveの API を使って全て自動化 動画編集は様々なツールやサービスを組み合わせて PHP のコードで腕力解決 「すごいシステムを作るのに必ずしもすごいことをする必要はない」と仰っていたのが印象的でした。 API の仕様をしっかり把握してそれを駆使する。それ以外は必要な環境+ PHP の腕力で地道に実現する。いずれもエンジニアリングの本質だと再認識したセッションです。 PHPカンファレンス 大LT大会 report by id:radiocat 大LT大会では16名の登壇者が次々とライトニング トーク されました。ここでは弊社から登壇した2名のスライドをご紹介させてください。 静的解析ではじめる負債コード解消 speakerdeck.com PhpStormのInspectionを使って負債コードを特定する方法をご紹介しました。Inspectionを使いながら開発を進めることで、 プログラマ は自分が担当している開発の範囲で負債コードを検知して少しずつ技術的負債を減らしていくことができています。 レガシーシステム に自動テストを導入する第一歩 speakerdeck.com 10年以上前にサービス開始したレガシープロダクトに PHPUnit を使った テスト駆動開発 を導入した話です。従来から存在する機能を API 化するタイミングで、まず既存機能のテストを作成してから API 化することで仕様変更に強い テスト駆動開発 の効果を実感することができました。 おわりに PHPカンファレンス では PHP の基礎から最新技術の導入事例まで幅広いテーマが扱われていました。 皆さんも今回紹介したイベントレポートやセッションの内容をぜひご自身のお仕事に取り入れてみてはいかがでしょうか。 弊社はオンラインで勉強会を開催しています。 PHP がテーマの勉強会もありますのでぜひご参加ください。 rakus.connpass.com 直近で開催されたLaravel/PHP8/Dockerをテーマとした勉強会にはのべ200人近くの方にご参加いただきました。 rakus.connpass.com エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
はじめに 皆さん、こんにちは。技術広報のitoken1013です。 今回は先日12/12(土)に開催の Developers Boost 2020 (デブスト)に参加してまいりましたので、当日の様子をお伝えできればと思います! 今回は ラク スも協賛の機会をいただき、ゴールドスポンサーとしてイベントに参加させていただいておりました! event.shoeisha.jp イベントの概要 30歳以下限定の若手エンジニアが登壇する人気イベントとして、毎年開催されていますデブスト。 今年のテーマは 『Share your ENGINE~ひとりじゃない~』 でした。 新型コロナウイルス の影響によって変化を余儀なくされた市場下において、エンジニアとしてのキャリアや スキルアップ をどう広げていくかを募るイベントテーマでした。 今年の大きな特徴として、初のオンライン形式での開催となりました。 セッションには計17名の登壇者が参加の上、会場もしくはZoom配信の形式で専用プラットフォームから配信をいただく形式でした。セッション終了後にはEventInというオンラインイベントツール上で質疑応答が行われ、オフラインと遜色ない距離感で登壇者と参加者が会話できる空間が醸成されていたと感じています。 Twitter でも #devboost 上から当日の賑やかな様子を感じ取ることができます。 従来のオフラインイベントと異なり、参加者の様子が見えない点は登壇者の方には不便だったかもしれません。ただ登壇者の皆様はその影響を感じさせず、どなたもスムーズに進行されていた点は流石だなと思いました。 若きとても優秀な登壇者の皆様、お疲れ様でした! ちなみにこの記事を書いている私はとっくに30歳以上なのですが、スポンサー特典として頂戴しましたチケットで皆様のご活躍を拝見しつつ、EventInのスポンサーブースで ラク スの紹介をさせていただきました。 セッションのご紹介 それではここからセッションのご紹介です。 個人的に特に印象に残りましたセッションを抜粋して紹介させていただきます。 古の大企業向け パッケージソフト の クラウド 移行にJoinして見えた面白さ リリースから24年の歴史を持つCOMPANYの クラウド 移行に関わったエピソードと共に、SREチーム所属の増井さんのキャリア展望を語っていただきました。 1100社が利用中の巨大サービスを AWS 移行ということで大きな挑戦でしたが、ご自身のキャリアを広げる挑戦の舞台として活用されていた点は非常にポジティブに映りました。 またSlackを活用した新しいサービスのインプット方法は私も非常に参考になりました。 世間では一見ネガティブな意味で捉えられがちなレガシーサービスとの関わりについても「オンプレ → クラウド 移行は エンタープライズ 領域で多数あり、これから求められる知識を先取りできる」とポジティブに転換できており、歴史の深さでは負けていない ラク スでも増井さんの思考はとても参考になる貴重なお話だったと感じています。 コミュニティ活動で差別化をめざすエンジニアとしての一手 t.co 弊社エンジニアとしてコミュニティ運営で主導的な役割を果たす加納の登壇です。 他の方のセッションとの違いとして、リアルタイムにアンケートを募る インタラクティブ なセッションを実施しました。 先ほどの発表で行っていたアンケートの結果です。 協力していただいた方、ありがとうございました! https://t.co/bV0gKh7WJj #devboost pic.twitter.com/3ynQkwUfMt — Y-Kanoh (@YKanoh65) 2020年12月12日 コミュニティ活動には自身・組織・キャリアの3側面におけるメリットが存在し、技術面以外のキャリアの差別化としてコミュニティの運営は大いに役立ちます。 コミュニティ活動で得られる学びと喜びを、これまで運営を体現してきた加納の資料から知っていただければと思います。 技術が好きで好きで好きでたまらないエンジニアが「取締役」になって思う、マネジメント キャリアパス 新卒でいきなりPMを任された小笠原さんより、 CDO (Chief Development Officer)になるまでの6年間におけるキャリアの中でのマネジメント論を語っていただきました。 最初は失敗だらけだったマネジメントも周囲の方の助けを借りながら、エンジニア、PdM、VPoEとキャリアを積むうちに徐々に時間の使い方を上達していったお話でした。 これまで非常に高いハードルで苦しいシーンも経験してきたのではと思うのですが、それでも同じ世代のエンジニアに対して「経営/マネジメント視点は最強装備、マネジメントは武器になる。興味があれば手を挙げてみよう。」と投げかける姿は印象的でした。 20代に関わらず、マネジメントで成長したい全ての世代に聞いていただきたい内容でした。 アウトプット駆動キャリア 学びをアウトプットすることの価値とその方法論について、ご自身も出版やコミュニティ運営に携わる土田さんにお話いただきました。 「アウトプット駆動」という言葉自体は耳慣れた方もいらっしゃるのでは思いますが、周囲と差別化するための具体的な方法については、深くご存知ではない方が多いのではと思います。 土田さんは「キャリアはアウトプットの積み重ね」と述べつつ、以下の3点からアウトプットのテーマを見つける方法を教えて下さいました。 自分の興味関心 世界のトレンド 日本の現状 一見ハードルの高いアウトプットについても、気になるニュースを リツイート するところからなど、スモールスタートをとることを薦めています。 今回のセッションに感化され、さっそくアウトプットを開始する方が増えたのではないかと思います。 職能横断型 スクラム 体制になってからのチーム改善活動 speakerdeck.com これまでバックエンド、フロンエンド、デザイナーなどの職能単位のチーム体制から、職能横断型のプロジェクト単位のチームへ転換した際に起こった課題と施策エピソードを語っていただきました。 タックマンモデルにおける形成期と混乱期ではそれまでの暗黙的なルールや慣習が通用しなくなり、どうすればより生産性が上がるかの試行錯誤が必要となります。登壇者の藤井さんが所属するストアーズ・ドット・ジェーピー様では直面した3つの課題に対し、施策を打ち出していきました。 どの課題も特に自社サービス開発の企業であれば、直面する可能性があるものではないかと感じています。また課題を「課題である」と認識するにもメンバーによってバラつきがあり、藤井さんが仰る通り、泥臭くても課題を出し続けるための場作りが重要だなと感じました。 組織運営をする上で非常に参考となるセッションでした。 Hello, World! 外 国語学 部英語学科系エンジニア 爆誕 までの軌跡 文系エンジニアが描くべき キャリアパス として、「掛け算式キャリア形成」を語っていただきました。 スタート時点で文系エンジニアは技術スキルが劣るものの、最初に訪れる技術の壁を乗り越えた先には能力的にバランスのいい人材となる。そして技術以外の得意領域と掛け合わせることで、レアな人材になる可能性を秘めているとのことでした。 登壇者の関本さんも未経験からスタートし数々の傷を負ってきましたが(面白かったです)、現在は英語とコミュニケーション能力を組み合わせたテッ クリード を目指しているとのことです。現在進行形で苦しんでいる日本中の文系エンジニアの方に勇気を与えるセッションだったと思います。 関本さんならきっと優秀なテッ クリード になれると思います! 凡人エンジニアの 生存戦略 t.co 1~2年目頃の若手エンジニアなら誰しもが思ったことのある将来への不安に冷静に向き合い、髙市さんがどのように成長していかれたのかを語っていただきました。 世間で注目を集めるような「楽しくて仕方がない、いつまでもやっていられる」というエンジニアとは距離感を感じて働かれていた髙市さんですが、 まつもとゆきひろ さんの勉強会で学んだエピソードや人間の特性を把握した上での取り組みにより、精神的な安定と自信を得ていきました。 中でも個人的には「個人で定期的なふりかえりを行う」が効果的な取り組みなのかなと感じています。 ただ漠然と不安を感じながら働くのではなく、意識的にアクションを打っていけば自然と解消できるんだなと学ばせていただきました。今回のデブストのイベントテーマである「ひとりじゃない」を感じさせていただける良い内容だったと思います。 不確定要素が強い時代の 生存戦略 ― U30が「好きなコト」で突き抜けるためには!? t.co ラストは Microsoft MVP でいらっしゃる堀尾さんによる、「好きなコト」で圧倒的に成長していくための戦略です。 堀尾さんがMixed Realityという分野を見つけ、どのようにMixed Realityにおける スペシャ リストになったかが語られています。 不確定要素が非常に多い現代だからこそ、自分がありたい姿(Being)の 言語化 とアウトプットはキャリアを突き詰める上で非常に重要だと感じました。 非常に熱い内容で、終盤の疲れを吹き飛ばしてくれる内容でした! おわりに 登壇された若手エンジニアの方々、あらためて今回はお疲れ様でした。 お恥ずかしながら私は今回が初のデブスト参加だったのですが、熱のこもった登壇を拝見させていただき、若手エンジニアにとって貴重な価値あるイベントと感じることができました。 また、このような場に立つ方であっても若い頃の自分と同じ悩みを抱えている方もいらっしゃり、イベントテーマである「ひとりじゃない」という共感を生むシーンも多かったのではないかと思います。 今回は初のオンライン開催にも関わらず、柔軟な開催形式によって無事にイベントが成功したと言えるのではと思います。 来年度がどのような形で開催されるかはまだ分かりませんが、オフライン・オンラインの両方を取り入れることによって日本全国から参加可能な大型カンファレンスに…ということも十分可能かとイメージしています。 ますます進化するデブストの今後にとても期待しています!
アバター
はじめに こんにちは ラク ス開発エンジニアのhyoshです。 激動の2020年も残りわずかとなる中、皆様はいかがお過ごしでしょうか。 今回は私が自作の Chrome 拡張機能 を用いて業務を効率化した方法についてご紹介させていただきます。 同じような課題に悩んでいる方のお力となれば幸いです。 はじめに 起きていた問題 どうやって解消したか Chrome拡張機能とは? 環境構築 必要知識 サンプル manifestファイルを作成する その他ファイルを作成する ブラウザに取り込む おわりに 起きていた問題 まだ私が他社に所属していた時の話ですが、エンジニアが本番作業を行う際にはWEBフォームから申請を行い、承認をもらってから行うというルールとなっていました。 ただこの申請において入力ミスが非常に多く、それに伴う差し戻しの煩雑さが日々ボディブローのように業務を侵食していました。 どうやって解消したか そもそも入力者自身が気づけないのが問題で、このページに入力チェックがあれば防げるんだけどなぁ…と思っていた時に行き着いたのが Chrome 拡張機能 でした。 そして結果的にチームオリジナルの入力チェックを行う 拡張機能 を自作した事で入力者によるミスをほぼゼロにすることができました。 Chrome 拡張機能 とは? Chrome 拡張機能 とは Chrome 内で利用できるアドオンであり、 ウェブストア からブラウザに追加する事で誰でも利用ができます。 非常に種類が豊富なので利用している方も多いかと思いますが、実は 簡単に自作 する事もできます。 以降は具体的な実装方法に関してご説明させていただきます。 環境構築 開発に必要な物は以下2つだけ。 Google Chrome お好みのエディタ つまり目の前のPCに Chrome さえ入っていればすぐに開発を始められます。この敷居の低さも魅力ですね。 必要知識 Chrome 拡張機能 の実体は JavaScript 、HTML、 CSS といった要素です。なのでこの辺りの基本知識があれば開発は可能です。 サンプル ここからは実際に作って動かすまでをやってみたいと思います。 公式ページにもちゃんとした チュートリアル があるのですが、ここではより簡単なDOM操作を行うだけの 拡張機能 を作ってみたいと思います。 もしこの記事で興味が湧きましたら、ぜひ下記 チュートリアル もお試しください。 developer.chrome.com manifestファイルを作成する manifest. json は 拡張機能 に関する定義を管理する心臓部となるファイルであり、必ず用意する必要があります。 { " name ": " オリジナル入力チェック ", " version ": " 1.0 ", " description ": " 必須チェックを追加する。 ", " content_scripts ": [ { " matches ": [ " http://*/tutrial/testhtml/ " ] , " js ": [ " jquery-3.5.1.min.js ", " content.js " ] } ] , " icons ": { " 48 ": " icon.png " } , " manifest_version ": 2 } name 拡張機能 の名前です。特に機能に影響はないので任意で構いません。 拡張機能 の管理画面や公開する場合はストアの機能名として使われます。 version 機能のバージョンです。公開する場合は自動更新に関わるので重要ですが、内部利用であれば任意で構いません。 manifest_version manifestファイル自体のバージョンですが現時点で「2」固定です。 ※ここまでが必須の項目で後は用途に応じて足していきます。 description 機能の説明です。 拡張機能 の管理画面や公開する場合はストアでの説明として使われます。 content_scripts js 今回のようにDOM操作を行う場合、使用するjsファイルを記載します。複数記載可能です。 matches スクリプト を適用させたいURLを記載します。複数記載可能で ワイルドカード も使用可能です。例えば全ページに適用させたい場合は「 http://* 」とします。 icons 拡張機能 のアイコンとなる画像を指定します。サイズ別で16、48、128が指定できストアやファビコンなど異なる用途で使われますが、今回は48だけで十分です。 以上、今回必要なmanifestファイルの構造に関してご説明させていただきましたが、他項目の解説は公式サイトが詳しいのでご参照ください。 developer.chrome.com その他ファイルを作成する manifest. json で定義した JavaScript を作成します。今回はボタン押下時に名前が空欄の場合にアラートを出し、背景色を変えるようにします。 $( function () { console.log( "コンテントスクリプト開始" ); $( "#btn" ).on( "click" , function () { const name = $( "#name" ).text(); if (name == "" ) { alert ( "名前を入力してください" ); $( "#name" ).attr( "style" , "background-color: #FFAAFF;" ); } } ); } ); また 拡張機能 ではないですが入力チェックしたい仮想ページとして以下を用意しています。 <!DOCTYPE html> < html > < head > < meta charset = "utf-8" /> < meta http-equiv = "X-UA-Compatible" content = "IE=edge" /> < title > Page Title </ title > < meta name = "viewport" content = "width=device-width, initial-scale=1" /> < style > ul { list-style : none ; padding : 0 ; margin : 0 ; } li + li { margin-top : 1em ; } label { display : inline-block ; width : 90px ; text-align : right ; } .button { padding-left : 90px ; } button { margin-left : 0.5em ; } </ style > </ head > < body > < ul > < li > < div > 入力チェックを足してみる </ div > </ li > < li > < label for = "name" > 名前: </ label > < input type = "text" id = "name" name = "user_name" /> </ li > < li > < label for = "addr" > 住所: </ label > < input type = "text" id = "addr" name = "user_addr" /> </ li > < li class = "button" > < button id = "btn" type = "submit" > 送信 </ button > </ li > </ ul > </ body > </ html > これで必要な準備は全て終わりました。フォルダ構成としては以下のような状態となり、これが一つの 拡張機能 の単位となります。 sample ├─manifest.json ├─content.js ├─jquery-3.5.1.min.js └─icon.png ブラウザに取り込む いよいよ作成した 拡張機能 をブラウザに取り込みます。といってもこれも非常に簡単です。 chrome ://extensions/を開き( ツールバー のアイコンでも開けます)右上の デベロッパ ーモードをオンにします。 「パッケージ化されていない 拡張機能 を読み込む」を選択し作成した 拡張機能 のフォルダを指定します。 これで作成した 拡張機能 が取り込まれました。 試しに仮想ページを開いてみるとURLがマッチしたため 拡張機能 が活性化し( ツールバー のアイコンに色がつく)、期待通りの動作をする事が確認できるかと思います。 ちなみに本体が JavaScript なのでブラウザの デベロッパ ーツールで デバッグ もできますし、何かしら修正した場合は再度取り込まなくても管理画面の更新ボタンから更新ができます。 また配布に関しては公開する場合は審査等が必要になりますが、組織内で使う場合はフォルダを各自で取り込む事で実現可能です。 おわりに 今回は Chrome 拡張機能 でも最もシンプルな特定ページのDOMを操作する方法をご説明させていただきました。 基礎的な内容にはなりますが私が行ったようにこれだけでも業務効率化に繋げる事も可能ですし、今回は割愛しましたが公式 チュートリアル にあるようなバックグラウンド処理や外部通信を活用する事でより幅広い用途に応用する事が可能です。 繰り返しにはなってしまいますがお手軽に始められるのが何より魅力なので、ブラウザベースでの課題が生じた際には選択肢としてぜひご検討いただければと思います。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
こんにちは、株式会社 ラク スで先行技術検証を行っている技術推進課のt_okkanです。 技術推進課では、新サービス立ち上げ時の開発速度アップを目的に、現在 ラク スでは採用されていない新しい技術の検証を行う、技術推進プロジェクトがあります。 今回はその技術推進プロジェクトで、モバイル クロスプラットフォーム について検証を行いましたので、その結果の報告を行います。 なお、別テーマの取り組みや、過去の取り組みに関しては、こちらからご覧ください。 tech-blog.rakus.co.jp モバイルクロスプラットフォーム 検証の目的 検証で使用したツール 省力化の定義 検証方法 検証結果 実装できなかった機能 NFC WebView クロスプラットフォームは開発を省力化できるか ライブラリについて 各フレームワークの所感 Ionic Framework 長所 短所 React Native 長所 短所 Flutter 長所 短所 フレームワークの選定基準 機能数 WebView スキル まとめ 参考 書籍 ブログ記事 公式ドキュメント モバイル クロスプラットフォーム 従来のモバイル アプリ開発 では、 iOS はSwiftやObjectiveCで、 Android は Java やKotlinで、各OSごとに別々の プログラミング言語 を用いて開発する必要がありました。 しかし、各OSごとに開発・テストするコストや、学習コストが高いことから、1つの ソースコード で異なるOS上でも同じ仕様、機能のアプリケーションを開発できるモバイル クロスプラットフォーム が開発されるようになりました。 現在、さまざまなモバイル クロスプラットフォーム の フレームワーク が存在しますが、大きく分けて3つに分類できます。 ハイブリット型 WebView上で動作し、HTML、 CSS 、 JavaScript で実装できる。Cordova、Ionic Framework、 Monaca など。 ネイティブ型 OSの描画エンジンを利用してUIを表示する。Xamarin、React Nativeなど。 独自レンダラー型 各OS上で動作する独自の レンダリング エンジンを利用してアプリを実行する。Flutter、Unityなど。 検証の目的 現在 ラクスのサービス の主軸は、ブラウザ上で動作する Webサービス です。 今後、既存のサービスのモバイルアプリへの移行や、新規サービスでのモバイル アプリ開発 があった場合、モバイル アプリ開発 にかかる 工数 を削減し開発の省力化を実現していきたいと思っています。 そのため、低コストでモバイル開発できる手法として、モバイル クロスプラットフォーム での開発を検討する必要があります。 そこで、本検証では クロスプラットフォーム でのモバイル開発がネイティブでのモバイル開発に比べ開発を省力化できるか、また省力化できる場合はどのツールを検討すべきかを示します。 Webサービス を主軸に置く企業の開発者の方にとって、 クロスプラットフォーム での開発を導入する上でのヒントになればと思います。 検証で使用したツール 本検証では、モバイル クロスプラットフォーム の各分類から フレームワーク を1つずつ選択し検証を行います。選択した フレームワーク はIonic Framework、React Native、Flutterになります。 Ionic Framework WebView上でWebアプリ(Angular、React、Vue)を実行する フレームワーク 。UI コンポーネント を提供し、ネイティブへのアクセスはCordovaやIonic社が開発しているCapacitorを利用して JavaScript とブリッジしている。 React Native JavaScriptEngine上でReactが実行される、ネイティブ型の フレームワーク 。Brideという機能を利用して、 JavaScript のコードから各OSに対応したUIやネイティブ API の実行を行っている。 Flutter Google が2018年にリリースした、独自レンダラ型の フレームワーク 。 Dart という プログラミング言語 で実装でき、各OS上で動作する Dart VM が画面の描画を行う。豊富なUIウィジェットが提供されており、ネイティブ機能へのアクセスは Dart のコードをネイティブコードに コンパイル して実行する。 省力化の定義 「 Webサービス 開発企業がモバイル開発を行う場合」という前提で、「省力化」の定義を立てました。 ※ネイティブ: iOS と Android のこと。開発言語はSwiftとKotlin ネイティブと同じ開発環境が整っていること ネイティブより学習コストが低い ネイティブより実装時間、コード量を削減できる ネイティブと同じ機能を実装できる クロスプラットフォーム での開発が上記の省力化の定義を満たせるのかを検証していきます。 検証方法 ネイティブ言語(Swift + Kotlin)と クロスプラットフォーム の各 フレームワーク (Ionic Framework + React Native + Flutter)で、同一の機能のサンプルアプリを実装し、その実装結果を比較しました。 以下のような実装した機能と比較した観点で比較し、省力化の定義を満たせているかを考察しました。 実装した機能 ローカルデータベース セキュアストレージ NFC カメラ Push通知 WebView 比較観点 比較観点 詳細 評価指標 比較対象 開発環境 エディター ◯:ネイティブと同等 △:ネイティブより劣っている ✖️:環境が提供されていない iOS : Xcode Android : Android Studio デバッグ ツール デザインツール ライブラリ評価機構 学習コスト プログラミング言語 ◯:ネイティブ1言語より低い △:ネイティブ1言語と同等 ✖️:ネイティブ1言語より高い iOS :Swift Android :Kotlin ライフサイクル 機能実装 実装時間 ◯:ネイティブより低い △:ネイティブと同等 ✖️:ネイティブより高い ネイティブの実装時間・コード量 コード量 機能実現 ◯:同じ機能を実装できる △:一部実装できない ✖️:全く実装できない iOS :Swift Android :Kotlin 検証結果 サンプルサプリを実装し、比較した結果は以下の通りです。 ※FE経験:Angular、React、Vueの経験があるフロントエンド経験者 ※BE経験: Java などの オブジェクト指向 プログラミングの経験のあるバックエンド経験者 ※実装時間・コード量に関しては本検証での数字です ※コード量は実装した行数と単語数から算出しました 比較観点 Ionic Framework React Native Flutter エディター ◯ Visual Studio Code ◯ Visual Studio Code ◯ Visual Studio Code Android Studio デバッグ ツール △ ブラウザDev Tools ◯ React Native DevTools ◯ Flutter Dev Tools デザインツール △ ブラウザDev Tools Hot reload △ ブラウザDev Tools Hot reload ライブラリ評価機構 ✖️ △ React Native Directory ◯ pub.dev プログラミング言語 学習コスト FE経験:◯ BE経験:△ TypeScript、 JavaScript 、Angular、React、Vue FE経験:◯ BE経験:△ TypeScript、 JavaScript 、React FE経験:△ BE経験:◯ Dart ライフサイクル学習コスト FE経験:◯ BE経験:△ Angular、React、Vue FE経験:◯ BE経験:△ React FE経験:△ BE経験:△ Flutter 実装時間 ◯ -46% ◯ -46% ◯ -67% コード量 ◯ -30% ◯ -25% ◯ -45% 機能実現 △ NFC 、WebView △ NFC ◯ 実装できなかった機能 NFC Ionic FrameworkとReact Nativeで、 iOS でType-Fの ICカード を読み込むことができなかった。 今回 Icoca を ICカード で使用し読み込みを実装したが、使用したライブラリがNDEFフォーマット以外のフォーマットに対応していなかったため、実装することができなかった。 Suica や Icoca などの Felica Standardのフォーマットに対応したライブラリを調査したが、見つけることができませんでした。 WebView Ionic Frameworkで、WebViewを実装することができなかった。Ionic Frameworkはアプリ起動時に作成されるWebView上で実行されているため、Ionic Frameworkから起動されているWebView以外のWebViewを作成することができません。 Ionic Framework上にOS内蔵ブラウザを表示してWebページを描画できますが、WebViewと比べると機能が限られます。 クロスプラットフォーム は開発を省力化できるか 本検証では、 クロスプラットフォーム はモバイル開発を省力化できる 、と結論しました。 理由としては以下の点が挙げられます。 実装時間、コード量を削減できる 学習コストは1つのネイティブ言語を学習するコストより低い 開発環境は同等、または劣っているものの代替手段がある 一部実装できない機能があるものの、ネイティブと同じ機能を実装できる また検証の結果から、 クロスプラットフォーム を導入する際はまずFlutterを検討すること 、としました。 Flutterが最も欠点が少なく汎用的であることから、まずはFlutterの検討を進めることをオススメします。 Dart の学習コストが、Ionic FramewrokやReact Nativeが Web標準 技術を使用できることと比較するとやや高いものの、元々は JavaScript の代替言語として開発された経緯もあり、実装しやすく高機能な プログラミング言語 です。また、以下で説明するようにライブラリの充実度でも、他の フレームワーク よりも優位であることがわかります。 ライブラリについて クロスプラットフォーム でネイティブの機能を利用する場合は、基本的には各 フレームワーク で提供されているライブラリを利用します。 そのため、ライブラリの質が実装や運用のコストに直結すると考えました。 そこで各プラットフォームでライブラリがどのように管理されているのか、調査・比較しました。 Ionic Framework React Native Flutter ライブラリ評価機構 なし React Native Directory pud.dev 評価方法 なし Directory Score pub points 実装で使用したライブラリ数 25 29 11 Ionic Framework ライブラリの評価機構が提供されていない。ライブラリの評価基準としては、公式・コミュニティ・ サードパーティ であるか、ドキュメントが充実しているか、を自身で調査する必要がある。 React Native React Native Directoryで管理されており、Directory Scoreで評価されている。評価方法は GitHub のfork、star、download数 React Native Directoryからの推奨 最終更新日が30日以内 180日以内に更新されているか open状態のissueが75個以内 である。 リポジトリ の評価が主な評価指標となっている。 Flutter pub.devで管理されており、pub pointsで評価されている。評価方法は、 Dart の規約にしたがっていること 依存関係を明記しており、全てのURLが HTTPS を利用していること OSI 認証ライセンスを使用していて、LICENSEファイルを提供している CHANGELOG ファイルを提供している ドキュメントを提供していること サンプルコードを提供している Publicな API のうち、20%以上のドキュメントを公開している Dart の静的解析に合格している 最新の実行環境で動作すること 最新のStableの Dart とFlutterのバージョンで動作すること である。ドキュメントの充実度、コードの動作保証などで評価を行っている。 上記の結果の通り、Flutterではpub pointsの値が高いほどライブラリが充実しており実装コストが低かったです。また、コード解析や最新版の実行環境での動作確認など、アプリの運用面でも助けになる情報が多い印象です。 React Nativeでは評価機構の仕組みはあるものの、Flutterと比べるとライブラリの人気度で評価されていると感じました。また、Ionic Frameworkは評価機構が存在しません。両方の フレームワーク に共通していることですが、実装してみてもライブラリによってはドキュメントが不足しており、ライブラリのコードを自身で解析して実装する必要もありました。また、実現したい機能をそのライブラリで実装できるかが判断できず、実際にコードを動かしてみて確認する必要があるものもありました。 また、今回の検証で使用したライブラリ数はFlutterが最も少なく、少ないライブラリ数で実装できることも挙げられます。Flutterが高機能であるため、React NativeやIonic Frameworkではライブラリが必要な機能( ルーター など)をライブラリなしで使用できます。 上記の面でもFlutterが クロスプラットフォーム の中では最も優位であるという結論に至りました。これ以外でも、UIウィジェット数なども影響しています。 各 フレームワーク の所感 Ionic Framework 長所 まずは、 開発速度が速い ことが挙げられます。検証結果でも最も早くサンプルアプリを実装することができました。Webの技術を流用できることがその理由であると考えられます。またHTML、 CSS 、 JavaScript で画面を構築できるため、 クロスプラットフォーム の中では最も UIの自由度が高い と思いです。またIonic FrameworkはPWAにも対応しており、同じコードをモバイルと PWAにビルドしデプロイ できます。 短所 まずは、ライブラリの評価機構がないことが挙げられます。ライブラリのドキュメントが不足していて、実際に実装しないと実現できる機能を把握できないケースが多々ありました。他の フレームワーク にはライブラリの評価機構があることから、ここは明確な短所であると言えます。 機能面ではWebViewを実装することができないことが挙げられます。仕組み上すでにWebView上で実行されているため、新たにWebViewを実装することができません。 クロスプラットフォーム でWebViewを利用する場合は、React NativeかFlutterを利用してください。 React Native 長所 まずは、各OSに準拠した ネイティブのUIを描画できる ことが挙げれらます。 iOS ではHuman Interface Guidelines仕組み上WebViewをで、 Android では Material Design で表示されます。OSのUIでアプリを表示したい場合はReactNativeが有効になります。 また Reactの知識やエコシステムを利用できる ことも挙げられます。ライブラリに関してはDOM操作を必要とするもの以外は基本的に、Reactのライブラリを流用できます。そのため、すでにWebアプリがReactで実装されている場合はコードを移植することもできます。 短所 まずはBridge機能によるパフォーマンスの低下が挙げられます。頻繁にネイティブ機能を利用する場合や、大量データを表示する場合、Bridge機能に負荷がかかりパフォーマンスが低下する可能性があります。開発元のReact Native Communityもこの問題を認識しており、今後Bridge機能を廃止する アーキテクチャ 変更を予定しています。 また、いまだメジャーリリースがないことも不安要素として挙げられます。 Flutter 長所 まずはネイティブ同等に 開発環境が整っている ことが挙げられます。Dev Toolsがかなり優秀でさらにHot reload機能もあることから、他の フレームワーク と比べて開発環境が圧倒的に整っています。また ライブラリ評価機構が整っている ことが挙げられます。pub pointsが高いライブラリを利用すると、 API リファレンスが整っており実装がしやすいです。また不具合時の調査も他の フレームワーク と比べて、行いやすいと思います。 Dart VM がUIの描画行っており、Bridge機能を利用しないため パフォーマンスが良好 であることも挙げられます。開発元が Google で開発に力を入れていることから、将来性にも期待できます。 短所 欠点はあまりないのですが、 Dart の学習コストがかかることが挙げられます。他の フレームワーク がWeb技術を使用できること比べると、学習コストが高くなります。ただ Dart は オブジェクト指向 の プログラミング言語 であり、 JavaScript の機能も多数取り入れているため、そこまで学習コストは高くないかと思います。 また、OSの標準UIで画面を描画する場合に実装コストが高くなることが挙げられます。FlutterはデフォルトでMaterial Desginで画面が描画されます。 iOS はHumanInterfaceGuidelinesで表示したい場合は、実行されているプラットフォームによって表示する ウィジェット を切り替える必要があるため実装コストが高くなります。この場合はReact Nativeを利用した方が有効かと思います。 フレームワーク の選定基準 機能数 機能数が多いもしくは不確定の場合はFlutterを利用してください。Flutter自体の機能とUIウィジェット数が他の フレームワーク よりも多く、パフォーマンスも安定しています。React NativeやIonic Frameworkは機能数が多い場合、 JavaScript のBridgeに負荷がかかりパフォーマンスが悪くなる可能性があります。 機能数が少なく、特定の機能しか実装しない場合は、Ionic FrameworkかReact Nativeを選択して下さい。 Web標準 機能を利用できるため開発コストを低く抑えることができます。 WebView Webサービス 企業では、既にリリースされているWebアプリをWebViewを利用してモバイルアプリで表示したい、という要件が出てくると思います。WebViewを利用する場合は、FlutterかReact Nativeを利用してください。Ionic Frameworkは仕組み上、WebViewを実装することができません。FlutterかReact Nativeかを選択する場合は、基本Flutterを選択してください。 スキル Angular、React、Vueなどの JavaScript フレームワーク の経験がある場合は、Ionic FrameworkかReact Nativeを選択してください。SPAの知識を流用でき、開発速度は一番速いです。しかし、Ionic FrameworkやReact Nativeには実装できない機能やライブラリが提供されていない機能がありますので、導入する前に調査をする必要があります。 Java などのバックエンドでの開発の経験がある場合は、Flutterを選択してください。 オブジェクト指向 で実装できるので学習コストは低いかと思います。 まとめ 本検証でのまとめです。 モバイル クロスプラットフォーム はモバイル開発を省力化できるかを検証しました。 検証方法としては、ネイティブとモバイル クロスプラットフォーム のツールで、同じ機能のサンプルアプリを実装し、その実装結果を比較し考察しました。 結論は以下のようになりました。 モバイル クロスプラットフォーム は ラク スにおいてモバイル開発を省力化できる 実装時間・コード量を削減でき、開発環境が整っており、機能を実装できる ツールによっては実装できない機能があるので把握すること フレームワーク の選定は、まずはFlutterを検討する 実装する機能数やスキルセットから、 フレームワーク の選定を行う 「開発環境」「UI」「ライブラリ」などでFlutterが最も欠点が少なく汎用的であることがわかりました。そのため、モバイル クロスプラットフォーム を検討する際は、まずFlutterの導入を考えてください。 参考 書籍 基礎から学ぶFlutter (C&R研究所, 2020) React Native ~JavaScriptによるiOS/Androidアプリ開発の実践 ( 技術評論社 , 2020) Ionicで作るモバイルアプリ制作入門 (C&R研究所, 2019) ブログ記事 React Nativeの Re-architecture について。 (投稿日:2020/02/27) Flutter vs Native vs React-Native: Examinig performance (投稿日:2020/05/11) 公式ドキュメント Flutter React Native Ionic Framework React Native Directory Score pub.dev Package scores & pub points エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
こんにちは。開発エンジニアの amdaba_sk( ペンネ ーム未定)です。 前回は「 機械学習をコモディティ化する AutoML ツールの評価 」、だいぶ間が空きましたが前々回は「 機械学習のライブラリ・プラットフォームをいくつか試した所感まとめ 」と、続けて 機械学習 をテーマとした記事を書きました。 これらの記事では 機械学習 モデルを作るまでのことしか言及していませんが、 機械学習 モデルは作ってそれで終わりのものでもありません。使ってなんぼのものなんです。かみせんプロジェクトとしての調査範囲からは外れますが、せっかくモデルを作ったならそれを使ったアプリも簡単なものでいいので作ってみたい。そう思うのは開発者として自然な感情ではないでしょうか。 というわけで今回は、「 機械学習 モデルを組み込んだ Web アプリを Python 初心者が作ってみた」という個人的な興味からやってみた系記事でございます。 なお後に述べるようにアプリの実装言語は Python を採用しますが、私はかみせんプロジェクトで初めて Python を触ったばかりの初心者です。 Python らしくないコードを書いている可能性もありますので、その点ご了承ください。 また「かみせんってなんやねん」と思われた方は ↓ のリンクからかみせんカテゴリの記事をご覧ください。 tech-blog.rakus.co.jp もくじ もくじ どんなアプリを作る? どんな分類をするのか? どうやってアプリを作る? 機械学習フレームワークは何にする? 実装言語と Web アプリのフレームワークは何にする? プロジェクト構成はどんな感じにする? 機械学習モデルはどう作る? Web アプリ本体はどう作る? 動かしてみる① 仕様をちょっと変えてみる 動かしてみる② まとめ 参考 どんなアプリを作る? なるべくシンプルなものがよいですね。あまり時間はかけたくないので。 過去 2 記事で主に取り扱った 機械学習 のタスクは、分類でした。ということは、ユーザーが送信したデータを 機械学習 モデルで分類し、その結果を提示するだけというのが簡単で良さそうです。また画面を作るのは面倒なので JSON API ということにしましょう。 分類するデータの形式は、またもや過去 2 記事を見ると、ひとつはテキスト、ひとつはテーブルを使っています。テー ブルデー タだと複数のフィールドを埋めてやらないといけないので、作った後お試しで使ってみる時にめんどくさそうですね。テキストにしましょう。 結局「 機械学習のライブラリ・プラットフォームをいくつか試した所感まとめ 」の冒頭で構想したものと似たようなアプリになりました。 分類したいテキストを含む JSON を受け付ける 送られてきたテキストが既存のカテゴリのどれに相当するかを推測する 分類の結果を JSON に入れて返す どんな分類をするのか? テキストを何のカテゴリに分類してくれるのかもここで考えておきましょう。要するにどんな学習データを使うのかという話ですが、今回は livedoor ニュース コーパス を使わせていただくことにします。 livedoor ニュース コーパス は「 livedoor ニュース」のうち、 クリエイティブ・コモンズ ライセンスが適用されるニュース記事を集めたもので、株式会社ロンウイットさんによって配布されています。 ここ からダウンロードすることができます。 ニュース コーパス には以下の 9 カテゴリのニュース記事が格納されています。 トピックニュース Sports Watch IT ライフハック 家電チャンネル MOVIE ENTER 独女通信 エス マックス livedoor HOMME Peachy これを学習することで、与えられたテキストが 9 カテゴリのうちどれに当てはまりそうかを推測することが出来るでしょう。 どうやってアプリを作る? 機械学習 フレームワーク は何にする? 機械学習 モデルを作る際の フレームワーク はなんだかんだ言って scikit-learn が使いやすいです。今回の主目的は 機械学習 モデルを作る部分ではないので、ここにあまり力を入れません。凝ったことは考えず、scikit-learn を使うことにします。 実装言語と Web アプリの フレームワーク は何にする? 機械学習 モデルが Python の フレームワーク で作られるとなると、それを使うアプリの方も実装言語は Python を使うのがやりやすいです。本記事の冒頭でも述べたように Python で Web アプリなんて作ったことはありませんが、まあ、簡単なものを試作するくらいなら何とかなるでしょう。 Python で Web アプリの フレームワーク といえば、少し調べると以下の二つが代表的なようです。 Django : フルスタ ックな Web アプリ フレームワーク Flask : マイクロな Web アプリ フレームワーク 今回の用途では Flask の方が手軽で良さそうです。が、ここではそのどちらでもなく、 FastAPI を選択します。 Web アプリの フレームワーク を調べていた際に「 Python 製 Web フレームワークを Flask から FastAPI に変えた話 」という記事を見つけました。それによれば、 しかし、どちらの フレームワーク を使う場合でも下記のような機能を使おうとすると プラグイン や サードパーティ の助けを借りる必要があります。 OpenAPI JSON Schema GraphQL WebSocket タイプヒントを使ったバリデーション 非同期処理 CORS の設定 リバースプロキシとの連携サポート Django も Flask も近年登場したサーバサイドの技術や Python 3 の新機能に対するネイティブサポートがちょっと弱いです。 とのことなのです。 Django も Flask についても私自身はあまり詳しく調査していませんが、この記事を信ずるのであればどちらを選んでも プラグイン の選定作業が加わることになってあまり楽できそうにないです。特に JSON API を作ろうとしているため、やっぱり OpenAPI や JSON Schema は入れたいです。 また FastAPI のドキュメントを見ていると、なんだかこれで作れそうな気がしてきました。それに タイプヒントを使ったバリデーション も、とっても好みです。 というわけで Web アプリの フレームワーク は FastAPI を使うことにします。 プロジェクト構成はどんな感じにする? 今回の Web アプリのプロジェクト構成は下のようなものにしました。これは初めに完全に決めたというよりも、作りながら試して結果こうなったという感じです。 my_ml_app ├── Pipfile ├── Pipfile.lock ├── text ... 学習データ置き場 ├── models ... 機械学習モデル置き場 ├── tokenizer.py ... 学習・アプリ共通依存モジュール ├── training.py ... 学習スクリプト └── my_ml_app.py ... Web アプリ本体スクリプト 「 ゼロから学ぶ Python 」というオンライン学習サイトによれば、「 The Hitchhiker’s Guide to Python 」というサイトで解説されている推奨構成に従うのがよいらしいです。今回の構成はあまり推奨構成に則っていないかもしれませんが、参考にはさせていただきました。 「 Cookiecutter 」等を使うことでテンプレートから ディレクト リ構成などひな型は作れるのですが、どのテンプレートがいいのかよくわからず結局上の構成は手で作っています。 機械学習 モデルはどう作る? 機械学習 モデルの作成 スクリプト は training.py です。 詳細な内容は今回の主眼ではないので省略しますが、Web アプリで使うために出来上がったモデルを シリアライズ してファイルに保存しておく必要があります 1 。 モデル作成の概略は以下の通りです。 形態素解析 器: Janome ベクトル化方式: Tf-Idf 分類 アルゴリズム : 単純 ベイズ 分類器 学習の際デー タセット を分割し、一部を性能測定に使っています。結果は以下の通りでした。モデルの性能は今回重要ではないのですが、まあ、そこそこなモデルになっているのではないでしょうか。 precision recall f1-score support dokujo-tsushin 0.68 0.91 0.78 218 it-life-hack 0.92 0.89 0.90 218 kaden-channel 0.89 0.93 0.91 216 livedoor-homme 1.00 0.25 0.40 128 movie-enter 0.84 0.97 0.90 218 peachy 0.80 0.71 0.75 210 smax 0.86 1.00 0.93 217 sports-watch 0.89 1.00 0.94 225 topic-news 0.98 0.74 0.84 192 accuracy 0.85 1842 macro avg 0.87 0.82 0.82 1842 weighted avg 0.87 0.85 0.84 1842 Web アプリ本体はどう作る? Web アプリ本体の スクリプト は my_ml_app.py です。とりあえず全文を見てみましょう。 from enum import Enum from fastapi import FastAPI from pydantic import BaseModel, Field import joblib from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.naive_bayes import MultinomialNB class CategoryName ( str , Enum): topic_news = 'topic-news' # トピックニュース sports_watch = 'sports-watch' # Sports Watch it_life_hack = 'it-life-hack' # ITライフハック kaden_channel = 'kaden-channel' # 家電チャンネル movie_enter = 'movie-enter' # MOVIE ENTER dokujo_tsushin = 'dokujo-tsushin' # 独女通信 smax = 'smax' # エスマックス livedoor_homme = 'livedoor-homme' # livedoor HOMME peachy = 'peachy' # Peachy class MyClassifier (): clf: MultinomialNB vec: TfidfVectorizer def __init__ ( self, classifier: MultinomialNB, vectrizer: TfidfVectorizer ): self.clf = classifier self.vec = vectrizer def classify (self, targetText: str ): v = self.vec.transform([targetText]) return self.clf.predict(v)[ 0 ] class ClassifyRequest (BaseModel): text: str = Field(..., max_length= 10000 ) app = FastAPI() my_classifier = MyClassifier( joblib.load( 'models/livedoor_tfidf_mnb.model' ), joblib.load( 'models/livedoor_tfidf.model' ) ) @ app.post ( '/classify' , response_model=CategoryName) async def classify (req: ClassifyRequest): return my_classifier.classify(req.text) 実にシンプルですね。シンプル過ぎて if も for も使う余地がありませんでした。 動かしてみる① Python 3 が使える環境にプロジェクトをデプロイ 2 し、プロジェクトの ディレクト リに移動。その後起動コマンドを実行します。 # pipenv run uvicorn my_ml_app:app --port 80 --host 0.0.0.0 --reload INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) INFO: Started reloader process [521] using statreload INFO: Started server process [528] INFO: Waiting for application startup. INFO: Application startup complete. サーバーが起動しました! FastAPI は SwaggerUI をホストしていますので、そこから API を動かしてみましょう。 SwaggerUI にアクセスしたところ 「Try it out」で本記事の冒頭部分を分類してみます。 { " text ": " 機械学習モデルを組み込んだ Web アプリを Python 初心者が作ってみた \n こんにちは。開発エンジニアの amdaba_sk(ペンネーム未定)です。 \n 前回は「機械学習をコモディティ化する AutoML ツールの評価」、だいぶ間が空きましたが前々回は「機械学習のライブラリ・プラットフォームをいくつか試した所感まとめ」と、続けて機械学習をテーマとした記事を書きました。 \n これらの記事では機械学習モデルを作るまでのことしか言及していませんが、機械学習モデルは作ってそれで終わりのものでもありません。使ってなんぼのものなんです。かみせんプロジェクトとしての調査範囲からは外れますが、せっかくモデルを作ったならそれを使ったアプリも簡単なものでいいので作ってみたい。そう思うのは開発者として自然な感情ではないでしょうか。 \n というわけで今回は、「機械学習モデルを組み込んだ Web アプリを Python 初心者が作ってみた」という個人的な興味からやってみた系記事でございます。 " } これを送信すると、結果が以下のように返ってきます。 " it - life - hack " どうやら本記事は「IT ライフハック 」に入ってそうな記事だそうです。 仕様をちょっと変えてみる ところで、送信したテキストがどのカテゴリに相当するのかをひとつだけ返してくるだけでは、そっけなく感じますね。 実際出来上がったものを見ると、欲ができてます。以下のようにちょっと仕様を変えてみましょうか。 どのカテゴリにどの程度の確率で分類されるのかのリストを返す その際、分類される確率の高い順にカテゴリを並べる この仕様変更は幸い Web アプリ側だけで対応できます。 my_ml_app.py を以下のように修正しましょう。 @@ -1,4 +1,5 @@ from enum import Enum +from typing import List from fastapi import FastAPI from pydantic import BaseModel, Field @@ -30,17 +31,30 @@ def classify(self, targetText: str): v = self.vec.transform([targetText]) - return self.clf.predict(v)[0] + result_proba = self.clf.predict_proba(v)[0] # <1> + order = (-result_proba).argsort() # <2>, <3> + ordered_cats = self.clf.classes_[order] # <4> + ordered_probas = result_proba[order] # <4> + return [ + { + 'category': cat, + 'probability': proba + } for cat, proba in zip(ordered_cats, ordered_probas) # <5> + ] # <6> class ClassifyRequest(BaseModel): text: str = Field(..., max_length=10000) +class ClassifyResponse(BaseModel): + category: CategoryName + probability: float + app = FastAPI() my_classifier = MyClassifier( joblib.load('models/livedoor_tfidf_mnb.model'), joblib.load('models/livedoor_tfidf.model') ) -@app.post('/classify', response_model=CategoryName) +@app.post('/classify', response_model=List[ClassifyResponse]) async def classify(req: ClassifyRequest): return my_classifier.classify(req.text) やることが増えたので少しコードも複雑になりました。ポイントを説明します。 推論実行のメソッドを predict から predict_proba に変更したことで、カテゴリ毎の確率を得ることが出来ます。並び順は分類器の classes_ 属性と一致しています。 predict_proba から返された配列に対して負符号を付けることで、要素の正負をすべて反転しています。これは次のステップで降順ソートにするためです。 要素の正負を反転した結果に対して numpy.argsort を行えば、値の大小に従ってソートした時の配列インデックスの変化を返してくれます。 Python ではリストや配列に対して [] にインデックスのリストを入れると、各インデックスに対応する値を指定した順序で返してくれます。ここでは 3 で得たインデックスのリストを使って、カテゴリのリスト( self.clf.classes_ )とカテゴリ毎の確率( result_proba )を並べ替えています。 zip 関数を使ってカテゴリと対応する確率をペアにしています。これで別々のリストになっていたものが一つにまとまって扱いやすくなりました。 return 以降はリスト内包表記と言われる構文です。5 で作成したリストのそれぞれの要素を、dict に詰め替えて新しいリストを作っています。この部分は for 文を使って下のように書くこともできます。 ret = [] for cat, proba in zip (ordered_cats, ordered_probas): ret.append({ 'category' : cat, 'probability' : proba }) return ret リスト内包表記と for 文、どっちが読みやすいかは人によるでしょう。私自身は、リスト内包表記は文ではなく式であるという点でリスト内包表記の方が好みです。また実行速度はリスト内包表記の方が若干速いらしいですね( Pythonのリスト内包の速度 )。 動かしてみる② サーバーを再起動して、SwaggerUI の画面を再度開きます。先ほどと同様にして「Try it out」で本記事の冒頭部分を分類してみましょう。結果は以下のようになりました。 [ { " category ": " it-life-hack ", " probability ": 0.3086756411902118 } , { " category ": " smax ", " probability ": 0.15842430053076112 } , { " category ": " dokujo-tsushin ", " probability ": 0.13005882520629944 } , { " category ": " kaden-channel ", " probability ": 0.1221002790185913 } , { " category ": " peachy ", " probability ": 0.11371989611168741 } , { " category ": " movie-enter ", " probability ": 0.04808770370861974 } , { " category ": " sports-watch ", " probability ": 0.04605206014172084 } , { " category ": " topic-news ", " probability ": 0.03650002186757273 } , { " category ": " livedoor-homme ", " probability ": 0.036381272224538394 } ] どうやら本記事は、9 カテゴリ内では「IT ライフハック 」に入ってそうではあるけれども、確率は 3 割程度でそんなに高くないようです。仕様変更によってより詳しい結果を知ることができるようになりました。 まとめ 以上、 機械学習 モデルを組み込んだ Web アプリを Python 初心者が作ってみました。意図してシンプルな仕様にしたこともあり、また フレームワーク の助けもありとっても簡単に動くものが作れました。 今回は 機械学習 モデルを組み込んだ Web アプリ を作りましたが、 機械学習 モデルを使わない場合も基本的な作り方はあまり変わらないのではないかと思います。これを読んでくださった方が Python で Web アプリを作る時、何かの参考になれば幸いです。 参考 livedoor ニュース コーパス - https://www.rondhuit.com/download.html scikit-learn - https://scikit-learn.org/stable/index.html Django - https://djangoproject.jp Flask - https://flask.palletsprojects.com/en/1.1.x/ FastAPI - https://fastapi.tiangolo.com/ja/ Python 製 Web フレームワーク を Flask から FastAPI に変えた話 - https://note.com/navitime_tech/n/nc0381517d067 ゼロから学ぶ Python - https://rinatz.github.io/python-book/ The Hitchhiker’s Guide to Python - https://docs.python-guide.org/ Cookiecutter - https://cookiecutter.readthedocs.io/en/1.7.2/ Python のリスト内包の速度 - https://qiita.com/intermezzo-fr/items/43f90e07e4cebe63aeb6 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com 実は今回大ハマりして一番苦労したのはこの部分だったりするのですが、話が逸れるので割愛します。 ↩ 今回はWSL2+Dockerでやっています。 ↩
アバター
はじめに みなさんこんにちはa_renrenです。 今年は、 新型コロナウイルス によって以前より家にいる時間が増え、何か家でできる趣味を探している方が増えているのではないしょうか。 今回は、そのような方におすすめのラズパイについてご紹介していきたいと思います。また、これからラズパイの購入を考えいる方やラズパイは聞いたことがあるけどどんなことができるかあまり知らない方も是非読んでみてください。最後に簡単にラズパイとLINEを連携する方法を載せています。少しでもラズパイに興味を持っていただけたら幸いです。 はじめに ラズパイとは ラズパイの種類 Raspberry Pi4 model B Raspberry Pi Zero ラズパイでできること カメラとして活用 プログラミング学習 センサーと連携 実際に触ってみた ラズパイ購入 セットアップ LINE Notify設定 メッセージの送信 終わりに 参考 ラズパイとは ラズパイとは正式名称を Raspberry PI ( ラズベリー パイ)といい、イギリスの ラズベリー 財団によって開発された シングルボードコンピュータ です。 シングルボードコンピュータ とはむき出しの一枚のプリント基板の上に、電子部品と最低限の入出力装置を付けただけのとてもシンプルなコンピュータです。 もともとは子供向けの安価な教育コンピュータとして開発されましたが、今では、コンピュータやプログラミングの学習のみならず電子工作やロボット、産業向けに利用されるようになってきました。 ラズパイの種類 初めてのラズパイが発売されてから10年近くの年月が経ち、ラズパイの種類もどんどんと増えてきました。 今では大きく分けて5種類のラズパイが発売されています。 ここでは、一番性能が高い最新のモデルと一番安いモデルを紹介します。 Raspberry Pi4 model B 国内で2019年11月末に発売された最新モデルです。 従来のモデルとの大きな違いは メモリの選択が可能(2GB、4GB、8GB) CPUのクロック数が1.2GHzから1.5GHzとなり、より高速化 microHDMIを2つ搭載 などがあげられ、全体的にコンピュータとしての性能が高まりました。 メモリの選択が可能になり、本格的なサーバの運用などに対応することが可能となったことでラズパイでできる選択肢の幅が広がりました。 従来のモデルとの互換性が低かったり、消費電力が増えたりなどのデメリットがいくつかあるようですが、 これからラズパイを購入しようとしている人はこのモデルを買えば問題はないと思います。 メモリに関しては、値が高ければ性能も高くなりますが値段も高くなるため、お財布と相談しながら決めましょう。 ちなみに私は4GBのメモリを搭載しているものを購入しました。 www.raspberrypi.org Raspberry Pi Zero 全モデルの中で一番安価なモデルで600円程度で買うことができます。 より多くの人にラズパイを体験してもらうことを目的として作られたモデルです。 ほかのモデルと比べると性能は劣りますが、あまりお金をかけずに楽しみたいという人におすすめです。 www.raspberrypi.org 最近だと、ラズパイとキーボードが一体化した Raspberry Pi 400というものが登場しました。 日本では2021年以降に発売予定のため、気になる方はぜひ買ってみてください。 www.raspberrypi.org ラズパイでできること ラズパイでは、デスクトップPCで行うインターネットの閲覧、ゲームのプレイから電子工作など多くのことを行うことができます。 皆さんの発想次第で様々な使い方ができます。 今回はラズパイでできる様々なことの中からいくつかおすすめを紹介いたします。 カメラとして活用 ラズパイにはカメラが搭載されていませんが、別途カメラモジュールを購入することでカメラとして機能させることができます。 一口にカメラと言っても、設定を行えば監視カメラやセンサーカメラ、チャットに決まった時間に自動で撮れた写真が送られてくるような定点カメラなど様々な使い方ができます。 追加で費用がかかりますが、汎用性が高く、設定が難しくないため初心者にもおすすめです。 nn-hokuson.hatenablog.com プログラミング学習 もともと学習目的で作られているため、 Python やScratchが標準でインストールされおり、初心者が躓きやすい導入部分がなく手軽に始めることが可能です。 また、 Linux の学習をこれから始めようとしている方にもおすすめです。 Linux のコマンドなど Linux を学習しようとお手元のパソコンに Linux をインストールする必要がありますが、何かしらトラブルがあった場合に一人で解決することが難しいことが多く途中で断念してしまう人は少なくないと思います。 ラズパイではOSを選択することができ、その中に Debian という Linuxディストリビューション が元となったRaspbianというOSがあります。 RaspbianをOSとして選択してラズパイを使用することで、簡単に Linux の学習を始めることができます。 センサーと連携 ラズパイには様々なセンサーモジュールが用意されています。 いくつかセンサーをご紹介します。 水温センサー 湿度センサー 人感(モーション)センサー ガスセンサー 光センサー 赤外線センサー タッチセンサー サウンド センサー 他にも様々なセンサーが用意されています。 水温センサーとラズパイを掛け合わせることで自宅の水槽の水温の管理、人感センサーと掛け合わせると、人感センサーが働いた時だけライトの点灯や防犯カメラの起動、ディスプレイの起動などを行うことができます。 また、これらのセンサーがまとまっているキットも発売されているため、色々試してみたい方にはおすすめです。 https://www.amazon.co.jp/gp/product/B0716B778T/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B0716B778T&linkCode=as2&tag=osusume8net01-22&linkId=93e83ae8d992e07a1ec4d0db9283a2ff www.amazon.co.jp 実際に触ってみた 今回は、ラズパイとLINEを連携してメッセージを送れるようにしてみます。 ラズパイ購入 私は、付属品がセットになっているこちらのスターターキットを Amazon で購入しました。 www.amazon.co.jp これから始める際に必要な HDMI ケーブルや microSD カードなどの部品がそろっているため、簡単に始めることができます。 また、本来であれば microSD カードにラズパイ用のOSを書き込んでおく必要がありますが、このスターターキットには、すでにRaspbianなどのOSが書き込まれた microSD カードが付属しているため、面倒な手間が省けます。 しかし、このスターターセットだけでは、ラズパイを操作することはできません。スターターセットに加え以下のものが必要となります。 キーボード マウス ディスプレイ 一応ディスプレイがなくともテレビなどで代用することができます。 今回購入したスターターキットの中身はこのような感じでした。 ラズパイ本体(4GB RAM) microSD カード(32GB) スイッチ付き電源アダプタ HDMI ケーブル×2 冷却ファン×2 ケース ヒートシンク ×3(取付済み) MicroSD カードリーダー 取り扱い説明書 ケースに取り付けるとこんな感じです。 ケースの上部に冷却ファンを取り付けることができ、本体に電源を入れるとファンが回り始めます。 ケースの取り付け方は説明書がありましたが、あまり詳しく書かれていないのとケースが堅かったため、取り付けに少し苦労しました。 このケースは、3つに分解することができるので、全部分解してから取り付けることをおすすめします。 セットアップ ラズパイの組み立てが終われば次は、モニターなどを接続してOSのインストールを開始します。 付属の microSD カードを差し込めば簡単にOSのインストールを行うことができます。 今回はRaspbianを選択しました。 こちらの画面で言語の設定と wifi の設定が可能となっています。 左上のインストールをクリックするとインストールが開始します。 インストールが完了するとパスワードなどの各種初期設定が開始されます。 こちらの設定は後でも行うことができますのでスキップしていただいても大丈夫です。 初期設定が終わるとこちらの画面が出てくるかと思います。 ひとまずセットアップはこれで終了です。 LINE Notify設定 一通り設定が終われば実際にLINEと連携してみましょう。 まずは、LINE Notifyにログインして トーク ンを発行します。 LINE Notifyは、 Webサービス やアプリなどに来た通知を簡単にLINEに送信することができるサービスです。 以下からログインすることができます。 LINE Notify ログインできたら、右上に名前が表示されるので、そちらをクリックし、マイページを選択してください。 下にスクロールするとアクセス トーク ンの発行があるので「 トーク ンを発行する」から トーク ンを発行します。 トーク ン名と通知を送る相手を選択します。 通知はグループにも送ることができます。 今回は、 トーク ン名を「ラズパイ」にして、送信相手は自分のアカウントを選択します。 選択後、「発行する」をクリックしてください。 すると トーク ンが発行されるのでそれをどこかにメモしておいてください。 以上で トーク ンの発行は終わりです。 メッセージの送信 次は、ラズパイの操作に入ります。 以下のコマンドをホーム画面の左上にあるLXTerminalで実行することでLINEにメッセージが送れます。 送るメッセージはmessage=の右側で指定することができます。 今回は、Helloというメッセージを送信してみます。 $ curl https://notify-api.line.me/api/notify -X POST -H "Authorization: Bearer XXXXXXXX" -F "message=Hello" XXXXXXXXの箇所を先ほど発行した トーク ンに書き換えてください。 実行後以下のステータスが返ってくると成功です。 {"status":200,"message":"ok"} 実際にLINEで確認してみましょう。 先ほどのmessageで指定したHelloというメッセージが送られてきているのが確認できます。 以上でLINEとの連携の設定は終わりになります。 終わりに 今回は、ラズパイの基本的な情報からできることまで簡単に紹介しました。 後半では簡単にラズパイとLINEを連携させてメッセージを送れるようにしましたが、ただコマンドを打ってメッセージを送るだけだとあまり実用性がありません。ここからさらに発展させると、カメラモジュールを組み合わせて、お留守番しているペットの写真を定期的にLINEに送信したり、赤外線センサーを組み合わせて郵便物の受け取りを通知させたりと様々な使い方ができるかと思います。 ここから先は皆さんの発想力でラズパイを自分色に変えてみてください! 参考 Raspberry Pi Documentation Raspberry Pi センサーでいろいろ作れる!おすすめ10選 - オススメPCドットコム ラズパイのモデルを比較 | M5Stack沼人の日記 Raspberry Pi(ラズパイ)からLINEにメッセージを通知する(コマンド編) | STONE-BOOKs エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
はじめに 初めまして。配配メール開発課 Jazumaです。 今回は PHP の フレームワーク Laravelの環境構築~基本機能の動作確認を行います。 Linux 環境での作業を前提としていますので Windows や Mac ではこの記事の手順でLaravelの環境構築をすることができません。予めご了承ください。 はじめに Laravelとは Laravelのメリット 動作環境 Laravelの環境構築 PHPのインストール Laravelのインストールや動作に必要なモジュールのインストール Composerをインストールする Laravelのインストール・プロジェクトの作成 Laravelの基本機能確認 ビルトインサーバの起動 ルーティングの設定 コントローラの作成 Viewファイルの作成 終わりに Laravelとは Laravelは2011年にリリースされた オープンソース の PHP フレームワーク であり、認証・データベースへのアクセス・入力値のチェックなどWeb開発に必要な機能が一通り備わっています。 Laravelの特徴として、 MVC モデルが採用されているということが挙げられます。 MVC モデルとはアプリケーション開発によくある処理をModel、View、Cotrollerの3つに分類して実装する手法です。 Model、View、Controllerはそれぞれ次のような機能を持ちます。 M: Model... データ処理をする。 取得したデータをControllerに渡す機能も持つ。 V: View... ユーザに表示する画面。Controllerにリク エス トを送ったり、Controllerが送ったレスポンスを画面に表示する。 C: Controller... Viewからリク エス トを受け取る。また、Modelから受け取った処理の結果をViewに対してレスポンスとして渡す機能を持つ。 MVC モデルは機能ごとにクラスが明確に分かれているため保守性の高いプログラムを簡単に書くことができるというメリットがあり、Laravelも例外ではありません。 Laravelのメリット Web開発をするにあたって、Laravelには以下のようなメリットがあります。 学習コストが比較的低い 前述の通りLaravelは MVC モデルに準拠しているため、どのファイルにどのような処理を書けばよいのか非常にわかりやすく、文法も単純なものが多いです。 そのため初心者でもWebアプリを効率的に開発することができます。 Webアプリに必要な機能を簡単に実装できる Laravelでは認証・エラー処理などのWebアプリケーションに不可欠な機能を簡単に実装することができます。例えば、「ユーザがリク エス トしたページが存在しない場合に404エラーページを返す」という処理は404.blade. php というViewファイルを作成するだけで実装できてしまいます。 フレームワーク が裏側でよしなにやってくれるというわけですね。この他にもコマンドを実行するだけで認証機能の実装に必要なControllerやViewファイルが作成されるなど、Web開発をスムーズに進めることができます。 コマンドが豊富 LaravelにはArtisanという コマンドライン ツールがデフォルトで備わっており コマンドライン からControllerやModelを作成したり、データベースを操作したりすることができます。 artisanコマンドの一例を以下に示します。(これらはほんの一部分にすぎません。 artisanコマンドの一覧が見たい時は php artisan listを実行します。) php artisan serve # ビルトインサーバを起動する php artisan make:model[controller] [ModelやController名] # Model[Controller]を作成する php artisan tinker #コマンドライン上でLaravelのプログラムを実行するモードを起動 動作環境 私は以下の環境で作業を行っています。 ホストOS: Windows10 Home ゲストOS: WSL2 Ubuntu20.04 PHP 7.4 Laravel 8.16 VSCode ver1.51 Laravelの環境構築 まずは以下の手順でLaravelの環境構築を行います。 PHP のインストール Laravelは PHP の フレームワーク ですので使う前に PHP をインストールする必要があります。 既に PHP がインストール済みの場合はこの手順は省略しても問題ありません。 以下のコマンドで PHP をインストールします。 #add-apt-repository コマンドをインストール $ sudo apt-get install software-properties-common \ # PHPをインストールするするためのppa:ondrej/phpリポジトリを追加 add-apt-repository ppa:ondrej/php \ # パッケージを最新化 sudo apt update \ # PHPをインストール apt-get install php7.4 php -vコマンドを実行してバージョンが表示されていれば正確にインストールされています。 PHP 7.4.7 (cli) (built: Jun 12 2020 07:44:38) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Zend OPcache v7.4.7, Copyright (c), by Zend Technologies Laravelのインストールや動作に必要なモジュールのインストール Laravelの 公式Webサイト では、Laravelを使うために以下のような PHP のモジュールが必要になると書かれています。 BCMath PHP Extension Ctype PHP Extension Fileinfo PHP extension JSON PHP Extension Mbstring PHP Extension OpenSSL PHP Extension PDO PHP Extension Tokenizer PHP Extension XML PHP Extension ZIP PHP Extension 初期状態ではBCMath, Mbstring, XML がインストールされていません。また、後述するComposerでLaravelの インストーラ コマンドを実行するにあたってzip 拡張機能 が必要になるので合わせてインストールします。 $ sudo apt-get php7.4-bcmath php7.4-mbstring php7.4-xml php7.4-zip このとき、各種モジュールのバージョンは必ず php 本体のバージョンと揃えるようにしてください。(モジュールのバージョンを指定しないことが原因でエラーがよく発生します) モジュールがインストールできたら php -mコマンドで正しくパッケージがインストールできているか確認します。 $ php -m [PHP Modules] bcmath ctype fileinfo json mbstring openssl PDO tokenizer xml zip (見やすくするために必要なモジュールのみを記載しています。) Composerをインストールする Composerとは PHP で開発するのに必要なパッケージやライブラリの依存関係を解決してくれるツールです。例えばLaravelでの開発にパッケージAが必要でパッケージAの導入にはパッケージBが必要でパッケージBを使うにはパッケージCが...というようなことになった場合、Composerがないとそれらを1つ1つインストールしなければなりません。このようなやり方ではインストール漏れやパッケージ毎のバージョン違いでエラーが発生しやすいです。 それに対して、Composerを導入していればパッケージAをインストールするとそれを使うのに必要なパッケージBやCを自動でインストールしてくれる上、バージョン管理も勝手にやってくれます。このような利点からComposerは PHP の各種 フレームワーク で開発する場合ほぼ必ず導入されており、LaravelでもComposerが活用されています。 以下のコマンドでComposerをインストールします。 php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" php -r "if (hash_file('sha384', 'composer-setup.php') === 'e0012edf3e80b6978849f5eff0d4b4e4c79ff1609dd1e613307e16318854d24ae64f26d17af3ef0bf7cfb710ca74755a') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" php composer-setup.php php -r "unlink('composer-setup.php');" カレント ディレクト リにComposerがインストールされますが、のちの手順を簡略化するためにパスの通っている ディレクト リに移動させます。 sudo mv composer.phar /usr/local/bin/composer Laravelのインストール・プロジェクトの作成 Composerの配置が完了したら以下のコマンドでLaravelの インストーラ をダウンロードします。 $ composer global require "laravel/installer" Laravel インストーラ のダウンロードが終わり次第、.bashrcを編集してComposerのvendor/bin ディレクト リにパスを通します。 $ vim ~/.bashrc export PATH="$PATH:$HOME/.config/composer/vendor/bin" パスを通せたら、Laravelのプロジェクトを作成するための ディレクト リを作り、その ディレクト リに移動してLaravel new コマンドを実行します。 $ mkdir Laravel_app $ cd Laravel_app $ Laravel new sample_app . . - Installing ralouphie/getallheaders (3.0.3): Downloading (100%) - Installing guzzlehttp/psr7 (1.7.0): Downloading (100%) - Installing guzzlehttp/promises (1.4.0): Downloading (100%) - Installing guzzlehttp/guzzle (7.2.0): Downloading (100%) - Installing dnoegel/php-xdg-base-dir (v0.1.1): Downloading (100%) - Installing nikic/php-parser (v4.10.2): Downloading (100%) - Installing psy/psysh (v0.10.4): Downloading (100%) - Installing laravel/tinker (v2.5.0): Downloading (100%) . . . Package manifest generated successfully. 72 packages you are using are looking for funding. Use the `composer fund` command to find out more! > @php artisan key:generate --ansi Application key set successfully. Application ready! Build something amazing. Laravel newコマンドでアプリケーションの開発に必要なパッケージが自動でインストールされていきます。 これでLaravelの開発をする準備ができました。 「Application ready! Build something amazing.」というメッセージが表示されたらLaravel_app ディレクト リで以下のコマンドを実行してLaravelのバージョンを確認してみましょう。 $ php artisan -v Laravel Framework 8.16.1 Laravelの環境構築が無事完了しました。ここから先ではいよいよLaravelの機能を使っていきます。 Laravelの基本機能確認 ビルトインサーバの起動 LaravelではWebサーバを構築しなくても備え付けのサーバ(ビルトインサーバ)によってWebアプリケーションの動作確認をすることができます。(ビルトインサーバはセキュリティや機能面で実用には堪えません。あくまでも開発中の動作確認に使うくらいの使用感です) 以下のコマンドを実行してLaravelのビルトインサーバを起動します。 $ php artisan serve Starting Laravel development server: http://127.0.0.1:8000 [Mon Nov 30 20:47:59 2020] PHP 7.4.12 Development Server (http://127.0.0.1:8000) started ブラウザの検索窓に localhost:8000 と入力してアクセスします。 上の画像のようにLaravelの起動画面が表示されれば成功です。 ルーティングの設定 ルーティングとは「このURLを呼び出したらこのコントローラを呼び出す」というようにURLとコントローラの対応付けをすることです。Laravelでは routes/web.php でルーティングを設定します。 web.php はデフォルトでは以下のようになっています。(コメント部分は省略) <?php use Illuminate\Support\Facades\Route; Route :: get ( '/' , function () { return view ( 'welcome' ) ; }) ; 上記のルーティングの内容を簡単にまとめると、「第一引数のURLがgetメソッドで呼ばれたときに第二引数内の関数を実行する」というものです。ここでは '/'、つまりホーム画面( localhost :8000)にアクセスしたときに welcome.blade.php という名前のViewファイルを返す処理になっています。 先ほどビルトインサーバを起動した際にこのルーティングが呼び出されたというわけですね。 続いて実際にルーティングを定義してみましょう。 web.php を以下のように編集します。 <?php use Illuminate\Support\Facades\Route; Route :: get ( '/' , function () { return view ( 'welcome' ) ; }) ; //追記部分 Route :: get ( '/hello' , function () { return 'hello' ; }) ; 新しく追加したルーティングは、'/hello'というURLをgetメソッドで呼び出すと'hello'という文字列を画面に表示するという内容です。Viewファイルではなく単に文字列を返すのは実用的ではありませんが今回は動作確認のためにこのような処理になっています。 それでは実際に localhost:8000/hello にアクセスしてみます。 上の画像のようにhelloと表示されていれば成功です。 コントローラの作成 続いてコントローラを作成します。 コマンドライン から以下のコマンドを実行します。 $ php artisan make:controller HelloController Controller created successfully. コマンドライン に上のようなメッセージが表示されていれば成功です。Laravelが自動でコントロー ラク ラスのファイルを作成してくれます。 Laravelではコントロー ラク ラスは app/Http 直下にControllerクラスのファイルが作成されます。 app/Http ディレクト リ直下に HelloController.php というファイルが作成されていることを確認しましょう。 無事作成されていますね。 続いて HelloController.php を以下のように変更します。 <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class HelloController extends Controller { //新規追加のメソッド public function index () { return "hello, world" ; } } 詳細は後述します。 さらに、 web.php の内容を変更します。 <?php use Illuminate\Support\Facades\Route; Route :: get ( '/' , function () { return view ( 'welcome' ) ; }) ; //変更箇所 Route :: get ( '/hello' , 'App\Http\Controllers\HelloController@index' ) ; ルーティングの内容を「'/hello'がgetメソッドで呼び出されたら HelloControllerのindexメソッドを呼び出す 」というように変えています。 HelloController.php のindexメソッドはhello, worldという文字列を返すという処理を行うので、先ほどと同じように localhost:8000/hello にアクセスしてhello, worldと表示されていればokです。 Viewファイルの作成 Controllerの次はViewを触っていきます。 resources/views ディレクト リの下に hello.blade.php というファイルを作成し、次のような内容にします。 <!DOCTYPE html> < html lang = "en" > < head > < meta charset = "UTF-8" > < meta name = "viewport" content = "width=device-width, initial-scale=1.0" > < title > Document </ title > </ head > < body > {{$message}} </ body > </ html > 次にコントロー ラク ラスに手を加えます。冒頭で書いたようにLaravelはControllerからViewファイルを呼び出すという処理の流れになっていますので、コントローラ側でViewファイルを呼び出す処理を実装しなければなりません。indexメソッドを次のように書き変えてください。 <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class HelloController extends Controller { public function index () { //変更箇所 $ message = "Hello Laravel!!" ; return view ( 'hello' , [ 'message' => $ message ]) ; } } 変数 $message にHello, Laravel!!という文字列を代入しています。これはLaravel固有の記法というわけではなく、 PHP そのものの文法です。 return文ではviewメソッドを返しており、第一引数で hello.blade.php を返すようにしています。 少し複雑なのが第二引数の ['message' => $message] という部分です。 これはViewファイルに配列でパラメータを渡すための引数で、ここではmessageというパラメータに上で宣言した変数 $message の値をセットしています。 つまり先ほどお見せした hello.blade.php 内の$messageというパラメータにはHello, Laravel!!という文字列がセットされているというわけですね。(Viewファイルの$messageはあくまでもパラメータであり、 HelloController.php で宣言した変数 $message そのものではありません。) それでは localhost:8000/hello にアクセスしてみましょう。 上の画像のようにHello, Laravel!!と表示されているでしょうか? 最後にViewファイルの文法について簡単に解説したいと思います。 < body > {{$message}} </ body > $message を囲んでいる二重括弧 {{ }} にはどのような意味があるのでしょうか。大きく分けて2つの機能があります。1つはパラメータにセットされている値を展開するという機能です。この二重括弧をつけていないとHello, Laravel!!という文字列ではなく、$messageという文字列がそのまま出力されてしまいます。 もう1つはセキュリティ対策の機能です。{{ }} で囲まれたパラメータは単にその値が展開されるだけではなく、内部的には htmlentities() 関数に渡されて値が表示されます。これにより、「<」や 「&」 などの特殊な意味を持つ文字が エス ケープされて単なる文字として出力されます。 特殊文字 が自動で エス ケープされるため、 XSS 攻撃(悪意を持ったユーザが javascript やhtmlタグを入力して他のユーザのブラウザで実行させる攻撃)を大きな手間をかけることなく防ぐことができます。( XSS の詳細は こちら ) 基本的な文法に沿って実装すれば意識せずともセキュリティ対策ができているというのもLaravelの大きな魅力です。 終わりに Laravelを使うと簡単かつ安全にWebアプリケーションを開発することができるということを体感していただけたのではないでしょうか。 今回は紹介することができませんでしたがこの他にも認証機能の実装や、データベースの操作も非常にスムーズに行うことができます。 まだまだLaravelには便利な機能がありますので、また機会がありましたらご紹介したいと思います。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
こんにちは ラク スの iketomo です。 ここ最近はとても寒くなってきました。洋服や家住まいを冬仕様に変更しようとしている今日この頃です。 今回は ガントチャート やエクセル( Excel )や他の ガントチャート のおすすめツールについて紹介させていただきます。 皆様もプロジェクトの スケジュール や タスク管理 には頭を悩ませることも多いかと思います。 是非この記事からガントーチャートの使い方を知っていただきプロジェクトで活用いただければと思います! ガントチャートとは ガントチャートとWBSとの違い ガントチャートのメリット 進捗の可視化 タスクの洗い出し 無理のない担当者アサイン ガントチャートを作成・使用する際の注意点 作業順序に誤りがないか タスクやリソースの重複がないか 情報が最新化されているか ツール紹介 エクセル(Excel) ・セルを塗潰し方式 ・関数編 Redmine Brabio おわりに ガントチャート とは ガントチャート はヘンリー・ガントさん工場の進捗を確認するためにおよそ100年前に生み出した工程管理の手法になります。 ガントチャート は主に スケジュール や タスク を管理するための表になります。 横棒グラフなどで可視化し プロジェクト全体の計画を 見える化 することでプロジェクトの進捗遅れや重要なタスクなどを視覚的に把握することができ、チームでスケジュールの進捗を共有をしながら進める際にエクセルなどで ガントチャート が使われることは一般的になっています。 ガントチャート と WBS との違い WBS はWork Breakdown Structureの略でタスクをある一定の基準で細分化したタスク一覧表になります。 開始日、終了日、 工数 や進捗を記入することで 全体の 工数 の見積もり や 全体進捗状況(何パーセント完了しているか) を把握することができます。 WBS でもスケジュール進捗を確認することができますが時間軸の概念がないので スケジュールの進捗の把握しやすさという点では ガントチャート の方が優れています。 WBS はタスクの洗い出し、 ガントチャート がスケジュールを可視化したものという関係になります。 ガントチャート の元となるタスクを洗い出す際に WBS を作成する必要があるので、 WBS の延長線上に ガントチャート があると考えてよいでしょう。 WBS と ガントチャート の違い ガントチャート のメリット 進捗の可視化 なんといっても ガントチャート を使う一番のメリット・おすすめ所はスケジュール・進捗の 見える化 になります。 「誰が」「いつ」「何をするのか」を視覚的に把握することができます。 スケジュールの遅れているのか?前倒しで進んでいるのかを自分や他のメンバーも含めメンバー全員に情報共有ができるので スケジュール遅れのトラブルにも即座に対応することができます。 タスクの洗い出し 上記でも述べましたがタスクを洗い出す段階で、 ガントチャート を作成する段階で WBS またはそれに近いものを作成することになります。 タスク漏れが発生してプロジェクトの終盤に追加が作業が発生したというような事態を招かないために 階層構造によりタスクを落とし込み、タスク漏れが発生しないようにすることが重要です。 この作業もエクセル( Excel )で行うことが多いでしょうか。 無理のない担当者 アサイ ン タスクに担当者を アサイ ンしていく段階で否が応でもリソース管理が意識できます。 個人に焦点を充てれば、タスクの重なりもすぐに気付くことができるので ガントチャート ではある期間にリソースが集中してしまうことを防ぐことができます。 ガントチャート を作成・使用する際の注意点 作業順序に誤りがないか あるタスクは前工程の作業が完了していないと進めれられない事があります。 ただ単に担当者と日程を割り振るだけではなく、タスクの依存関係を考慮して担当者と日程を アサイ ンしましょう。 タスクやリソースの重複がないか このタスクは誰誰さんしかできない。などとどうしてもプロジェクトの中心メンバーに大事なタスクが集中しがちです。 ですが、1人は同時に複数のタスクをするにも限界があり、進捗遅れの原因になります。 なるべく同時期に1人に複数のタスクが アサイ ンされないようスケジュールを組んでいきましょう。 情報が最新化されているか プロジェクトでは予期せぬトラブルはつきものです。 タスクの抜けがあった、進捗が遅れた等、様々な要因によってスケジュールは変更が必要とされます。 そういった変更を ガントチャート に反映しないと、 ガントチャート 自体が形骸化してしまい、全体進捗を把握するという ガントチャート の旨味が消えてしまいます。 ツール紹介 ガントチャート を実際に使うときの代表的な3ツールを紹介させていただきます。 エクセル( Excel ) まずは皆さんの使いなれているエクセル( Excel )です。 ガントチャート を作るうえでエクセル( Excel )の良いところはすべてにおいて万能なところです。 ・任意で管理項目を増やしたい ・タスクが増えてきたので別途切り出したい ・担当者別に見たい ・完了したタスクは非表示にする ・一度作ったタスクをコピペして新しいタスクを作成する 等といったことが エクセル( Excel )では容易できます。 初めて ガントチャート を使い始める人にはまずエクセル( Excel )をお勧めします。 逆にエクセル( Excel )の悪いところは ・タスク アサイ ン時に通知することができない。 ・スケジュール全体を変更する際にの手間が多い。 等と言ったことが挙げられます。 ここでエクセル( Excel )での ガントチャート の作り方を2つ紹介させていただきます。 ・セルを塗潰し方式 担当者のスケジュール アサイ ン部分の日程をエクセル( Excel )のセルに塗りつぶしていく形式です。 エクセル( Excel )を利用した原始的な方法ではありますが簡易に作ることができ、このフォーマットを流用されるケースが多いです。 担当者ごとに色を変えることで、見た目で担当者を判断することができます。 またエクセル( Excel )のフィルターを利用すれば、各担当者にフォーカスして個人スケジュールを把握することもできます。 デメリットはスケジュールの変更にともないエクセル( Excel )のセルをペタペタと切り貼りする 工数 が多いことになります。 エクセル( Excel )セルを塗潰し方式 ・関数編 エクセル( Excel )関数で ガントチャート に対応する方法を紹介させていただきます。 ベースの表は先ほど紹介させていただいたエクセル( Excel )のセルを塗潰し方式と変わりありません。 セルを塗りつぶしていた部分をエクセル( Excel )のIF関数を利用して自動的に表示する方法になります。 「日付」開始日」「終了日」の3つのセルを利用して、該当のタスクのスケジュールに該当する日かを判定して「■」を表示しています。 エクセルの式は右記の通りです =IF(AND($E5<=K$2,K$2<=$F5),"■","") 「日付」K2のセルのと、「開始日」E5のセルと「終了日」F5のセルをIF関数で比較して ・開始日と終了日の間にあれば「日付」K5のセルに「■」を表示 ・開始日と終了日の間になければ「日付」K5のセルは空白 と判断しています。 簡単なエクセル( Excel )関数なので皆様も使ってみたり、アレンジしてみてください。 見た目をもっと良くしようと思うなら、条件付き書式を利用することでセルの色を変えることもできます。 エクセル( Excel ) IF関数 Redmine Redmine で簡易に ガントチャート を使用することができます。 ・チケットがそのまま ガントチャート になり、改めて ガントチャート を作る手間が必要がない。 ・チケットと完全連携できる ・担当者 アサイ ンやチケットの変更があった時にメール通知することができる といった事が最大のメリットになるでしょう。 Redmine をプロジェクト管理・タスク管理に使用している方も多いと思います。 その時にあまり手間をかけずに ガントチャート を使ってみたいという方にお勧めです。 あくまで簡易なので、いろいろな不都合はあります。 ・担当者ごとのスケジュールを見るのが手間 ・タスク登録が手間 ・完了したタスクを非表示にできないので縦に長くなる ・見た目が質素 などなど redmine.jp Brabio Brabioは ガントチャート の作成・更新の手間をなるべく効率化するための クラウド のツールになります。 5人まではフリーで使用できるのでぜひお試しで使ってみてください。 「 ガントチャート 作るならエクセルの10倍速い」の謳い文句の通りドラッグでタスク登録や コピー機 能など、タスク登録や変更をアシストしてくれるUIがとても充実しています。 工数 管理ができないことが玉に瑕ですが、Web上での登録の煩わしさはかなり軽減されています。 といっても、エクセルのUIの簡易さ、拡張性の高さに比べれば見劣りするところもあります。 ただBrabioはエクセル出力する事もできるので、 ガントチャート の大枠をBrabioで作成し エクセルでダウンロードしてあとはエクセル管理に切り替えるということも可能です。 Brabio brabio.jp おわりに 最後に ガントチャート の書き方で参考になる書籍をご紹介。 www.amazon.co.jp www.amazon.co.jp この記事は ラクス Advent Calendar 2020 - Qiita の2日目に参加しています。 よければ是非 ラクス Advent Calendar 2020 - Qiita も覗いてみてください。 今回は ガントチャート について説明させていただきました。 プロジェクト管理とは切っても切り離せないスケジュール管理をガントーチャートを使って プロジェクトメンバーと一緒に、抜け漏れなく、効率良く対応していきましょう。 本記事の内容が多くのプロジェクトのお役に立てますと嬉しいです。 それでは! エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
id:radiocat です。11/17~18に開催された Agile Japan 2020で登壇の機会を頂きましたのでレポートします。 Agile Japanとは スポンサーとしても参加 イベントの風景 変わる勇気・変えない勇気 登壇の現場 セッション紹介:「中小企業のエンジニアチームを”楽”にする」を目指す組織マネジメントの変わる勇気と変えない勇気 なぜアジャイル?なぜビジョン? チームにアジャイルを取り入れてカイゼン文化を生み出す ビジョンを生み出してヤクの毛刈りから脱出 ビジョンづくりを継続して自己目的化から脱出 私たちの「変わる勇気と変えない勇気」 Agile Japanとは 今年で12年目となる日本最大規模の アジャイル のイベントです。今年は5月に東京で開催される予定でしたが、コロナの影響でいったん中止となったあと、改めてオンライン方式でこの11月に開催されることになりました。 2020.agilejapan.jp スポンサーとしても参加 弊社はスポンサーとしても参加させて頂いており、公式サイトのセッションスケジュールのページにはしっかりと弊社のバナーが表示されていました。ありがとうございます。 セッションスケジュールのページに表示されている弊社のバナー 実は昨年もスポンサーとして参加させて頂き、ブログ記事を投稿しています。 tech-blog.rakus.co.jp イベントの風景 今回のイベントは eventhub というプラットフォーム上で配信されました。セッション動画が2トラック並行で ライブ配信 され、画面右ではslidoで質疑応答が行えるようになっていました。 Agile Japan 2020 オンライン会場 同じ画面上でセッションスケジュールや運営からのお知らせを確認したり、参加者同士の情報交換のためのメッセージ機能もありました。他にもスポンサーの出店ブースで資料をダウンロードしたり、参加者のスケジュールを押さえて個別ミーティングを行う機能もあり、リアルイベントの会場で行っていたことがそのままオンライン会場で再現されていました。オンラインイベントの進化を感じます。 変わる勇気・変えない勇気 今年のイベントテーマは「変わる勇気・変えない勇気」でした。公式サイトのメッセージには、 アジャイル の広まりや日本経済の状況などを踏まえ、今までの仕組みや習慣を見つめ直して未来へ向けてチャレンジする時が来たと言えますが、すぐに変えられない部分も多くあり、変わる部分と変えない部分を勇気を持って見極めていきましょうと書かれています。 このテーマを踏まえて弊社からもセッション公募に応募させて頂き、登壇の機会を頂きました。 登壇の現場 イベントは平日の昼間に開催ということで、オフィスの会議室からオンライン登壇させて頂きました。大阪のオフィスからでも手軽に参加できる点はオンラインイベントならではです。 オフィスの会議室からオンライン登壇 セッション紹介:「中小企業のエンジニアチームを”楽”にする」を目指す組織マネジメントの変わる勇気と変えない勇気 ここからは登壇させて頂いたセッション内容をご紹介します。 なぜ アジャイル ?なぜビジョン? 今回は「ビジョン」という言葉に焦点を当てて、 アジャイル とビジョンについてお話ししました。 Agile Japan 2018のテーマは「Why Agile 」でした。「なぜ アジャイル に取り組むのか?」ということが語られる背景として、 アジャイル を取り入れること自体を目的にすることの危険性がよく叫ばれています。また、ヤクの毛を刈るように アジャイル に取り組むことだけを続けてしまい、組織が本来目指すべき大きな目標を見失ってしまうこともあります。 この発表では、私たちのチームがWhyと向き合って アジャイル を取り入れ、ビジョンを生み出すことで、ヤクの毛刈りや自己目的化から脱出してきた事例をお伝えしました。 チームに アジャイル を取り入れて カイゼン 文化を生み出す 2019年に現在のチーム体制がスタートし、チームの立ち上げを図る中で最初に目指したのが アジャイル を取り入れながら カイゼン 文化を生み出すことでした。 まずは PDCAサイクル を習慣化するために、1週間単位の計画をしっかり立てて、その後ふりかえりを導入しました。そして、スケジュールマネジメントを強化するためにスプリント制度を導入し、チームのパフォーマンスを最大化するためにサブチーム体制へ移行しました。 アジャイル の要素を少しずつ取り入れて カイゼン 文化を定着させ、チームの成長を実感することができました。しかし一方で、 カイゼン に終わりがなく、 スクラム も未定着でした。 スクラム の要素であるスプリント制度を導入してはいますが、この時点ではまだ反復開発と呼んでおり、 スクラム の要素をすべて取り入れることはできていませんでした。 カイゼン には終わりがなく、いつ スクラム になるのかも見えていない、まさにヤクの毛刈り状態です。「みんなで アジャイル 」には「 アジャイル の旅を成功させる第一歩は、そもそもなぜ仕事のやり方を変えたいのかを理解することだ。」と書かれています。私たちはなぜ アジャイル を取り入れて カイゼン 文化を生み出した先で何を実現したいのか?と考えることにしました。つまり、チームのビジョンを生み出すということです。 ビジョンを生み出してヤクの毛刈りから脱出 書籍「ザ・ビジョン」によると、以下のようにビジョンを生み出す3つの基本要素が紹介されています。 有意義な目的 明確な価値観 未来のイメージ 弊社は「中小企業を楽にする」という理念を掲げています。限られたリソース、規制やルールのしがらみに縛られることも多いのが中小企業です。私たち自身もその環境に身を置いています。まず、中小企業のエンジニアチームである私たちがこれまでに取り組んできた「 アジャイル を土台にした カイゼン 文化」を継続して、チームの一人ひとりが成長することが、有意義な目的であり、明確な価値観であると考えました。 そして、私たちの有意義な目的と明確な価値観を具体化していく取り組みをそのままモデルにすることを未来のイメージと捉えました。これらを踏まえて定義したのが「中小企業のエンジニアチームを”楽”にするモデルをつくる」というビジョンです。 そして、ビジョンに向けて段階的に アジャイル を取り入れていくロードマップを作成しました。まずはチームビルディングを行って、アウトプットを安定化します。次に、パフォーマンスアップを目指して、リリース速度を上げ、プロダクトアウトカムを強化します。そして、変革・再ビルディングのためにチームをスケールアップさせ、最後にこれらの取り組みをモデル化するというロードマップです。 アジャイル を土台にしてビジョンを生み出したことで、この先にどうありたいのか?を明確にすることができ、チームの実態をふまえて今後どのように成長していくかのイメージが持てるようになりました。一方で、具体的なアクションは決まっていないので、チームの全員が完全に腹落ちしているわけでもない課題がありました。 実際にその課題がすぐ表面化しました。ロードマップの2つめのステージである「リリース速度アップ」は実態にあっていないことがわかりました。 アジャイル を取り入れることが目的となってしまい、実態と合わない目標になっていたのです。つまり、自己目的化に陥っていました。 前出の書籍「ザ・ビジョン」には「ビジョンづくりは現在進行系のプロセスであり、たえずそれについて話し合っていく必要がある。」と書かれています。ビジョンを実現するためには、何がいちばん大切なのかを思い出させて、みんながビジョンを見失わないように助け、可能な限り障害を取り除いて、ビジョンづくりを継続する必要があるのです。 ビジョンづくりを継続して自己目的化から脱出 ビジョンはつくっただけではなく、継続的につくり続ける必要があることに気づいた私たちは早速ロードマップを見直しました。実態に沿っていない「リリース速度アップ」への取り組みをいったん保留し、まずプロダクトアウトカム強化に取り組むことにしました。事業部門との連携を強化し、「 プロダクトマネジメント 体制」を構築しました。これまで取り入れてきた アジャイル を継続しながら、プロダクトにフォーカスしていく体制を目指しています。 サブチーム体制も実態に合わせて見直しました。開発力が安定してきたので、オフショアチームの支援を開発リード側のサブチームに移し、よりプロダクト開発に注力する体制にしました。また、オペレーションリード側はチームの成長を目指してDevOpsなどの新たなテーマに取り組む体制にしています。 チームがビジョンを見失わないように様々な取り組みを行っています。半期ごとのチーム目標設定の際には、必ずビジョンとそれに向けた現状をおさらいしています。1on1ではフラットな相談だけでなく、チームのビジョンと個人の成長目標のすり合わせを行っています。ビジョンに向けて ドラッカー 風エクサイズを行ってチーム内の価値観のすり合わせも行いました。中堅メンバー中心にロードマップの次の戦略を考えるチーム戦略会議も行っています。 また、ビジョンを浸透させるためにビジョンに向けたアウトプットも行っています。自社で開催しているイベントやエンジニアブログで、ビジョンへ向けた取り組み事例を紹介しています。今回の アジャイル ジャパンのようなイベントでの発信もビジョンを浸透させるアウトプットのひとつです。 アウトプットすることで、自分たち自身のビジョンに対する認識を定着することにつながります。ただ、イベントへの参加やブログの発信などは、採用や ブランディング など会社としての別の目的もあります。それらとチームのビジョンをすり合わせながら、積極的に関わりを持つことが、チームのビションづくりを継続させます。1つひとつは小さいアウトプットでも、モデルをつくるという自分たちのビジョンに向けた意思表示を継続することで、小さく試して育てていくことにつながると考えています。 私たちの「変わる勇気と変えない勇気」 最後に、私たちの「変わる勇気と変えない勇気」についてまとめます。変わる勇気とは、 アジャイル を土台にしたチームのスタイルです。変えない勇気とは、ビジョンに向かう姿勢です。 アジャイル を土台にしたチームのスタイルは、 カイゼン を続けたり、アクションを見直し続けるために、常に変わる勇気が必要です。ビジョンに向かっていく姿勢は、 スクラム への適応をチームの目標にせずにビジョンづくりを継続し、ビジョンに向けたチームの取り組みをアウトプットし続けるという、姿勢を変えない勇気が必要です。2つの勇気を継続することで、チームの現状は少しずつ スクラム にも近づいています。 ビジョンに向かっていく姿勢を変えない勇気をもつことで、 アジャイル を土台にして常に変わっていく勇気を生み出すのです。 以上のように、 アジャイル とビジョンはチームの継続的な成長につながると考えています。そのために私たちが取り組んでいるのが、 カイゼン 文化を生み出して、ビジョンを生み出し、継続していくという、3つのステップです。この内容が中小企業のエンジニアチームの皆さんの継続的な成長のお役に立てれば幸いです。 継続的な成長のために仲間を募集しています 私たちのチームでは スクラム マスターを募集しています。スライドでもご紹介した「ビジョンづくりを実現するリーダーシップ」を発揮して、私たちのチームで一緒に働いてみませんか? もちろん、 スクラム マスター以外の様々な職種も募集中です。よろしければぜひご連絡ください。 career-recruit.rakus.co.jp
アバター