友達用TypeScript入門 シリーズで「コードを書いて動かす」までは一通りやった。
この記事はその先、フルスタックエンジニアを目指すなら何を学ぶか をまとめたロードマップ。

ここに書くのは 特定の言語やフレームワークに依存しない基本 だけにする。シリーズではTypeScriptとHonoを使ったけど、内容はRubyでもGoでもPythonでも同じように使える。「どの言語でやるか」は後で選べばいい。言語は手段で、ここに書く概念が本体。

一気に読み切る必要はない。次に何をやるか迷ったときに戻ってくるページとして使ってほしい。

もうできる(と思っている)こと

以下はすでに持っている前提で、この記事では扱わない。

  • Git — commit / push / branch / Pull Request。「動いていた状態に戻せる」という学習の安全ネットはすでにあるものとして、この先のフェーズでは説明なしで使う
  • インフラの基礎 — サーバの仕組み、VPN、サブネット設計、最低限のセキュリティ知識。ネットワークやサーバそのものの話はしない
  • Vim / ターミナル — エディタとシェル操作で手が止まらない。コマンドはそのまま書く

これはかなり有利な条件で、入門者の多数派は「コードは書けるがインフラがわからない」側から来るが、その逆。フェーズ6(コンテナ)と7(公開と運用)は馴染みやすいはずで、慣れていないのはフロントエンドとデータベースまわり。この記事もそこに厚みを置いている。

「(と思っている)」の通り、自己申告でいい。進めていて怪しくなったらその場で調べて戻ればいいだけで、最初に棚卸しテストをする必要はない。

「フルスタック」とは何か

フルスタックエンジニアの定義は人によってブレるが、実用的にはこう捉えるのがいい。

1つのWebサービスを、画面からデータベースまで自分ひとりで作って公開できる人

全レイヤーの専門家になる、という意味ではない。レイヤーごとの専門家には敵わなくていい。代わりに「全部がつながった状態で動かせる」ことに価値がある。

Webサービスのレイヤーを並べるとこうなる。

ブラウザ (HTML / CSS / JavaScript)    ← フロントエンド
    ↓ HTTP
APIサーバ (言語は何でもいい)           ← バックエンド
    ↓ SQL
データベース
---------------------------------------
テスト、コンテナ、デプロイ先、ログ      ← 全部を支える土台

フルスタックを目指す学習とは、この図の 矢印も含めて全部を一度自分の手で通す こと。どれか1つを深く掘るのは、その後でいい。

よく参照される roadmap.sh の Full Stack ロードマップ もほぼこの構成で描かれている。ノードの数が多いが、全部やる必要はない。最初にやるべきものだけを以下のフェーズで示す。

ロードマップ全体像

フェーズテーマ答えられるようになる問い
1Webの全体像URLを打ってから画面が出るまでに何が起きている?
2フロントエンドの基本画面はどうやって作られ、どう更新される?
3バックエンドの基本サーバは何をしていて、APIはどう設計する?
4データベースの基本データはどこに、どんな形で保存する?
5テストの基本壊れていないことを、どうやって機械に確認させる?
6コンテナの基本「手元では動く」をどうやって無くす?
7公開と運用localhostの外で動かすには何が要る?
8横断する基本認証・セキュリティ・CIはどのレイヤーの話?

各フェーズに「作るもの」を置いてある。読むだけのフェーズは1つもない。題材は何でもいいが、おすすめは入門シリーズと同じく「タスク管理アプリ」を1個決めて、フェーズが進むごとに同じアプリを育てていくこと。

フェーズ1: Webの全体像を掴む

すべての土台。ブラウザのアドレスバーにURLを打ってEnterを押してから画面が表示されるまでに、何が起きているのかを言葉で説明できるようにする。

押さえる概念:

  • DNSexample.com という名前が、どうやってサーバの住所(IPアドレス)になるのか
  • HTTP — リクエストとレスポンス。メソッド(GET / POST / PUT / DELETE)、ステータスコード(200 / 404 / 500)、ヘッダとボディ
  • クライアントとサーバ — 「お願いする側」と「待ち受けて返事する側」という役割分担
  • HTML / CSS / JavaScriptの役割 — 構造・見た目・動き、という3つの責務の分離

資料:

やること:

  • ブラウザの開発者ツールの Networkタブ を開いて、適当なサイトを表示し、飛んでいるリクエストを観察する。メソッド、ステータスコード、レスポンスの中身を実際に見る
  • curl で同じURLを叩いて、ブラウザがやっていることを手動で再現する

ゴール: 「URLを打ってから画面が出るまで」を、DNS → HTTP → サーバ → レスポンス → 描画の流れで人に説明できる。

フェーズ2: フロントエンドの基本

ブラウザ側の話。ここで押さえる概念は、ReactだろうがVueだろうが、どのフレームワークを後で選んでも変わらない。

押さえる概念:

  • HTMLは文書の構造 — 見出し、リスト、フォーム。見た目ではなく意味でタグを選ぶ
  • CSSはスタイル — セレクタで要素を選び、プロパティを当てる。レイアウトの基本(Flexbox)
  • DOM — HTMLがブラウザの中でツリー構造のオブジェクトになること。JavaScriptはこのツリーを書き換えることで画面を動かす
  • イベント — クリックや入力をきっかけにコードが動く仕組み
  • 状態と画面の同期 — 「データが変わったら画面も変える」を手作業でやるとどれだけ大変か。これを体感しておくと、後でフレームワークを選んだときに「何を解決してくれているのか」が一発でわかる

資料:

  • MDN Learn web development — HTML / CSS / JavaScriptの構造化されたコース。フロントエンドの教材はまずこれで、足りなくなることはほぼない

やること:

  • タスク一覧を表示するページをHTMLとCSSだけで手書きする
  • JavaScriptを足して「ボタンを押すとタスクが増える」「クリックで完了になる」を素のDOM操作で作る。フレームワークは使わない

ゴール: フレームワークなしで、動く画面を1枚作ったことがある。そして「データと画面の同期が面倒」を体感している。

フェーズ3: バックエンドの基本

サーバ側の話。ここも概念は言語非依存で、どの言語のWebフレームワークも結局同じことをしている。

押さえる概念:

  • Webサーバの仕事 — リクエストを待つ → 内容を見る → レスポンスを組み立てて返す → また待つ。これの繰り返しでしかない
  • ルーティング — 「このURLにこのメソッドで来たら、この処理」という対応表
  • APIとJSON — 画面(HTML)ではなくデータ(JSON)を返すサーバ。フロントエンドとの分業はここで生まれる
  • RESTの考え方 — URLは「リソース(名詞)」を表し、メソッドが「操作(動詞)」を表す。POST /tasks でタスク作成、GET /tasks/1 で取得、という規約
  • ステートレス — サーバはリクエストごとの記憶を持たない。だから「誰からのリクエストか」を毎回伝える仕組み(後述の認証)が要る

資料:

  • roadmap.sh Backend — バックエンド領域の全体像。繰り返すが、全部やるためのものではなく確認用
  • 『Webを支える技術』のREST章 — フェーズ1で買っていればここで再読する

やること:

  • 好きな言語でタスクAPIを作る(GET /tasks で一覧、POST /tasks で追加、PUT /tasks/:id で完了)。シリーズをやったならHono版が既にあるので、それでもいいし、別の言語で作り直すと「概念が言語をまたいで同じ」ことが確認できておもしろい
  • フェーズ2で作った画面から fetch でこのAPIを叩いてつなげる。ここで高確率で CORSエラー に出会う。誰もが一度は踏むエラーなので、エラーメッセージを読んで「なぜブラウザがこれを止めるのか」まで調べる

ゴール: 画面 → HTTP → API → レスポンス → 画面更新、の一周が自分の書いたコードでつながっている。

フェーズ4: データベースの基本

ここまでのアプリには致命的な弱点がある。サーバを再起動するとデータが全部消える。データがメモリ上にしかないから。これを解決するのがデータベースで、バックエンドエンジニアリングの核心はだいたいここにある。

押さえる概念:

  • 永続化 — プログラムの寿命とデータの寿命を切り離すこと
  • SQL — データベースに話しかけるための言語。SELECT / INSERT / UPDATE / DELETEWHERE、そして JOIN。どの言語を選んでもSQLだけは共通なので、ここへの投資は絶対に無駄にならない
  • テーブル設計 — データを「どんな列を持つ表」に分けるか。「タスク」と「ユーザー」を別テーブルにして関連づける、という考え方(正規化の入り口)
  • 主キーと外部キー — 行を一意に特定するIDと、テーブル同士のつながり

資料:

  • SQLBolt — ブラウザ上でSQLを書いて即結果が見える形式のチュートリアル。JOIN まで終えれば十分
  • SQLZoo — 練習問題を量こなしたいとき用

やること:

  • まずDB単体でSQLに触れる(SQLBoltで十分)
  • タスクAPIの保存先を、メモリ上の配列からデータベースに置き換える。最初のDBは SQLite 一択でいい。サーバを別に立てる必要がなく、ただのファイル1個として動くから
  • サーバを再起動してもタスクが残ることを確認する。これがこのフェーズで一番確認したいこと

ゴール: 再起動してもデータが消えないアプリ。そして簡単なSQLを自力で読み書きできる。

フェーズ5: テストの基本

ここまででアプリには画面・API・DBが揃った。すると新しい問題が出てくる。何かを変えるたびに、全部の動作を手で確認するのが現実的でなくなる。タスク追加を直したらタスク完了が壊れていた、に気づけない。これを機械に確認させるのがテスト。

押さえる概念:

  • テストは「壊れたことに気づく仕組み」 — 書いた瞬間より、3ヶ月後に改造するときに効く。安心して変更できる状態を作るのが目的
  • ユニットテスト — 関数ひとつを「この入力ならこの出力」で検証する。構造はどの言語でも同じで、準備する → 実行する → 検証する(Arrange / Act / Assert)の3拍子
  • 結合テスト — 部品をつなげて検証する。APIに実際にリクエストを送ってレスポンスを確かめる、など
  • E2Eテスト — ブラウザを自動操縦して、ユーザーの操作そのものを再現する
  • テストピラミッド — 下(ユニット)を厚く、上(E2E)を薄く。上に行くほど本物に近いが、遅くて壊れやすいから
  • テストしやすいコードは良いコード — テストを書こうとすると「ロジックが画面やDBと密結合で切り出せない」壁に当たる。これが設計を見直すきっかけになる

資料:

やること:

  • 選んだ言語のテストランナーで、タスク操作のロジックにユニットテストを書く(追加できる、完了にできる、存在しないIDでも落ちない)
  • APIに実際にリクエストを送る結合テストを1本書く
  • わざと実装を壊して、テストが赤くなるのを見る。赤を見たことがないテストは信用できない

ゴール: ワンコマンドで「壊れていないこと」を確認できる。改造が怖くなくなっている。

フェーズ6: コンテナの基本

「手元では動くのに、別のマシンでは動かない」。原因はだいたい環境の差分で、言語のバージョン、DBの有無、OSの違い…と無限にある。この差分を消すために、アプリと実行環境を丸ごとパッケージして持ち運ぶ のがコンテナで、事実上の標準ツールがDocker。

押さえる概念:

  • イメージとコンテナ — イメージは「環境のスナップショット(レシピ)」、コンテナは「それを実際に起動したもの(料理)」。1つのイメージから何個でもコンテナを起動できる
  • Dockerfile — 環境構築の手順(OSはこれ、言語を入れて、依存を入れて、起動コマンドはこれ)をコードとして書いたもの。「環境構築手順書」が実行可能になったと思えばいい
  • ポートのマッピング — コンテナの中は外から隔離されているので、-p 3000:3000 のように穴を開けて外とつなぐ
  • ボリューム — コンテナは消えたら中のデータも消える。残したいデータ(DBのファイルなど)は外側に置く
  • docker compose — 「アプリのコンテナ」と「DBのコンテナ」のような複数コンテナを、設定ファイル1枚で一斉に起動する仕組み

資料:

  • Docker公式 Get Started — 公式チュートリアル。イメージ → コンテナ → composeの流れを一通り体験できる
  • Play with Docker — ブラウザ上でDockerを試せる環境。インストール前の素振りに

やること:

  • タスクアプリのDockerfileを書いて、docker builddocker run で動かす
  • docker composeで「アプリ + DB」を1コマンドで立ち上げる構成にする。このときDBをSQLiteから PostgreSQL に乗り換えてみるといい。composeならDBサーバを立てるのが一瞬になるし、フェーズ4で学んだSQLがそのまま通用することも確認できる
  • 一度 docker compose down で全部消して、もう一度 up するだけで同じ環境が再現されることを確認する。これがコンテナの価値そのもの

ゴール: git clone して docker compose up するだけで、誰のマシンでも同じアプリが立ち上がる。

フェーズ7: 公開と運用

localhost で動くものと、インターネット上で動くものの間には壁が一枚ある。これを一度越えると「作ったものを人に見せられる」ようになり、学習のモチベーションが大きく変わる。

押さえる概念:

  • 本番環境と開発環境 — 自分のPCと、公開されているサーバは別物。「手元では動くのに本番で動かない」は定番のトラブル
  • 環境変数 — DBの接続先やAPIキーなど「環境ごとに違う値・コードに書いてはいけない値」を外から渡す仕組み
  • HTTPS — 通信の暗号化。今は公開プラットフォームがほぼ自動でやってくれるが、「なぜ必要か」は知っておく
  • ログ — 本番で何かが起きたとき、唯一の手がかり。console.log の延長線上にあるが、「後から読む人のために書く」という意識が入る

やること:

  • フロントエンドとAPIを無料枠のあるプラットフォームにデプロイする。CloudflareVercelRender など、選んだ言語に合わせて選べばいい。「GitHubにpushしたら自動でデプロイされる」構成にするのが今の標準
  • フェーズ6でコンテナ化してあれば、RenderやCloud Runのように Dockerfileをそのまま渡せばデプロイできる プラットフォームも選べる。手元で動いたコンテナがそのまま本番になる、というコンテナの価値がここで回収される
  • スマホからアクセスして動くことを確認する
  • わざとエラーが起きるリクエストを送って、プラットフォームのログ画面でそれを見つける練習をする

ゴール: URLを友達に送れる状態。そして本番でエラーが起きたときにログを見にいける。

フェーズ8: 横断する基本

ここまでで「動くものを作って公開する」は一周した。最後は、特定のレイヤーに属さずすべてを横断する基本。実務との距離が一気に縮まるのはここから。

認証と認可

「ログインしているのは誰か(認証)」と「その人に何が許されているか(認可)」は別の概念。サーバはステートレス(フェーズ3)なので、「誰か」を毎回伝える仕組みとしてCookieとセッションがある。あわせて、パスワードは絶対にそのまま保存しない(ハッシュ化する)という鉄則もここで学ぶ。

やること: タスクアプリに「ユーザーごとに自分のタスクだけ見える」を足す。ライブラリに頼っていいが、Cookieに何が入っていて、サーバがそれをどう検証しているかは開発者ツールで観察する。

セキュリティの基礎

ネットワーク側のセキュリティは知っている前提なので、ここで足すのは Webアプリケーション固有 の攻撃。最低限、名前と仕組みを知っておくべきものが3つ。SQLインジェクション(入力値をSQLに直接埋め込むと注入される)、XSS(入力値をHTMLに直接埋め込むとスクリプトが動く)、CSRF(ログイン済みユーザーに意図しないリクエストを踏ませる)。共通の教訓は「ユーザーの入力を信用しない」。

資料: 安全なウェブサイトの作り方(IPA) — 日本語の定番。 OWASP Top 10 — 世界標準のリスク一覧。

CI(継続的インテグレーション)

フェーズ5で書いたテストを、「pushするたびに自動で走り、壊れていたら教えてくれる」仕組みに載せる。GitHub Actionsで設定できる。コンテナ(フェーズ6)もここで効いてくる。CIのマシンは自分のPCとは別環境だが、コンテナ化してあれば同じ環境でテストが走る。「緑のチェックがついたものだけマージする」は、チーム開発の基本動作そのもの。

入力値の検証

フォームやAPIに来る値は、期待した形をしている保証がない。境界(リクエストを受け取った直後)で検証して、不正なら 400 を返す。どの言語にもバリデーションライブラリがあるが、「境界で検証する」という考え方自体が本体。

言語選びについて

どのフェーズも、特定の言語を前提にしていない。実際、フェーズ3〜4を別の言語でもう一周すると「ルーティング、JSON、SQL、全部同じことをしている」と気づくはずで、その気づきこそが2言語目の最大の収穫になる。

選ぶときの観点だけ置いておく。

  • 求人・現場で使われているか — 仕事にしたいなら、TypeScript / Ruby / Go / Python / PHP / Javaあたりが堅い
  • 情報の多さ — 詰まったときに日本語の情報があるか
  • 書いていて楽しいか — 続けられることが何より強い

どれを選んでも、この記事の概念はそのまま持ち越せる。だから安心して後で選べばいい。

進め方のコツ

最後に、技術の話より大事かもしれない話。

同じアプリを育て続ける。 フェーズごとに新しいアプリを作るのではなく、同じタスク管理アプリに画面を足し、DBを足し、認証を足していく。「全部がつながって動く状態を維持し続ける」ことが、フルスタックの訓練そのもの。

写経したら、必ず改造する。 チュートリアルを完走した直後は「わかった気」になっているだけのことが多い。期限を足す、タグを足す、並び替えを足す。改造して初めてエラーに出会い、エラーに出会って初めて理解する。

エラーメッセージを読む。 エラーは原因を教えてくれる唯一の情報源。読まずに消そうとせず、まず最後まで読む。開発者ツールとログを見る癖は、どの言語に行っても通用する。

ロードマップを完璧に埋めようとしない。 roadmap.shの項目は、現役のエンジニアでも全部は埋まっていない。ロードマップは次にやることを選ぶためのもので、全部やるためのものではない。

期間の目安は気にしすぎない。 よく「フルスタックまで3〜5年」と言われるが、それは仕事として通用するレベルの話。「自分のアプリを画面からDBまで作って公開する」だけなら、週末ペースで数ヶ月で届く。まずそこを目指すのがいい。

資料まとめ

本文に出てきたものの一覧。

資料領域
MDNWeb技術全般の辞書。困ったらまずここ
MDN Learn web developmentHTML / CSS / JSの体系的コース
roadmap.sh領域ごとの全体像の確認用
『Web技術の基本』Webの仕組みを図解で俯瞰する入門書
『Webを支える技術』HTTPとRESTを体系的に学ぶ定番書
SQLBoltブラウザでSQLを練習
The Practical Test Pyramidテストの種類と配分の考え方
『テスト駆動開発』テストファーストの考え方の原典
Docker公式 Get Startedコンテナの公式チュートリアル
安全なウェブサイトの作り方(IPA)セキュリティの日本語定番資料
The Odin Project / freeCodeCamp英語でよければ、作りながら進むフルカリキュラム

ここまで来たら、もう入門記事を読む側ではなく、自分の作ったものについて記事を書く側。完走したら、ぜひ「アプリを公開するまで」を自分のブログに書いてほしい。