11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

記事投稿キャンペーン 「2024年!初アウトプットをしよう」

(未経験)技術士1次試験の過去問演習アプリつくった [Rails API + Next.js]

Last updated at Posted at 2024-01-23

はじめに

はじめまして!
エンジニア転職を目指してプログラミングスクールRUNTEQで学習中のけーちゃんと申します。
2023年1月より、完全未経験からRuby on Railsを中心に学習し、この度、ポートフォリオとして「技術士1次試験 基礎•適性科目 過去問ドリル」をリリースしたので、ご紹介させていただきます!

注意事項

私はプログラミング学習中で、初学者です。
内容に誤りがある場合があります。
コメント等で教えていただけると幸甚です。

作成したアプリ

アプリ名: 技術士1次試験 基礎•適性科目 過去問ドリル

opengraph-image.png

サービス URL: https://www.proengineer1exam.com
GitHub URL: https://github.com/K-chan41/pro_engineer_1st_exam_app

サービスの概要

公益社団法人日本技術士会が年1回開催する技術士1次試験の基礎科目と適性科目の過去問対策ができるサービスです。
過去問を実際に解き解答を選択し、正答、解説を確認できます。
ユーザー登録をしていただくと、問題にフラグを立てたり、間違えた問題を復習することができます。

作った理由

私自身が当該の試験を受験した際に、完全解説つき学習アプリがなく、過去問解説は書籍ばかりで、スマホで過去問対策ができず困った経験があり、これから受験する方に向けて制作しました。
また、せっかくサービスをつくるのであれば、「万人受けするおもしろいサービスを作る」よりは、「多少ニッチでも、必要な人に確実に使っていただけるような実用的なサービスを作りたい」との思いがありました。一過性のブームで終わるよりも、長く愛好してくれる方がいるようなサービスにしたいと思って作成しました。
とくに、ITパスポートや基本情報、FP、宅建などで知られる過去問道場さんのように、必要な人に必要とされるサービスにしたいとの思いが強くありました。

サービスの機能

過去問演習機能

令和2年度から令和5年度の基礎科目と適性科目、全180問を収録しており、演習することができます。

問題選択 問題演習
Image from Gyazo Image from Gyazo
過去4年分の演習が可能です 1問ごとに正誤と解説を確認できます

※掲載している技術士試験の過去問題データは公益社団法人日本技術士会から利用許諾を得て使用しています。

フラグ機能、マイページ

登録ユーザーの方は、問題にフラグを立てることができます。フラグを立てた問題はマイページで確認できます。

フラグ機能 マイページ
Image from Gyazo
不安な問題や間違えた問題にフラグを立てることができます フラグした問題を確認、再出題することができます(10問)

マイページではそのほかに、ランダムに出題したり、直近間違えた問題を確認、再出題することができます(10問)。

ログイン/新規登録、お問い合わせフォーム

お名前、メールアドレス、パスワードで新規登録できます。
お名前とメールアドレスでお問い合わせフォーム送信できます。
PWA導入してます)

ログイン/新規登録 お問い合わせフォーム
Image from Gyazo Image from Gyazo

工夫したところ

見ため

ReactのUIライブラリ、Mantineを使用しました。
私自身デザインができるわけでもないのに、HTML、CSSを自分で書くのは絶対に危険だと思い、なんとしてもコンポーネントで開発を行いたく、React学習を始めました。
また、絶対にスマホでも快適に表示させたかったので、レスポンシブ対応がすぐにできるようなものでやりたかった思いもありました。

TOPページでサーバー側からデータを取ってきている部分などにloadingのコンポーネントを入れたりして、ユーザーのストレスを軽減しようとしました。

Image from Gyazo

Latex形式のコンパイル

問題や、解説のデータはChatGPTを使いつつ、自力で作成しました。
数式については、Latexの形式で保存し、API側から下記のような感じででてきたものをフロント側でレンダリングしています。

APIからのレスポンスボディの一部
{
    "id": "93",
    "type": "question",
    "attributes": {
    ~省略~
        "commentary": "この問題では、引張力 \\( Fa \\) と圧縮力 \\( Fb \\) がそれぞれ正規分布に従っているとされています。合力 \\( F = Fa - Fb \\) が200N以上の引張力となる確率を求める問題です。\n\nまず、合力 \\( F \\) の平均と標準偏差を求めます。\n\n- \\( F \\) の平均\\( \\mu_F = \\mu_{Fa} - \\mu_{Fb} = 300N - 200N = 100N \\)\n- \\( F \\) の標準偏差 \\( \\sigma_F = \\sqrt{\\sigma_{Fa}^2 + \\sigma_{Fb}^2} = \\sqrt{30^2 + 40^2} = \\sqrt{900 + 1600} = \\sqrt{2500} = 50N \\)\n\n次に、合力 \\( F \\) が200N以上となる確率を求めます。これは、\\( F \\) が \\( \\mu_F + 2\\sigma_F \\) 以上となる確率に相当します。\n\n- \\( \\mu_F + 2\\sigma_F = 100N + 2 \\times 50N = 200N \\)\n\nこの値が \\( z = 2.0 \\) に相当するので、\\( z \\) 以上となる確率は2.28%です。\n\nしたがって、棒部材の合力が200N以上の引張力となる確率は2.28%となります。",
  ~省略~
    },

上記のなかの\\(\\)で囲まれた文字等が、下記のようにきれいな数式で表示されます。
Image from Gyazo

JavaScriptライブラリのKatexを使用しました(下記、一部抜粋)。
Katexでレンダリングマークダウンでレンダリング表示

src/app/questions/page.tsx
import katex from 'katex';
import { marked } from 'marked';


const renderMarkdownAndLatex = async (markdownText: string) => {
    // 1. LaTeX数式のレンダリング
    let latexProcessedText = markdownText.replace(/\\\((.*?)\\\)/g, (match, formula) => {
      return katex.renderToString(formula, { throwOnError: false, displayMode: false });
    }).replace(/\\\[(.*?)\\\]/g, (match: any, formula: string) => {
      return katex.renderToString(formula, { throwOnError: false, displayMode: true });
    });
    
    // 2. Markdownのレンダリング
    return marked(latexProcessedText);
};

csvからseedを使ってデータを格納

今回、自分で問題や解答のデータをcsvで作成しAPIを作りました。
csvからseedでテーブルにデータを入れました。

seed.rb
require 'csv'

# Subjects
csv_text = File.read(Rails.root.join('db', 'csv_data', 'subjects.csv'))
csv = CSV.parse(csv_text, headers: true, encoding: 'UTF-8')
csv.each do |row|
  Subject.create!({
    year: row['year'].to_i,
    exam_subject: row['exam_subject'].to_i
  })
end
puts "Imported #{csv.size} rows to Subjects"

主な使用技術と選定理由

フロントエンド(主なもの)

  • Next.js 14.0.3
  • React 18
  • Mantine 7.3.x
  • Nodemailer 6.9.7

技術選定理由

React、Next.js

自分でHTML、CSSを書くのは正直怖く(とんでもないデザインのものを作ってしまう気がした)、コンポーネントを使って開発を行いたかったので、Reactを学習し始めました。Next.jsはReactベースのフレームワークのなかでもディフェクトスタンダードになりつつあると感じたので、Next.jsにしました。また、App Routerによるフォルダーベースでのルーティングができるのも自分にとっては新鮮で、React Routerよりも容易に感じました。

ただ、先輩方もよく仰っていますが、私のように「やってみたい」だけの理由で学習をするのではなく、就活を見据えて、「御社に入りたくて、〇〇の技術をつかったPFを作りました」と言えるくらい戦略立てて技術選定、開発したほうがいいと思います。

Mantine

数あるコンポーネントのなかで、Mantineを選んだのは、RUNTEQの大先輩いないさんのTechFinderをみて「こんな見た目のサイトつくりたい!」と思ったのが一番の理由です(技術的には足元にもおよんでいませんが)。一応、Reactを学ぶなかで、MUIも触ってみましたが、最終的に「やっぱりMantineのほうが統一感があっていい」と感じたので、Mantineにしました。

Nodemailer

お問い合わせフォームはMantineのuseFormと、Node.jsで動作するメール送信用のライブラリのNodemailerを使用して、作成しました。OAuth2.0を使って問い合わせ本人と管理者(私)にGメールが飛ぶようになっています。実装は下記記事が参考になりました。
実装に際して、サーバーアクションかAPIルートにするか悩みましたが、ちょっとサーバーアクションの理解が浅かったのとnodemailerに関してAPIルートの情報しかネットで見つけられなかったこともあり、今回はAPIルートにしました。

バックエンド

  • Ruby on Rails(APIモード) 7.0.4
  • ruby 3.1.2
  • PostgreSQL

技術選定理由

Ruby on Rails

プログラミングスクールで学習したのがRuby on Railsで、未経験ながら、もっとも慣れていたため今回使いました。

インフラ

  • Vercel
  • Heroku

技術選定理由

大前提として、私自身のインフラ知識が乏しかったので、とにかく簡単で自分が確実にデプロイできるPaaSを選ぼうと思ってました。

Vercel

Next.jsを開発したVercel社が運営するホスティングサービスで、Next.jsとの親和性が高く、GitHubと連携させるとpushするだけでデプロイしてくれるのがなによりもよかったです。一度別アプリ等を自分なりにデプロイして試した上で、Vercelに決定しました。

Heroku

こちらも、プログラミングスクール内で一度触ったことがあり、安心感があったので、使いました。同じく、GitHubと連携させるとpushするだけでデプロイまで行ってくれるように設定できるのが好きでした。

ER図

Image from Gyazo

勉強期間、開発期間

ここからは、RUNTEQで学習中の方や、未経験からプログラミングを学習して、Webアプリを制作しようとしている方に向けて、私の経験をお伝えさせていただきます。
現在、モダンJavaScriptのポートフォリオへの採用熱が高まっており、RUNTEQ界隈や未経験組のXを見ていても、最近は2人に1人くらいの勢いで、Reactや、Vueなどのフロントを使っている方を見かけます。
ただ、スクールのカリキュラムではRuby on Railsで完結するWebアプリが中心なので、別途、勉強する時間を設けなくてはいけません
私の場合ですが、勉強期間と開発期間合わせ、3ヶ月くらいかかってます。(私の効率が悪いだけかもしれませんが、)働きながらの方はそのくらいは見積もっておいたほうがいいと思います。

たぶん、自分のWebアプリにReactとかを取り入れるか迷っている未経験の方がいるかなと思うので、どのくらいのスケジュール感でいけそうか、私の開発、勉強時間が一つの判断材料になれば幸いです。
ちなみに、私は平日仕事をしながらの学習で、カリキュラムの進捗と卒業は割りとぎりぎりなほうでした。

あくまで、私自身の学習と開発にかかった時間です。
もっと、効率的に勉強することはできると思います。働きながらの場合の目安として見ていただければ幸いです。
また、フルコミの方や、カリキュラムを早く終えた方はもっと時間に余裕があるので、もっと開発に時間を割いてブラッシュアップに力を入れることもできると思います。

勉強期間

まず、開発を開始する前に勉強した内容は以下です。

  • Rails APIモード
  • JavaScript
  • React
  • TypeScript
  • Next.js

スクールのカリキュラムを終えた(卒業認定を受けた)のは9月末頃で、2023年12月末までにMVPするというマイルストーンを自分で立てて、取り組みました。
また、上記に加えて、私の場合は、問題文や解説文の試験情報を手作りしたので、それも平行して行いました。

自分でコンテンツをつくるのは絶対におすすめしません!!! 絶対にオープンデータでできるものを考えたほうがいいです!!!

Rails APIモード (約2週間:2023年10月10日〜2023年10月21日)

こちらは、RUNTEQのアディショナルのカリキュラムにある、Rails API編をそのままやりました。

JavaScript、React (約1ヶ月:2023年10月1日〜2023年10月30日)

その後、フロント側の勉強をどうやってやっていけばいいのかな〜と思いつつ、Rails APIとどんな感じでやり取りし合うのかイメージがわかなかったので、Youtubeで無料の動画を見ながら真似をしてアプリをつくったりしてました(このときはReactをまったく理解しておらず、とにかくコードを書き写しただけでした)。

なんとなくReact + Rails APIのWebアプリ開発の雰囲気がわかったところで、つぎにReactのチュートリアルをやろうとしたのですが、意味がまったく分からず、やばいってなりました。おそらくJavaScriptの知識が乏しいせいだとなんとなくは理解しつつ、どうしようか本屋で本を眺めていると、基礎から学ぶ React/React Hooksの本と出会いました。この本は、Reactのチュートリアルに挫折した人向けに書かれています。最初にJavaScriptについて説明してくれているところがあり、大変わかりやすく、Reactに必要なJavaScriptの知識が網羅されています。
書籍を一通り読みながら、なんとなく理解してきたので、同時にReactチュートリアルもやり始めました。この段階で、やっとチュートリアルの言ってる内容をおおかた理解しはじめました。

React、TypeScript、Next.js (約2週間:2023年11月20日〜2023年11月30日)

Reactチュートリアルをおおかた終え、Reactの概念的な部分は理解したので、さあ、create-react-appしようかと思ったのですが、実装のイメージがまだわかず、フレームワークとかを勉強すべきでは、、、と思い始めました。
そこで、有名なこれからはじめるReact実践入門 コンポーネントの基本からNext.jsによるアプリ開発までの書籍をやりはじめ、TypeScript、Next.js、Vercelへのデプロイ方法まで網羅しました。
TypeScript、Next.jsに関してはそこまで詳細を説明してくれているわけではないですが、「TypeScriptはChatGPTでなんとかなるだろう」、「Next.jsはドキュメントが英語だけどなんとなく読みやすいし大丈夫だろう」と思い、やっと、そろそろ実装はじめるぞと思える段階まできました。

開発期間

バックエンド側 (約1週間:2023年10月31日〜2023年11月7日)

私の制作するWebアプリは単純で、ほぼほぼ、RUNTEQのRails API編で学習したことをそのまま活かせたので、困ることはありませんでした(ただ、テーブルに格納するデータを自分で作るのには膨大な時間がかかりました、何度も言いますが絶対におすすめしません)。

フロントエンド側 (約1ヶ月:2023年12月1日〜2024年1月5日)

11月に3週間ほど現職の出張があったり、業務が忙しく、毎日残業や会食づけで全く勉強する時間がとれない時期がありました。
そろそろ、開発を始めなくては本格的にまずいなと直感的に思いながら、create-next-appをして、フロントエンド側の開発を始めました。
Mantineのコンポーネントはどれも可愛くて、いろんなコンポーネントを吟味して楽しみながら実装しました。

心残り、今後の課題

以下のことを今後の課題だと感じています。

  • サーバーアクション:やっぱり、Next.js 14を使っているのであれば、APIルートではなく、サーバーアクションにチャレンジしてみるべきだと思いました。次はリベンジしたいです。
  • ログイン認証:自作のAPIで認証をしたのですが、Firebase Authなどでユーザー体験を向上させるべきだったかなと思っています。しかし、初めてのRails APIで、自分で認証の仕組みを1から作ったのはとても勉強にはなりました。
  • コンポーネントの設計:再レンダリングの範囲やひとつのファイルに多くのロジックを書いていたり、重複して書いている箇所が多くあり、コンポーネント設計の考え方を学ぶ必要があると思っています。なにかいい教材があれば教えていただければ嬉しいです。
  • テスト:現在、テストを一切書いていないのでそろそろ書いていきます。

おわり

今回始めて0からWebアプリを作成しましたが、本当にたくさんの学びがありました。
自分の知識不足課題も多くみつかり、次への宿題も多くみつかりました。

だいぶ、のんびりと勉強、開発をしてしまいましたが、それも含め、自分のレベル感かなとも感じています。
本記事がこれから開発しようとしている方や、技術選定に悩んでいる方、お仕事をしながら学習している方、みなさまのなにかの参考になれば幸いです。
最後までご覧いただき、ありがとうございました:blush:

11
8
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
11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?