Slide 1

Slide 1 text

フルスタックエンジニアとしてゼロ からサービスを作る時に 考えていること 田中 友彩

Slide 2

Slide 2 text

田中 友彩(たなか ゆい) •所属 AI事業本部 CyberPOP •職種 フルスタックエンジニア 商談からはじめ、インフラ、サーバーサイド、 Webフロント、Android、iOSまで一気通貫です •最近よく使う技術 Nuxt.js, Typescript, Golang, Kotlin, AWS, GCP, Terraform, Datadog ML系など   @yuit1552

Slide 3

Slide 3 text

はじめに 最近一人で構築したサービスを例に、 •開発の各ポイントでどういう思想で設計・構築したか •フルスタックエンジニアの視点でみたときの発想 などのお話をしようと思います。

Slide 4

Slide 4 text

1.ソーシャルアプリをゼロから構築したときの話 2.ニュース配信サイトをゼロから構築したときの話

Slide 5

Slide 5 text

ソーシャルアプリを ゼロから構築したときの話

Slide 6

Slide 6 text

要件の内容を整理 要件定義 基本設計 詳細設計 PG ソーシャルアプリとして考えると •会員の登録、プロフィール閲覧などができる •文章、つぶやき、画像などの投稿ができる •他の会員の内容、投稿などを検索できる •他の人と交流できるような仕掛けがある (いいね、フォロー、返信、DMなど)

Slide 7

Slide 7 text

要件の内容を整理 もう少し細かいこと考えると、例えば •ハッシュタグ、レコメンドなど検索する仕掛けをどうするか •いいねなどのリアクションに対するリアルタイム性をどうするか •DMにはグループDMなど、付加機能をどこまで持たせるか •既存システムがある場合アカウントを共通化するか などなど 要件定義 基本設計 詳細設計 PG

Slide 8

Slide 8 text

要件定義で特に意識していること •企画者の要望をどうやったら叶えられるか案を提案する •実現可否をはっきり伝える •やりたいことに対しての落とし所を見つける 要件定義 基本設計 詳細設計 PG

Slide 9

Slide 9 text

要件定義で特に意識していること •企画者の要望をどうやったら叶えられるか案を提案する •実現可否をはっきり伝える •やりたいことに対しての落とし所を見つける 要件の認識のズレやモレを できる限り少なくすること 要件定義 基本設計 詳細設計 PG

Slide 10

Slide 10 text

落とし所のポイント リリースしたい時期はいつか? 予算は? 大体この観点で落とし所話します。 要件定義 基本設計 詳細設計 PG

Slide 11

Slide 11 text

リリース時期について •一刻も早く出したい、という場合 要件定義 基本設計 詳細設計 PG

Slide 12

Slide 12 text

リリース時期について •一刻も早く出したい、という場合 →理由 例えば、競合他社がいて、他社より 早めに出して先攻有利性を取りたい 要件定義 基本設計 詳細設計 PG

Slide 13

Slide 13 text

リリース時期について •なるべく早くしたいが、○○の機能はどうしても欲しい 要件定義 基本設計 詳細設計 PG

Slide 14

Slide 14 text

リリース時期について •なるべく早くしたいが、○○の機能はどうしても欲しい →理由 例えば、後発サービスなので、ある程度遅くてもい いが、画期的な○○な機能が欲しいから、機能を優 先させたい 要件定義 基本設計 詳細設計 PG

Slide 15

Slide 15 text

この案件の落とし所 ソーシャルとしては後発サービスだが、 ・狙っているターゲット層が他サービスと異なる ・メインで考えている○○の機能は他にない などから、結果的に競合にならないと判断でき、 ある程度機能を優先することに。 要件定義 基本設計 詳細設計 PG

Slide 16

Slide 16 text

もちろん最初から全部入れるのは辛いので優先度をきめ、 必須にしたものは この案件の落とし所 要件定義 基本設計 詳細設計 PG

Slide 17

Slide 17 text

もちろん最初から全部入れるのは辛いので優先度をきめ、 必須にしたものは この案件の落とし所 既存システムとのアカウント共通化 要件定義 基本設計 詳細設計 PG

Slide 18

Slide 18 text

新しいサービスを作った時一番最初の時点で、 その後の運営側のサービス展開を考えてプラットフォーム構 想を想定して作るケースって業界的に結構少ないと思いませ んか? 既存システムとのアカウント共通化 要件定義 基本設計 詳細設計 PG

Slide 19

Slide 19 text

システムごとにユーザー管理機能を作ってることが多いの で、共通プラットフォーム化する場合の アカウントを統合する時、大変だった人が少なからずいると思 います^^; 既存システムとのアカウント共通化 要件定義 基本設計 詳細設計 PG

Slide 20

Slide 20 text

•運営してるサービスはRailsで出来た画面とビジネスロジックが結構絡 み合ったモノリスなサービス •認証機能もRails用の認証ライブラリ「Sorcery」に完全に依存して全部 くっついていた •だいぶ大きなモノリスになってたので認証APIをRailsに用意しても高負 荷に耐えられそうにないし、メインサービスに影響がでる 既存システムの状態 要件定義 基本設計 詳細設計 PG

Slide 21

Slide 21 text

完全に新規で作ってしまうのと既存ユーザーにアカウントの移行作業を してもらう必要がありますよね(時々そういうサービスあるかと思います) そうすると、そこでサービスを離脱してしまうユーザーがいると思うので、 既存サービスのアカウントと互換させつつ新認証基盤を作ったほうがい いと思い、 企画者に提案したところ、OKをもらえたので 新認証基盤の検討 要件定義 基本設計 詳細設計 PG

Slide 22

Slide 22 text

これ以上絡み合う前に新認証基盤を マイクロサービスで作っちゃおう!

Slide 23

Slide 23 text

互換性を保つ場合の一番のポイントとして考えたのは 認証基盤を作る上で 要件定義 基本設計 詳細設計 PG

Slide 24

Slide 24 text

互換性を保つ場合の一番のポイントとして考えたのは 認証基盤を作る上で パスワードの暗号化(ハッシュ化)アルゴリズムが同 じであること 要件定義 基本設計 詳細設計 PG

Slide 25

Slide 25 text

パスワードを保存する方法の王道パターンとしては、非可逆系のハッ シュ化(MD5,SH256, BCryptなどなど)を使うことと、それと組み合わせる、 ストレッチ、ペッパー、ソルトなどの手法かと思います。 認証基盤を作る上で 要件定義 基本設計 詳細設計 PG

Slide 26

Slide 26 text

パスワードさえどうにかなれば、あとは辻褄を合われば良いと 思ったので、既存システムと互換性を保てるかどうかを判断するため、 この要件定義の時点で、実現性の検証の工数を数日もらいました。 認証基盤を作る上で 要件定義 基本設計 詳細設計 PG

Slide 27

Slide 27 text

「Sorcery」のソースコードを調べて、 そのシステムでどう使ってるかを分析した結果、状態がわかり 利用しているアルゴリズムも大丈夫そうだったので 検証にて 要件定義 基本設計 詳細設計 PG

Slide 28

Slide 28 text

「Sorcery」のソースコードを調べて、 そのシステムでどう使ってるかを分析した結果、状態がわかり 利用しているアルゴリズムも大丈夫そうだったので 検証にて Golangでその処理を再現しました 要件定義 基本設計 詳細設計 PG

Slide 29

Slide 29 text

既存の「Sorcery」で作ったアカウントが Golangの検証APIでログインできることまで確認できたので、そのまま突 き進むこととなりました。 検証の結果 要件定義 基本設計 詳細設計 PG

Slide 30

Slide 30 text

次に基本設計

Slide 31

Slide 31 text

要件定義で作る機能の方向性をあらかた決めたので、 基本設計で決めたことは、ざっくりいうと •画面の下書き(ワイヤーフレーム)を作ってもらう •デザイナーさんに、デザインコンセプトとか作ってもらう •必要なデータを考える 基本設計の方向性 要件定義 基本設計 詳細設計 PG

Slide 32

Slide 32 text

基本設計の方向性 まず、画面のワイヤーとデザインについて話しましたが、 企画者とデザイナーさんと話す時に最初に伝えたことは 要件定義 基本設計 詳細設計 PG

Slide 33

Slide 33 text

•スマホアプリとWebで同じデザインでも再現難易度が違うので、どちら でもブレにくいマテリアルデザインを基本としてデザインを作って欲しい 基本設計の方向性 要件定義 基本設計 詳細設計 PG

Slide 34

Slide 34 text

•スマホアプリとWebで同じデザインでも再現難易度が違うので、どちら でもブレにくいマテリアルデザインを基本としてデザインを作って欲しい •全画面作ると時間かかると思うので、テーマカラーや数ページ基本と なるコンポーネントを含む画面をデザインしてもらい、他の画面はある 程度私にお任せして欲しい。 基本設計の方向性 要件定義 基本設計 詳細設計 PG

Slide 35

Slide 35 text

基本設計の方向性 デザインと画面仕様がカッチリきまってしまうと、、、 例えば、一覧系画面はどうしてもページングがいい と言われると、 要件定義 基本設計 詳細設計 PG

Slide 36

Slide 36 text

基本設計の方向性 検索結果をサマリーしにくいNoSQLとか 使いづらくなったりとか(ロジックで頑張れば、、、) デザインと画面仕様がカッチリきまってしまうと、、、 例えば、一覧系画面はどうしてもページングがいい と言われると、 要件定義 基本設計 詳細設計 PG

Slide 37

Slide 37 text

基本設計の方向性 逆にデータ設計をガチガチに固めてしまうと、、、 例えば、RDBだとGroup byで検索結果の countが取れるからsummaryはしやすいので、 ページングは作りやすい 要件定義 基本設計 詳細設計 PG

Slide 38

Slide 38 text

基本設計の方向性 DynamoDBのようなNoSQLだと全体のカウントととりづらいの で、ページングしづらい。(Scan使うとフルスキャンになるし)な ので「もっと見る」的なUIに制限してもらうことがある。 要件定義 基本設計 詳細設計 PG

Slide 39

Slide 39 text

そういったところふまえ、 画面の落とし所を決めました

Slide 40

Slide 40 text

データ設計について ソーシャルアプリなので、 •プロフィールなどユーザー関連のデータ •投稿に関するデータ •フォローやいいねなど、ユーザーの出会いのきっかけを作る系のデー タ •ハッシュタグなど検索しやすくするためのデータ  等々 要件定義 基本設計 詳細設計 PG

Slide 41

Slide 41 text

データ設計について 必要なデータはいろいろあると思いますし、データの リレーションや依存性など考えることはいろいろ ありますが、ここで気にしたポイントとしては、 要件定義 基本設計 詳細設計 PG

Slide 42

Slide 42 text

データ設計について 必要なデータはいろいろあると思いますし、データの リレーションや依存性など考えることはいろいろ ありますが、ここで気にしたポイントとしては、 扱うデータの性質を考える 要件定義 基本設計 詳細設計 PG

Slide 43

Slide 43 text

データ設計について 簡単にいうと、そのデータは 要件定義 基本設計 詳細設計 PG

Slide 44

Slide 44 text

データ設計について 簡単にいうと、そのデータは •読み込みが多いか 要件定義 基本設計 詳細設計 PG

Slide 45

Slide 45 text

データ設計について 簡単にいうと、そのデータは •読み込みが多いか •書き込みが多いか 要件定義 基本設計 詳細設計 PG

Slide 46

Slide 46 text

データ設計について サーバーサイド、インフラ視点でそこを気にする ポイントの大体は 要件定義 基本設計 詳細設計 PG

Slide 47

Slide 47 text

データ設計について サーバーサイド、インフラ視点でそこを気にする ポイントの大体は 大量のアクセス、データをどう早くさばくか? 要件定義 基本設計 詳細設計 PG

Slide 48

Slide 48 text

データ設計について 読み込みが多いデータをさばく手段として、例えば 要件定義 基本設計 詳細設計 PG

Slide 49

Slide 49 text

データ設計について 読み込みが多いデータをさばく手段として、例えば •RDBを使っている場合、Master、Slave構成にする 要件定義 基本設計 詳細設計 PG

Slide 50

Slide 50 text

データ設計について 読み込みが多いデータをさばく手段として、例えば •RDBを使っている場合、Master、Slave構成にする •CDNを使ってAPIやページごとキャッシュする 要件定義 基本設計 詳細設計 PG

Slide 51

Slide 51 text

データ設計について 読み込みが多いデータをさばく手段として、例えば •RDBを使っている場合、Master、Slave構成にする •CDNを使ってAPIやページごとキャッシュする •RedisやMemcachedなどインメモリでキャッシュする 要件定義 基本設計 詳細設計 PG

Slide 52

Slide 52 text

データ設計について 読み込みが多いデータをさばく手段として、例えば •RDBを使っている場合、Master、Slave構成にする •CDNを使ってAPIやページごとキャッシュする •RedisやMemcachedなどインメモリでキャッシュする などなど、キャッシュを頼ることが多いかと思います 要件定義 基本設計 詳細設計 PG

Slide 53

Slide 53 text

データ設計について 書き込みが多いデータをさばく手段として、例えば 要件定義 基本設計 詳細設計 PG

Slide 54

Slide 54 text

データ設計について 書き込みが多いデータをさばく手段として、例えば •書き込み基本性能の高いNoSQL系に保存する 要件定義 基本設計 詳細設計 PG

Slide 55

Slide 55 text

データ設計について 書き込みが多いデータをさばく手段として、例えば •書き込み基本性能の高いNoSQL系に保存する •書き込む値が複数ある場合並列化するなどロジックで頑張 る 要件定義 基本設計 詳細設計 PG

Slide 56

Slide 56 text

データ設計について 書き込みが多いデータをさばく手段として、例えば •書き込み基本性能の高いNoSQL系に保存する •書き込む値が複数ある場合並列化するなどロジックで頑張 る •即時性を求めない場合は、Queueなどに入れて逐次処理 要件定義 基本設計 詳細設計 PG

Slide 57

Slide 57 text

データ設計について 書き込みが多いデータをさばく手段として、例えば •書き込み基本性能の高いNoSQL系に保存する •書き込む値が複数ある場合並列化するなどロジックで頑張 る •即時性を求めない場合は、Queueなどに入れて逐次処理 •インメモリに一時的に書き込みあとで永続化 などなど 要件定義 基本設計 詳細設計 PG

Slide 58

Slide 58 text

データ設計について 基本設計の時点でそこまで考えるのか? というのもありますが、なぜかというと、例えば 要件定義 基本設計 詳細設計 PG

Slide 59

Slide 59 text

データ設計について 基本設計の時点でそこまで考えるのか? というのもありますが、なぜかというと、例えば 「DynamoDBは料金も安いし、オートスケールしてくれるしパ フォーマンスも良いから使おう」 要件定義 基本設計 詳細設計 PG

Slide 60

Slide 60 text

データ設計について 基本設計の時点でそこまで考えるのか? というのもありますが、なぜかというと、例えば 「DynamoDBは料金も安いし、オートスケールしてくれるしパ フォーマンスも良いから使おう」 と思って採用したとします 要件定義 基本設計 詳細設計 PG

Slide 61

Slide 61 text

データ設計について DynamoDBは仕組み上、検索パフォーマンスを出すために Queryを使う場合、複合条件が2つまでかつ、それを5パター ンしか作れないという制限があったりします。 要件定義 基本設計 詳細設計 PG

Slide 62

Slide 62 text

データ設計について ECサイトなど絞り込み条件が多いサイトだと、複合条件が、い くら以上で、カテゴリがこれで、メーカーはこれで、色は、、、み たいな複雑な条件がありますが、DynamoDBでは検索機能を 充実させることが結構つらかったりします。 要件定義 基本設計 詳細設計 PG

Slide 63

Slide 63 text

データ設計について 検索条件などを充実させたい場合は、RDBが有効だったりす るので、そうするとRDBとNoSQLだとデータの関連性の考え方 が違うので、データ設計に影響してきます。 (NoSQLは結構、非正規化しないと扱えなかったり) 要件定義 基本設計 詳細設計 PG

Slide 64

Slide 64 text

データ設計について なので、この時点で、 •扱うデータの性質を見極め採用するものを決める •対策が必要になった時の回避策が使えるか考えておく 要件定義 基本設計 詳細設計 PG

Slide 65

Slide 65 text

データ設計について このソーシャルアプリで扱うデータは基本ユーザー自身が中 心なので、比較的単純なデータが多く、NoSQLでもRDBでもど ちらでも問題なかったので、料金が安くと基本パフォーマンス が高いDynamoDBを採用しました。 要件定義 基本設計 詳細設計 PG

Slide 66

Slide 66 text

データ設計について 他、性能が良く複雑なクエリを扱えるものだとクラウドでいえ ば、 •Amazon Aurora •Amazon DocumentDB •Cloud Spanner とかあると思いますが、 要件定義 基本設計 詳細設計 PG

Slide 67

Slide 67 text

データ設計について 料金が結構するので予算のあるサービスであればいいです が、スタートアップ系だと予算が限りなく少ないので、初回は 選択肢にならないことが多いかと思います 要件定義 基本設計 詳細設計 PG

Slide 68

Slide 68 text

基本設計しめ このサービスも予算が少ないのでDynamoDBを採用しました が、読み込みが多いデータにはキャッシュを駆使したり、ロ ジックでカバーしたりと料金を抑えつつ、工夫して構築する方 向性にしました。 要件定義 基本設計 詳細設計 PG

Slide 69

Slide 69 text

次に詳細設計・PG

Slide 70

Slide 70 text

採用したもの インフラ 全てAWS。Terraformでコード化 ● ECS Fargate ● DynamoDB ● RDS (MySQL) ● AppSync ● CloudFront ● Elasticache(Redis) ● Lambda ● Pinpoint ● Amplify ● Cognito ● Code Pipeline ● Route53 など Androidアプリ Android Architecture Components を基本としたMVVM ● ViewModel ● LiveData ● Room ● coroutine-flow ● retrofit2 ● okhttp3 ● groupie ● threetenabp ● glide ● koin など サーバーサイド Golangでマイクロサービス ● go-chi ● grpc ● gorm ● cobra ● zap ● robfig/cron など Webフロント Nuxt.jsでBFF入れつつvuetify ● Nuxt.js ● TypeScript ● tsconfig-paths ● Vuetify ● grpc_tools_node_protoc_ts ● prettier ● express など 要件定義 基本設計 詳細設計 PG

Slide 71

Slide 71 text

インフラの概要 ECS Fargate ・・・ コンテナオーケストレーション DynamoDB ・・・ NoSQL のDB RDS(MySQL)・・・RDB CloudFront ・・・CDN ElastiCache ・・・インメモリキャッシュ Lambda  ・・・みんなよく使うと思うサーバーレス Amplify  ・・・スマホアプリなどを作るのに最適なAWSのいくつかのサービスをまとめ+それを使いやすくしたツールのセット AppSync ・・・GraphQLの マネージド(Amplifyの一貫にもなってる) Pinpoint  ・・・Push通知(Amplifyの一貫にもなってる) Cognito  ・・・認証基盤(Amplifyの一貫にもなってる) Route53  ・・・DNSサーバーとかドメイン管理。 要件定義 基本設計 詳細設計 PG

Slide 72

Slide 72 text

インフラの概要 ECS Fargate を採用した理由 • インスタンスそのものを管理しなくていい → OSの脆弱性パッチ当てとかしなくていい • AWSの他サービスと親和性高い→EC2とか使ってても乗り換えが比較的容易 • ECS Fargateのversion up の頻度はかなりゆっくりなのでversionの追従が楽 要件定義 基本設計 詳細設計 PG

Slide 73

Slide 73 text

インフラの概要 ECS Fargate を採用した理由 • インスタンスそのものを管理しなくていい → OSの脆弱性パッチ当てとかしなくていい • AWSの他サービスと親和性高い→EC2とか使ってても乗り換えが比較的容易 • ECS Fargateのversion up の頻度はかなりゆっくりなのでversionの追従が楽 一人でやったのでとりあえずお手軽なのが嬉しい( ^ω^ ) 要件定義 基本設計 詳細設計 PG

Slide 74

Slide 74 text

インフラの概要 他考えたサービス 大人気「kubernetes」、のマネージドEKS 別案件でGoogleのGKEを使っていたが、確かにPodのスケールがECSより早くスパイクに強かったり(設定次 第ではありますが)して非常に優秀だと思いますが、 要件定義 基本設計 詳細設計 PG

Slide 75

Slide 75 text

インフラの概要 他考えたサービス 大人気「kubernetes」、のマネージドEKS 別案件でGoogleのGKEを使っていたが、確かにPodのスケールがECSより早くスパイクに強かったり(設定次 第ではありますが)して非常に優秀だと思いますが、 • 頻繁にあるkubernetes本体のバージョンアップにノードを追従していくのが面倒  (特に一人でやってるとかなり面倒) 要件定義 基本設計 詳細設計 PG

Slide 76

Slide 76 text

インフラの概要 他考えたサービス 大人気「kubernetes」、のマネージドEKS 別案件でGoogleのGKEを使っていたが、確かにPodのスケールがECSより早くスパイクに強かったり(設定次 第ではありますが)して非常に優秀だと思いますが、 • 頻繁にあるkubernetes本体のバージョンアップにノードを追従していくのが面倒  (特に一人でやってるとかなり面倒) • デプロイの仕組みを独自につくる必要が結構ある (CI/CDはECSでも使うとしても、マニフェストファイル変更した時の扱いとかとか、、、) 要件定義 基本設計 詳細設計 PG

Slide 77

Slide 77 text

インフラの概要 他考えたサービス 大人気「kubernetes」、のマネージドEKS EKSもFargateが登場してからノードの管理が不要になりましたが、それでも頻繁に上がるversionへの追従 が大変なのと初回はやはり仕組み考えるのに時間かかるので、いくら高機能でも 要件定義 基本設計 詳細設計 PG

Slide 78

Slide 78 text

インフラの概要 他考えたサービス 大人気「kubernetes」、のマネージドEKS EKSもFargateが登場してからノードの管理が不要になりましたが、それでも頻繁に上がるversionへの追従 が大変なのと初回はやはり仕組み考えるのに時間かかるので、いくら高機能でも プロダクトの規模からすればオーバースペックだった (一人でkubeメンテつらい他もあるし、、、) 要件定義 基本設計 詳細設計 PG

Slide 79

Slide 79 text

インフラの概要 ということで、ECS Fargateを採用しました。 また、そのあとのデプロイなども楽にするため、こんな感じのお手軽パイプライン組みました。 GitHub Action上で ・docker build ・ECR へ docker push 要件定義 基本設計 詳細設計 PG

Slide 80

Slide 80 text

インフラの概要 ということで、ECS Fargateを採用しました。 また、そのあとのデプロイなども楽にするため、こんな感じのお手軽パイプライン組みました。 GitHub Action上で ・docker build ・ECR へ docker push Cloud Watch Eventで ECRを監視し、pushされたら CodePipeLine実行 要件定義 基本設計 詳細設計 PG

Slide 81

Slide 81 text

インフラの概要 ということで、ECS Fargateを採用しました。 また、そのあとのデプロイなども楽にするため、こんな感じのお手軽パイプライン組みました。 GitHub Action上で ・docker build ・ECR へ docker push Cloud Watch Eventで ECRを監視し、pushされたら CodePipeLine実行 buildステージは飛ばすように し、ECRからdockerイメージ を取得しdeploy 要件定義 基本設計 詳細設計 PG

Slide 82

Slide 82 text

インフラの概要 ECSがデプロイするまでの一連の全設定とパイプラインは、どのマイクロサービスでも大体変わらないため Terraformでこんな感じのmoduleを作ってマイクロサービス増えてもいいようにお手軽化。 要件定義 基本設計 詳細設計 PG

Slide 83

Slide 83 text

インフラの概要 ECSがデプロイするまでの一連の全設定とパイプラインは、どのマイクロサービスでも大体変わらないため Terraformでこんな感じのmoduleを作ってマイクロサービス増えてもいいようにお手軽化。 オプションとして、「private = true」 にしたらALB作らずServiceDiscoveryを利用した Internal Onlyなマイクロサービスに 要件定義 基本設計 詳細設計 PG

Slide 84

Slide 84 text

インフラの概要 ECSがデプロイするまでの一連の全設定とパイプラインは、どのマイクロサービスでも大体変わらないため Terraformでこんな感じのmoduleを作ってマイクロサービス増えてもいいようにお手軽化。 証明書を指定したら ALBを含んだpublicなマイクロサービスに 要件定義 基本設計 詳細設計 PG

Slide 85

Slide 85 text

インフラの概要 マイクロサービスごとに異なるロールの設定やTask定義はこんな感じでmoduleを指定する時に 渡すようにして柔軟性を持たせた マイクロサービスごとにことなるロール 要件定義 基本設計 詳細設計 PG

Slide 86

Slide 86 text

インフラの概要 マイクロサービスごとに異なるロールの設定やTask定義はこんな感じでmoduleを指定する時に 渡すようにして柔軟性を持たせた サイドカーとか違う場合の タスク定義のテンプレをいくつか用意 要件定義 基本設計 詳細設計 PG

Slide 87

Slide 87 text

インフラの概要 マイクロサービスごとに異なるロールの設定やTask定義はこんな感じでmoduleを指定する時に 渡すようにして柔軟性を持たせた それぞれ、moduleの呼び出し時に指定 要件定義 基本設計 詳細設計 PG

Slide 88

Slide 88 text

インフラの概要 もう一つインフラのはなしでは、Amplify、AppSync、Pinpoint、Cognitoあたりの話を。 AmplifyはCloudFormationやTerraformなどと考え方が似ていてサービスを構築管理するための サービス・ツール郡(フロントをつくるライブラリもありますけど)という感じです。 Terraformでインフラ構築してる場合で、AppSync、Pinpoint、Cognitoなど構築する時に、 Amplifyを使うか?Terraformで全部統一したいか? と実は選択肢があります。 要件定義 基本設計 詳細設計 PG

Slide 89

Slide 89 text

インフラの概要 私はとりあえず「Terraformで全部統一してみたい」と思い、最初は頑張って 「AppSync、Pinpoint、Cognito」あたりをTerraform書きました。 インフラ自体はできたのですが、、、 要件定義 基本設計 詳細設計 PG

Slide 90

Slide 90 text

インフラの概要 私はとりあえず「Terraformで全部統一してみたい」と思い、最初は頑張って 「AppSync、Pinpoint、Cognito」あたりをTerraform書きました。 インフラ自体はできたのですが、、、 Androidの実装するときに結局Amplifyコマンドや プラグインが必要になりました 要件定義 基本設計 詳細設計 PG

Slide 91

Slide 91 text

インフラの概要 AppSyncのスキーマを元に Androidのファイルを自動生成す るのでコマンドが必要でした Androidプラグインも必要 要件定義 基本設計 詳細設計 PG

Slide 92

Slide 92 text

インフラの概要 Pinpoint、Cognitoもインフラ自体はいけますが、Androidの呼 び出し時にAmplifyのSDKを呼び出すとかあったり、それぞれ 素のSDKでもいけますけど、AwsConfigの定義が自力だと管理 面倒だったので、この2つに関してはTerraformをやめて Amplifyで構築することにしました。 要件定義 基本設計 詳細設計 PG

Slide 93

Slide 93 text

インフラの概要 またAppSyncを採用した理由ですが、DMとかのリアルタイムの画面の変 化に対応するためWebSocketを使いたかったのですが、ゼロからの実 装は非常に面倒なので、AppSyncの@aws_subscribeでお手軽 WebSocketを使いました。 GraphQL自体の機能はほぼ使いませんでした( ̄▽ ̄) 要件定義 基本設計 詳細設計 PG

Slide 94

Slide 94 text

インフラの概要 GraphQLのメリットは、呼び出し側がQueryを書いて欲しいデータを欲しいものだけ可変にとれる。 というところがあると思います。API側は全部のデータが取れるように組む必要はあります。 通常はアプリとサーバーサイドと担当わかれてるので、JSONのAPIを使ってる場合とかだと、 項目なかったら増やして、、、とかそういうやりとりが発生するかと思います。 それのやりとりを軽減することができる手段の一つとしてGraphQLがあるかと思いますが、 (AppSync単体でみた場合は、オートスケールが楽だったりとかありますが) 要件定義 基本設計 詳細設計 PG

Slide 95

Slide 95 text

インフラの概要 フルスタックのメリットとしては、 項目足りなかったら自分でAPIいじればいいのでGraphQLつかわずともまったく問題は なく、またAppSyncではHttpProxyとかLambdaとかも使えますが、わざわざAppSync経由 させる必要はなく、直接アプリからAPIを呼びだた方が早くメンテしやすかったので純粋 なGraphQLとしての機能は、ほとんど使いませんでした(^^;) 要件定義 基本設計 詳細設計 PG

Slide 96

Slide 96 text

サーバーサイドの概要 APIは全てGolangで作りました。基本的な設計思想はGolangのコンセプトでもある、標 準ライブラリだけでAPIサーバーとか作れるというところが好きで、痒いところだけ、部 分的にライブラリを使うという感じにしました。なので巨大なフレームワークのコンセプト 系のライブラリは使いませんでした。 (そのフレームワークの書き方が基準になるため、やめようと思った時に大変になるか ら) 要件定義 基本設計 詳細設計 PG

Slide 97

Slide 97 text

サーバーサイドの概要 大きいフレームワーク的なライブラリで言うと、 JavaとかやってきてるとDIコンテナ(Springとか)とか良く使ってましたが、 GolangにもGoogle製の「Wire」とかがあったりします。 ためしてみましたが、どうしてもWireの書き方に依存するので、コンセプトから離れてい くなぁ、、、と思い採用はせず、Golangで良くやる、 最初の方でインスタンスを生成して渡していくことにしました。 要件定義 基本設計 詳細設計 PG

Slide 98

Slide 98 text

Androidアプリの概要 Android Architecture Component(AAC)を基本として作りMVVMで作りました。 SwiftだとRxSwiftや、AndroidにもRxJavaとかはあります。SwiftとかもSwiftUIが出てきたり、AndroidもAACが標 準になってきてるので、Rxは使いたくなくAACでいきました。 ただし、Rxであった便利な関数とかはAACになかったりするので、coroutine-flowを使って、 Rxであった便利関数に相当する機能使い補いました。 要件定義 基本設計 詳細設計 PG

Slide 99

Slide 99 text

Androidアプリの概要 このアプリを作った時に採用したDIコンテナライブラリの「Koin」 この子がすごくに気に入りました( ^ω^ ) 広く使われている「Dagger」とかもありますが、初回のお作法が面倒だったり、アノテーションがみずらかった りと、なんか昔ながらのDIコンテナだなぁ。。。と思ってたところとてもシンプルでかつ、AndroidのDI使わない 場合の書き方に近く、見やすいKoinに出会いました。 要件定義 基本設計 詳細設計 PG

Slide 100

Slide 100 text

Androidアプリの概要 インスタンス生成時 コンストラクタで受け取り たいインスタンスの型を指 定し 要件定義 基本設計 詳細設計 PG

Slide 101

Slide 101 text

Androidアプリの概要 定義したコンストラクタの分だ 実際のインスタンスを設定す る インスタンス生成時 要件定義 基本設計 詳細設計 PG

Slide 102

Slide 102 text

Androidアプリの概要 Koinの初期化 MainのApplication()で初期化 要件定義 基本設計 詳細設計 PG

Slide 103

Slide 103 text

Androidアプリの概要 利用する時も、ActitityやFragmentで こんな感じでDIされてるオブジェクト を取ってくる viewModel意外もInjectで呼び出し 呼び出し時 要件定義 基本設計 詳細設計 PG

Slide 104

Slide 104 text

やっぱりお手軽なのはいいですね!

Slide 105

Slide 105 text

と、ここでいろいろ触ってる立場で思い 立ったことが、

Slide 106

Slide 106 text

Golangのインスタンス生成するときに、 Koinの書き方参考にしたらみやすくで きるんじゃ!?

Slide 107

Slide 107 text

ということで、Golangのリファクタ

Slide 108

Slide 108 text

サーバーの話にちょっと戻って インスタンス生成時 引数で受け取りたい インスタンスの型を 指定し 要件定義 基本設計 詳細設計 PG

Slide 109

Slide 109 text

サーバーの話にちょっと戻って インスタンス生成時 こんな感じで定義した引数の 分だけ実際のインスタンスを 設定する 要件定義 基本設計 詳細設計 PG

Slide 110

Slide 110 text

サーバーの話にちょっと戻って インスタンス生成するための initializer.goというファイルを作っ て分割し 初期化の全体。 起動ロジックとかRoutingとかはこのファイルに含 めず、Usecase、 Repository、clinet、serviceな どのインスタンス生成だけを処理まとめる 要件定義 基本設計 詳細設計 PG

Slide 111

Slide 111 text

サーバーの話にちょっと戻って 初期化時 mainでinitializerを呼び出し 実際に初期化 要件定義 基本設計 詳細設計 PG

Slide 112

Slide 112 text

サーバーの話にちょっと戻って 呼び出し時 初期化したインスタンスを Routerに渡して使う structに保持している インスタンスを利用する 要件定義 基本設計 詳細設計 PG

Slide 113

Slide 113 text

見やすくなった!

Slide 114

Slide 114 text

こんな感じで、言語変わっても 設計思想は参考にできるとこはたくさ んあるので、いろいろな視点から コード書いてます

Slide 115

Slide 115 text

Webフロントの概要 Webフロントは、Nuxt.js(Vue)を採用しました。 理由としては、管理画面向けだったのでInputの要素が多く、 v-modelによる双方向バインディングが書きやすかったからです。 また、Nuxt.jsのServerMiddleWareで、Node.jSのBFF-API作って 画面用にちょっと加工するためのAPIとか用意しました (私のQiita記事とかでも書いてます) 要件定義 基本設計 詳細設計 PG

Slide 116

Slide 116 text

Webフロントの概要 ReactやNextも使ったことありますがReactでFormik等のライブラリを使わ ない場合 要件定義 基本設計 詳細設計 PG

Slide 117

Slide 117 text

Webフロントの概要 ReactやNextも使ったことありますがReactでFormik等のライブラリを使わ ない場合 onChange等でInputの変化を検知し ↓ 要件定義 基本設計 詳細設計 PG

Slide 118

Slide 118 text

Webフロントの概要 ReactやNextも使ったことありますがReactでFormik等のライブラリを使わ ない場合 onChange等でInputの変化を検知し ↓ componentのstateに値を入れる ↓ 要件定義 基本設計 詳細設計 PG

Slide 119

Slide 119 text

Webフロントの概要 ReactやNextも使ったことありますがReactでFormik等のライブラリを使わ ない場合 onChange等でInputの変化を検知し ↓ componentのstateに値を入れる ↓ propsでcallbackする 要件定義 基本設計 詳細設計 PG

Slide 120

Slide 120 text

Webフロントの概要 ReactやNextも使ったことありますがReactでFormik等のライブラリを使わ ない場合 onChange等でInputの変化を検知し ↓ componentのstateに値を入れる ↓ propsでcallbackする Callbackが深くなる。。。 要件定義 基本設計 詳細設計 PG

Slide 121

Slide 121 text

Webフロントの概要 ReactやNextも使ったことありますがReactでFormik等のライブラリを使わ ない場合 onChange等でInputの変化を検知し ↓ componentのstateに値を入れる ↓ propsでcallbackする かといってライブラリ使うと、ラ イブラリに依存してしまうから、 やめたくなった時にやめるの大 変になる 要件定義 基本設計 詳細設計 PG

Slide 122

Slide 122 text

Webフロントの概要 ReactやNextも使ったことありますがReactでFormik等のライブラリを使わ ない場合 onChange等でInputの変化を検知し ↓ componentのstateに値を入れる ↓ propsでcallbackする かといってライブラリ使うと、ラ イブラリに依存してしまうから、 やめたくなった時にやめるの大 変になる GolangでWire使わなかった時と 同じ気持ちです 要件定義 基本設計 詳細設計 PG

Slide 123

Slide 123 text

Webフロントの概要 ReactもHooksが登場してきたあたりから、 かなり見やすくなったので、閲覧系がメインでFormが少ない サービスであれば、Reactでもいいかと思っています。 要件定義 基本設計 詳細設計 PG

Slide 124

Slide 124 text

ニュースサイトを ゼロから構築したときの話

Slide 125

Slide 125 text

概要 Wordpressで運用していたニュースサイトでしたが、Wordpressが重たく なってきたので刷新するという依頼を受けました。 また、記事を書くライターさんも何人もいるので運用も考えて アーキテクチャを決める必要がありました。

Slide 126

Slide 126 text

Wordpressで落ち入りがちなこと •プラグインをたくさん入れて重たくなる •単体で扱うことが多いためスパイクに耐えられないことが多い •冗長構成にする場合Rsyncでファイル同期になる •デザインを独自にしようとするとかなりPHPのテンプレートを いじる必要が出てくる などなど

Slide 127

Slide 127 text

Wordpressの便利なところ •やはり、ニュースサイトとか作る上での機能は充実している •5.0以降は「Gutenberg」というブロック式エディタを採用しているので、 記事の品質を統一しやすい などなど

Slide 128

Slide 128 text

アーキテクチャの方向性 •運用を考えた場合、使い勝手をWordpressに近づけたいけど、 エディタとかから選定して管理画面つくるの面倒 •サイトのパフォーマンスあげたい •高負荷に強いサイトにしたい •画面も自由に開発したい

Slide 129

Slide 129 text

アーキテクチャの方向性 •サイトのパフォーマンスあげたい •高負荷に強いサイトにしたい →ECS Fargate使って水平スケールしたり、CDN使って負荷  に強くしたい •画面も自由に開発したい →Nuxt.js(Vue)とかNext.js(React)

Slide 130

Slide 130 text

アーキテクチャの方向性 •運用を考えた場合、使い勝手をWordpressに近づけたいけど、 エディタとかから選定して管理画面つくるの面倒 →Wordpress管理画面だけ使えないかな。。。

Slide 131

Slide 131 text

アーキテクチャの方向性 •運用を考えた場合、使い勝手をWordpressに近づけたいけど、 エディタとかから選定して管理画面つくるの面倒 →Wordpress管理画面だけ使えないかな。。。 お、REST-APIあるから、JSONとって フロントだけ作ればいけそう https://developer.wordpress.org/rest-api/

Slide 132

Slide 132 text

アーキテクチャの方向性 ということで •REST-APIと管理画面だけWordpressを使用 •フロント側はNuxt.jsでゼロから構築 •インフラはECS Fargateと、CloudFrontとかでキャッシュ入れよう という方向性にしました

Slide 133

Slide 133 text

考えた全体アーキテクチャ ※ALBとかVPCとか、細かいのは割愛

Slide 134

Slide 134 text

考えた全体アーキテクチャ WordPressの公式DockerfileをベースにS3 プラグインを含んだ状態のDockerfileを作 成。複数コンテナを配置して 水平スケール可能に ※ALBとかVPCとか、細かいのは割愛

Slide 135

Slide 135 text

考えた全体アーキテクチャ Wordpressの画像用S3。 閲覧者はCloudFront を経由してアクセス ※ALBとかVPCとか、細かいのは割愛

Slide 136

Slide 136 text

考えた全体アーキテクチャ WordpressのREST-APIは CloudFront経由してBFFからアクセス ※ALBとかVPCとか、細かいのは割愛

Slide 137

Slide 137 text

考えた全体アーキテクチャ Nuxt.js内部にBFF作ったので、そこへのア クセスもCloudFront経由 (nuxtのbaseURLと、browserBaseURLを両 方ともCloudFront①のドメインを指定) ※ALBとかVPCとか、細かいのは割愛

Slide 138

Slide 138 text

考えた全体アーキテクチャ 公開するURLは、CloudFrontのドメイン ※ALBとかVPCとか、細かいのは割愛

Slide 139

Slide 139 text

•カテゴリページとハッシュタグページが要件として必要で タグ名やカテゴリ名から記事を検索する必要があったが 、WorkPress の記事APIのタグとカテゴリの条件がID指定だった → BFFで名称からIDを逆引きできる様に アプリキャッシュ(メモリ上のMapに数分ごとにロード) ちょっと工夫したこと

Slide 140

Slide 140 text

•カテゴリページとハッシュタグページが要件として必要で タグ名やカテゴリ名から記事を検索する必要があったが 、WorkPress の記事APIのタグとカテゴリの条件がID指定だった → BFFで名称からIDを逆引きできる様に アプリキャッシュ(メモリ上のMapに数分ごとにロード) •ドメインを持つ3箇所に CloudFrontを入れ、 WordPressへのアクセスを極力抑え、パフォーマンスを維持した ちょっと工夫したこと

Slide 141

Slide 141 text

いろいろな視点を組み合わせることで 安定した 高パフォーマンスなニュースサイトが作 れました( ^ω^ )

Slide 142

Slide 142 text

最後に

Slide 143

Slide 143 text

私は「フルスタックエンジニア」として働いてますが、 現代は技術の幅がかなり広く、一つ一つ深く知るにはそれなりの時間と 努力が必要で、私ももちろん人の何倍も技術に時間を使ってます。 大変ではありますが、広く深く知っているからできることだったり、楽しさ があったりのするので、それがとてもやりがいになっています。 最後に

Slide 144

Slide 144 text

最後に また、今回お話したことは、弊社の案件とは全く関わりがない 私個人が、副業で依頼され一人で構築したサービスです。 今回の事例は名前は伏せておりますが副業先にも了承を いただいています。

Slide 145

Slide 145 text

いろいろな開発を行ってくことで広く深いスキルを身に付けることがで き、会社のプロダクトでも、その技術を生かしています。 もちろん、どのプロダクトもサービスの根幹に関わるノウハウは口外でき ませんが、根底の技術スキルはほとんど一緒です。 最後に

Slide 146

Slide 146 text

「技術の循環」をすることで、より良いプロダクトになるし、 またこうやって発表の機会をいただき公開することで、 業界自体がもっと広い視点で発展して行って欲しいと思い、 今回の様なテーマで語らせていただきました。 これを見ていただいた方のご参考になれば幸いです。 最後に

Slide 147

Slide 147 text

ありがとうございました