OBJECT STORAGE / CLOUD ARCHITECTURE
オブジェクトストレージの仕組み|Supabase Storageで学ぶバケット・メタデータ・アクセス制御
写真やPDFを安全に保管するとき、ファイル名・バケット・キー・メタデータがそれぞれ何をしているのか。身近なWeb開発から、ストレージの設計原理まで順序よく理解します。
01|身近な例:プロフィール画像はどこに保存しますか
Next.jsでユーザーのプロフィール画面を作るとします。利用者が写真をアップロードすると、ブラウザは画像のバイト列を送信し、画面にはその画像が表示されます。しかし、写真そのものをユーザーテーブルの文字列カラムへ入れる必要はありません。画像はストレージへ保存し、データベースには「どの画像かを表すキー」を持たせる方法があります。
Supabaseを使う構成なら、画像はSupabase Storageへ、表示名やプロフィールの情報はPostgresへ、と役割を分けられます。これにより画像の配信と会員情報の検索を別々に設計できます。
画像を選んでアップロード
→バケットとキーで画像を管理
→プロフィールと画像キーを保存
02|まず三つを区別します:ブロック・ファイル・オブジェクト
同じ写真を扱う場合でも、記憶領域をどの単位で利用者に見せるかによって方式が変わります。ブロックは番号の付いた固定長の区画、ファイルはディレクトリと名前で扱うデータ、オブジェクトは識別子(キー)とメタデータを伴うデータのまとまりです。
| 方式 | アクセスする単位 | 利用者側の操作 | 代表的な用途 |
|---|---|---|---|
| ブロック | 番号で指定する固定長の領域 | OSがファイルシステムを構築し、ブロックを読み書きします。 | 仮想マシンのディスク、DBの記憶領域 |
| ファイル | パスで指定するファイル | /docs/a.pdf のような階層パスを使います。 | 共有フォルダ、NAS |
| オブジェクト | キーで指定するオブジェクト | APIで保存・取得・削除します。 | 画像、動画、バックアップ、ログ |
03|ブロックの実体を具体的に想像します
ブロックストレージを「同じ大きさの引出しが何千個も並んだ棚」だと考えます。例えば番号0・1・2・3の引出しへデータを分割して保存します。OSはその上にファイルシステムを構成して、「photo.pngの内容は、どのブロックに入っているか」という対応関係を管理できます。
対してオブジェクトストレージの利用者は通常、ブロック番号を指定しません。avatars/user-42.pngというキーをAPIに渡せば、その画像オブジェクトを取得します。内部で実際のデータをどの装置・どの区画へ置くかはストレージシステムが管理します。
04|オブジェクトは三点セットで考えます
オブジェクトは、①画像・動画・文書などのデータ本体、②その内容や属性を表すメタデータ、③特定のデータを指し示す識別子(キー)を中心に管理されます。例えばキーがavatars/user-42.png、Content-Typeがimage/png、内容が画像のバイト列という組合せです。
| 要素 | 例 | 必要な理由 |
|---|---|---|
| データ本体 | PNGのバイト列 | 表示・ダウンロードする実際の内容です。 |
| キー | avatars/user-42.png | 保存・取得・削除対象を指定します。 |
| メタデータ | Content-Type: image/png | 形式や属性を読み取る助けになります。 |
| バケット | user-uploads | 関連オブジェクトをまとめる名前空間・設定単位です。 |
05|バケットとキー:フォルダに見えても本質は異なります
バケット(bucket)は、オブジェクトをまとめて管理する入れ物です。キー(key)は、その中の対象を識別する名前です。次の例でavatars/user-42.pngに含まれる「/」は、階層を表現したいときに使える文字です。オブジェクトストレージ内部に、通常のOSのフォルダと同じ実体が必須という意味ではありません。
Supabaseの管理画面ではフォルダのように見えますが、実装の考え方は「バケット+オブジェクト名」で対象を特定する方式です。バケット名とキーの役割を分けて覚えると、後述のStorage APIが読みやすくなります。
06|HTTP APIで保存・取得・削除します
REST(Representational State Transfer、レスト)はWeb APIの設計スタイルです。オブジェクトストレージはHTTP経由のAPIを提供することが多く、保存・取得・削除などの処理を識別子に対して行います。S3互換APIでは一般にPUT・GET・DELETEを使います。Supabase StorageのJavaScript SDKは、これらの詳細をラップしたupload・download・removeなどを提供しています。
bucket + avatars/user-42.png
→認証・権限・保存先を確認
→画像のバイト列とヘッダー
| 操作 | 意図 | 注意点 |
|---|---|---|
| PUT / upload | キーへデータを保存します。 | 同一キーをどう扱うかはAPIとオプション次第です。 |
| GET / download | キーに対応するデータを取得します。 | 非公開バケットならアクセス制御が必要です。 |
| DELETE / remove | キーのオブジェクトを削除します。 | 一覧取得権限とは別の権限になることがあります。 |
07|Next.jsとSupabase Storageでアップロードします
ブラウザで認証済みのユーザーが画像を保存する例です。Storageのバケットを用意し、必要なStorage用RLSポリシーを設定してから利用します。次は画像ファイルを受け取る関数の核心部分です。
import { createClient } from "@supabase/supabase-js";
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!
);
// 認証セッションが設定され、適切なRLSポリシーがある前提です。
async function uploadAvatar(file: File, userId: string) {
const path = "avatars/" + userId + "/" + crypto.randomUUID() + ".png";
const { data, error } = await supabase.storage
.from("user-uploads")
.upload(path, file, { contentType: file.type, upsert: false });
if (error) throw error;
return data.path; // DBにはこのキーを保存できます。
}08|公開バケットと非公開バケットを分けます
商品の一般公開画像なら公開バケットが便利な場合があります。一方、本人確認書類や非公開の請求書は、適切な認証・認可のある非公開バケットに置く必要があります。「URLを推測されにくくすること」はアクセス制御の代わりにはなりません。
| 対象 | 公開方針 | 理由 |
|---|---|---|
| サイトのロゴ | 公開してよい場合があります。 | だれでも表示する画像です。 |
| 会員のプロフィール画像 | 用途により公開・非公開を判断します。 | 公開範囲を設計します。 |
| 請求書PDF | 通常は非公開が適切です。 | 個人情報・取引情報が含まれます。 |
09|RLSと署名付きURLを混同しないようにします
RLS(Row Level Security、行単位のアクセス制御)はPostgresの行単位でアクセスを制限する仕組みです。Supabase Storageでは、関連するメタデータに対してポリシーを適用し、認証されたユーザーの操作を制御できます。
署名付きURL(signed URL)は、期限付きのアクセス権をURLへ含め、受信者が特定のオブジェクトを取得できるようにする手段です。署名付きURLが有効な間は、そのURLを知っている相手にアクセスされる可能性があるため、秘密として扱います。署名付きURLを作る権限と、発行済みURLを利用することも区別します。
10|SQLのテーブルとオブジェクトは何を持ち分けますか
Postgresで会員データを管理する場合、プロフィールの表示名、ユーザーID、画像キーなどは検索・結合できる表で扱います。画像のバイト列自体はStorageへ分ける方法があります。ただし、両者は別の操作で更新されるので、アップロード失敗やDB更新失敗のときにゴミデータ・古い参照が残らないように設計します。
-- 保存するのは画像本体ではなく、オブジェクトキーです。
create table profiles (
user_id uuid primary key,
display_name text not null,
avatar_path text
);
-- avatar_path の例:avatars/<user-id>/<uuid>.png11|ファイル名をキーに使うときの注意点
同じ名前で上書きすると、意図せず別ユーザーの画像を置き換えたり、CDNキャッシュに古い内容が残ったりすることがあります。キーにUUIDのような一意の値を含め、元のファイル名は必要に応じて別の属性として保存する方法が有効です。
拡張子だけでファイル形式を判断せず、ファイルの大きさやContent-Typeを検証します。画像のアップロードがあるアプリでは、想定外の形式や過大なサイズを防ぐ制限も必要です。
12|オブジェクトストレージが大量データに向く理由
オブジェクトに固有キーがあると、アプリケーションは特定の物理ディスクやディレクトリ配置を直接意識する必要がありません。ストレージ側ではデータ配置・複製・分散などの仕組みを組み合わせられます。このため、画像、映像、ログ、バックアップ、データレイクのような大量の非構造化データで広く利用されます。
13|耐久性・可用性・整合性は別々です
耐久性(Durability)はデータが失われにくいこと、可用性(Availability)は必要なときに利用できること、整合性(Consistency)は読出し時にどの更新結果が見えるかに関係します。複製、イレイジャーコーディング(消失訂正符号)、異なる障害領域への配置などは保存の信頼性を高めますが、具体的な保証はサービスや契約によって異なります。
| 概念 | 問い | 例 |
|---|---|---|
| 耐久性 | 保存した画像を失いにくいですか。 | 複製・消失訂正符号による保護です。 |
| 可用性 | いま画像を取得できますか。 | サーバー・ネットワーク障害への対策です。 |
| 整合性 | 更新直後にどの版が読めますか。 | サービスの読出し一貫性モデルに依存します。 |
14|S3・Supabase・NAS・SANの役割を整理します
S3(Simple Storage Service、エススリー)はAmazon Web Servicesのオブジェクトストレージサービスです。Supabase Storageはアプリケーションから利用しやすいストレージAPIやアクセス制御を提供します。一方、NAS(Network Attached Storage)はネットワーク越しのファイル共有、SAN(Storage Area Network)は主にブロックストレージを提供する構成で利用されます。
| 名称 | 何を表すか | アクセスの発想 |
|---|---|---|
| Supabase Storage | 開発者向けオブジェクト保存・配信サービス | バケットとパス(キー)を指定します。 |
| Amazon S3 | オブジェクトストレージサービス | バケットとキーを指定します。 |
| NAS | ネットワーク接続型ストレージ | 共有ファイル・ディレクトリを扱います。 |
| SAN | ストレージ専用ネットワーク | ホストへブロック単位の記憶装置を提供します。 |
15|バージョニング・ライフサイクル・CDN
保存するデータが増えると、バックアップだけでなく運用の設計が重要です。バージョニングは上書き前の版を残す考え方、ライフサイクルは一定期間後の移動・削除を自動化する考え方、CDN(Content Delivery Network、コンテンツ配信ネットワーク)は画像などを利用者に近い場所から配信しやすくする仕組みです。これらの機能や設定方法は提供サービスによって異なります。
16|失敗しやすい設計を具体例で確認します
| 状況 | 起こり得る問題 | 改善の考え方 |
|---|---|---|
| 請求書を公開バケットへ配置 | URLを知る第三者が取得するおそれがあります。 | 非公開バケットと適切な認可を使います。 |
| 他人のuserIdをキーに指定可能 | 所有者の異なるデータへ書込むおそれがあります。 | ユーザーIDは認証情報から検証します。 |
| 画像のURLだけDBに保存 | 環境変更やURL形式変更へ追従しにくくなります。 | バケットとキーを保存する設計も検討します。 |
| 画像の上書きだけに依存 | CDNなどで古い画像が残ることがあります。 | バージョン付き・一意キーを検討します。 |
17|操作ラボ:誰がどのオブジェクトを読めますか
バケットを公開・非公開で切り替え、利用者・オブジェクトキー・操作を変更してください。取得(GET)、保存(PUT)、削除(DELETE)の成功・失敗を観察すると、識別子で対象を指定することと、アクセスを許可されることが別だと理解できます。
操作ラボ|バケットとオブジェクトのアクセス判定
実サービスに接続しないローカルシミュレーターです。ここではアクセス規則を単純化し、署名付きURLは「有効なGET許可」として表しています。
操作を選んで実行してください。
| キー(識別子) | 所有者 | MIME | サイズ |
|---|---|---|---|
| avatars/user-42.png | user-42 | image/png | 82 B(概念値) |
| receipts/2026/order-17.pdf | user-17 | application/pdf | 240 B(概念値) |
実際のSupabaseでは、StorageのRLSポリシー、バケット設定、操作種別、アップロード方式などが権限を決定します。公開バケットでも書込み・削除が誰にでも許可されるわけではありません。
18|まとめ:何を識別し、誰に許可するか
ブロックは固定長の記憶区画、ファイルはパスによる階層管理、オブジェクトはデータ本体・メタデータ・キーのまとまりです。Next.jsやSupabaseで画像を扱うときも、バケットとキーで保存先を指定し、Storage APIでデータを読み書きし、認証・RLS・公開範囲で権限を制御するという構造は変わりません。
「データをどの単位で取り出すのか」「データの所在を何で識別するのか」「誰に操作を許可するのか」の三つを順に考えると、ストレージ設計を体系的に理解できます。