自分のパソコンで開発しているときは問題なく動いていたのに、いざインターネットに公開したら、その機能だけがぱたっと動かなくなる。開発ツールの画面を開くと、赤い文字で「CORS」から始まる見慣れないエラーが出ている。Web開発を始めた人の多くが、一度はここでつまずきます。

結論から言うと、これはあなたのコードが壊れたわけではありません。ブラウザには「今表示しているサイトと違う場所への通信を、一部制限する」というセキュリティの仕組みがあり、それに引っかかっているのです。この記事では、なぜ起きるのか、そしてどこをどう直せば安全に解決できるのかを、専門用語を噛み砕いて順番に整理します。

ムチオ
ムチオ
ローカルでは動いてたのに、公開したら急にこのエラー…。ぼくのコード、どっか壊しちゃったのかな。
ルミナ
ルミナ
落ち着いて大丈夫ですよ。それはコードの壊れではなく、ブラウザの安全装置が働いている合図です。仕組みが分かれば、直す場所もはっきりします。

結論:ブラウザの安全装置に引っかかっている

CORSエラーの正体を一言でいうと、ブラウザが持っている「同一オリジン以外との通信を一部制限する」セキュリティ機能に、あなたのアプリの通信が引っかかっている状態です。

ブラウザは、今開いているサイトが、別の場所へ勝手にデータを取りに行ったり送ったりするのを、無条件には許しません。もし何の制限もなければ、悪意のあるサイトがあなたの気づかないうちに他のサービスへアクセスし、情報を抜き取れてしまうからです。そうした事故を防ぐための「初期設定の守り」だと考えてください。

つまりCORSエラーは、故障ではなく、ブラウザが「この通信、勝手に通していいのか確認が取れていませんよ」と教えてくれているサインなのです。ここを理解しておくと、この先の話がぐっと分かりやすくなります。

掘り下げ①:そもそも「オリジン」とは何か

キーになる言葉が「オリジン」です。ブラウザは、通信相手が同じオリジンか、違うオリジンかで扱いを変えます。

オリジンとは、次の3つの組み合わせのことです。

  • スキーム … httphttps か、という通信の種類の部分。
  • ホスト … example.com のような、いわゆるドメイン名の部分。
  • ポート … :3000 のような、同じドメインの中で入口を分ける番号。省略されていることも多い。

この3つが「すべて」一致して、はじめて同じオリジンとみなされます。逆にいうと、1つでも違えば、ブラウザから見れば別の場所です。たとえば次のような場合、見た目は似ていても別オリジンになります。

  • https://example.comhttp://example.com(スキームが違う)
  • https://example.comhttps://api.example.com(ホストが違う)
  • http://localhost:3000http://localhost:8080(ポートが違う)
ムチオ
ムチオ
えっ、example.comapi.example.com って、ほぼ同じ場所じゃないの?
ルミナ
ルミナ
気持ちは分かります。でもブラウザは、スキーム・ホスト・ポートの3点セットを機械的に見比べるんです。頭に api. が付くだけでもホストが違うので、別オリジン。人間の感覚より少しきびしめ、と覚えておいてください。

Webアプリでは、画面を表示するフロントエンドと、データをやり取りするAPIを、あえて別のドメインやポートに分けて運用することがよくあります。この時点で両者は別オリジンになり、CORSの話が関わってきます。フロントとAPIがそれぞれ何をしているのかは、APIとはであわせて整理できます。

掘り下げ②:CORSとは「許可の仕組み」であって「エラーの名前」ではない

CORSは Cross-Origin Resource Sharing の略で、日本語にすると「オリジンをまたいだ資源の共有」です。名前だけ見ると難しそうですが、中身はシンプルです。

これは、APIサーバ側が「このオリジンからのアクセスなら受け入れていいですよ」という許可を、ブラウザに伝えるための仕組みです。具体的には、APIがデータを返すときの「HTTPレスポンスヘッダー」という、いわば通信に添える案内書きの部分に、許可するオリジンを書き込みます。ブラウザはそれを読んで、通信を通すかどうかを判断します。

ここで初心者がつまずきやすいのが、CORSという言葉のイメージです。

ムチオ
ムチオ
CORS って、エラーそのものの名前だと思ってた。
ルミナ
ルミナ
そこはよく誤解される点です。CORSは本来「別オリジンとのやり取りを許可するための仕組み」の名前なんです。その許可の設定が足りていないときに出るのが、いわゆるCORSエラー。仕組みそのものは、むしろ通信を安全に成立させるための味方なんですよ。

つまりCORSは、通信をブロックするためのものではなく、「必要なオリジンにはきちんと扉を開けるための」仕組みです。扉の開け方を設定し忘れると、ブラウザが安全側に倒してブロックし、その結果がエラーとして見える、という順番です。

なぜエラーになるのか

ここまでを踏まえると、エラーが起きる流れは次のように整理できます。

前提として、多くのWebアプリでは、フロントエンドとAPIを別々のドメインに分けています。この2つは別オリジンです。フロントエンドから別オリジンのAPIへデータを取りに行こうとしたとき、APIサーバ側に「このフロントからのアクセスは許可する」という設定がなければ、ブラウザは「許可の確認が取れていない」と判断します。そして安全のために、その通信をブロックします。これが、画面に赤く出るCORSエラーの中身です。

大事なのは、ブラウザは「悪いことが起きた」からブロックしているのではなく、「許可が確認できないから、念のため止めている」という点です。だから、正しく許可を伝えてあげれば、通信はすんなり通るようになります。

掘り下げ③:だからローカルでは出ず、本番で初めて出る

多くの人が混乱するのが、冒頭のむちおのように「自分のパソコンでは動いたのに」という点です。これには理由があります。

開発中は、フロントエンドもAPIも同じパソコン(localhost)の中で動かしていることが多く、この場合は同一オリジン、あるいは別オリジンでも手元だけの緩い設定で動いてしまいがちです。ところが本番環境に公開すると、フロントは https://your-app.com、APIは https://api.your-app.com のように、ドメインが分かれて配置されることがよくあります。ここで初めて「別オリジン」の条件がそろい、許可設定の不足が表面化するのです。

ムチオ
ムチオ
じゃあ、動かなくなったフロント側のコードを直せばいいのかな?
ルミナ
ルミナ
そこが一番の勘違いポイントなんです。エラーはフロント側の画面に出るので、つい表示している側を疑いたくなりますよね。でも、許可を出す側はAPIサーバのほうです。フロントをいくらいじっても直らないのは、扉の鍵を持っているのがサーバ側だからなんですよ。
ムチオ
ムチオ
なるほど!エラーが見える場所と、直す場所が違うんだ。それは焦るわけだ。

エラーメッセージはブラウザ(フロント側)で表示されますが、原因と直す場所はAPIサーバ側にある。この「見える場所と直す場所のズレ」が、CORSエラーがやっかいに感じる大きな理由です。許可を出すのがなぜサーバ側なのかは、サーバとはを読むと役割分担がすっきりします。

どう解決するか

解決の基本は、APIサーバ側で「どのオリジンからのアクセスを受け入れるか」を設定することです。

具体的には、APIがデータを返すときのHTTPレスポンスヘッダーに、Access-Control-Allow-Origin という項目を用意し、そこに許可したいフロントエンドのオリジンを指定します。たとえばフロントが https://your-app.com なら、そのオリジンを許可対象として書いておく、というイメージです。こうしておくと、ブラウザはヘッダーを読んで「このフロントは許可されている」と判断し、通信を通します。

多くの言語やフレームワークには、この設定を扱うための仕組みが用意されています。難しく身構える必要はなく、要は「APIサーバに、通したいフロントのオリジンを教えてあげる」という一点に尽きます。

掘り下げ④:全部許可する設定は危険

ここが、この記事でいちばん覚えておいてほしい注意点です。

CORSエラーに焦ると、「よく分からないから、いっそ全部のオリジンを許可してしまえば消えるだろう」と考えたくなります。Access-Control-Allow-Origin にすべてを表す記号(ワイルドカードと呼ばれます)を入れれば、確かにエラーは消えます。ですが、これはおすすめできません。

全部を許可するということは、あなたのAPIに対して、見ず知らずの別サイトからのアクセスまで扉を開けてしまうということです。本来通す必要のないオリジンまで受け入れてしまうと、悪意のあるサイトから利用され、情報を取られたり悪用されたりする脆弱性につながる可能性があります。

ムチオ
ムチオ
でも、全部許可したらエラーは消えるんでしょ?楽じゃない?
ルミナ
ルミナ
目の前のエラーは消えます。ただ、それは玄関の鍵を外して「誰でもどうぞ」にするのと同じことなんです。楽ですが、招きたくない人まで入れてしまう。だから、通したいフロントのオリジンだけを指定して、必要な通信だけ許可する設計にしておくのが安全です。

原則は「必要な通信だけを許可する」ことです。とくに最近はAIに開発を任せる場面も増えていますが、その際も、AIが手っ取り早くエラーを消すために全許可の設定を入れてしまうことがあります。出てきた設定が全許可になっていないかは、人の目で確かめておきたいところです。サーバ側の許可設定を含む安全の考え方は、AIで作ったアプリのサーバは安全か(認証と認可)でさらに掘り下げています。

次の一歩

CORSエラーは、次の3点を押さえると怖くなくなります。

  • 原因は、ブラウザが別オリジンとの通信を安全のために制限しているから。
  • 直す場所は、エラーが見えるフロント側ではなく、許可を出すAPIサーバ側。
  • 直し方は、レスポンスヘッダー(Access-Control-Allow-Origin など)で、通したいフロントのオリジンだけを許可する。全許可は避ける。

仕組みの土台になっているフロントとAPIの通信はAPIとは、許可を出すサーバの役割はサーバとはで、あわせて理解を固められます。

まとめ

  • CORSエラーは、ブラウザが同一オリジン以外との通信を制限するセキュリティ機能によって起きる。故障ではない。
  • オリジンは、スキーム・ホスト・ポートの3点セット。1つでも違えば別オリジンになる。
  • CORSは「別オリジンとの通信を許可する仕組み」の名前であって、エラーそのものの名前ではない。
  • 直すのはフロント側ではなくAPIサーバ側。レスポンスヘッダーに許可するオリジンを指定する。
  • 全部のオリジンを許可する設定は、脆弱性につながる可能性があるため避け、必要な通信だけ許可する。

独学でつまずくのは、知識そのものが足りないからというより、「何をどの順番で学ぶか」が見えていないことが多いものです。CORSのように、エラーの見える場所と直す場所がずれている落とし穴は、地図があるかないかで理解の速さが変わります。あなたの目標から逆算した学ぶ順番を、1対1で一緒に整理していくこともできます。