80
42

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

未経験者が「グラフ画像の読取り効率化」アプリを開発した話【Laravel / Vue.js / Docker / AWS】

Last updated at Posted at 2022-01-25

1. はじめに

本記事は実務未経験者ポートフォリオとして個人開発したWebアプリ学習過程などをご紹介します。
未経験からエンジニア転職を目指す方々のお役に立てれば嬉しいです。

2. 開発したアプリ 「 PLOTemo 」 とは ?

アプリを簡単に説明すると、
「グラフ画像のプロットデータ読み取りを効率化 & メモ管理」ができるアプリです。

前職絡みの課題を解決するニッチなアプリとなっております。

名前の由来はプロット(plot) + メモ(memo) で PLOTeme(プロッテモ)です。

top2.gif

主な特徴

  • 画像化されたグラフのデータポイントを効率的に読み取る
  • クラウド上にメモのように保存・一括管理が可能。
  • 検索で必要なデータがすぐに見つかり、CSVダウンロードでデータがすぐに使える

アプリを試す

PLOTemo (プロッテモ)」
アプリURL:https://plot-memo-app.com/
(現在は公開しておりません)

  • 「ゲストログイン」 or 「機能を試す」ボタンで登録せずに機能が試せます。
    ※ゲストユーザーは一部機能を制限しております。
  • 本アプリは基本的にPCでの使用を想定しておりますが、スマホ対応もしております。

3. 制作背景

本アプリを作った背景

前職 (メーカー開発職) で、グラフデータを読み取って設計計算などで活用する機会が多くありました。
その中で画像化されたデータ(PDFのスクショや紙の画像化データ)は、プロットポイントのデータ化ができず、目視で目盛りを読み取って手動でデータ化する必要があり、非効率でミスもおこりやすいという問題がありました。
そこで、グラフ画像の読み取りアプリを使っていました。
しかし、仕事で使っていたアプリは下記のような不便さを感じていました。

不便に感じていた点

  • UIの問題で初めての人には使いにくい。
  • windows専用のデスクトップアプリで異なるデバイスからアクセスできない。
  • 一度読み取ったデータはアプリ上で保存できない。(別管理しないと後で確認できない & 再利用できない。)
  • 読み取ったデータがすぐに使える形式ではなく、Excelなどで使う場合は加工して使う必要があった。

そこで・・・

UIを意識 しながら、下記の利便性を組み合わせたグラフ画像の読み取り効率化アプリを作成しました。
webで利用可能 + メモ形式で一括管理し、再利用可能 + 検索、CSVダウンロードですぐに使える

4. 主な機能の紹介

グラフ読み取り、プロットメモの作成

アップロードされたグラフ画像を表示し、軸設定後に読み取りたいポイントをクリックして値を取得 & 保存する。

  1. ドラッグ&ドロップ or ファイル選択で画像を読み込む。
  2. X軸、Y軸の最小値・最大値の設定。
  3. グラフ画像上で読み取りたいポイントをクリックして値を取得。
  4. メモを記入し、保存する。

register.gif

CSVダウンロード機能

  1. CSVダウンロードをクリックする。
  2. 読み取ったデータがダウンロードされ、データを加工せずにグラフ作成できる。

csv.gif

メモの検索機能

  • 日時のソート
  • お気に入り検索
  • タグ検索
  • キーワード検索 (スペースでOR検索)

search.gif

ゴミ箱機能

  • ゴミ箱一覧表示
  • 復元
  • 完全削除

trash.gif

アカウント設定機能

  • プロフィールの変更 (ニックネーム、アバター画像)
  • メールアドレスの変更
  • パスワードの変更
  • 退会確認・処理

account.gif

5. 使用技術と選定理由

バックエンド

  • PHP 7.4.1
  • Laravel 6.20.34

選定理由

  • 初学者が学ぶ上でのドキュメントが豊富なRuby、PHPに絞り込み。
  • PHPを選定した理由は、希望勤務地の関西にて求人数がRubyに比べて多かったこと。

フロントエンド

  • HTML、CSS、Sass
  • MDBootstrap 4.19.1
  • Vue.js 2.6.14

選定理由
【Bootstrap】
・BootstrapはPHPの教材で学習する際に使用しており、学習コストの面で選定。
・MDBootstrapは既存のコンポーネントなどを確認して、本アプリに使えそうということで採用。
・実際に使ってみて、しっくりこないところは適宜CSSやSassでカスタマイズ

【Vue.js】
・グラフ読み取り機能ではCanvas APIを使って描画をするためにJavaScriptが必要だった。
・将来実装したい機能も考えた時に複雑になりそうだったので、JQueryではなく、
 アプリ規模に応じて柔軟にスケールアップできるVue.jsを選定
・ReactやAngularと比べ学習コストが低い。
・開発するアプリに対してライブラリが十分だった。

インフラ

  • Docker 20.10.7 / docker-compose 1.29.2 (開発環境)
  • AWS (EC2, ALB, ACM, S3, RDS, Route53, VPC, IAM)
  • MySQL 8.0.26
  • nginx 1.20.0

選定理由
・AWS/Dcokerは興味がある企業で多く用いられており、勉強のために使用。
・AWSは、就職してからだと中々触れないこともあるみたいなので、手を動かして勉強するには良い機会だった。
・Herokuは教材で使用ことがあり、読み込みがかなり遅く感じた。

その他

  • Git / GitHub
  • VSCode
  • Canva (ロゴや図の作成)
  • Draw.io (ER図、インフラ構成図の作成)
  • Sequel Ace (DBクライアントツール)

6. ER図

PF_ER図.png

ER図の簡単な説明

テーブル名  保存情報 補足
users ユーザー情報 -
graphs グラフ画像やタイトルなどの基本情報 ゴミ箱機能のためソフトデリート用のカラムを用意。
axis_plots 軸設定時のクリック座標 グラフ上のX, Y軸の最小値・最大値のクリック座標(x,y)を格納。
axis_values 軸設定時の値 ユーザーがグラフ画像上から読み取ったX, Y軸の最小値・最大値の値を格納。
canvases Canvasの情報 (サイズ) 画面サイズによってCanvasのサイズが変わるため、プロットデータがずれないようにベースのサイズを保持して座標の補正計算に使用。
plot_data プロットデータ (値と画像) ・データ系列の追加ができるようにgraphsテーブルに対して1対多の関係で設定 (nameカラムも用意)。
・メモ一覧表示でプロットデータを画像化して表示するため、値データだけではなく、画像化した名前データも格納。
tags メモにつけるタグ -
graph_tag グラフとタグの中間テーブル -

7. インフラ構成図

インフラ構成図.png

インフラはコスト現状のアプリ規模のことを考えて、冗長化はさせておらず、自分が思う最低限の構成としました。

  • HTTPS化のために、SSL/TLSサーバー証明書をACMで取得し, ALBに関連付け。
  • httpでアクセスされた場合は、httpsでリダイレクト
  • 独自ドメインでアクセス可

8. 機能一覧

前述した主な機能と一部重複しますが、アプリ内の機能一覧を列記します。

認証機能

  • 新規登録
  • ログイン / ログアウト
  • ゲストユーザーログイン
    • 全ての操作は可能だが、一部のDB更新は無効化 (条件分岐でリダイレクトしてメッセージを返す)
  • バリデーション (Laravel)

認可機能

  • ログインユーザーと異なるユーザーの情報にアクセスした際に403(権限)エラーレスポンスを返す。

アカウント設定機能

  • CRUD処理
  • プロフィール (画像、名前) 編集 (intervention、imageとGDライブラリ)
  • プロフィール画像のプレビュー (Vue)
  • メールアドレス、パスワード編集
  • 退会処理と確認のUI (Laravel、 Vue)
  • バリデーション (Laravel)

グラフ画像のプロット & メモ機能

  • プロットメモ一覧表示

    • Canvas画像とグラフ画像を重ねて配置 (Sass)
    • ページネーション (Laravel)
    • ツールチップ(マウスホバー時にヒントの表示)
    • タグ機能 (vue-tags-input, Vue)
    • お気に入り機能 (axios, Vue, Laravel)
    • N + 1問題の解消
  • プロットメモの新規作成 / 編集機能

    • グラフ画像アップロード (Vue, Laravel, axios, Canvas API)

      • ドラッグ&ドロップ or 選択
      • 画像をCanvasに表示
      • 画像の保持 (非同期通信でサーバーに保存&セッションで名前データの保持)
      • 画像のバリデーション (非同期通信でエラーレスポンスを取得)
    • 軸設定機能 (Vue, Canvas API)

      • Canvasのレスポンシブ対応 (Canvasサイズを取得して計算に用いる)
      • x軸、y軸の設定
      • 軸設定の誤操作防止モーダル
      • 設定完了時のチェックマーク
      • クリックイベント毎に異なる表記をCanvasへ描画
      • 軸設定のリセット機能
    • プロットデータの読み取り機能 (Vue, Laravel, axios, Canvas API)

      • クリックポイントをCanvasへ描画
      • クリックポイント値を軸設定した値に換算して取得してテキストエリアに表示
      • クリックデータとテキストエリアの表示の双方向バイディング
      • テキストエリアの更新イベントを検知して再描画
      • テキストエリアの値を規則性を持たせ表示 (桁数、カンマ区切り、改行)
      • プロットデータを画像化して、非同期でサーバーへ保存
      • 座標の角度補正 (画像が傾いている場合でも座標の角度を補正する)
    • メモ作成機能 (vue-tags-input, Laravel)

      • タイトル、メモ、タグの保存
      • canvasデータとplotデータの保存
      • バリデーション
      • バリデーション後のold値、画像の保持
      • 保存タブのcanvasの誤操作防止モーダル

CSVダウンロード機能

  • データベースのプロットデータをすぐに使える形に加工

メモ検索機能

  • 検索結果が見つからなかったことを明示的に表示
  • 下記をAND条件の絞り込み (セッションで条件を保持)
    • お気に入り有無
    • タグ名
    • ソート
  • ページネーション (コレクションクラスの型のため LengthAwarePaginatorクラス を使用)
  • キーワード検索機能 (スペース区切りで or条件 が設定可能)

ゴミ箱機能

  • メモをゴミ箱に移動 (論理削除)
  • ゴミ箱にあるメモの一覧表示 (論理削除されたメモを表示)
  • ゴミ箱が空の状態を明示的に表示
  • リストア、完全削除 (物理削除)

その他

  • レスポンシブ対応
  • パンくずリスト
  • サクセス、エラーのトースト通知 (vue-toasted Vue)

9. 今後実装したい機能

今回は主軸となる機能を優先的に実装して、余計な機能は省きました。
今後は更なる利便性を考慮して下記の機能追加を考えております。

・テストコード
・Canvas内での虫眼鏡機能
・プロットポインタの色設定機能(カラーピッカーによる色設定&DB保存)
・データ系列の追加機能 (DBのカラムは追加済み)
・プロット表示データのソート機能
・多様なグラフに対応、片対数・両対数軸のグラフに対応
・チーム設定機能
 (社内で使うことを想定してチーム内でグラフの共有・アクセス権設定機能)
・タグ管理機能
・軸の自動検出、プロットデータの自動プロット
 (PHP、JSのライブラリは使えそうなものなし。GoogleのAIのAPIのサンプルを見たが、アプリとの相性が悪かった。Pythonは出来そうなライブラリがあった。)
・アプリで スクショ機能をつけてそのままアップロードできる。
・アプリ内でグラフ化と各種分析
 (読み取りから、分析、管理まで簡単に素早くワンストップで行えるようにしたい)

10. 作成時に特に工夫したところ、反省点

N+1の改善

一旦機能を作ってから、デバッグツールでN+1問題が発生してそうな箇所に当たりをつけて確認しました (全部で4箇所)。
現状のスケールでは問題はないですが、バックエンドとして重要なところだと思うので、勉強もかねて修正しました。

コードの書き方

再利用できそうなコードは、共通部品として切り分けを積極的に行いました。
ただ、まだまだ自信がないところなので今後、保守性が高いコードを積極的に学習していきたいです。

反省点 : Vueに関しては、知識が浅すぎるまま進めたため一部のコンポーネントが肥大化して、後で修正するときにかなり苦労しました。

Git / GitHubを用いて模擬チーム開発

チーム開発をした経験を活かして、習慣付けのため個人でもチーム開発風に開発しました。

  • issueでタスクを管理。
    スクールではタスクはTrelloで管理していましたが、今回は、コミット、プルリクエストに紐付けができるissueを用いました。
  • GitHub Flowに基づいて、開発を進める。
  • issueやプルリクは後で見返して検索しやすいようにタグ付けを行う。

反省点 : issueやプルリク、コミットの粒度のルールを予め自分なりに決めておくことで、もう少しスムーズに運用できたのかなと思いました。

(参考 : issueのスクショ)

スクリーンショット 2022-01-25 19.14.11.png

【図解】git-flow、GitHub Flowを開発現場で使い始めるためにこれだけは覚えておこう
GitHubのissueを活用した、個人アプリの開発手順を書いてみた

デザイン

  • ユーザー目線に立って分かりにくいところがないか意識する。
  • 実際のメモアプリなどをみて、部品や挙動などを参考にする。
  • 配色はできるだけ少なくする(ベースカラー、アクセントカラー、その他グレー系の目立たない色)。
  • bootstrapをベースに自分のアプリに合わせてCSS, Sassでカスタマイズ。

反省点 : 結局カスタマイズに時間がかかったことと、Vue.jsとの相性を考えるとBootstrap以外のフレームワークでも良かったかも

▼参考にしたフリー素材まとめサイト
プロのWebデザイナーが使う商用OKのフリー素材サイト

Canvasの描画データと画像データがずれないようにレスポンシブに対応

▼ 内容が技術的な細かい話なので、不要な方は飛ばしてください。

CanvasはJSを使って絵などを描画できます。

今回はグラフ画像の上にプロットデータを描画するキャンバスを重ね合わせています。
ただ、画面サイズが変わると描画領域のサイズを変えないと描画データと重ねているグラフ画像データのずれが生じます。
(Canvasは描画領域のサイズと画面上に表示されているサイズの2つがあります。)
しかし、Canvasサイズを変えるとCanvasの仕様の都合で描画データがリセットされてしまいます。

ネットで解決策を調べましたが、データをCanvasの機能を使って保存して、再描画するというやり方がありましたが、どうも上手くいかずに苦労しました。

そこで、Canvasの初回作成時のサイズを保持して、描画するたびにそのベースサイズと現状のCanvasサイズの比率を用いて、描画データの座標を補正するというやり方を考えました。

反省点 : この考え方は今思うと単純ですが、当時は色々複雑に考えすぎて、どんどん沼にハマって時間を浪費しました。。。

11. 苦労したところ

日々エラーとの戦いで、楽しみながらも苦労してました。
ただ、そのおかげでコードに関しては、エラーが出ても冷静に原因の切り分けを行なって、怪しそうな所を特定し、デバッグしながら追っていけるようにはなりました。

AWSに関しては、エラーの解決方法に慣れてなかったこともあり、かなり苦労しました。AWSのエラーに対する恐怖心が消えるくらいまで理解したいです。。

PHP / Laravel

  • 描画データの値の保存方法 (DBの構成や、カラムの型など悩んだ)
  • ページネーションを使いながら、特定のページで特定の処理をする。 (HTTPリクエストにpageメソッドがあったのでそれを用いて条件分岐することで解決。公式に載ってなかったので苦労した)
  • コレクションクラスのページネーション (paginateメソッドは使えないので、LengthAwarePaginatorクラスを使用)
  • 絞り込み検索とソートの仕様 (検索の仕様とロジックを考えるのに苦労しました。)

JS/ Vue.js

  • JSの小数の演算誤差 (JSの計算仕様(IEEE 754(浮動小数点数演算標準))では、計算値によって誤差が出て、悩まされた)
  • Vueのリアクティブにならない条件やライフサイクルに起因するエラー (デバッグしながら一つ一つ苦戦しながら解決していった)
  • 非同期通信のレスポンスデータの表示 (Laravelのバリデーション結果の中身や表示方法に苦労)
  • 画像ファイルの保持 (ファイルは保持できないので、バリデーション時の扱いに困った)
  • テキストエリアの内容と描画データを双方向バインディング化 (配列の扱いやデータ更新のタイミングの仕様を考えるのに苦労)
  • メモ一覧表示にプロットデータの表示 (表示のさせ方に苦労しました。最終的に値データとは別に画像データを保存し、グラフ画像とプロット画像を重ねました。)
  • プロットデータの角度補正 (Canvasサイズの補正した値にさらに補正をかけたため、ややこしくなりノートに図を起こしながら整理しました。)
  • 複雑な配列処理 (JSで配列処理が多く、慣れない内は大変でした。ただ、PHPでも考え方は自体は共通していたのでそこは良かったです。)

AWS

  • s3に保存できているはずの画像が表示されない(s3のバケットのアクセス制御の設定が間違っていた)
  • HTTPS化 (設定ミスだったが、原因を特定するのに時間がかかった)

12. 学習期間、内容

2021年 5月末 【学習開始】

  • 基本情報技術者試験の勉強、受験(6月末)、合格
  • Progate (HTML, CSS, PHP)

基本情報の学習理由は、IT全般への興味はあったものの自分が知らないことが多すぎたので、基礎を体系的に学ぶためです。
受験理由は、合格して自信をつけて、その後の学習意欲に繋げるためです。

7月〜10月 【オンラインスクール + 自己学習】

  • オンラインスクールに入会

    • Git (コマンドベース)
    • PHP (課題に対するロジックを考えて実装)
    • Laravel (簡単なCRUDアプリ作成と動画共有SNSアプリ作成)
    • 追加課題 (アプリに追加の機能実装)
    • 共同開発でQiita風のアプリ作成
  • オンライン教材や書籍などで自己学習

    • PHP, Laravel, JS, Vue.js, git, Docker
    • WEB技術

スクールの学習について

共同開発が経験でき、かつPHP/Laravelの基礎を学ぶためスクールに入りました。

スクールといえど能動的な姿勢じゃないと自分が思い描く成長はできないと思ったので下記を意識しました。

  • レビュアーの負担軽減のため、プルリク文に 「タスク内容」「実装コードの補足」「特に見てほしい箇所」「テスト内容・結果」 などを書く。
  • 一つ一つのコードに対して、いろんな書き方の中から、なぜそうしたかを説明できるように意識する。
  • チームでの開発が円滑に進むための情報共有や様々な媒体でのアウトプット
  • 課題や共同開発のタスクを早く終わらして積極的に学習する。

10月〜12月【ポートフォリオ実装〜デプロイ】

  • PFアプリの実装
  • AWSの学習
  • デプロイ

10月までにPFの構想や仕様をある程度考えていました。
ポートフォリオは作る上で不足している知識も多かったので、学習しながら進めました

特にVue.jsは簡単なアプリしか作ったことがなかったので、メインの部分に入る前に
PFの簡単な部分(画像プレビュー、ドラックアンドドロップ、トースト通知など)で徐々に慣れていきました。

PFを作り終わった後はかなりの成長を実感し、アウトプットしながらの学習の効果を改めて感じました。

アプリについては、現在も少しずつ改善をしてます。

参考 : 草画像

スクリーンショット 2022-01-25 16.20.02.png

こう見ると結構時間がかかりました。。

13. 学習教材

学習開始からポートフォリオ作成までに学習・参考した教材をご紹介します。
(スクール、progate、ドットインストール以外)

ただ、 教材全てを完璧に行うと時間が足りないため自分に必要な知識を選別しながら学習しました。
また、Techpitは気になる教材がたくさんあったため、Unlimitedに加入して、実際にどんな感じか見て学習するかどうかを判断していました。

PHP, Laravel

▼ 生のPHPのアプリを初めて体験しました。やはりフレームワークないと大変。。

▼ 定番の青本。個人的にLaravelを学び始めの時にこれがあって本当に良かったと思う一冊でした。

▼ 青本が良かったので緑本も買ったが、難しかったです。ただ、ポートフォリオを作成中に必要な場面があり、何度か参考にさせてもらいました。

▼ 実際にLaravelと生のPHPで同じアプリを作ることで、フレームワークの便利さを改めて実感しました。

▼ 気になる部分を実際にを作りながら、本アプリではタグ機能やお気に入り機能を参考にしました。

JavaScript / Vue.js

▼ Vue.jsを採用する上で、近年なぜJavaScriptが注目されているのか、全体像をつかむために下記の動画が最適でした。

▼ Vue.jsの基礎部分を学びました。

▼ 公式で分かりにくい表現があった場合は、下記を参考にしました。ただ、詳しくは書かれていない所もあったので、その時は都度ネットで調べました。

Bootstrap

▼ 公式で分かりにくい表現があった場合は、下記書籍を参考にしました。

Git/ GitHub

▼ Gitコマンドの裏側で何が起こっているかを学ぶことで、Gitを使う上でのもやもや感がなくなりました。

WEB技術

AWS

▼ 上記でAWSの全体像と基礎的な知識を学びました。

▼ LarvelをAWSにデプロイする過程で必要な知識を学びました。CI/CDは今回のアプリへの導入メリットがほとんどないと考えて学習していませんが、必要になったら学んでみたいです。

Docker

Dockerはまだまだ知識不足のため実務で使う場合は、もう少し本格的に学習しようと思います。

▼ 実際の環境構築はLaravel, Vueということもあって下記(導入〜後編まで)を参考にしました。

設計, データベース

▼ 今回設計はガッツリしていませんが、アプリを作る上でどういう手順で作成すべきかということを知識として知っておきたかったため、下記を参考にしました。

基本情報技術者

ネットワークやデータベースの基礎、設計などアプリ開発する上で重要なことも学べて良かったです。

IT業界の知識

ネットの情報は断片的な情報しかなかったので、本で業界知識を学びました。

14. さいごに

今回はメンターサービスなどを利用せずに進めたため、上手くいかなかった時の絶望感は半端なかったです。
しかし、本当に形にしたいという自分の思い入れが強いサービスだったからこそ、デプロイまですることができました。

改めて自分のアイデアを形にできるのは本当に夢がある職業だなと思いました!
(現職のハードウェアで何か作って売ろうと思おうと莫大な費用がかかる)

作っている途中にも他のアプリのアイデアが出てきたり、それを想像しながらワクワクしていました。
一方で、自分の技術力はまだまだ浅いということも改めて実感しました。

就職後は「技術力の向上」 や 「アプリを使ってもらう仕組み」などを身につけて別の個人開発にも挑戦し続けたいです。
そして、個人アプリで小遣い程度にでも利益を出せるようになることが、エンジニアとしての目標の一つです!

長くなりましたが最後まで読んでいただきありがとうございました!

15. 参考記事

80
42
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
80
42

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?