目次
| 章 | タイトル | 内容 |
|---|---|---|
| 1. | はじめに | この記事の背景と対象読者 |
| 2. | シェル・OSの基礎 | プロセス、PATH、パーミッション、パイプ |
| 3. | ネットワークの基礎 | IP、DNS、HTTP、TCP/IP、SSL/TLS |
| 4. | データ構造とアルゴリズム | 配列、ハッシュ、O記法 |
| 5. | データベースの基礎 | SQL、インデックス、トランザクション、正規化 |
| 6. | Gitの内部構造 | 3エリア、ブランチの正体、マージとリベース |
| 7. | セキュリティの基礎 | 認証/認可、ハッシュ/暗号化、XSS/SQLi |
| 8. | 設計の基礎 | 関心の分離、MVC、SOLID |
💡 この記事の一番おすすめの使い方
この記事をそのまま読むより、AIに「この記事を参考に授業して」と投げて、対話形式で学ぶほうが圧倒的に定着します。実際、自分もClaude相手に授業→テスト→深掘り→復習テストのサイクルを回して理解しました。読んで「ふーん」で終わるより、「Q: PATHとは?」「A: えーと...」のやり取りのほうが記憶に残ります。ぜひ試してみてください。
はじめに
実務経験1年、大学でCSを学んでいない自分が「これ基本中の基本なのに知らなかった...」と気づいた知識をまとめました。
きっかけは .zshrc の意味を聞かれて「macのbashのこと?」と答えたこと。動くコードは書けるけど、裏側で何が起きているかを理解していなかった。
この記事の対象読者:
- CS系の学位なしでエンジニアをやっている人
- 「なんとなく動いてるけど仕組みがわからない」ことが多い人
- Next.js / Rails / TypeScriptあたりで実務をしている人
この記事で得られること:
- 実務で毎日触っている技術の「裏側」が見える
- 「command not found」「Permission denied」などのエラーに自力で対処できる
- 先輩エンジニアとの会話で出てくる用語がわかるようになる
1. シェル・OSの基礎
シェルとは
シェルは 人間とOS(カーネル)の間の通訳 です。
あなた → シェル(zsh) → カーネル(macOSの中核) → ハードウェア
zshもbashも「通訳の種類」が違うだけ。.zshrc はzsh版の .bashrc(シェルの設定ファイル)。macOS Catalina以降はデフォルトがzsh。
プロセス
コマンドを実行するたびに プロセス(実行中のプログラム)が生まれる。
ps aux | grep node # nodeのプロセスを探す
lsof -i :3000 # ポート3000を使っているプロセスを探す
kill 12345 # PID指定で終了(SIGTERM: お願い終了)
kill -9 12345 # 強制終了(SIGKILL: 即死)
実務で遭遇する場面: next dev が「ポート3000が使用中」で起動できないとき → 前のプロセスが残っている → lsof -i :3000 でPID確認 → kill で解決。
PATH
PATHは 「コマンドを探しに行くフォルダの一覧表」 です。
echo $PATH
# /opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin
: 区切りのリストで、左から順に探す。
nodeと打つ
→ /opt/homebrew/bin/node ある? → ない
→ /usr/local/bin/node ある? → あった! → 実行!
「command not found」の正体 = PATHに書かれたフォルダを全部探したけど見つからなかった。
「PATHを通す」 = PATHに新しいフォルダを追加すること。
# .zshrcに書く
export PATH="/my/custom/bin:$PATH" # 先頭に追加 = 優先度高
asdfのshimの仕組み
asdf(バージョン管理ツール)を使っている場合、which node すると .asdf/shims/node が出てくる。これは本物のnodeではなく 中継役(shim) 。
nodeと打つ → shim(受付係)が見つかる → 今の設定バージョンを確認 → 本物のnodeに転送
PATHを書き換えずにバージョンを切り替えられるのが利点。
パーミッション(chmod)
chmod = change mode。ファイルのアクセス権限を変更するコマンド。
権限は3種類で、それぞれ数値が対応している:
| 権限 | 記号 | 数値 |
|---|---|---|
| 読み取り | r | 4 |
| 書き込み | w | 2 |
| 実行 | x | 1 |
3桁の数字は「オーナー・グループ・その他」の権限:
chmod 755 script.sh
# 7(=4+2+1) → オーナー: rwx
# 5(=4+1) → グループ: r-x
# 5(=4+1) → その他: r-x
chmod 600 ~/.ssh/id_rsa
# 6(=4+2) → オーナー: rw-
# 0 → グループ: ---(何もできない)
# 0 → その他: ---(何もできない)
「Permission denied」の原因 = 実行権限(x)がない → chmod +x script.sh で解決。
標準入出力とパイプ・リダイレクト
すべてのプロセスには3つの「パイプ」がある:
| 名前 | 番号 | 意味 |
|---|---|---|
| stdin | 0 | 入力 |
| stdout | 1 | 通常の出力 |
| stderr | 2 | エラー出力 |
> # stdoutをファイルに書く(1> の省略形)
2> # stderrをファイルに書く
2>&1 # stderrをstdoutと同じ場所に(&はチャンネル番号の印)
| # 左のstdoutを右のstdinに繋ぐ(パイプ)
cat access.log | grep "ERROR" | wc -l
# cat → 全行をstdoutに流す
# | → grepのstdinに渡す
# grep → ERRORを含む行だけstdoutに流す
# | → wc -lのstdinに渡す
# wc -l → 行数を数えて表示
2. ネットワークの基礎
IPアドレスとポート
IPアドレス = マンションの住所(例: 133.242.50.10)
ポート = 部屋番号(例: :3000)
| ポート | 用途 |
|---|---|
| 80 | HTTP |
| 443 | HTTPS |
| 3000 | Next.js開発サーバー |
| 5432 | PostgreSQL |
「ポート3000が使用中」= 3000番の部屋にもう別のプロセスが住んでいる。
DNS(Domain Name System)
ドメイン名をIPアドレスに変換する 電話帳 。
dandori.app → DNSに問い合わせ → 76.76.21.21
| レコード種別 | 役割 | 使う場面 |
|---|---|---|
| Aレコード | ドメイン → IPアドレス(直接指定) | 自前サーバー(ConoHa, AWS EC2) |
| CNAMEレコード | ドメイン → 別のドメイン(転送) | ホスティング(Vercel等) |
Vercel + CNAME: IPの管理はVercelに任せるので、サーバーのIPが変わってもこちらは何もしなくていい。
自前サーバー + Aレコード: IPを直接指定するので、サーバー移行時は自分で書き換える必要がある。
HTTP(HyperText Transfer Protocol)
ブラウザとサーバーの会話ルール。
| メソッド | 役割 |
|---|---|
| GET | データ取得 |
| POST | データ作成 |
| PUT / PATCH | データ更新(全体 / 一部) |
| DELETE | データ削除 |
| ステータスコード | 意味 |
|---|---|
| 2xx | 成功 |
| 3xx | リダイレクト |
| 4xx | クライアント側のミス(401=認証失敗、403=権限なし、404=見つからない) |
| 5xx | サーバー側のミス |
ヘッダー = 本文(body)を読む前に必要なメタ情報。「このデータをどう扱えばいいか」の指示書。
ネットワークの層構造
HTTP → 「何を話すか」(会話の内容)
SSL/TLS → 通信を暗号化する
TCP → 確実に届ける(パケット分割・再送)
IP → 正しい住所に届ける
各層が独立して動けるのがポイント。HTTPは「TCPが確実に届けてくれる前提」で会話の内容だけ考えればいい。
http:// vs https:// の違いは 通信が暗号化されているかどうか 。
3. データ構造とアルゴリズム
主なデータ構造
| データ構造 | 特徴 | 実務例 |
|---|---|---|
| 配列(Array) | 順番に並ぶ。インデックスでアクセス | items[0] |
| ハッシュ(Object) | キーと値のペア。キーで一発アクセス | user["name"] |
| スタック(Stack) | LIFO(後入れ先出し) | ブラウザの「戻る」ボタン |
| キュー(Queue) | FIFO(先入れ先出し) | ジョブキュー |
| 木構造(Tree) | 親子関係があるデータ | DOM、ファイルシステム、Reactコンポーネント |
計算量(O記法)
データがn個あるときの処理時間の目安:
| 計算量 | 意味 | 100万件での回数 |
|---|---|---|
| O(1) | データが増えても速度が変わらない | 1回 |
| O(log n) | 半分ずつ絞る回数 | 約20回 |
| O(n) | データに比例して遅くなる | 100万回 |
| O(n²) | データが倍で4倍遅くなる | 1兆回 |
O(log n)のイメージ: 1〜100万の数当てゲームで「もっと大きい/小さい」のヒントがもらえるなら、毎回半分に絞れるので約20回で当てられる。log₂(1,000,000) ≈ 20。
実務での改善例
// ❌ O(n²) - ループの中で毎回find
users.forEach(user => {
const order = orders.find(o => o.userId === user.id)
})
// ✅ O(n) - 先にハッシュマップを作る
const orderMap = {}
orders.forEach(o => { orderMap[o.userId] = o }) // O(n)
users.forEach(user => {
const order = orderMap[user.id] // O(1)で取得
})
4. データベースの基礎
基本用語
テーブル = Excelのシート1枚
カラム = 列(id, name, amountなど)
レコード = 行(1件のデータ)
CRUDとHTTPの対応
| 操作 | SQL | HTTP |
|---|---|---|
| Create | INSERT | POST |
| Read | SELECT | GET |
| Update | UPDATE | PUT / PATCH |
| Delete | DELETE | DELETE |
インデックス
本の巻末の索引と同じ。検索を O(n) → O(log n) に高速化する。データをあらかじめソートしておき、半分ずつ絞って探す。
トランザクション
複数の操作をまとめて「全部成功 or 全部失敗」にする仕組み。
BEGIN;
INSERT INTO estimates (name, amount) VALUES ('E社見積もり', 70000);
INSERT INTO histories (action, detail) VALUES ('create', 'E社見積もりを作成');
COMMIT; -- 両方成功 → 確定
-- 失敗時は ROLLBACK → 全部取り消し
正規化とJOIN
正規化 = データの重複をなくす設計。テーブルを分けて company_id などで紐づける。
JOIN = 分けたテーブルを取得時に結合する。
これが「リレーショナル」データベースの名前の由来。
5. Gitの内部構造
3つのエリア
| エリア | 役割 | コマンド |
|---|---|---|
| ワーキングディレクトリ | ファイルを編集する場所 | vim app.js |
| ステージング | コミットに含めるものを選ぶ | git add |
| リポジトリ | スナップショットを保存 | git commit |
3つの内部オブジェクト
| オブジェクト | 役割 |
|---|---|
| blob | ファイルの中身 |
| tree | ディレクトリ構造 |
| commit | スナップショット(tree + 親コミット + メタ情報) |
ブランチの正体
ブランチは コミットを指すポインタ(付箋) 。git branch feature は今いるコミットに付箋を貼るだけ。ファイルコピーは起きない。だから一瞬。
HEAD = 今自分がどのブランチにいるかを指すポインタ。
マージ vs リベース
| 項目 | マージ | リベース |
|---|---|---|
| やること | 2つの履歴を合流 | 自分のコミットを相手の最新の後ろに付け直す |
| コミット | マージコミット(親が2つ)が生まれる | コミットが作り直される(ハッシュが変わる) |
| 履歴 | 枝分かれが残る | 一直線になる |
| 使いどころ | 共有済みブランチ | まだpushしてない自分のブランチ |
git-worktree
1つの .git で複数のワーキングディレクトリを持つ。ブランチ切り替え不要で複数ブランチを同時に作業できる。オブジェクトは共有されるのでディスク容量もほとんど増えない。
6. セキュリティの基礎
認証と認可
| 認証(Authentication) | 認可(Authorization) | |
|---|---|---|
| 問い | あなたは誰? | あなたは何ができる? |
| 具体例 | ログイン | 権限チェック |
| 失敗時のHTTP | 401 Unauthorized | 403 Forbidden |
ハッシュと暗号化
| ハッシュ | 暗号化 | |
|---|---|---|
| 方向 | 一方通行(元に戻せない) | 双方向(鍵で元に戻せる) |
| 用途 | パスワード保存 | 通信の保護(HTTPS, SSH) |
パスワードをそのまま保存せず、ハッシュ化して保存する。ログイン時は入力をハッシュ化して保存済みハッシュと比較するだけなので、元に戻す必要がない。
代表的な攻撃と対策
| 攻撃 | 内容 | 対策 |
|---|---|---|
| XSS | 悪意あるスクリプトをページに埋め込む | ユーザー入力をエスケープ(ReactのJSXは自動対応) |
| SQLインジェクション | SQL文に不正入力を埋め込む | プレースホルダー使用(ORMが自動対応) |
7. 設計の基礎
設計の目的
変更に強いコードを作ること。 1箇所直しても別の場所が壊れない、安心して触れるコードを目指す。
関心の分離
1つのモジュールは1つのことだけやる。バリデーション・DB保存・通知を1つの関数に詰め込まない。
MVC
| コンポーネント | 役割 | Railsでの場所 |
|---|---|---|
| Model | データとビジネスロジック | app/models/ |
| View | 画面表示 | app/views/ |
| Controller | リクエストを受けてMとVを繋ぐ | app/controllers/ |
SOLID原則(特に重要な2つ)
S - 単一責任の原則: クラスや関数は1つの理由でだけ変更されるべき。見積もりクラスがメール送信までやるのは違反。
O - 開放閉鎖の原則: 既存コードを修正せずに拡張できるようにする。if文の追加ではなく、ハッシュマップ等で差し替え可能にする。
// ❌ 追加のたびに既存コードを修正
function calcDiscount(type, amount) {
if (type === "early") return amount * 0.1
if (type === "bulk") return amount * 0.15
if (type === "vip") return amount * 0.2 // ← 追加
}
// ✅ 新しいタイプを追加するだけで既存コードに触らない
const strategies = {
early: (amount) => amount * 0.1,
bulk: (amount) => amount * 0.15,
}
strategies.vip = (amount) => amount * 0.2 // 追加だけ
デザインパターン(実務で使う3つ)
| パターン | 説明 | 実務例 |
|---|---|---|
| Strategy | 処理を差し替え可能にする | 割引タイプごとの計算ロジック |
| Observer | 何か起きたら通知する |
addEventListener, useEffect
|
| Factory | オブジェクトの生成をまとめる | 種類に応じたインスタンス生成 |
おわりに
大学4年間で学ぶCS基礎を7領域に凝縮してまとめました。各領域はもっと深くなりますが、「全体像を知っている」と「知らない」の差はめちゃくちゃ大きい です。
この記事の知識があれば:
- ターミナルのエラーの原因を自力で特定できる
- コードレビューで「なぜこの設計か」が理解できる
- 先輩エンジニアの会話についていける
CSを専攻していなくても、実務の中でこれらを1つずつ理解していけば十分戦えます。
参考
株式会社シンシアでは、実務未経験のエンジニアの方や学生エンジニアインターンを採用し一緒に働いています。
※ シンシアにおける働き方の様子はこちら
シンシアでは、年間100人程度の実務未経験の方が応募し技術面接を受けます。その経験を通し、実務未経験者の方にぜひ身につけて欲しい技術力(文法)をここでは紹介していきます。