<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>バックエンド ‣ てんハロ｜未経験エンジニアのIT学習ログ</title>
	<atom:link href="https://it-bokenki.com/category/backend/feed/" rel="self" type="application/rss+xml" />
	<link>https://it-bokenki.com</link>
	<description>Hello Worldから、今日も生きてる</description>
	<lastBuildDate>Tue, 22 Jul 2025 14:22:04 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://it-bokenki.com/wp-content/uploads/2025/06/cropped-ブログ　アイコン-32x32.png</url>
	<title>バックエンド ‣ てんハロ｜未経験エンジニアのIT学習ログ</title>
	<link>https://it-bokenki.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>【初心者向け】Pay.jpとは？クレカ決済を爆速導入できるサービスを解説！特徴・使い方・実装例まとめ</title>
		<link>https://it-bokenki.com/2025/07/22/pay-jp/</link>
					<comments>https://it-bokenki.com/2025/07/22/pay-jp/#respond</comments>
		
		<dc:creator><![CDATA[てんハロ運営者]]></dc:creator>
		<pubDate>Tue, 22 Jul 2025 14:22:03 +0000</pubDate>
				<category><![CDATA[Next.js]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[バックエンド]]></category>
		<category><![CDATA[Pay.jp]]></category>
		<guid isPermaLink="false">https://it-bokenki.com/?p=5089</guid>

					<description><![CDATA[<p>※当サイトはアフィリエイト広告を利用しています。商品リンクにはプロモーションを含む場合があります。 未経験でも気軽に！サブスク型プログラミングスクール【Freeks】 困ってた自分に届けたい話 「クレジットカード決済をサ [&#8230;]</p>
<p>The post <a href="https://it-bokenki.com/2025/07/22/pay-jp/">【初心者向け】Pay.jpとは？クレカ決済を爆速導入できるサービスを解説！特徴・使い方・実装例まとめ</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span class="fz-12px">※当サイトはアフィリエイト広告を利用しています。商品リンクにはプロモーションを含む場合があります。</span></p>



<div style="text-align: center;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=457GS5+A4DB02+5JVK+BXQOH">
<img fetchpriority="high" decoding="async" border="0" width="300" height="250" alt="" src="https://www20.a8.net/svt/bgt?aid=250611125612&#038;wid=001&#038;eno=01&#038;mid=s00000025904002005000&#038;mc=1"></a>
<img decoding="async" border="0" width="1" height="1" src="https://www12.a8.net/0.gif?a8mat=457GS5+A4DB02+5JVK+BXQOH" alt=""></div>



<p class="has-text-align-center"><a href="https://px.a8.net/svt/ejp?a8mat=457GS5+A4DB02+5JVK+BX3J6">未経験でも気軽に！サブスク型プログラミングスクール【Freeks】</a></p>



<h2 class="wp-block-heading"><span id="toc1">困ってた自分に届けたい話</span></h2>



<p>「クレジットカード決済をサイトに組み込みたい…でも難しそう」<br>いざ調べてみると、知らない英語・セキュリティの話・カード情報の取り扱いなど、何をどうすればいいか混乱…。</p>



<p><br>そんなときに出会ったのが <strong>「Pay.jp（ペイジェーピー）」</strong>。<br>コード数行で決済ができるようになり、「え、こんなに簡単でいいの？」と驚き。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-r sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="てんハロ運営者" class="speech-icon-image"/></figure><div class="speech-name">てんハロ運営者</div></div><div class="speech-balloon">
<p>この記事は、同じように困っていた方への<strong>備忘録兼シェア</strong>として書いています。</p>
</div></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">Pay.jpとは？</span></h2>



<p><strong>Pay.jp</strong> は、<strong>クレジットカード決済を簡単に導入できる日本発の決済サービス</strong>です。</p>



<ul class="wp-block-list">
<li>Visa / Mastercard / JCB / AMEX などに対応</li>



<li>JavaScriptやAPI経由で簡単に組み込み可能</li>



<li>セキュリティ対策もばっちり（PCI DSS準拠）<br>PCI DSS：クレジットカード情報を安全に扱うための世界共通のルール</li>



<li>日本語ドキュメント完備＆開発者向けにやさしい</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc3">どんなときに使うの？</span></h2>



<p>たとえばこんな場面で使えます。</p>



<ul class="wp-block-list">
<li>ECサイトで商品を購入するときの決済</li>



<li>サブスク（月額課金）サービスの実装</li>



<li>会員登録＋決済を一括で処理</li>



<li>アプリ内課金のバックエンド処理　など</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc4">なぜPay.jpが選ばれているのか？</span></h2>



<p>クレジットカード決済サービスはたくさんありますが、「使いやすさ」「サポートの手厚さ」「日本向けかどうか」などで違いがあります。</p>



<p>以下は、Pay.jpと他の代表的なサービスを比較した表です。</p>



<figure class="wp-block-table"><table><thead><tr><th>項目</th><th><strong>Pay.jp</strong></th><th><strong>Stripe</strong></th><th><strong>Square</strong></th><th><strong>Komoju</strong></th></tr></thead><tbody><tr><td>開発元</td><td>日本</td><td>アメリカ</td><td>アメリカ</td><td>日本</td></tr><tr><td>日本語サポート</td><td><span class="bold-red">◎</span>（完全対応）</td><td>△（一部対応）</td><td>△（やや弱め）</td><td>◎（完全対応）</td></tr><tr><td>導入のしやすさ</td><td><span class="red">◎</span>（数行で完結）</td><td>○（高機能だが設定が複雑）</td><td>○（ノーコード寄り）</td><td>○（初期設定が少し複雑）</td></tr><tr><td>カード情報の取り扱い不要</td><td><span class="red">◎</span>（トークン化でOK）</td><td>◎（同様）</td><td>◎（同様）</td><td>◎（同様）</td></tr><tr><td>決済手数料（参考）</td><td>3.0%〜</td><td>3.6%〜</td><td>3.25%〜</td><td>3.6%〜</td></tr><tr><td>定期課金対応</td><td><span class="red">◎</span></td><td>◎</td><td>△（回数券などで代用）</td><td>◎</td></tr><tr><td>日本の決済文化への対応</td><td><span class="red">◎</span>（コンビニ払い・銀行振込など）</td><td>△（海外寄り）</td><td>△（海外寄り）</td><td>◎（多様な支払い手段）</td></tr><tr><td>管理画面の使いやすさ</td><td><span class="red">◎</span>（直感的で見やすいUI）</td><td>○（多機能だがやや複雑）</td><td>○</td><td>○</td></tr></tbody></table></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc5">実装内容</span></h2>



<h3 class="wp-block-heading"><span id="toc6">実際の流れ（1回課金）</span></h3>



<ol class="wp-block-list">
<li>ユーザーがカード情報を入力（Pay.jsを使ってトークン化）</li>



<li>トークンをバックエンド（Python/Nodeなど）に送る</li>



<li>バックエンドがトークンを使ってPay.jp APIで課金</li>
</ol>



<p>&#x1f449; <strong>自分のサーバーでカード番号を扱わないから、セキュリティ的にも安心！</strong></p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc7">Pay.jpを利用するために必要なものは？</span></h3>



<ul class="wp-block-list">
<li>Pay.jpのアカウント：無料で登録OK</li>



<li>公開鍵（フロント用）と秘密鍵（バックエンド用）のAPIキー：Pay.jpのダッシュボードで取得</li>



<li>JavaScript or バックエンド（Python, PHP, Nodeなど）の知識少し</li>
</ul>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc8">デモで見る「1回課金」の実装イメージ</span></h3>



<figure class="wp-block-image aligncenter size-full is-resized"><img decoding="async" width="554" height="296" src="https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-22-22.28.02.png" alt="【初心者向け】Pay.jpとは？クレカ決済を爆速導入できるサービスを解説！" class="wp-image-5094" style="width:322px;height:auto" srcset="https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-22-22.28.02.png 554w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-22-22.28.02-300x160.png 300w" sizes="(max-width: 554px) 100vw, 554px" /></figure>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">&#x1f5a5;&#xfe0f; フロントエンドの実装（Next.js）</span></p>



<p>tsxファイルで、トークン作成後にAPI呼び出しを行います。</p>



<p>下記の「&#x2705; 1つ渡せばOK」のコードですが、<code>cardNumber</code> 要素だけを <code>createToken</code> に渡しても、同じ <code>elements</code> インスタンスから作られ、かつ <code>mount()</code> された要素が揃っていれば、Pay.jp 側で裏側で統合されて処理されます。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>"use client";
import { useEffect, useRef } from "react";
import { createCharge } from "@/lib/api/charge";

export default function CardForm() {
  const numberRef = useRef&lt;any>(null);
  const expiryRef = useRef&lt;any>(null);
  const cvcRef = useRef&lt;any>(null);

  useEffect(() => {
    const payjp = Payjp("pk_test_********");
    const elements = payjp.elements();

    numberRef.current = elements.create("cardNumber");
    expiryRef.current = elements.create("cardExpiry");
    cvcRef.current = elements.create("cardCvc");

    numberRef.current.mount("#card-number");
    expiryRef.current.mount("#card-expiry");
    cvcRef.current.mount("#card-cvc");
  }, []);

  const handleSubmit = async () => {
    const payjp = Payjp("pk_test_********");
    const result = await payjp.createToken(numberRef.current); // &#x2705; 1つ渡せばOK

    if (result.error) {
      alert("カード情報が正しくありません");
    } else {
      const token = result.id;
      await createCharge({ token, amount: 1000 });
    }
  };

  return (
    &lt;>
      &lt;div id="card-number" />
      &lt;div id="card-expiry" />
      &lt;div id="card-cvc" />
      &lt;button onClick={handleSubmit}>支払う&lt;/button>
    &lt;/>
  );
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">use client</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">useEffect</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">useRef</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">react</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">createCharge</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">@/lib/api/charge</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">default</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">function</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">CardForm</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">numberRef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">useRef</span><span style="color: #ECEFF4">&lt;</span><span style="color: #81A1C1">any</span><span style="color: #ECEFF4">&gt;</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">null</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">expiryRef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">useRef</span><span style="color: #ECEFF4">&lt;</span><span style="color: #81A1C1">any</span><span style="color: #ECEFF4">&gt;</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">null</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">cvcRef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">useRef</span><span style="color: #ECEFF4">&lt;</span><span style="color: #81A1C1">any</span><span style="color: #ECEFF4">&gt;</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">null</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">useEffect</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">payjp</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Payjp</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">pk_test_********</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">elements</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">payjp</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">elements</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">numberRef</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">current</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">elements</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">create</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">cardNumber</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">expiryRef</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">current</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">elements</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">create</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">cardExpiry</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">cvcRef</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">current</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">elements</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">create</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">cardCvc</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">numberRef</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">current</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">mount</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">#card-number</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">expiryRef</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">current</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">mount</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">#card-expiry</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">cvcRef</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">current</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">mount</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">#card-cvc</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span><span style="color: #D8DEE9FF"> [])</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">handleSubmit</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">payjp</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Payjp</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">pk_test_********</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">result</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">payjp</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">createToken</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">numberRef</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">current</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// &#x2705; 1つ渡せばOK</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">result</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">error</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">alert</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">カード情報が正しくありません</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">result</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">id</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">createCharge</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">amount</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1000</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> (</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;div</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">id</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">card-number</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;div</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">id</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">card-expiry</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;div</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">id</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">card-cvc</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;button</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">onClick</span><span style="color: #81A1C1">={</span><span style="color: #D8DEE9">handleSubmit</span><span style="color: #81A1C1">}&gt;</span><span style="color: #D8DEE9FF">支払う</span><span style="color: #81A1C1">&lt;/button&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;/&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  )</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<p>tsファイルで、クライアントコンポーネントで取得したトークンと、金額をFastAPIサーバーへ安全に送信するためのAPI呼び出し関数</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>type ChargePayload = {
  token: string;
  amount: number;
};

export const createCharge = async (
  payload: ChargePayload
): Promise&lt;"ok" | "error"> => {
  try {
    const res = await fetch(`${process.env.NEXT_PUBLIC_BACKEND_URL}/api/charge`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });
    return res.ok ? "ok" : "error";
  } catch (e) {
    return "error";
  }
};</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">type</span><span style="color: #D8DEE9FF"> ChargePayload </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  token</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">string;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  amount</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">number;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">createCharge</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> (</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">payload</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> ChargePayload</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> Promise</span><span style="color: #ECEFF4">&lt;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">ok</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">error</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">try</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">res</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">fetch</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">`</span><span style="color: #81A1C1">${</span><span style="color: #D8DEE9">process</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">env</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">NEXT_PUBLIC_BACKEND_URL</span><span style="color: #81A1C1">}</span><span style="color: #A3BE8C">/api/charge</span><span style="color: #ECEFF4">`</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">method</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">POST</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">headers</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Content-Type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">application/json</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">body</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">JSON</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">stringify</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">payload</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">res</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">ok</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">?</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">ok</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">error</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">catch</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">e</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">error</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">&#x1f9ea; バックエンドの実装（FastAPI）</span></p>



<p>Pay.jpのPython SDKを使って、受け取ったトークンを使い課金処理をします。<br>事前準備で<strong>Pay.jpが提供しているPython用のSDK（ソフトウェア開発キット）</strong>を <strong><code>pip install payjp</code> </strong>とコマンド実行してインストールしましょう。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import payjp
from fastapi import FastAPI, Request

payjp.api_key = "sk_test_********"  # 秘密鍵を設定

app = FastAPI()

@app.post("/api/charge")
async def charge(request: Request):
    body = await request.json()
    token = body&#91;"token"&#93;
    amount = body&#91;"amount"&#93;

    try:
        charge = payjp.Charge.create(
            amount=amount,
            currency="jpy",
            card=token
        )
        return {"status": "success", "charge_id": charge.id}
    except payjp.error.PayjpError as e:
        return {"status": "error", "message": str(e)}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> payjp</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> fastapi </span><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> FastAPI</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> Request</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">payjp</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">api_key </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">sk_test_********</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88"># 秘密鍵を設定</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">app </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">FastAPI</span><span style="color: #ECEFF4">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">@</span><span style="color: #D08770">app</span><span style="color: #ECEFF4">.</span><span style="color: #D08770">post</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/api/charge</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">charge</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">request</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> Request</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    body </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> request</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">json</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">    token </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> body</span><span style="color: #ECEFF4">&#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">token</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">&#93;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    amount </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> body</span><span style="color: #ECEFF4">&#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">amount</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">&#93;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">try</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        charge </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> payjp</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">Charge</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">create</span><span style="color: #ECEFF4">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">amount</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">amount</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">currency</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">jpy</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">card</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">token</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">status</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">success</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">charge_id</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> charge</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">id</span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">except</span><span style="color: #D8DEE9FF"> payjp</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">error</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">PayjpError </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> e</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">status</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">error</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">message</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">str</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">e</span><span style="color: #ECEFF4">)}</span></span>
<span class="line"></span></code></pre></div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc9">なぜトークン化はフロントで行う？</span></h3>



<ul class="wp-block-list">
<li>クレジットカード番号は<strong>絶対にバックエンドに送ってはいけない</strong>（セキュリティリスク）<br>→クレジットカード番号は PCI DSS などの厳しいルールに則って管理する必要があり、サーバーで直接扱うと大きなセキュリティリスクになります。そのため、Pay.jsを使って<strong>トークン化</strong>（疑似的なカード情報への変換）を行い、サーバーではそのトークンだけを扱うことで、<strong>セキュリティを保ちながら決済処理</strong>ができます。</li>



<li>Pay.jsがカード番号をトークンに変換してくれる（createToken）</li>



<li>自分のサーバーでは<strong>トークンしか扱わない</strong>ため、安心・安全</li>
</ul>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc10">実装注意ポイントまとめ</span></h3>



<ul class="wp-block-list">
<li>公開鍵（pk_test_〜）はフロントで使う</li>



<li>秘密鍵（sk_test_〜）はバックエンドで使う</li>



<li>カード番号などはトークン化され、<strong>自分のサーバーでは触れない仕組み</strong>になっている（PCI DSS対応）</li>



<li>開発モードではテストカード <code>4242 4242 4242 4242</code> が使える（有効期限やCVCは適当でOK）<br><a href="https://docs.pay.jp/v1/testcard" title="">テストカード一覧</a></li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>他のAPI連携の記事はこちらです！</p>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-together is-style-normal-card">
<a href="https://it-bokenki.com/2025/06/26/nextauth-js/" title="Next.jsでログイン機能を実装｜NextAuth.jsでID・パスワード認証対応" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://it-bokenki.com/wp-content/uploads/2025/06/２行-15-320x180.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/２行-15-320x180.png 320w, https://it-bokenki.com/wp-content/uploads/2025/06/２行-15-120x68.png 120w, https://it-bokenki.com/wp-content/uploads/2025/06/２行-15-160x90.png 160w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">Next.jsでログイン機能を実装｜NextAuth.jsでID・パスワード認証対応</div><div class="blogcard-snippet internal-blogcard-snippet">Next.js アプリにログイン機能を追加したい方へ。NextAuth.js を使った ID・パスワード認証、セッション管理、コールバック設定までやさしく解説。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">it-bokenki.com</div></div></div></div></a>
<p></p>
</div>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-together is-style-normal-card">
<a href="https://it-bokenki.com/2025/07/08/docker-mailpit/" title="【初心者向け】Mailpitで開発中のメール送信を安全にテストする方法【Docker + Next.js対応】" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://it-bokenki.com/wp-content/uploads/2025/07/２行-22-320x180.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://it-bokenki.com/wp-content/uploads/2025/07/２行-22-320x180.png 320w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-22-120x68.png 120w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-22-160x90.png 160w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-22-376x212.png 376w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">【初心者向け】Mailpitで開発中のメール送信を安全にテストする方法【Docker + Next.js対応】</div><div class="blogcard-snippet internal-blogcard-snippet">開発中のメール送信テスト、毎回Gmailを使っていませんか？Mailpitを使えば、ローカル環境でメールの送信・確認が簡単＆安全にできます。DockerとNext.jsを使った導入手順を初心者向けに解説します。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">it-bokenki.com</div></div></div></div></a>
<p></p>
</div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc11">初心者におすすめなのはどれ？</span></h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>条件</th><th>おすすめサービス</th></tr></thead><tbody><tr><td>はじめて決済を導入する人</td><td>&#x2705; Pay.jp</td></tr><tr><td>海外展開も視野に入れている場合</td><td>&#x2705; Stripe</td></tr><tr><td>店舗＋ネットで使いたい</td><td>&#x2705; Square</td></tr><tr><td>コンビニ払いや多様な支払いを取り入れたい</td><td>&#x2705; Komoju</td></tr></tbody></table></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="てんハロ運営者" class="speech-icon-image"/></figure><div class="speech-name">てんハロ運営者</div></div><div class="speech-balloon">
<p>おつかれさまでした！</p>
</div></div><p>The post <a href="https://it-bokenki.com/2025/07/22/pay-jp/">【初心者向け】Pay.jpとは？クレカ決済を爆速導入できるサービスを解説！特徴・使い方・実装例まとめ</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://it-bokenki.com/2025/07/22/pay-jp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【初心者OK】FastAPI×MySQLをDockerで連携！Pythonで爆速開発する方法</title>
		<link>https://it-bokenki.com/2025/07/10/fastapi/</link>
					<comments>https://it-bokenki.com/2025/07/10/fastapi/#respond</comments>
		
		<dc:creator><![CDATA[てんハロ運営者]]></dc:creator>
		<pubDate>Wed, 09 Jul 2025 15:32:30 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[バックエンド]]></category>
		<category><![CDATA[開発事例]]></category>
		<category><![CDATA[Docker]]></category>
		<guid isPermaLink="false">https://it-bokenki.com/?p=4594</guid>

					<description><![CDATA[<p>未経験でも気軽に！サブスク型プログラミングスクール【Freeks】 困ってた自分に届けたい話 ・・・いや、はじめてのPython開発でそれ言う！？フォルダ構成？DB接続？何もわからん！ でも、調べまくって、なんとか Fa [&#8230;]</p>
<p>The post <a href="https://it-bokenki.com/2025/07/10/fastapi/">【初心者OK】FastAPI×MySQLをDockerで連携！Pythonで爆速開発する方法</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<div style="text-align: center;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=457GS5+A4DB02+5JVK+BXQOH">
<img loading="lazy" decoding="async" border="0" width="300" height="250" alt="" src="https://www20.a8.net/svt/bgt?aid=250611125612&#038;wid=001&#038;eno=01&#038;mid=s00000025904002005000&#038;mc=1"></a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www12.a8.net/0.gif?a8mat=457GS5+A4DB02+5JVK+BXQOH" alt=""></div>



<p class="has-text-align-center"><a href="https://px.a8.net/svt/ejp?a8mat=457GS5+A4DB02+5JVK+BX3J6">未経験でも気軽に！サブスク型プログラミングスクール【Freeks】</a></p>



<h2 class="wp-block-heading"><span id="toc1">困ってた自分に届けたい話</span></h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/themes/cocoon-master/images/man.png" alt="上司" class="speech-icon-image"/></figure><div class="speech-name">上司</div></div><div class="speech-balloon">
<p>FastAPIで、フロントから送られた<br>名前・メールアドレス・パスワードをMySQLに登録しておいて</p>
</div></div>



<p>・・・いや、<strong>はじめてのPython開発でそれ言う！？</strong><br>フォルダ構成？DB接続？何もわからん！</p>



<p>でも、調べまくって、なんとか <strong>FastAPI × MySQL × Docker</strong> で爆速開発できました。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-r sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="てんハロ運営者" class="speech-icon-image"/></figure><div class="speech-name">てんハロ運営者</div></div><div class="speech-balloon">
<p>この記事は、同じように困っていた方への<strong>備忘録兼シェア</strong>として書いています。</p>
</div></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">使用した技術スタック</span></h2>



<ul class="wp-block-list">
<li><strong>FastAPI</strong>（Python製の軽量Webフレームワーク）</li>



<li><strong>MySQL</strong>（データベース）</li>



<li><strong>Docker Compose</strong>（複数のコンテナをまとめて起動）</li>



<li><strong>Next.js</strong>（フロントエンド／フォーム送信で使用）</li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc3">プロジェクト構成</span></h2>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="940" height="640" src="https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.18.48.png" alt="【初心者OK】FastAPI×MySQLをDockerで連携！Python開発環境を最速構築する方法" class="wp-image-4624" style="width:760px;height:auto" srcset="https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.18.48.png 940w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.18.48-300x204.png 300w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.18.48-768x523.png 768w" sizes="auto, (max-width: 940px) 100vw, 940px" /></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc4">FastAPI × Docker 開発環境のセットアップ</span></h2>



<h3 class="wp-block-heading"><span id="toc5">環境変数（.env.local）の設定方法</span></h3>



<p>環境変数をルート直下に <code>.env.local</code> として作成します。（開発環境で実行するため）<br>Dockerコンテナ間通信では <code>DB_HOST</code> を MySQL サービス名にします。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>DB_HOST=
DB_PORT=
DB_NAME=
DB_USER=
DB_PASSWORD=</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">DB_HOST</span><span style="color: #81A1C1">=</span></span>
<span class="line"><span style="color: #D8DEE9">DB_PORT</span><span style="color: #81A1C1">=</span></span>
<span class="line"><span style="color: #D8DEE9">DB_NAME</span><span style="color: #81A1C1">=</span></span>
<span class="line"><span style="color: #D8DEE9">DB_USER</span><span style="color: #81A1C1">=</span></span>
<span class="line"><span style="color: #D8DEE9">DB_PASSWORD</span><span style="color: #81A1C1">=</span></span></code></pre></div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc6">Docker（MySQL × FastAPI 連携）の書き方</span></h3>



<p><span class="keyboard-key">対象ファイル</span>：docker/docker-compose.yml</p>



<p>MySQLとFastAPIを同時に立ち上げるDocker Compose設定です。</p>



<p>すでにMySQLの設定がある場合は、FastAPIの定義だけ追加してください。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>version: '3'
services:
  mysql:
    image: mysql:8.0
    ... # 詳細は別記事へ

  FastAPI:
    build:
      context: ..　　// Dockerfile がある位置を指定
      dockerfile: docker/Dockerfile
    container_name: 任意のコンテナ名
    ports:
      - "8000:8000"
    volumes:
      - ../backend:/app
    env_file:
      - ../.env.local
    depends_on:　　// 「このアプリは mysql が先に起動していないとダメだよ」という意味
      - mysql</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">version</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">3</span><span style="color: #ECEFF4">&#39;</span></span>
<span class="line"><span style="color: #D8DEE9FF">services</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">  mysql</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    image</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> mysql</span><span style="color: #ECEFF4">:</span><span style="color: #B48EAD">8.0</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9FF"> # </span><span style="color: #D8DEE9">詳細は別記事へ</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  FastAPI</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    build</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">      context</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">..</span><span style="color: #D8DEE9FF">　　</span><span style="color: #616E88">// Dockerfile がある位置を指定</span></span>
<span class="line"><span style="color: #D8DEE9FF">      dockerfile</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">docker</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">Dockerfile</span></span>
<span class="line"><span style="color: #D8DEE9FF">    container_name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">任意のコンテナ名</span></span>
<span class="line"><span style="color: #D8DEE9FF">    ports</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">8000:8000</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    volumes</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">..</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">backend</span><span style="color: #ECEFF4">:</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">app</span></span>
<span class="line"><span style="color: #D8DEE9FF">    env_file</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">..</span><span style="color: #81A1C1">/</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">env</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">local</span></span>
<span class="line"><span style="color: #D8DEE9FF">    depends_on</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF">　　</span><span style="color: #616E88">// 「このアプリは mysql が先に起動していないとダメだよ」という意味</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mysql</span></span></code></pre></div>



<p>MySQLの設定方法は下記の記事をチェックしてください。</p>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-together is-style-normal-card">
<a href="https://it-bokenki.com/2025/07/03/docker-mysql/" title="DockerでMySQLをローカル構築｜Mac対応・CLI操作と文字化け対策も解説" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://it-bokenki.com/wp-content/uploads/2025/07/２行-18-320x180.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://it-bokenki.com/wp-content/uploads/2025/07/２行-18-320x180.png 320w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-18-120x68.png 120w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-18-160x90.png 160w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-18-376x212.png 376w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">DockerでMySQLをローカル構築｜Mac対応・CLI操作と文字化け対策も解説</div><div class="blogcard-snippet internal-blogcard-snippet">DockerでMacにMySQLの開発環境を一瞬で構築！Apple Silicon対応のインストール手順、docker-compose.ymlと.env連携、utf8mb4設定、ターミナル操作でのDB作成まで初心者にもわかりやすく解説しています。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">it-bokenki.com</div></div></div></div></a>
<p></p>
</div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc7">FastAPIアプリ起動設定</span></h3>



<p><span class="keyboard-key">対象ファイル</span>：docker/ Dockerfile</p>



<p>FastAPIアプリの<strong>起動手順を定義</strong>する Dockerfile を用意します。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">&#x26a0;&#xfe0f; 注意点</span></p>



<ul class="wp-block-list">
<li>大文字スタートの <code>Dockerfile</code> というファイル名でなければいけない</li>



<li>拡張子は <strong>不要・つけてはいけない</strong>（<code>.txt</code>や<code>.py</code>などはNG）</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// Pythonの軽くて早いバージョンを指定
FROM python:3.10-slim

// 実行時に.pycファイルを作らないように設定（大量にできてGitに上げれなくなる）
ENV PYTHONDONTWRITEBYTECODE=1

// コンテナ内で作業するディレクトリを作成
WORKDIR /app

// ホスト側の ./backend フォルダを、コンテナ内の /app に丸ごとコピー
COPY ./backend /app

// requirements.txt をコピーして、必要なライブラリをインストール
COPY ./backend/requirements.txt .

RUN pip install --upgrade pip
RUN pip install -r requirements.txt

// アプリを起動
CMD &#91;"uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"&#93;</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// Pythonの軽くて早いバージョンを指定</span></span>
<span class="line"><span style="color: #D8DEE9">FROM</span><span style="color: #D8DEE9FF"> python</span><span style="color: #ECEFF4">:</span><span style="color: #B48EAD">3.10</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">slim</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// 実行時に.pycファイルを作らないように設定（大量にできてGitに上げれなくなる）</span></span>
<span class="line"><span style="color: #D8DEE9">ENV</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PYTHONDONTWRITEBYTECODE</span><span style="color: #81A1C1">=</span><span style="color: #B48EAD">1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// コンテナ内で作業するディレクトリを作成</span></span>
<span class="line"><span style="color: #D8DEE9">WORKDIR</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">app</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// ホスト側の ./backend フォルダを、コンテナ内の /app に丸ごとコピー</span></span>
<span class="line"><span style="color: #D8DEE9">COPY</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">backend</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">app</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// requirements.txt をコピーして、必要なライブラリをインストール</span></span>
<span class="line"><span style="color: #D8DEE9">COPY</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">backend</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">requirements</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">txt</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">RUN</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pip</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">--</span><span style="color: #D8DEE9">upgrade</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pip</span></span>
<span class="line"><span style="color: #D8DEE9">RUN</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pip</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">r</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">requirements</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">txt</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// アプリを起動</span></span>
<span class="line"><span style="color: #D8DEE9">CMD</span><span style="color: #D8DEE9FF"> &#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">uvicorn</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">main:app</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">--host</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">0.0.0.0</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">--port</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">8000</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">--reload</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">&#93;</span></span></code></pre></div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc8">requirements.txt の作成とバージョン管理</span></h3>



<p><span class="keyboard-key">対象ファイル</span>：backend/requirements.txt</p>



<p>Pythonパッケージの<strong>インストール一覧</strong>を記述します。</p>



<p>下記のコマンドで、Dockerで一括で自動インストールすることができます。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>pip install -r requirements.txt </code></pre></div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">&#x1f331; 豆知識</span></p>



<p><strong>パッケージ名しか書いていない場合</strong>：常に最新バージョンがインストールされる（試作段階・練習中向け）</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>fastapi
uvicorn
SQLAlchemy
PyMySQL
python-dotenv</code></pre></div>



<p><strong>バージョンを指定している場合</strong>：誰が使っても同じ環境になる（チーム開発・本番運用向け）</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>fastapi==0.116.0
uvicorn==0.35.0
SQLAlchemy==2.0.41
PyMySQL==1.1.1
python-dotenv==1.1.1</code></pre></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc9">.gitignore の設定でGitをクリーンに保つ</span></h2>



<p><span class="keyboard-key">対象ファイル</span>：.gitignore</p>



<p>Pythonのをインストールすると自動生成ファイルができて、Gitにそのまま上げると大変なことになります。<br>下記のように設定すると、Gitに不要なファイルが混ざらなくなります。おすすめです。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code># バーチャル環境除外
venv/

# Pythonのバイトコードキャッシュを無視
__pycache__/
*.pyc
*.pyo
*.pyd</code></pre></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc10">テーブル作成</span></h2>



<p>事前に <code>users</code> テーブルを作っておきましょう。DockerのMySQL内で作成できます。</p>



<p>作成方法については、下記の記事をご覧ください。</p>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-together is-style-normal-card">
<a href="https://it-bokenki.com/2025/07/03/drizzle/" title="Drizzleとは？TypeScriptで型安全にSQL・マイグレーションを管理する方法" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://it-bokenki.com/wp-content/uploads/2025/07/1-1-320x180.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://it-bokenki.com/wp-content/uploads/2025/07/1-1-320x180.png 320w, https://it-bokenki.com/wp-content/uploads/2025/07/1-1-120x68.png 120w, https://it-bokenki.com/wp-content/uploads/2025/07/1-1-160x90.png 160w, https://it-bokenki.com/wp-content/uploads/2025/07/1-1-376x212.png 376w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">Drizzleとは？TypeScriptで型安全にSQL・マイグレーションを管理する方法</div><div class="blogcard-snippet internal-blogcard-snippet">Drizzle ORMを使って、TypeScriptで型安全にSQLやマイグレーションを管理する方法をわかりやすく解説。初期設定からスキーマ定義、リレーション設定まで丁寧に紹介！</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">it-bokenki.com</div></div></div></div></a>
</div>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-together is-style-normal-card">
<a href="https://it-bokenki.com/2025/07/03/docker-mysql/" title="DockerでMySQLをローカル構築｜Mac対応・CLI操作と文字化け対策も解説" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://it-bokenki.com/wp-content/uploads/2025/07/２行-18-320x180.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://it-bokenki.com/wp-content/uploads/2025/07/２行-18-320x180.png 320w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-18-120x68.png 120w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-18-160x90.png 160w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-18-376x212.png 376w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">DockerでMySQLをローカル構築｜Mac対応・CLI操作と文字化け対策も解説</div><div class="blogcard-snippet internal-blogcard-snippet">DockerでMacにMySQLの開発環境を一瞬で構築！Apple Silicon対応のインストール手順、docker-compose.ymlと.env連携、utf8mb4設定、ターミナル操作でのDB作成まで初心者にもわかりやすく解説しています。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">it-bokenki.com</div></div></div></div></a>
</div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc11">Next.jsで登録フォームを作成</span></h2>



<p>下記は登録フォームの <code>registerForm.tsx</code> の内容の内容です。<br><code>register/page.tsx</code> で呼び出すと、下記の画像のような登録フォームになります。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>"use client";

import { useState } from "react";

export default function RegisterForm() {
  const &#91;form, setForm&#93; = useState({
    name: "",
    email: "",
    password: "",
  });

  const &#91;message, setMessage&#93; = useState("");

  const handleChange = (e: React.ChangeEvent&lt;HTMLInputElement>) => {
    setForm({ ...form, &#91;e.target.name&#93;: e.target.value });
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    try {
      const res = await fetch("http://localhost:8000/registration", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(form),
      });

      const data = await res.json();
      if (res.ok) {
        setMessage("登録成功！ ユーザーID: " + data.user_id);
      } else {
        setMessage("登録失敗: " + (data.detail || "エラーが発生しました"));
      }
    } catch (error) {
      console.error("エラー:", error);
      setMessage("通信エラーが発生しました");
    }
  };

  return (
    &lt;form onSubmit={handleSubmit} className="space-y-4 max-w-md mx-auto mt-10">
      &lt;div>
        &lt;label htmlFor="name" className="block font-medium mb-1">
          お名前
        &lt;/label>
        &lt;input
          id="name"
          name="name"
          placeholder="例：山田 太郎"
          value={form.name}
          onChange={handleChange}
          required
          className="border px-3 py-2 w-full"
        />
      &lt;/div>

      &lt;div>
        &lt;label htmlFor="email" className="block font-medium mb-1">
          メールアドレス
        &lt;/label>
        &lt;input
          id="email"
          name="email"
          placeholder="例：taro@example.com"
          type="email"
          value={form.email}
          onChange={handleChange}
          required
          className="border px-3 py-2 w-full"
        />
      &lt;/div>

      &lt;div>
        &lt;label htmlFor="password" className="block font-medium mb-1">
          パスワード
        &lt;/label>
        &lt;input
          id="password"
          name="password"
          placeholder="半角英数字8文字以上"
          type="password"
          value={form.password}
          onChange={handleChange}
          required
          className="border px-3 py-2 w-full"
        />
      &lt;/div>

      &lt;button
        type="submit"
        className="bg-blue-600 text-white px-4 py-2 rounded w-full"
      >
        ユーザー登録
      &lt;/button>

      {message &amp;&amp; &lt;p className="mt-4 text-sm text-gray-700">{message}&lt;/p>}
    &lt;/form>
  );
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">use client</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">useState</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">react</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">default</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">function</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">RegisterForm</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">form</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">setForm</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">useState</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">email</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">password</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">message</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">setMessage</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">useState</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">handleChange</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">e</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> React</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">ChangeEvent</span><span style="color: #ECEFF4">&lt;</span><span style="color: #D8DEE9FF">HTMLInputElement</span><span style="color: #ECEFF4">&gt;)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">setForm</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9">form</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">&#91;</span><span style="color: #D8DEE9">e</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">target</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">name</span><span style="color: #88C0D0">&#93;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">e</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">target</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">value</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">handleSubmit</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">e</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> React</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">FormEvent</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">e</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">preventDefault</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">try</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">res</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">fetch</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">http://localhost:8000/registration</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">method</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">POST</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">headers</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Content-Type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">application/json</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">body</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">JSON</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">stringify</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">form</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">data</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">res</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">json</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">res</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">ok</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">setMessage</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">登録成功！ ユーザーID: </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">data</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">user_id</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">setMessage</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">登録失敗: </span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">data</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">detail</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">||</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">エラーが発生しました</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">catch</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">error</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #D8DEE9">console</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">error</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">エラー:</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">error</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">setMessage</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">通信エラーが発生しました</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> (</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;form</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">onSubmit</span><span style="color: #81A1C1">={</span><span style="color: #D8DEE9">handleSubmit</span><span style="color: #81A1C1">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">space-y-4 max-w-md mx-auto mt-10</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;div&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;label</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">htmlFor</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">block font-medium mb-1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          お名前</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;/label&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;input</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">id</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">name</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">name</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">name</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">placeholder</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">例：山田 太郎</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">value</span><span style="color: #81A1C1">={</span><span style="color: #D8DEE9">form</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">name</span><span style="color: #81A1C1">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">onChange</span><span style="color: #81A1C1">={</span><span style="color: #D8DEE9">handleChange</span><span style="color: #81A1C1">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">required</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">border px-3 py-2 w-full</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;/div&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;div&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;label</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">htmlFor</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">email</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">block font-medium mb-1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          メールアドレス</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;/label&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;input</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">id</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">email</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">name</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">email</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">placeholder</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">例：taro@example.com</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">type</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">email</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">value</span><span style="color: #81A1C1">={</span><span style="color: #D8DEE9">form</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">email</span><span style="color: #81A1C1">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">onChange</span><span style="color: #81A1C1">={</span><span style="color: #D8DEE9">handleChange</span><span style="color: #81A1C1">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">required</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">border px-3 py-2 w-full</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;/div&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;div&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;label</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">htmlFor</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">password</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">block font-medium mb-1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          パスワード</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;/label&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;input</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">id</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">password</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">name</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">password</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">placeholder</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">半角英数字8文字以上</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">type</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">password</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">value</span><span style="color: #81A1C1">={</span><span style="color: #D8DEE9">form</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">password</span><span style="color: #81A1C1">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">onChange</span><span style="color: #81A1C1">={</span><span style="color: #D8DEE9">handleChange</span><span style="color: #81A1C1">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">required</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">border px-3 py-2 w-full</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;/div&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;button</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">type</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">submit</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">bg-blue-600 text-white px-4 py-2 rounded w-full</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        ユーザー登録</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;/button&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">{</span><span style="color: #D8DEE9">message</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;p</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">mt-4 text-sm text-gray-700</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;{</span><span style="color: #D8DEE9">message</span><span style="color: #81A1C1">}&lt;/p&gt;}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;/form&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  )</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<figure class="wp-block-image size-large has-custom-border"><img loading="lazy" decoding="async" width="1024" height="575" src="https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.29.03-1024x575.png" alt="【初心者OK】FastAPI×MySQLをDockerで連携！Python開発環境を最速構築する方法" class="wp-image-4625" style="border-width:1px" srcset="https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.29.03-1024x575.png 1024w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.29.03-300x168.png 300w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.29.03-768x431.png 768w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.29.03-120x68.png 120w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.29.03-160x90.png 160w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.29.03-320x180.png 320w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.29.03-376x212.png 376w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.29.03-1320x741.png 1320w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-09-18.29.03.png 1340w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc12">FastAPIのバックエンド側の実装</span></h2>



<h3 class="wp-block-heading"><span id="toc13">各ファイルの役割</span></h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>ファイル</th><th>内容</th></tr></thead><tbody><tr><td><code>backend/db.py</code></td><td>DB接続の設定を記述</td></tr><tr><td><code>backend/main.py</code></td><td>FastAPIの本体とCORS、ルーティング設定</td></tr><tr><td><code>backend/models/user.py</code></td><td>usersテーブル定義（UUID、カラムなど）</td></tr><tr><td><code>backend/schemas/user.py</code></td><td>Pydanticで受け取りバリデーション</td></tr><tr><td><code>backend/utils/common_fields.py</code></td><td>登録時の共通フィールドを自動付与</td></tr><tr><td><code>backend/routers/registration.py</code></td><td>POSTでデータ受取→DB保存処理</td></tr></tbody></table></figure>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc14">db.py：DB接続設定</span></h3>



<p><code>.env.local </code>を読み込んで DB に接続する準備をする</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>from sqlalchemy import create_engine // DBとの接続エンジンを作るための関数
from sqlalchemy.orm import sessionmaker, declarative_base
from dotenv import load_dotenv  // .envファイルから環境変数を読み込むための関数
import os // 環境変数を取得するための標準ライブラリ

// ルートの.env読み込み
load_dotenv(dotenv_path=".env.local")

DB_HOST = os.getenv("DB_HOST")
DB_PORT = os.getenv("DB_PORT")
DB_NAME = os.getenv("DB_NAME")
DB_USER = os.getenv("DB_USER")
DB_PASSWORD = os.getenv("DB_PASSWORD")

// データベース接続用のURLを作成
DB_URL = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}?charset=utf8mb4"

// 接続準備
engine = create_engine(DB_URL)
SessionLocal = sessionmaker(bind=engine, autocommit=False, autoflush=False)
Base = declarative_base()</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sqlalchemy</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">create_engine</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// DBとの接続エンジンを作るための関数</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">sqlalchemy</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">orm</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">sessionmaker</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">declarative_base</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">dotenv</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">load_dotenv</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">// .envファイルから環境変数を読み込むための関数</span></span>
<span class="line"><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">os</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// 環境変数を取得するための標準ライブラリ</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// ルートの.env読み込み</span></span>
<span class="line"><span style="color: #8FBCBB">load_dotenv</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">dotenv_path</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">.env.local</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">DB_HOST</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">os</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">getenv</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">DB_HOST</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #8FBCBB">DB_PORT</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">os</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">getenv</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">DB_PORT</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #8FBCBB">DB_NAME</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">os</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">getenv</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">DB_NAME</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #8FBCBB">DB_USER</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">os</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">getenv</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">DB_USER</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #8FBCBB">DB_PASSWORD</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">os</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">getenv</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">DB_PASSWORD</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// データベース接続用のURLを作成</span></span>
<span class="line"><span style="color: #8FBCBB">DB_URL</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">f</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}?charset=utf8mb4</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// 接続準備</span></span>
<span class="line"><span style="color: #8FBCBB">engine</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">create_engine</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">DB_URL</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #8FBCBB">SessionLocal</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">sessionmaker</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">bind</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">engine</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">autocommit</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">False</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">autoflush</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">False</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #8FBCBB">Base</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">declarative_base</span><span style="color: #D8DEE9FF">()</span></span></code></pre></div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc15">main.py：アプリ起動とCORS設定</span></h3>



<p>FastAPIアプリを起動し、CORS設定とルーター登録を行います。</p>



<p>Next.js開発環境で実行しているので、今回は<code>http://localhost:3000</code>を指定（ここは環境変数設定にしたほうがいいかもです）</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware 　// 別ドメインからのアクセスを許可するための設定
from routers import registration

// FastAPIアプリケーションの本体を作成
app = FastAPI()

// CORS（クロスオリジン）設定を追加：別のドメインからアクセスを許可する
app.add_middleware(
    CORSMiddleware,
    allow_origins=&#91;"http://localhost:3000"&#93;,  // フロントエンド（Next.js）からのアクセスを許可
    allow_credentials=True,  // クッキーなどの認証情報を含めた通信を許可
    allow_methods=&#91;"*"&#93;,  // GETやPOSTなど、すべてのHTTPメソッドを許可
    allow_headers=&#91;"*"&#93;,  // すべてのリクエストヘッダーを許可（認証トークンなど）
)

// APIの処理を追加（今回はregistration.pyのルーター）
app.include_router(registration.router)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">fastapi</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">FastAPI</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">fastapi</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">middleware</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">cors</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">CORSMiddleware</span><span style="color: #D8DEE9FF"> 　</span><span style="color: #616E88">// 別ドメインからのアクセスを許可するための設定</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">routers</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">registration</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// FastAPIアプリケーションの本体を作成</span></span>
<span class="line"><span style="color: #8FBCBB">app</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">FastAPI</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// CORS（クロスオリジン）設定を追加：別のドメインからアクセスを許可する</span></span>
<span class="line"><span style="color: #8FBCBB">app</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">add_middleware</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">CORSMiddleware</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">allow_origins</span><span style="color: #D8DEE9FF">=&#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">http://localhost:3000</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">// フロントエンド（Next.js）からのアクセスを許可</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">allow_credentials</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">True</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">// クッキーなどの認証情報を含めた通信を許可</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">allow_methods</span><span style="color: #D8DEE9FF">=&#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">*</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">// GETやPOSTなど、すべてのHTTPメソッドを許可</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">allow_headers</span><span style="color: #D8DEE9FF">=&#91;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">*</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">// すべてのリクエストヘッダーを許可（認証トークンなど）</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// APIの処理を追加（今回はregistration.pyのルーター）</span></span>
<span class="line"><span style="color: #8FBCBB">app</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">include_router</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">registration</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">router</span><span style="color: #D8DEE9FF">)</span></span></code></pre></div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc16">models/user.py：ユーザーテーブル定義</span></h3>



<p>SQLAlchemyで <code>userテーブル</code> 構造を定義します。主キーは <code>UUID</code> を自動生成。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import uuid
from sqlalchemy import Column, String, Boolean, DateTime
from db import Base

class Users(Base):
    __tablename__ = "users"

    user_id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    name = Column(String(100), nullable=False)
    email = Column(String(100), nullable=False, unique=True)
    password = Column(String(255), nullable=False)
    updated_by = Column(String(100))
    updated_at = Column(DateTime)
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">uuid</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">sqlalchemy</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Column</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">String</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Boolean</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">DateTime</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">db</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Base</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Users</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">Base</span><span style="color: #D8DEE9FF">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">__tablename__</span><span style="color: #D8DEE9FF"> = </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">users</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">user_id</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">Column</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF">(36)</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">primary_key</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">True</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">default</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">lambda</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">str</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">uuid</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">uuid4</span><span style="color: #D8DEE9FF">()))</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">Column</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF">(100)</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">nullable</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">False</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">email</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">Column</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF">(100)</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">nullable</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">False</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">unique</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">True</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">password</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">Column</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF">(255)</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">nullable</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">False</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">updated_by</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">Column</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF">(100))</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">updated_at</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">Column</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">DateTime</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<p>uuidについて、もっと知りたい方は下記の記事をどうぞ！</p>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-together is-style-normal-card">
<a href="https://it-bokenki.com/2025/07/10/uuid/" title="UUIDとは？主キーに使われる理由と連番との違いをわかりやすく解説" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://it-bokenki.com/wp-content/uploads/2025/07/２行-1-320x180.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://it-bokenki.com/wp-content/uploads/2025/07/２行-1-320x180.png 320w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-1-120x68.png 120w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-1-160x90.png 160w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-1-376x212.png 376w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">UUIDとは？主キーに使われる理由と連番との違いをわかりやすく解説</div><div class="blogcard-snippet internal-blogcard-snippet">UUIDはなぜ主キーに使われるのか？連番との違いやメリット・デメリット、UUIDの種類（v1〜v5）まで初心者向けにやさしく解説。PythonでのUUIDの生成方法も紹介します。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">it-bokenki.com</div></div></div></div></a>
</div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc17">schemas/user.py：バリデーション用スキーマ定義</span></h3>



<p>フロントから送られてくる入力値（name, email, password）をバリデーションします。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>from pydantic import BaseModel

class UserCreate(BaseModel):
    name: str
    email: str
    password: str</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pydantic</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">BaseModel</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">UserCreate</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">BaseModel</span><span style="color: #D8DEE9FF">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">name</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">str</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">email</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">str</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">password</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">str</span></span></code></pre></div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc18">utils/common_fields.py：共通項目の自動付与</span></h3>



<p><code>updated_by</code> や <code>updated_at</code> などの共通項目を自動で付与します。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>from datetime import datetime, timezone, timedelta

def generate_common_fields():
    jst_now = datetime.now(timezone(timedelta(hours=9)))
    return {
        "updated_by": "system",
        "updated_at": jst_now,
    }
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">datetime</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">datetime</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">timezone</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">timedelta</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">generate_common_fields</span><span style="color: #D8DEE9FF">():</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">jst_now</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">datetime</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">now</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">timezone</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">timedelta</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">hours</span><span style="color: #D8DEE9FF">=9)))</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        &quot;</span><span style="color: #8FBCBB">updated_by</span><span style="color: #D8DEE9FF">&quot;: &quot;</span><span style="color: #8FBCBB">system</span><span style="color: #D8DEE9FF">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        &quot;</span><span style="color: #8FBCBB">updated_at</span><span style="color: #D8DEE9FF">&quot;: </span><span style="color: #8FBCBB">jst_now</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc19">routers/registration.py：登録処理ルーターの作成</span></h3>



<p>POSTされた情報をDBに保存するルーターです。辞書展開でスキーマ＋共通フィールドを結合します。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session　　// DBとのやりとりの型（Session）を指定
from db import SessionLocal
from models.user import Users
from schemas.user import UserCreate
from utils.common_fields import generate_common_fields

router = APIRouter()

// データベースとの接続を一時的に確立して、使い終わったら自動で切るための仕組み
def get_db():
    db = SessionLocal()  // DB接続を開始
    try:
        yield db　　 // データを登録・検索
    finally:
        db.close()　// DB接続を終了
        
@router.post("/registration")
def create_user(user: UserCreate, db: Session = Depends(get_db)):
    common_fields = generate_common_fields()

    db_user = Users(
        **user.dict(),
        **common_fields
    )

    db.add(db_user)
    db.commit()

    return {"message": "登録成功"}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">fastapi</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">APIRouter</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Depends</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">sqlalchemy</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">orm</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Session</span><span style="color: #D8DEE9FF">　　</span><span style="color: #616E88">// DBとのやりとりの型（Session）を指定</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">db</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SessionLocal</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">models</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Users</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">schemas</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">UserCreate</span></span>
<span class="line"><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">utils</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">common_fields</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">generate_common_fields</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">router</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">APIRouter</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// データベースとの接続を一時的に確立して、使い終わったら自動で切るための仕組み</span></span>
<span class="line"><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">get_db</span><span style="color: #D8DEE9FF">():</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">db</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">SessionLocal</span><span style="color: #D8DEE9FF">()  </span><span style="color: #616E88">// DB接続を開始</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">try</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">yield</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">db</span><span style="color: #D8DEE9FF">　　 </span><span style="color: #616E88">// データを登録・検索</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">finally</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">db</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">close</span><span style="color: #D8DEE9FF">()　</span><span style="color: #616E88">// DB接続を終了</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span></span>
<span class="line"><span style="color: #D8DEE9FF">@</span><span style="color: #8FBCBB">router</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">post</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/registration</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">create_user</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">user</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">UserCreate</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">db</span><span style="color: #D8DEE9FF">: </span><span style="color: #8FBCBB">Session</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">Depends</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">get_db</span><span style="color: #D8DEE9FF">)):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">common_fields</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">generate_common_fields</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">db_user</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">Users</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">**</span><span style="color: #8FBCBB">user</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">dict</span><span style="color: #D8DEE9FF">()</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">**</span><span style="color: #8FBCBB">common_fields</span></span>
<span class="line"><span style="color: #D8DEE9FF">    )</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">db</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">add</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">db_user</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">db</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">commit</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF">&quot;</span><span style="color: #8FBCBB">message</span><span style="color: #D8DEE9FF">&quot;: &quot;</span><span style="color: #8FBCBB">登録成功</span><span style="color: #D8DEE9FF">&quot;</span><span style="color: #ECEFF4">}</span></span></code></pre></div>



<p>※ここで辞書化の記事をつくっていれよう！</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc20">トラブル対応：ログでFastAPIのエラーを確認する方法</span></h2>



<p>ログをリアルタイムで監視するには、以下のコマンドを使いましょう。</p>



<p><code>-f</code> は <code>--follow</code> の略で「ログを継続して追いかける」オプションです。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>docker logs -f コンテナ名</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">logs</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">コンテナ名</span></span></code></pre></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="てんハロ運営者" class="speech-icon-image"/></figure><div class="speech-name">てんハロ運営者</div></div><div class="speech-balloon">
<p>おつかれさまでした！</p>
</div></div><p>The post <a href="https://it-bokenki.com/2025/07/10/fastapi/">【初心者OK】FastAPI×MySQLをDockerで連携！Pythonで爆速開発する方法</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://it-bokenki.com/2025/07/10/fastapi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>初心者向け：FastAPIの環境構築ガイド【5分でAPIが動く】</title>
		<link>https://it-bokenki.com/2025/07/10/fastapi-setup/</link>
					<comments>https://it-bokenki.com/2025/07/10/fastapi-setup/#respond</comments>
		
		<dc:creator><![CDATA[てんハロ運営者]]></dc:creator>
		<pubDate>Thu, 10 Jul 2025 11:48:30 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[バックエンド]]></category>
		<guid isPermaLink="false">https://it-bokenki.com/?p=4580</guid>

					<description><![CDATA[<p>未経験でも気軽に！サブスク型プログラミングスクール【Freeks】 困ってた自分に届けたい話 ・・・いや、FastAPIって何？PythonでWebサーバー作ったことないけど！？何から始めればいいの…？ でも、調べてみた [&#8230;]</p>
<p>The post <a href="https://it-bokenki.com/2025/07/10/fastapi-setup/">初心者向け：FastAPIの環境構築ガイド【5分でAPIが動く】</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<div style="text-align: center;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=457GS5+A4DB02+5JVK+BXQOH">
<img loading="lazy" decoding="async" border="0" width="300" height="250" alt="" src="https://www20.a8.net/svt/bgt?aid=250611125612&#038;wid=001&#038;eno=01&#038;mid=s00000025904002005000&#038;mc=1"></a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www12.a8.net/0.gif?a8mat=457GS5+A4DB02+5JVK+BXQOH" alt=""></div>



<p class="has-text-align-center"><a href="https://px.a8.net/svt/ejp?a8mat=457GS5+A4DB02+5JVK+BX3J6">未経験でも気軽に！サブスク型プログラミングスクール【Freeks】</a></p>



<h2 class="wp-block-heading"><span id="toc1">困ってた自分に届けたい話</span></h2>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/themes/cocoon-master/images/man.png" alt="上司" class="speech-icon-image"/></figure><div class="speech-name">上司</div></div><div class="speech-balloon">
<p>FastAPIでAPIサーバー立てて。仮想環境つくって、動かして。</p>
</div></div>



<p>・・・いや、<strong>FastAPIって何？PythonでWebサーバー作ったことないけど！？</strong><br>何から始めればいいの…？</p>



<p>でも、調べてみたら、意外とコマンドだけでサクサク環境構築できる。<br><strong>「さすが爆速APIフレームワーク」って言われるだけある！</strong></p>



<p>環境構築に不安がある方でも、<strong>手順どおりに進めれば5分でAPIが動く</strong>はず。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-r sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="てんハロ運営者" class="speech-icon-image"/></figure><div class="speech-name">てんハロ運営者</div></div><div class="speech-balloon">
<p>この記事は、同じように困っていた方への<strong>備忘録兼シェア</strong>として書いています。</p>
</div></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">FastAPIとは？</span></h2>



<p><strong>ひとことで言うと、「爆速でAPIが作れるPython製フレームワーク」です。</strong></p>



<p><span class="keyboard-key">&#x1f9e9; 特徴</span></p>



<ul class="wp-block-list">
<li><strong>少ないコードで、読みやすく整理されたAPIが作れる</strong></li>



<li><strong>自動でAPIの説明書（ドキュメント）を作成してくれる</strong></li>



<li><strong>入力ミスを事前にチェックできる仕組みがある</strong></li>



<li><strong>処理速度が速く、ストレスが少ない</strong></li>



<li><strong>書き方が直感的で覚えやすい</strong></li>



<li><strong>機能を後から追加しやすく、拡張性が高い</strong></li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc3">前提：Pythonがインストールされていること</span></h2>



<p>まず、ターミナルで以下のコマンドを実行し、Pythonが使える状態か確認しましょう。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>python3 --version

# 実行結果
Python 3.9.6</code></pre></div>



<p>バージョンが 3.x 系であればOKです。<br>もし <code>command not found</code> と出る場合は、MacにPythonをインストールする手順を先に確認してください。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc4">FastAPI 環境構築手順</span></h2>



<h3 class="wp-block-heading"><span id="toc5">STEP 1：VSCodeで拡張機能をインストール</span></h3>



<p>以下の2つの拡張機能をインストールしておくと、開発がスムーズになります。</p>



<ul class="wp-block-list">
<li><strong>Python</strong>：Microsoft公式のPython拡張機能</li>



<li><strong>Pylance</strong>：コード補完とエラーチェックを強化する拡張機能</li>
</ul>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc6">STEP 2：プロジェクトフォルダを作成</span></h3>



<p>例として、<code>backend/</code> フォルダ内で作業を進めます。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>mkdir backend
cd backend</code></pre></div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc7">STEP 3：仮想環境を作成＆有効化（Macの場合）</span></h3>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code># 仮想環境作成
python3 -m venv venv

# 仮想環境の有効化
source venv/bin/activate</code></pre></div>



<p>プロンプトが <code>(venv)</code> と表示されれば、仮想環境が有効になっています。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc8">STEP 4：FastAPIと実行サーバーをインストール</span></h3>



<p>FastAPIを実際に動かすには、まず2つのパッケージをインストールするだけでOKです。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>pip install fastapi uvicorn</code></pre></div>



<p>このコマンドを実行するだけで、FastAPIを動かすのに必要な最低限の環境が整います。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">&#x1f449; インストールされる主なパッケージ</span></p>



<p>① <code>fastapi</code>：PythonでAPIを簡単に作るためのツール</p>



<ol class="wp-block-list">
<li>「こういうURLにアクセスされたら、こう返すよ！」っていうルールを書く</li>



<li>入力ミスがあったら、自動で「それ間違ってるよ」って教えてくれる</li>



<li>作ったAPIの説明書を自動でつくってくれる</li>
</ol>



<p>② <code>uvicorn</code>：FastAPIを動かすサーバー</p>



<ol class="wp-block-list">
<li>作ったAPIを動かすための土台（サーバー）になる</li>



<li>サーバーを起動すると、<strong>ブラウザで <code>http://localhost:8000</code> を開くだけで結果を見られる</strong></li>



<li><code>http://localhost:8000/docs</code> にアクセスすれば、<strong>ボタン付きのテスト画面でAPIを試せる</strong></li>
</ol>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<p>FastAPIを実行するにはこの2つだけで<strong>一通りの動作確認が可能</strong>です。<br>データベース連携やセキュリティ対策などをする場合は、追加でパッケージを入れていきます<br>（例：<code>sqlalchemy</code>, <code>pydantic[email]</code>, <code>python-jose</code> など）。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc9">STEP 5：main.py を作成してAPI定義</span></h3>



<p>このコードは「ルートURLにアクセスしたらJSONでメッセージを返すだけ」の最小APIです。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "Hello FastAPI!"}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">fastapi</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">FastAPI</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">app</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">FastAPI</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">@</span><span style="color: #8FBCBB">app</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">get</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">read_root</span><span style="color: #D8DEE9FF">():</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF">&quot;</span><span style="color: #8FBCBB">message</span><span style="color: #D8DEE9FF">&quot;: &quot;</span><span style="color: #8FBCBB">Hello</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">FastAPI</span><span style="color: #D8DEE9FF">!&quot;</span><span style="color: #ECEFF4">}</span></span></code></pre></div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc10">STEP 6：APIを起動</span></h3>



<p>以下のコマンドで開発サーバーを起動します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>uvicorn main:app --reload</code></pre></div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc11">STEP 7：動作確認リンク</span></h3>



<p>以下のURLにアクセスして、FastAPIが動いているか確認しましょう。</p>



<figure class="wp-block-table"><table><thead><tr><th>URL</th><th>内容</th></tr></thead><tbody><tr><td><a href="http://localhost:8000" title="">http://localhost:8000</a></td><td><code>{"message": "Hello FastAPI!"}</code> が表示される</td></tr><tr><td><a class="" href="http://localhost:8000/docs">http://localhost:8000/docs</a></td><td><strong>ボタンでAPIを試せる画面</strong><br>開発中に「このAPIちゃんと動くかな？」って確認するときに使う</td></tr><tr><td><a class="" href="http://localhost:8000/redoc">http://localhost:8000/redoc</a></td><td><strong>読む専用のAPI説明ページ</strong><br>「どんなAPIがあるか知りたいな〜」って一覧で見たいときに使う</td></tr></tbody></table></figure>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">実際の画面</span></p>



<p>&#x25b6; <a href="http://localhost:8000" title="">http://localhost:8000</a> の表示画面</p>



<figure class="wp-block-image aligncenter size-full has-custom-border"><img loading="lazy" decoding="async" width="700" height="186" src="https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-08-15.09.17.png" alt="初心者向け：FastAPIの環境構築ガイド【5分でAPIが動く】" class="wp-image-4581" style="border-width:1px" srcset="https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-08-15.09.17.png 700w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-08-15.09.17-300x80.png 300w" sizes="auto, (max-width: 700px) 100vw, 700px" /></figure>



<p>&#x25b6; <a href="http://localhost:8000" title="">http://localhost:8000</a><a class="" href="http://localhost:8000/docs">/docs</a> の表示画面</p>



<figure class="wp-block-image size-large has-custom-border"><img loading="lazy" decoding="async" width="1024" height="223" src="https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.56.56-1024x223.png" alt="初心者向け：FastAPIの環境構築ガイド【5分でAPIが動く】" class="wp-image-4823" style="border-width:1px" srcset="https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.56.56-1024x223.png 1024w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.56.56-300x65.png 300w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.56.56-768x167.png 768w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.56.56-1536x334.png 1536w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.56.56-2048x445.png 2048w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.56.56-1320x287.png 1320w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>&#x25b6; <a href="http://localhost:8000/redoc" title="">http://localhost:8000/redoc</a></p>



<figure class="wp-block-image size-large has-custom-border"><img loading="lazy" decoding="async" width="1024" height="270" src="https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.57.29-1024x270.png" alt="初心者向け：FastAPIの環境構築ガイド【5分でAPIが動く】" class="wp-image-4824" style="border-width:1px" srcset="https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.57.29-1024x270.png 1024w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.57.29-300x79.png 300w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.57.29-768x202.png 768w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.57.29-1320x348.png 1320w, https://it-bokenki.com/wp-content/uploads/2025/07/スクリーンショット-2025-07-10-18.57.29.png 1450w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>ここまでできれば、FastAPIのローカル開発環境は完成です。<br>あとはルーティングを増やしたり、DBとつないだり、自由にAPI開発を進めていけます。<br><br>&#x1f527; 開発に活用する具体的な実装例はこちらで紹介しています</p>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-together is-style-normal-card">
<a href="https://it-bokenki.com/2025/07/10/fastapi/" title="【初心者OK】FastAPI×MySQLをDockerで連携！Pythonで爆速開発する方法" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://it-bokenki.com/wp-content/uploads/2025/07/２行-6-320x180.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://it-bokenki.com/wp-content/uploads/2025/07/２行-6-320x180.png 320w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-6-120x68.png 120w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-6-160x90.png 160w, https://it-bokenki.com/wp-content/uploads/2025/07/２行-6-376x212.png 376w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">【初心者OK】FastAPI×MySQLをDockerで連携！Pythonで爆速開発する方法</div><div class="blogcard-snippet internal-blogcard-snippet">初心者でも安心！FastAPIとMySQL、Dockerを使ってユーザー登録APIを構築する手順をわかりやすく解説。Next.jsとの連携方法や環境構築、登録フォームの実装まで丁寧に紹介します。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">it-bokenki.com</div></div></div></div></a>
<p></p>
</div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="てんハロ運営者" class="speech-icon-image"/></figure><div class="speech-name">てんハロ運営者</div></div><div class="speech-balloon">
<p>おつかれさまでした！</p>
</div></div>



<p></p><p>The post <a href="https://it-bokenki.com/2025/07/10/fastapi-setup/">初心者向け：FastAPIの環境構築ガイド【5分でAPIが動く】</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://it-bokenki.com/2025/07/10/fastapi-setup/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[&#8230;nextauth] とは？Next.jsでログイン認証を実装する方法【App Router対応】</title>
		<link>https://it-bokenki.com/2025/06/27/nextauth/</link>
					<comments>https://it-bokenki.com/2025/06/27/nextauth/#respond</comments>
		
		<dc:creator><![CDATA[てんハロ運営者]]></dc:creator>
		<pubDate>Fri, 27 Jun 2025 03:58:43 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[Next.js]]></category>
		<category><![CDATA[バックエンド]]></category>
		<category><![CDATA[フロントエンド]]></category>
		<category><![CDATA[nextauth]]></category>
		<category><![CDATA[ログイン機能]]></category>
		<category><![CDATA[認証機能]]></category>
		<guid isPermaLink="false">https://it-bokenki.com/?p=3536</guid>

					<description><![CDATA[<p>※当サイトはアフィリエイト広告を利用しています。商品リンクにはプロモーションを含む場合があります。 Instagramフォロワー数9,500人を越える人気のもち・大福店 えにかいたもち 困ってた自分に届けたい話 初めてロ [&#8230;]</p>
<p>The post <a href="https://it-bokenki.com/2025/06/27/nextauth/">[…nextauth] とは？Next.jsでログイン認証を実装する方法【App Router対応】</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span class="fz-12px">※当サイトはアフィリエイト広告を利用しています。商品リンクにはプロモーションを含む場合があります。</span></p>



<div style="text-align: center;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T911P+F006GI+51FE+NZROH">
<img loading="lazy" decoding="async" border="0" width="300" height="250" alt="" src="https://www27.a8.net/svt/bgt?aid=230528653907&#038;wid=001&#038;eno=01&#038;mid=s00000023513004030000&#038;mc=1"></a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www11.a8.net/0.gif?a8mat=3T911P+F006GI+51FE+NZROH" alt=""></div>



<p class="has-text-align-center"><a href="https://px.a8.net/svt/ejp?a8mat=3T911P+F006GI+51FE+NWRNM">Instagramフォロワー数9,500人を越える人気のもち・大福店 えにかいたもち</a></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc1">困ってた自分に届けたい話</span></h2>



<p>初めてログイン機能を作ったとき、「ログイン状態をどうやって保持すればいいの？」「セッションって何？」と疑問だらけ。</p>



<p>ググって出てきたコードをコピペしてみても、うまく動かず。<br>認証の仕組みが見えづらくて、「これで本当に安全なのかな？」と不安になることも…。</p>



<p>そんなときに出会ったのが <code>NextAuth.js</code>。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="てんハロ運営者" class="speech-icon-image"/></figure><div class="speech-name">てんハロ運営者</div></div><div class="speech-balloon">
<p>この記事は、同じように困っていた方への<strong>備忘録兼シェア</strong>として書いています。</p>
</div></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">Next.js をもっと詳しく学びたい人へおすすめの本</span></h2>



<p><span class="keyboard-key">&#x25b6; 動かしながら基礎から学びたい人に</span><br>「まずは手を動かしたい！」という人にぴったりの一冊。基本構造から丁寧に解説されており、Next.jsとReactの連携も自然に身につきます。初学者でもステップを追いやすく、サンプルアプリの構築を通して理解を深められる構成です。</p>



<table cellpadding="0" cellspacing="0" border="0" style=" border:1px solid #ccc; width:300px;"><tr style="border-style:none;"><td style="vertical-align:top; border-style:none; padding:10px; width:140px;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=459I7K+A7CH0Y+249K+BWGDT&#038;a8ejpredirect=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2FB0D9PT5FVJ%2F%3Ftag%3Da8-affi-321185-22"><img decoding="async" border="0" alt="" src="https://m.media-amazon.com/images/I/41IcDiqx7jL._SS160_.jpg" /></a></td><td style="font-size:12px; vertical-align:middle; border-style:none; padding:10px;"><p style="padding:0; margin:0;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=459I7K+A7CH0Y+249K+BWGDT&#038;a8ejpredirect=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2FB0D9PT5FVJ%2F%3Ftag%3Da8-affi-321185-22">動かして学ぶ！Next.js/React開発入門</a></p><p style="color:#cc0000; font-weight:bold; margin-top:10px;">新品価格<br/>￥3,168<span style="font-weight:normal;">から</span><br/><span style="font-size:10px; font-weight:normal;">(2025/7/21 23:18時点)</span></p></td></tr></table>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www10.a8.net/0.gif?a8mat=459I7K+A7CH0Y+249K+BWGDT" alt="">



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">&#x25b6; Reactの経験があり、次のステップへ進みたい人に</span><br>「Reactは少し触ったことがあるけど、Next.jsを仕事で使いこなしたい」という人向け。実践を意識した構成で、Webアプリの構造、レンダリング戦略、SEO対応など、現場で必要なノウハウが詰まっています。</p>



<table cellpadding="0" cellspacing="0" border="0" style=" border:1px solid #ccc; width:300px;"><tr style="border-style:none;"><td style="vertical-align:top; border-style:none; padding:10px; width:140px;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=459I7K+A7CH0Y+249K+BWGDT&#038;a8ejpredirect=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2FB0F9PXRFHD%2F%3Ftag%3Da8-affi-321185-22"><img decoding="async" border="0" alt="" src="https://m.media-amazon.com/images/I/41zubkTAnmL._SS160_.jpg" /></a></td><td style="font-size:12px; vertical-align:middle; border-style:none; padding:10px;"><p style="padding:0; margin:0;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=459I7K+A7CH0Y+249K+BWGDT&#038;a8ejpredirect=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2FB0F9PXRFHD%2F%3Ftag%3Da8-affi-321185-22">React Next.js 実践プログラミング入門: React Next.js モダンWeb開発実践ガイド</a></p><p style="color:#cc0000; font-weight:bold; margin-top:10px;">新品価格<br/>￥3,300<span style="font-weight:normal;">から</span><br/><span style="font-size:10px; font-weight:normal;">(2025/7/21 23:17時点)</span></p></td></tr></table>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www11.a8.net/0.gif?a8mat=459I7K+A7CH0Y+249K+BWGDT" alt="">



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">&#x25b6; App Routerを本格的に学びたいエンジニアへ</span><br>App Routerを軸に、最新のNext.js開発に対応した本格派。中級者以上の方が「一歩先へ進みたい」と感じたときに読みたい一冊。デザインパターンや設計の視点もあり、長期的に役立つ内容です。</p>



<table cellpadding="0" cellspacing="0" border="0" style=" border:1px solid #ccc; width:300px;"><tr style="border-style:none;"><td style="vertical-align:top; border-style:none; padding:10px; width:140px;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=459I7K+A7CH0Y+249K+BWGDT&#038;a8ejpredirect=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2FB0CW1KC9N8%2F%3Ftag%3Da8-affi-321185-22"><img decoding="async" border="0" alt="" src="https://m.media-amazon.com/images/I/51SeLrEQrQL._SS160_.jpg" /></a></td><td style="font-size:12px; vertical-align:middle; border-style:none; padding:10px;"><p style="padding:0; margin:0;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=459I7K+A7CH0Y+249K+BWGDT&#038;a8ejpredirect=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2FB0CW1KC9N8%2F%3Ftag%3Da8-affi-321185-22">実践Next.js —— App Routerで進化するWebアプリ開発 エンジニア選書</a></p><p style="color:#cc0000; font-weight:bold; margin-top:10px;">新品価格<br/>￥3,665<span style="font-weight:normal;">から</span><br/><span style="font-size:10px; font-weight:normal;">(2025/7/21 23:18時点)</span></p></td></tr></table>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www13.a8.net/0.gif?a8mat=459I7K+A7CH0Y+249K+BWGDT" alt="">



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc3">[&#8230;nextauth] ってなに？</span></h2>



<p><code>[...nextauth]</code> は、Next.jsの「<strong>キャッチオールルート</strong>」という仕組みを使った特別なファイルです。</p>



<p>これは、<code>/api/auth/</code> 以下の複数のAPIエンドポイント（ログイン・ログアウトなど）を<br><strong>1つのファイルでまとめて管理できる便利な仕組み</strong>です。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc4">なぜ[&#8230;nextauth] は必要なの？</span></h2>



<p>NextAuth.js を使うと、認証に関するさまざまなAPIが自動的に使われます。</p>



<p>たとえば、こんなエンドポイントがあります。</p>



<figure class="wp-block-table is-style-regular"><table class="has-fixed-layout"><thead><tr><th>APIルート</th><th>概要</th></tr></thead><tbody><tr><td>/api/auth/signin</td><td>ログインページ</td></tr><tr><td>/api/auth/signout</td><td>ログアウト処理</td></tr><tr><td>/api/auth/session</td><td>現在のログイン状態確認</td></tr><tr><td>/api/auth/callback/credentials</td><td>ログイン成功後にユーザー情報を処理</td></tr><tr><td>/api/auth/csrf</td><td>ログイン中のユーザーを識別するための電子的な証明書を取得<br>※電子的な証明書＝トークン</td></tr></tbody></table></figure>



<p>これらを<strong>1つ1つ手動で作ると管理が大変</strong>です。</p>



<p>そこで、<code>[...nextauth]</code> というファイル1つにまとめることで、<br><strong>これらすべてのAPIルートを一括で定義・管理できる</strong>ようになります。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc5">App Router で実装</span></h2>



<p>Next.js 13 以降では、新しく登場した <code>app/</code> ディレクトリを使う構成（App Router）が推奨されています。これが <strong>新規プロジェクトやモダンな構成に適した形</strong>です。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc6">App Router のファイル構成</span></h3>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="992" height="378" src="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-27-11.36.42.png" alt="[...nextauth] とは？Next.jsでログイン実装" class="wp-image-3684" style="width:644px;height:auto" title="[...nextauth] とは？Next.jsでログイン実装" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-27-11.36.42.png 992w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-27-11.36.42-300x114.png 300w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-27-11.36.42-768x293.png 768w" sizes="auto, (max-width: 992px) 100vw, 992px" /></figure>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc7">App Router の実装内容</span></h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>// app/api/auth/[&#8230;nextauth]/route.ts
// 認証のエントリーポイント
import NextAuth from &#8220;next-auth/next&#8221;;
import { authOptions } from &#8220;@/lib/auth&#8221;;
// NextAuthに設定を渡して処理を作成
const handler = NextAuth(authOptions);
// App RouterではGETとPOSTのメソッドを個別にエクスポートする必要あり
export { handler as GET, handler as POST };
</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// app/api/auth/[...nextauth]/route.ts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// 認証のエントリーポイント</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">NextAuth</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth/next</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">authOptions</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">@/lib/auth</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// NextAuthに設定を渡して処理を作成</span></span>
<span class="line"><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">handler</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">NextAuth</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">authOptions</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// App RouterではGETとPOSTのメソッドを個別にエクスポートする必要あり</span></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">handler</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">GET</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">handler</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">POST</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>// lib/auth.ts
import CredentialsProvider from &#8220;next-auth/providers/credentials&#8221;;
import type { Session } from &#8220;next-auth&#8221;;
import type { JWT } from &#8220;next-auth/jwt&#8221;;　// NextAuth.jsが使っているトークン（認証情報）の型名
import type { NextAuthOptions } from &#8220;next-auth&#8221;;
// JWTにカスタム情報（role）を追加する場合の型定義
interface Token extends JWT {
  role?: string;
}
export const authOptions: NextAuthOptions = {
  // ① ログイン方法の指定（ここではIDとパスワードによる認証）
  providers: [
    CredentialsProvider({
      name: &#8220;Credentials&#8221;,
      credentials: {
        username: { label: &#8220;ユーザーID&#8221;, type: &#8220;text&#8221; },
        password: { label: &#8220;パスワード&#8221;, type: &#8220;password&#8221; },
      },
      // 認証処理：環境変数のユーザー名・パスワードと一致すれば成功
      async authorize(credentials) {
        if (
          credentials?.username === process.env.ADMIN_USERNAME &amp;&amp;
          credentials?.password === process.env.ADMIN_PASSWORD
        ) {
          return { id: &#8220;1&#8221;, name: &#8220;管理者&#8221;, role: &#8220;admin&#8221; };
        }
        return null; // 認証失敗
      },
    }),
  ],
  // ② カスタムページ（ログイン画面など）を指定
  pages: {
    signIn: &#8220;/auth/signin&#8221;, // 独自ログインページを使う場合
  },
  // ③ セッションの設定（JWT方式を利用）
  session: {
    strategy: &#8220;jwt&#8221;,  // サーバーセッションではなくトークンで管理
    maxAge: 100,      // トークンの有効期限（秒）
  },
  // ④ コールバック処理（トークンやセッションに追加情報を含める）
  callbacks: {
    // JWT作成時：ユーザー情報からroleをtokenに追加
    async jwt({ token, user }: { token: Token; user?: unknown }) {
      if (user &amp;&amp; typeof user === &#8220;object&#8221; &amp;&amp; &#8220;role&#8221; in user) {
        token.role = (user as { role?: string }).role;
      }
      return token;
    },
    // セッション作成時：tokenからroleを取り出してsessionに追加
    async session({ session, token }: { session: Session; token: Token }) {
      session.user = {
        &#8230;session.user,
        role: token.role ?? null,
      } as typeof session.user &amp; { role?: string | null };
      return session;
    },
  },
};
</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// lib/auth.ts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">CredentialsProvider</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth/providers/credentials</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">type</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Session</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">type</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">JWT</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth/jwt</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">　</span><span style="color: #616E88">// NextAuth.jsが使っているトークン（認証情報）の型名</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">type</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NextAuthOptions</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// JWTにカスタム情報（role）を追加する場合の型定義</span></span>
<span class="line"><span style="color: #81A1C1">interface</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Token</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">extends</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB; font-weight: bold">JWT</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  role</span><span style="color: #81A1C1">?:</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">string</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">authOptions</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">NextAuthOptions</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// ① ログイン方法の指定（ここではIDとパスワードによる認証）</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">providers</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> [</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">CredentialsProvider</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #D8DEE9">name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Credentials</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #D8DEE9">credentials</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">username</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">label</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">ユーザーID</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">type</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">text</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">password</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">label</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">パスワード</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">type</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">password</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #ECEFF4">      </span><span style="color: #616E88">// 認証処理：環境変数のユーザー名・パスワードと一致すれば成功</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">authorize</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">credentials</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #D8DEE9">credentials</span><span style="color: #ECEFF4">?.</span><span style="color: #D8DEE9">username</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">===</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">process</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">env</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">ADMIN_USERNAME</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #D8DEE9">credentials</span><span style="color: #ECEFF4">?.</span><span style="color: #D8DEE9">password</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">===</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">process</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">env</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">ADMIN_PASSWORD</span></span>
<span class="line"><span style="color: #D8DEE9FF">        ) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">id</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">管理者</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">role</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">admin</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// 認証失敗</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  ]</span><span style="color: #ECEFF4">,</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// ② カスタムページ（ログイン画面など）を指定</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">pages</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">signIn</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/auth/signin</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// 独自ログインページを使う場合</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// ③ セッションの設定（JWT方式を利用）</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">strategy</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">jwt</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">// サーバーセッションではなくトークンで管理</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">maxAge</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">100</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF">      </span><span style="color: #616E88">// トークンの有効期限（秒）</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// ④ コールバック処理（トークンやセッションに追加情報を含める）</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">callbacks</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// JWT作成時：ユーザー情報からroleをtokenに追加</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">jwt</span><span style="color: #ECEFF4">({</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> token</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Token</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> user</span><span style="color: #81A1C1">?:</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">unknown</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">})</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">typeof</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">===</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">object</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">role</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">token</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">role</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> role</span><span style="color: #81A1C1">?:</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">string</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">role</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// セッション作成時：tokenからroleを取り出してsessionに追加</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">session</span><span style="color: #ECEFF4">({</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> session</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Session</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> token</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Token</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">})</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">user</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">role</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">role</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">??</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">typeof</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> role</span><span style="color: #81A1C1">?:</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">string</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">null</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">session</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc8">Pages Router で実装</span></h2>



<p><code>pages/</code> ディレクトリを使う旧構成で、Next.js 初期から使われていたルーターです。<br>今でも既存プロジェクトではよく使われていますが、<strong>新規プロジェクトではあまり使われません</strong>。<br>今後は <code>app/</code> を使う App Router が推奨されています。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc9">Pages Router のファイル構成</span></h3>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="1054" height="234" src="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-27-11.36.58.png" alt="[...nextauth] とは？Next.jsでログイン実装" class="wp-image-3685" style="width:644px;height:auto" title="[...nextauth] とは？Next.jsでログイン実装" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-27-11.36.58.png 1054w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-27-11.36.58-300x67.png 300w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-27-11.36.58-1024x227.png 1024w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-27-11.36.58-768x171.png 768w" sizes="auto, (max-width: 1054px) 100vw, 1054px" /></figure>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc10">Pages Router の実装内容</span></h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>// pages/api/auth/[&#8230;nextauth].ts
import NextAuth from &#8220;next-auth&#8221;;
import CredentialsProvider from &#8220;next-auth/providers/credentials&#8221;;
import type { Session } from &#8220;next-auth&#8221;;
import type { JWT } from &#8220;next-auth/jwt&#8221;;
// JWTにカスタム情報（role）を追加する場合の型定義
interface Token extends JWT {
  role?: string;
}
export default NextAuth({
  // ① ログイン方法の指定（ここではIDとパスワードによる認証）
  providers: [
    CredentialsProvider({
      name: &#8220;Credentials&#8221;,
      credentials: {
        username: { label: &#8220;ユーザーID&#8221;, type: &#8220;text&#8221; },
        password: { label: &#8220;パスワード&#8221;, type: &#8220;password&#8221; },
      },
      // 認証処理：環境変数のユーザー名・パスワードと一致すれば成功
      async authorize(credentials) {
        if (
          credentials?.username === process.env.ADMIN_USERNAME &amp;&amp;
          credentials?.password === process.env.ADMIN_PASSWORD
        ) {
          return { id: &#8220;1&#8221;, name: &#8220;管理者&#8221;, role: &#8220;admin&#8221; };
        }
        return null; // 認証失敗
      },
    }),
  ],
  // ② カスタムページ（ログイン画面など）を指定
  pages: {
    signIn: &#8220;/auth/signin&#8221;, // 独自ログインページを使う場合
  },
  // ③ セッションの設定（JWT方式を利用）
  session: {
    strategy: &#8220;jwt&#8221;,  // サーバーセッションではなくトークンで管理
    maxAge: 100,      // トークンの有効期限（秒）
  },
  // ④ コールバック処理（トークンやセッションに追加情報を含める）
  callbacks: {
    // JWT作成時：ユーザー情報からroleをtokenに追加
    async jwt({ token, user }: { token: Token; user?: unknown }) {
      if (user &amp;&amp; typeof user === &#8220;object&#8221; &amp;&amp; &#8220;role&#8221; in user) {
        token.role = (user as { role?: string }).role;
      }
      return token;
    },
    // セッション作成時：tokenからroleを取り出してsessionに追加
    async session({ session, token }: { session: Session; token: Token }) {
      session.user = {
        &#8230;session.user,
        role: token.role ?? null,
      } as typeof session.user &amp; { role?: string | null };
      return session;
    },
  },
});</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// pages/api/auth/[...nextauth].ts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">NextAuth</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">CredentialsProvider</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth/providers/credentials</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">type</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Session</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">type</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">JWT</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth/jwt</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// JWTにカスタム情報（role）を追加する場合の型定義</span></span>
<span class="line"><span style="color: #81A1C1">interface</span><span style="color: #D8DEE9FF"> Token </span><span style="color: #81A1C1">extends</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB; font-weight: bold">JWT</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  role</span><span style="color: #81A1C1">?:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">string;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">default</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">NextAuth</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// ① ログイン方法の指定（ここではIDとパスワードによる認証）</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">providers</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> [</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">CredentialsProvider</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Credentials</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">credentials</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">username</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">label</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">ユーザーID</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">type</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">text</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">password</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">label</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">パスワード</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">type</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">password</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #ECEFF4">      </span><span style="color: #616E88">// 認証処理：環境変数のユーザー名・パスワードと一致すれば成功</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">authorize</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">credentials</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #D8DEE9">credentials</span><span style="color: #ECEFF4">?.</span><span style="color: #D8DEE9">username</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">===</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">process</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">env</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">ADMIN_USERNAME</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #D8DEE9">credentials</span><span style="color: #ECEFF4">?.</span><span style="color: #D8DEE9">password</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">===</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">process</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">env</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">ADMIN_PASSWORD</span></span>
<span class="line"><span style="color: #D8DEE9FF">        ) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">id</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">管理者</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">role</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">admin</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// 認証失敗</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  ]</span><span style="color: #ECEFF4">,</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// ② カスタムページ（ログイン画面など）を指定</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">pages</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">signIn</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/auth/signin</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// 独自ログインページを使う場合</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// ③ セッションの設定（JWT方式を利用）</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">session</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">strategy</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">jwt</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">// サーバーセッションではなくトークンで管理</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">maxAge</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">100</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF">      </span><span style="color: #616E88">// トークンの有効期限（秒）</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// ④ コールバック処理（トークンやセッションに追加情報を含める）</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">callbacks</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// JWT作成時：ユーザー情報からroleをtokenに追加</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">jwt</span><span style="color: #ECEFF4">({</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> token</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> Token</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> user</span><span style="color: #81A1C1">?:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">unknown</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">})</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">typeof</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">===</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">object</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">role</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">token</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">role</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> role</span><span style="color: #81A1C1">?:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">string</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">role</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// セッション作成時：tokenからroleを取り出してsessionに追加</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">session</span><span style="color: #ECEFF4">({</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> session</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> Session</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> token</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> Token </span><span style="color: #ECEFF4">})</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">user</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">role</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">role</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">??</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">typeof</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> role</span><span style="color: #81A1C1">?:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">string</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">null</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">session</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc11">まとめ</span></h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>比較項目</th><th>Pages Router</th><th>App Router</th></tr></thead><tbody><tr><td>構成</td><td>1ファイル完結型</td><td>設定分離型（lib/auth.ts）推奨</td></tr><tr><td>エクスポート方法</td><td>export default</td><td>export { GET, POST }</td></tr><tr><td>推奨</td><td>App Router移行前<br>既存プロジェクト</td><td>Next.js 13以降の新規開発</td></tr></tbody></table></figure>



<p>ファイル1つ（または2つ）で以下すべてのAPIが動く！そのため、それぞれを個別に作る必要なし！</p>



<ul class="wp-block-list">
<li><code>/api/auth/signin</code></li>



<li><code>/api/auth/signout</code></li>



<li><code>/api/auth/session</code></li>



<li><code>/api/auth/callback/credentials</code></li>



<li><code>/api/auth/csrf</code></li>
</ul>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="てんハロ運営者" class="speech-icon-image"/></figure><div class="speech-name">てんハロ運営者</div></div><div class="speech-balloon">
<p>おつかれさまでした！</p>
</div></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-together is-style-default">
<a href="https://it-bokenki.com/2025/06/26/azure-blob/" title="Azure Blob Storage にファイルをアップロードする方法【Next.js × React】" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://it-bokenki.com/wp-content/uploads/2025/06/２行-14-320x180.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/２行-14-320x180.png 320w, https://it-bokenki.com/wp-content/uploads/2025/06/２行-14-120x68.png 120w, https://it-bokenki.com/wp-content/uploads/2025/06/２行-14-160x90.png 160w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">Azure Blob Storage にファイルをアップロードする方法【Next.js × React】</div><div class="blogcard-snippet internal-blogcard-snippet">Next.jsとAzure Blob Storageを使ったファイルアップロードの実装方法を初心者向けに解説。設定手順からReactでのUI作成、APIの書き方まで！</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">it-bokenki.com</div></div></div></div></a>
<p></p>
</div>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<div style="height:0px" aria-hidden="true" class="wp-block-spacer"></div><p>The post <a href="https://it-bokenki.com/2025/06/27/nextauth/">[…nextauth] とは？Next.jsでログイン認証を実装する方法【App Router対応】</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://it-bokenki.com/2025/06/27/nextauth/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Next.jsでログイン機能を実装｜NextAuth.jsでID・パスワード認証対応</title>
		<link>https://it-bokenki.com/2025/06/26/nextauth-js/</link>
					<comments>https://it-bokenki.com/2025/06/26/nextauth-js/#respond</comments>
		
		<dc:creator><![CDATA[てんハロ運営者]]></dc:creator>
		<pubDate>Thu, 26 Jun 2025 09:12:47 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[Next.js]]></category>
		<category><![CDATA[バックエンド]]></category>
		<category><![CDATA[フロントエンド]]></category>
		<category><![CDATA[ログイン機能]]></category>
		<guid isPermaLink="false">https://it-bokenki.com/?p=3615</guid>

					<description><![CDATA[<p>※当サイトはアフィリエイト広告を利用しています。商品リンクにはプロモーションを含む場合があります。 Instagramフォロワー数9,500人を越える人気のもち・大福店 えにかいたもち 困ってた自分に届けたい話 初めてロ [&#8230;]</p>
<p>The post <a href="https://it-bokenki.com/2025/06/26/nextauth-js/">Next.jsでログイン機能を実装｜NextAuth.jsでID・パスワード認証対応</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span class="fz-12px">※当サイトはアフィリエイト広告を利用しています。商品リンクにはプロモーションを含む場合があります。</span></p>



<div style="text-align: center;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T911P+F006GI+51FE+NZROH">
<img loading="lazy" decoding="async" border="0" width="300" height="250" alt="" src="https://www27.a8.net/svt/bgt?aid=230528653907&#038;wid=001&#038;eno=01&#038;mid=s00000023513004030000&#038;mc=1"></a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www11.a8.net/0.gif?a8mat=3T911P+F006GI+51FE+NZROH" alt=""></div>



<p class="has-text-align-center"><a href="https://px.a8.net/svt/ejp?a8mat=3T911P+F006GI+51FE+NWRNM">Instagramフォロワー数9,500人を越える人気のもち・大福店 えにかいたもち</a></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc1">困ってた自分に届けたい話</span></h2>



<p>初めてログイン機能を作ったとき、「ログイン状態をどうやって保持すればいいの？」「セッションって何？」と疑問だらけ。</p>



<p>ググって出てきたコードをコピペしてみても、うまく動かず。<br>認証の仕組みが見えづらくて、「これで本当に安全なのかな？」と不安になることも…。</p>



<p>そんなときに出会ったのが <code>NextAuth.js</code>。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="てんハロ運営者" class="speech-icon-image"/></figure><div class="speech-name">てんハロ運営者</div></div><div class="speech-balloon">
<p>この記事は、同じように困っていた方への<strong>備忘録兼シェア</strong>として書いています。</p>
</div></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">Next.js をもっと詳しく学びたい人へおすすめの本</span></h2>



<p><span class="keyboard-key">&#x25b6; 動かしながら基礎から学びたい人に</span><br>「まずは手を動かしたい！」という人にぴったりの一冊。基本構造から丁寧に解説されており、Next.jsとReactの連携も自然に身につきます。初学者でもステップを追いやすく、サンプルアプリの構築を通して理解を深められる構成です。</p>



<table cellpadding="0" cellspacing="0" border="0" style=" border:1px solid #ccc; width:300px;"><tr style="border-style:none;"><td style="vertical-align:top; border-style:none; padding:10px; width:140px;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=459I7K+A7CH0Y+249K+BWGDT&#038;a8ejpredirect=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2FB0D9PT5FVJ%2F%3Ftag%3Da8-affi-321185-22"><img decoding="async" border="0" alt="" src="https://m.media-amazon.com/images/I/41IcDiqx7jL._SS160_.jpg" /></a></td><td style="font-size:12px; vertical-align:middle; border-style:none; padding:10px;"><p style="padding:0; margin:0;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=459I7K+A7CH0Y+249K+BWGDT&#038;a8ejpredirect=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2FB0D9PT5FVJ%2F%3Ftag%3Da8-affi-321185-22">動かして学ぶ！Next.js/React開発入門</a></p><p style="color:#cc0000; font-weight:bold; margin-top:10px;">新品価格<br/>￥3,168<span style="font-weight:normal;">から</span><br/><span style="font-size:10px; font-weight:normal;">(2025/7/21 23:18時点)</span></p></td></tr></table>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www10.a8.net/0.gif?a8mat=459I7K+A7CH0Y+249K+BWGDT" alt="">



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">&#x25b6; Reactの経験があり、次のステップへ進みたい人に</span><br>「Reactは少し触ったことがあるけど、Next.jsを仕事で使いこなしたい」という人向け。実践を意識した構成で、Webアプリの構造、レンダリング戦略、SEO対応など、現場で必要なノウハウが詰まっています。</p>



<table cellpadding="0" cellspacing="0" border="0" style=" border:1px solid #ccc; width:300px;"><tr style="border-style:none;"><td style="vertical-align:top; border-style:none; padding:10px; width:140px;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=459I7K+A7CH0Y+249K+BWGDT&#038;a8ejpredirect=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2FB0F9PXRFHD%2F%3Ftag%3Da8-affi-321185-22"><img decoding="async" border="0" alt="" src="https://m.media-amazon.com/images/I/41zubkTAnmL._SS160_.jpg" /></a></td><td style="font-size:12px; vertical-align:middle; border-style:none; padding:10px;"><p style="padding:0; margin:0;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=459I7K+A7CH0Y+249K+BWGDT&#038;a8ejpredirect=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2FB0F9PXRFHD%2F%3Ftag%3Da8-affi-321185-22">React Next.js 実践プログラミング入門: React Next.js モダンWeb開発実践ガイド</a></p><p style="color:#cc0000; font-weight:bold; margin-top:10px;">新品価格<br/>￥3,300<span style="font-weight:normal;">から</span><br/><span style="font-size:10px; font-weight:normal;">(2025/7/21 23:17時点)</span></p></td></tr></table>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www11.a8.net/0.gif?a8mat=459I7K+A7CH0Y+249K+BWGDT" alt="">



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">&#x25b6; App Routerを本格的に学びたいエンジニアへ</span><br>App Routerを軸に、最新のNext.js開発に対応した本格派。中級者以上の方が「一歩先へ進みたい」と感じたときに読みたい一冊。デザインパターンや設計の視点もあり、長期的に役立つ内容です。</p>



<table cellpadding="0" cellspacing="0" border="0" style=" border:1px solid #ccc; width:300px;"><tr style="border-style:none;"><td style="vertical-align:top; border-style:none; padding:10px; width:140px;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=459I7K+A7CH0Y+249K+BWGDT&#038;a8ejpredirect=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2FB0CW1KC9N8%2F%3Ftag%3Da8-affi-321185-22"><img decoding="async" border="0" alt="" src="https://m.media-amazon.com/images/I/51SeLrEQrQL._SS160_.jpg" /></a></td><td style="font-size:12px; vertical-align:middle; border-style:none; padding:10px;"><p style="padding:0; margin:0;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=459I7K+A7CH0Y+249K+BWGDT&#038;a8ejpredirect=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2FB0CW1KC9N8%2F%3Ftag%3Da8-affi-321185-22">実践Next.js —— App Routerで進化するWebアプリ開発 エンジニア選書</a></p><p style="color:#cc0000; font-weight:bold; margin-top:10px;">新品価格<br/>￥3,665<span style="font-weight:normal;">から</span><br/><span style="font-size:10px; font-weight:normal;">(2025/7/21 23:18時点)</span></p></td></tr></table>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www13.a8.net/0.gif?a8mat=459I7K+A7CH0Y+249K+BWGDT" alt="">



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc3">全体構成</span></h2>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="602" height="750" src="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-14.50.51.png" alt="Next.jsでログイン機能を実装｜NextAuth.jsでID・パスワード認証対応" class="wp-image-3618" style="width:425px;height:auto" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-14.50.51.png 602w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-14.50.51-241x300.png 241w" sizes="auto, (max-width: 602px) 100vw, 602px" /></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc4">認証設定（lib/auth.ts）</span></h2>



<p><strong>Next.js でログイン機能を作るときに必要な「設定ファイル」</strong>です。<br>NextAuth.js というライブラリが、このファイルを見てどう動くか決めます。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc5">NextAuthの設定内容</span></h3>



<h4 class="wp-block-heading"><span><strong>ログイン方式の設定（providers）</strong></span></h4>



<p>「どんな方法でログインできるようにするか」を決める場所です。</p>



<div style="height:1px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">例</span>：</p>



<ul class="wp-block-list">
<li>ユーザー名とパスワードでログイン ： <strong>CredentialsProvider</strong> を使う</li>



<li>Google アカウントでログイン ： <strong>GoogleProvider</strong><code> </code>を使う</li>



<li>GitHub アカウントでログイン ： <strong>GitHubProvider</strong> を使う</li>
</ul>



<p>→ 今回は「IDとパスワードでログインしたい」ので <code>CredentialsProvider</code> を使います。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><span><strong><strong>セッション管理（session）</strong></strong></span></h4>



<p>「ログイン状態（セッション）をどうやって覚えておくか？」を設定します。</p>



<div style="height:1px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">例</span>：</p>



<ul class="wp-block-list">
<li><strong>jwt</strong>：サーバーに保存せず、ログイン情報をクッキーに入れて管理（軽い）</li>



<li><strong>database</strong>：ログイン情報をデータベースに保存（管理がしっかり）</li>
</ul>



<p>→ 今回は簡単な構成にしたいので、<code>jwt</code> を使っています。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="wp-block-heading"><span><strong><strong><strong>コールバック関数（callbacks）</strong></strong></strong></span></h4>



<p>「ログインしたあと、追加で何かしたいとき」に使います。</p>



<div style="height:1px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="keyboard-key">例</span>：</p>



<ul class="wp-block-list">
<li>ログインしたユーザーの「名前」や「権限（adminなど）」をセッションに保存する</li>



<li>トークンに extra 情報を加える</li>
</ul>



<p>→ 今回は、「管理者かどうか（role）」をセッションに入れています。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc6">lib 配下にファイルを配置する理由</span></h3>



<p><code>lib</code> は「<strong>ロジック（処理）や設定などの共通ユーティリティを置く場所</strong>」という意味で使われます。<code>auth.ts</code> は<strong>アプリ全体で使う「認証の設定」</strong> をまとめたものなので、<code>lib</code> に置くのが自然です。</p>



<p><span class="keyboard-key">&#x1f5c2; <strong>配置イメージ</strong></span></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>ディレクトリ</th><th>役割</th></tr></thead><tbody><tr><td><code><strong>lib/</strong></code>配下</td><td>アプリ全体で使い回すロジックや設定の置き場</td></tr><tr><td><strong><code>app/api/</code></strong>配下 　もしくは<strong><code>　　　　　pages/api/</code></strong>配下</td><td>APIルート（APIエンドポイント）</td></tr><tr><td><strong><code>components/</code></strong>配下</td><td>UIの部品化されたパーツの置き場</td></tr></tbody></table></figure>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc7">実装内容</span></h3>



<p><strong><span class="keyboard-key">&#x26a0;&#xfe0f; 実装時の注意点</span></strong></p>



<ul class="wp-block-list">
<li>ログインID・パスワードは直書き厳禁。今回は.envに直書きしてしまっています。<br>（次回、Azure SQL Databaseにパスワード等を格納する記事出します！）</li>



<li><code>role</code> など独自の情報をセッションやトークンに保持したい場合は、<code>callbacks</code> を使って明示的に追加します。</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>import CredentialsProvider from &#8220;next-auth/providers/credentials&#8221;;
import type { Session } from &#8220;next-auth&#8221;;
import type { JWT } from &#8220;next-auth/jwt&#8221;;
interface Token extends JWT {
  role?: string;
}
export const authOptions = {
  // CredentialsProvider の設定（IDとパスワードでログインさせるための仕組み）
  providers: [
    CredentialsProvider({
      // ログイン画面のフォームの中身
      credentials: {
        username: { label: &#8220;ユーザーID&#8221;, type: &#8220;text&#8221; },
        password: { label: &#8220;パスワード&#8221;, type: &#8220;password&#8221; },
      },
      // 入力されたIDとパスワードが正しいかチェックする関数
      async authorize(credentials) {
        if (
          credentials?.username === process.env.[&#8220;任意の環境変数名&#8221;] &amp;&amp;
          credentials?.password === process.env.[&#8220;任意の環境変数名&#8221;]
        ) {
          return { id: &#8220;1&#8221;, name: &#8220;管理者&#8221;, role: &#8220;admin&#8221; };
        }
        return null;
      },
    }),
  ],
  // 独自に作成するページのパス
  pages: {
    signIn: &#8220;/auth/signin&#8221;,
  },
  // セッションの設定
  session: {
    strategy: &#8220;jwt&#8221; as const,
    maxAge: 100,
  },
  // ログイン後、ユーザー情報（user）やトークン（token）に追加情報（ここでは role）を保持・共有
  callbacks: {
    // useSession() で取り出すとき、session.user にも role を渡す
    async session({ session, token }: { session: Session; token: Token }) {
      session.user = {
        &#8230;session.user,
        role: token.role ?? null,
      } as typeof session.user &amp; { role?: string | null };
      return session;
    },
    // ログイン後、トークンに role を保存
    async jwt({ token, user }: { token: Token; user?: unknown }) {
      if (user &amp;&amp; typeof user === &#8220;object&#8221; &amp;&amp; &#8220;role&#8221; in user) {
        token.role = (user as { role?: string }).role;
      }
      return token;
    },
  },
};
</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">CredentialsProvider</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth/providers/credentials</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">type</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Session</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">type</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">JWT</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth/jwt</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">interface</span><span style="color: #D8DEE9FF"> Token </span><span style="color: #81A1C1">extends</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB; font-weight: bold">JWT</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  role</span><span style="color: #81A1C1">?:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">string;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">authOptions</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// CredentialsProvider の設定（IDとパスワードでログインさせるための仕組み）</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">providers</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> [</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">CredentialsProvider</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">      </span><span style="color: #616E88">// ログイン画面のフォームの中身</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">credentials</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">username</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">label</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">ユーザーID</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">type</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">text</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">password</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">label</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">パスワード</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">type</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">password</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">},</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">      </span><span style="color: #616E88">// 入力されたIDとパスワードが正しいかチェックする関数</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">authorize</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">credentials</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #D8DEE9">credentials</span><span style="color: #ECEFF4">?.</span><span style="color: #D8DEE9">username</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">===</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">process</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">env</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">[</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">任意の環境変数名</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">] </span><span style="color: #81A1C1">&amp;&amp;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #D8DEE9">credentials</span><span style="color: #ECEFF4">?.</span><span style="color: #D8DEE9">password</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">===</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">process</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">env</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">[</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">任意の環境変数名</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">        ) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">id</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">管理者</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">role</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">admin</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  ]</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// 独自に作成するページのパス</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">pages</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">signIn</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/auth/signin</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// セッションの設定</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">session</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">strategy</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">jwt</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">const</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">maxAge</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">100</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// ログイン後、ユーザー情報（user）やトークン（token）に追加情報（ここでは role）を保持・共有</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">callbacks</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// useSession() で取り出すとき、session.user にも role を渡す</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">session</span><span style="color: #ECEFF4">({</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> session</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> Session</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> token</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> Token </span><span style="color: #ECEFF4">})</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">user</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">role</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">role</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">??</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">typeof</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">session</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> role</span><span style="color: #81A1C1">?:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">string</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">null</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">session</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// ログイン後、トークンに role を保存</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">jwt</span><span style="color: #ECEFF4">({</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> token</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> Token</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> user</span><span style="color: #81A1C1">?:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">unknown</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">})</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">typeof</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">===</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">object</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">role</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">token</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">role</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">user</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> role</span><span style="color: #81A1C1">?:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">string</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">role</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">token</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc8">認証エンドポイント（app/api/auth/[...nextauth]/route.ts）</span></h2>



<p><strong>APIルートの設定</strong>です。NextAuth の設定を使ってログイン処理などを実行できるようにします。</p>



<p><strong><span class="keyboard-key">&#x26a0;&#xfe0f; 実装時の注意点</span></strong></p>



<ul class="wp-block-list">
<li><code>route.ts</code> では NextAuth をラップし、GET/POST 両方のメソッドをエクスポートする必要があります。</li>



<li><code>authOptions</code> を正しく <code>lib/auth.ts</code> からインポートできていることを確認してください。</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>import NextAuth from &#8220;next-auth/next&#8221;;
import { authOptions } from &#8220;@/lib/auth&#8221;;
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">NextAuth</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth/next</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">authOptions</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">@/lib/auth</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">handler</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">NextAuth</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">authOptions</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">handler</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">GET</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">handler</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">POST</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc9">アプリ全体で認証を使う（components/Providers.tsx）（app/layout.tsx）</span></h2>



<p><strong><strong>セッション（ログイン状態）をアプリ全体で共有</strong></strong>できるようにするためのコンポーネントです。</p>



<p><strong><strong>アプリのレイアウト全体を </strong><code><strong>Providers</strong></code><strong> で囲み、どのページでもログイン情報を使える</strong></strong>ようにします。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc10">SessionProviderとは</span></h3>



<p><code>SessionProvider</code> は、<strong>ログイン状態（セッション）をアプリ全体で使えるようにするための部品</strong>です。</p>



<p>囲んでいないと、<br><code>useSession()</code>（ログイン状態を取得する関数）<br><code>getSession()</code>（セッション情報を取得する関数）<br>などが正しく動作しません。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc11">SessionProvider を直接 layout.tsxに記載しない理由</span></h3>



<p>Next.js App Router では <strong><code>layout.tsx</code> はサーバーコンポーネントであることが前提</strong> です。なので、以下のような理由で <code>SessionProvider</code> を直接 <code>layout.tsx</code> に書けないことがあります。</p>



<p><span class="keyboard-key">&#x2757;問題の背景</span></p>



<ul class="wp-block-list">
<li><code>SessionProvider</code> は <strong>クライアントコンポーネント（<code>"use client"</code> が必要）</strong></li>



<li>一方で、<code>layout.tsx</code> はデフォルトで <strong>サーバーコンポーネント</strong></li>



<li>サーバーコンポーネントに <code>use client</code> をつけると、<code>metadata</code> などのサーバー専用機能が使えなくなる</li>
</ul>



<p><code>SessionProvider</code> を直接 <code>layout.tsx</code> に書くと、<code>layout.tsx</code> 全体がクライアントコンポーネントになり、Next.js 本来の機能（<code>metadata</code> など）が使えなくなる。</p>



<p>そのため、<strong>別のクライアントコンポーネントに切り出してラップする</strong>のが推奨されているわけです。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc12">実装内容</span></h3>



<p><span class="keyboard-key">&#x2705; 解決策</span>：<code>&lt;Providers&gt;</code> コンポーネントを別に作成して、ラップする！！</p>



<p><code>Providers.tsx</code> を作って <code>"use client"</code> をつけることで、</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>&#8220;use client&#8221;;
import { SessionProvider } from &#8220;next-auth/react&#8221;;
export function Providers({ children }: { children: React.ReactNode }) {
  return &lt;SessionProvider>{children}&lt;/SessionProvider>;
}</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">use client</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SessionProvider</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth/react</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">function</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Providers</span><span style="color: #ECEFF4">({</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">children</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> children</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> React</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">ReactNode </span><span style="color: #ECEFF4">})</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #8FBCBB">SessionProvider</span><span style="color: #81A1C1">&gt;{</span><span style="color: #D8DEE9">children</span><span style="color: #81A1C1">}&lt;/</span><span style="color: #8FBCBB">SessionProvider</span><span style="color: #81A1C1">&gt;;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<p>これを <code>layout.tsx</code> 側で下記のようにラップする。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>import type { Metadata } from &#8220;next&#8221;;
import { Providers } from &#8220;@/components/Providers&#8221;;
import &#8220;./globals.css&#8221;;
export const metadata: Metadata = {
  title: &#8220;Create Next App&#8221;,
  description: &#8220;Generated by create next app&#8221;,
};
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    &lt;html lang=&#8221;en&#8221;>
      &lt;body>
        &lt;Providers>{children}&lt;/Providers>
      &lt;/body>
    &lt;/html>
  );
}</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">type</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Metadata</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Providers</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">@/components/Providers</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">./globals.css</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">metadata</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> Metadata </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">title</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Create Next App</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">description</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Generated by create next app</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">default</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">function</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">RootLayout</span><span style="color: #ECEFF4">({</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">children</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> children</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> React</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">ReactNode </span><span style="color: #ECEFF4">})</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> (</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;html</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">lang</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">en</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;body&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;</span><span style="color: #8FBCBB">Providers</span><span style="color: #81A1C1">&gt;{</span><span style="color: #D8DEE9">children</span><span style="color: #81A1C1">}&lt;/</span><span style="color: #8FBCBB">Providers</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;/body&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;/html&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  )</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc13">ログインフォーム（app/auth/signin/page.tsx）</span></h2>



<p><strong><strong>ユーザーがログインIDとパスワードを入力</strong></strong>し、ログイン処理を実行するフォームです。</p>



<p><strong><span class="keyboard-key">&#x26a0;&#xfe0f; 実装時の注意点</span></strong></p>



<ul class="wp-block-list">
<li><code>signIn("credentials")</code> の引数 <code>redirect: false</code> を忘れると、自動遷移してしまいエラー処理が難しくなります。</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>&#8220;use client&#8221;;
import { useState } from &#8220;react&#8221;;
import { signIn } from &#8220;next-auth/react&#8221;;
export default function SignInForm() {
  const [userId, setUserId] = useState(&#8220;&#8221;);
  const [password, setPassword] = useState(&#8220;&#8221;);
  const [errorMsg, setErrorMsg] = useState(&#8220;&#8221;);
  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setErrorMsg(&#8220;&#8221;);
    const res = await signIn(&#8220;credentials&#8221;, {
      redirect: false,
      username: userId,
      password,
    });
    if (res?.error) {
      setErrorMsg(&#8220;ログインIDまたはパスワードが間違っています&#8221;);
    } else if (res?.ok) {
      window.location.href = &#8220;/download&#8221;;
    } else {
      setErrorMsg(&#8220;不明なエラーが発生しました&#8221;);
    }
  };
  return (
    &lt;div className=&#8221;flex items-center justify-center min-h-screen bg-cover bg-center&#8221; style={{ backgroundImage: &#8220;url(&#8216;/images/white-background.png&#8217;)&#8221; }}>
      &lt;form onSubmit={handleSubmit} className=&#8221;bg-white p-8 rounded shadow-md w-[500px] mx-auto&#8221;>
        &lt;h1 className=&#8221;text-2xl font-bold mb-6 text-center&#8221;>ログイン&lt;/h1>
        &lt;label className=&#8221;block mb-4&#8243;>
          &lt;span className=&#8221;block text-gray-700 font-semibold mb-1&#8243;>ログインID&lt;/span>
          &lt;input type=&#8221;text&#8221; value={userId} onChange={(e) => setUserId(e.target.value)} required className=&#8221;w-full px-3 py-2 border border-gray-300 rounded&#8221; />
        &lt;/label>
        &lt;label className=&#8221;block mb-4&#8243;>
          &lt;span className=&#8221;block text-gray-700 font-semibold mb-1&#8243;>パスワード&lt;/span>
          &lt;input type=&#8221;password&#8221; value={password} onChange={(e) => setPassword(e.target.value)} required className=&#8221;w-full px-3 py-2 border border-gray-300 rounded&#8221; />
        &lt;/label>
        {errorMsg &amp;&amp; &lt;p className=&#8221;text-red-600 text-center mb-4&#8243;>{errorMsg}&lt;/p>}
        &lt;button type=&#8221;submit&#8221; className=&#8221;w-full bg-blue-600 text-white py-2 rounded hover:bg-blue-700&#8243;>ログイン&lt;/button>
      &lt;/form>
    &lt;/div>
  );
}</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">use client</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">useState</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">react</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">signIn</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth/react</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">default</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">function</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">SignInForm</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">userId</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">setUserId</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">useState</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">password</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">setPassword</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">useState</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">errorMsg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">setErrorMsg</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">useState</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">handleSubmit</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">e</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> React</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">FormEvent</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">e</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">preventDefault</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">setErrorMsg</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">res</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">signIn</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">credentials</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">redirect</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">false</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">username</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">userId</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #D8DEE9">password</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">res</span><span style="color: #ECEFF4">?.</span><span style="color: #D8DEE9">error</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">setErrorMsg</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">ログインIDまたはパスワードが間違っています</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">res</span><span style="color: #ECEFF4">?.</span><span style="color: #D8DEE9">ok</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #D8DEE9">window</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">location</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">href</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/download</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">setErrorMsg</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">不明なエラーが発生しました</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> (</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;div</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">flex items-center justify-center min-h-screen bg-cover bg-center</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">style</span><span style="color: #81A1C1">={</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">backgroundImage</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">url(&#39;/images/white-background.png&#39;)</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">}&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;form</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">onSubmit</span><span style="color: #81A1C1">={</span><span style="color: #D8DEE9">handleSubmit</span><span style="color: #81A1C1">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">bg-white p-8 rounded shadow-md w-[500px] mx-auto</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;h1</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">text-2xl font-bold mb-6 text-center</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">ログイン</span><span style="color: #81A1C1">&lt;/h1&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;label</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">block mb-4</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #81A1C1">&lt;span</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">block text-gray-700 font-semibold mb-1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">ログインID</span><span style="color: #81A1C1">&lt;/span&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #81A1C1">&lt;input</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">type</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">text</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">value</span><span style="color: #81A1C1">={</span><span style="color: #D8DEE9">userId</span><span style="color: #81A1C1">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">onChange</span><span style="color: #81A1C1">={</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">e</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">setUserId</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">e</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">target</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">value</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">required</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">w-full px-3 py-2 border border-gray-300 rounded</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;/label&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;label</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">block mb-4</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #81A1C1">&lt;span</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">block text-gray-700 font-semibold mb-1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">パスワード</span><span style="color: #81A1C1">&lt;/span&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #81A1C1">&lt;input</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">type</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">password</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">value</span><span style="color: #81A1C1">={</span><span style="color: #D8DEE9">password</span><span style="color: #81A1C1">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">onChange</span><span style="color: #81A1C1">={</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">e</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">setPassword</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">e</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">target</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">value</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">required</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">w-full px-3 py-2 border border-gray-300 rounded</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;/label&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">{</span><span style="color: #D8DEE9">errorMsg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;p</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">text-red-600 text-center mb-4</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;{</span><span style="color: #D8DEE9">errorMsg</span><span style="color: #81A1C1">}&lt;/p&gt;}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">&lt;button</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">type</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">submit</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">w-full bg-blue-600 text-white py-2 rounded hover:bg-blue-700</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">ログイン</span><span style="color: #81A1C1">&lt;/button&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;/form&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;/div&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  )</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc14">未ログイン時のログイン誘導（components/Login.tsx）</span></h2>



<p><strong><strong>ユーザーが未ログインだった場合に、ログインボタンを表示してログイン画面に誘導</strong></strong>する処理です。</p>



<p><strong><span class="keyboard-key">&#x26a0;&#xfe0f; 実装時の注意点</span></strong></p>



<ul class="wp-block-list">
<li><code>useSession()</code> を使うには、呼び出し元が <code>SessionProvider</code> 配下である必要があります。</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>&#8220;use client&#8221;;
import { signIn } from &#8220;next-auth/react&#8221;;
export default function Login() {
  return (
    &lt;div className=&#8221;mt-8 text-center&#8221;>
      &lt;button
        className=&#8221;text-blue-600 underline&#8221;
        onClick={() => signIn(undefined, { callbackUrl: &#8220;/auth/signin&#8221; })}
      >
        &#x1f512; 管理者ログインはこちら
      &lt;/button>
    &lt;/div>
  );
}
</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">use client</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">signIn</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next-auth/react</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">default</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">function</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Login</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> (</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;div</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">mt-8 text-center</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;button</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">className</span><span style="color: #81A1C1">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">text-blue-600 underline</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">onClick</span><span style="color: #81A1C1">={</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">signIn</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">undefined</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">callbackUrl</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/auth/signin</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        &#x1f512; 管理者ログインはこちら</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">&lt;/button&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">&lt;/div&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  )</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc15">実行画面</span></h2>



<p>下記のリンク押下で、ログイン画面が表示される</p>



<figure class="wp-block-image size-large has-custom-border"><img loading="lazy" decoding="async" width="1024" height="86" src="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.06-1024x86.png" alt="Next.jsでログイン機能を実装｜NextAuth.jsでID・パスワード認証対応" class="wp-image-3668" style="border-width:1px" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.06-1024x86.png 1024w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.06-300x25.png 300w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.06-768x64.png 768w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.06.png 1360w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p>ログインID・パスワードを入力</p>



<figure class="wp-block-image size-large has-custom-border"><img loading="lazy" decoding="async" width="1024" height="595" src="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.20-1024x595.png" alt="Next.jsでログイン機能を実装｜NextAuth.jsでID・パスワード認証対応" class="wp-image-3669" style="border-width:1px" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.20-1024x595.png 1024w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.20-300x174.png 300w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.20-768x447.png 768w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.20.png 1424w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p>ログイン完了したら、管理者画面が表示される（この画面のコードはなし）</p>



<figure class="wp-block-image size-large has-custom-border"><img loading="lazy" decoding="async" width="1024" height="282" src="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.39-1024x282.png" alt="Next.jsでログイン機能を実装｜NextAuth.jsでID・パスワード認証対応" class="wp-image-3670" style="border-width:1px" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.39-1024x282.png 1024w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.39-300x83.png 300w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.39-768x212.png 768w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.39-1536x424.png 1536w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-26-18.09.39.png 1646w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="てんハロ運営者" class="speech-icon-image"/></figure><div class="speech-name">てんハロ運営者</div></div><div class="speech-balloon">
<p>おつかれさまでした！</p>
</div></div>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-together is-style-default">
<a href="https://it-bokenki.com/2025/06/16/use-client/" title="Next.jsの「use client」とは？サーバーコンポーネントとクライアントコンポーネントの違い" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://it-bokenki.com/wp-content/uploads/2025/06/２行-12-320x180.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/２行-12-320x180.png 320w, https://it-bokenki.com/wp-content/uploads/2025/06/２行-12-120x68.png 120w, https://it-bokenki.com/wp-content/uploads/2025/06/２行-12-160x90.png 160w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">Next.jsの「use client」とは？サーバーコンポーネントとクライアントコンポーネントの違い</div><div class="blogcard-snippet internal-blogcard-snippet">Next.jsの &quot;use client&quot; の意味と、サーバー・クライアントコンポーネントの違いを初心者向けに解説します。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">it-bokenki.com</div></div></div></div></a>
<p></p>
</div>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<div style="height:0px" aria-hidden="true" class="wp-block-spacer"></div><p>The post <a href="https://it-bokenki.com/2025/06/26/nextauth-js/">Next.jsでログイン機能を実装｜NextAuth.jsでID・パスワード認証対応</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://it-bokenki.com/2025/06/26/nextauth-js/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>メール配信の強い味方「SendGrid」を徹底解説！</title>
		<link>https://it-bokenki.com/2025/06/11/what-is-sendgrid/</link>
					<comments>https://it-bokenki.com/2025/06/11/what-is-sendgrid/#respond</comments>
		
		<dc:creator><![CDATA[てんハロ運営者]]></dc:creator>
		<pubDate>Wed, 11 Jun 2025 02:15:57 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[バックエンド]]></category>
		<category><![CDATA[Next.js]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[SendGrid]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[自動送信メール]]></category>
		<guid isPermaLink="false">https://it-bokenki.com/?p=2872</guid>

					<description><![CDATA[<p>でじぼうです。 メール配信を専門に行なってくれるAPI「SendGrid」についてご説明します。 SendGridって、そもそも何？ SendGridは、メール送信用のクラウドサービス（SaaS）です。RESTful A [&#8230;]</p>
<p>The post <a href="https://it-bokenki.com/2025/06/11/what-is-sendgrid/">メール配信の強い味方「SendGrid」を徹底解説！</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>でじぼうです。</p>



<p>メール配信を専門に行なってくれるAPI「SendGrid」についてご説明します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="でじぼう" class="speech-icon-image"/></figure><div class="speech-name">でじぼう</div></div><div class="speech-balloon">
<p>この記事は下記の方がおすすめ！<br></p>



<ul class="wp-block-list">
<li style="font-size:15px">SendGridってなに？</li>



<li style="font-size:15px">Makeってなに？</li>



<li style="font-size:15px">API×ローコードツールの実装方法が知りたい！</li>
</ul>
</div></div>



<div style="text-align: center;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3TB6RG+C3TBLE+4RIG+BYT9D">
<img loading="lazy" decoding="async" border="0" width="468" height="60" alt="" src="https://www26.a8.net/svt/bgt?aid=230629372732&#038;wid=001&#038;eno=01&#038;mid=s00000022228002010000&#038;mc=1"></a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www16.a8.net/0.gif?a8mat=3TB6RG+C3TBLE+4RIG+BYT9D" alt=""></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc1">SendGridって、そもそも何？</span></h2>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="500" height="200" src="https://it-bokenki.com/wp-content/uploads/2025/06/4-1.png" alt="SendGridでのメール配信の仕組みを示す図" class="wp-image-2925" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/4-1.png 500w, https://it-bokenki.com/wp-content/uploads/2025/06/4-1-300x120.png 300w" sizes="auto, (max-width: 500px) 100vw, 500px" /></figure>



<p>SendGridは、<strong>メール送信用のクラウドサービス（SaaS</strong>）です。<br>RESTful API や SMTP を使って、Webサービスやアプリケーションから簡単にメールを送信できます。</p>



<p>たとえば、お問い合わせフォームや会員登録後の自動返信メールを、SendGrid経由で確実にユーザーへ届けることができます。</p>



<p>アプリ側では、宛先や本文をSendGridに渡すだけで、あとはSendGridが送信処理を代行してくれる仕組みです。<br></p>



<div class="wp-block-cocoon-blocks-tab-box-1 blank-box bb-tab bb-memo block-box">
<p class="has-small-font-size"><span class="marker">SaaS（サース）</span>：完成されたアプリをインターネット経由で利用できるサービス<br><span class="marker">RESTful API</span>：Webサービス同士がデータをやり取りするための「決まりごと」に基づいた通信方法<br><span class="marker">SMTP</span>：メールを送信するための通信ルール（プロトコル）のひとつ</p>
</div>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">なぜSendGridを使うの？（エンジニア的メリット）</span></h2>



<p>「メール配信くらい自分でプログラム書けばいいんじゃない？」と思う方もいるかもしれません。でも、実はSendGridを使うことには、エンジニアにとってたくさんのメリットがあるんです。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading has-ex-e-background-color has-background"><span id="toc3">メリット1：メールの「到達率」が格段に上がる！</span></h3>



<p>自分でメールサーバーを立ててメールを送ろうとすると、送信元IPアドレスの評価が悪くて迷惑メール扱いされてしまったり、受信側のサーバーからブロックされてしまったりすることがよくあります。</p>



<p>SendGridは、長年の運用実績と高い技術力で、<span class="marker-under"><strong>メールが「迷惑メール」として扱われにくく、高い確率でユーザーの受信トレイに届く</strong></span>ように工夫されています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading has-ex-e-background-color has-background"><span id="toc4">メリット2：大量のメール配信も楽々！</span></h3>



<p>キャンペーンメールやニュースレターなど、一度に数千、数万といった大量のメールを送りたい場合、自分でシステムを組むのは非常に大変です。処理に時間がかかったり、サーバーがダウンしてしまったりするリスクもあります。</p>



<p>SendGridは、<span class="marker-under"><strong>大量のメールを高速かつ安定して配信できるインフラ</strong></span>を持っています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading has-ex-e-background-color has-background"><span id="toc5">メリット3：開発コスト・運用コストが大幅に削減できる！</span></h3>



<p>もし自分でメール配信システムをゼロから作るとしたら、</p>



<p>◆ メールサーバーの構築・設定<br>◆ 迷惑メール対策<br>◆ エラーハンドリング<br>◆ 配信状況の監視<br>◆ セキュリティ対策</p>



<p>など、やるべきことが山積みです。これらをすべて自前で実装・運用するのは、時間も労力も莫大にかかります。</p>



<p>利用すれば、<span class="marker-under"><strong>これらの面倒な作業をすべてSendGridに任せることができます</strong></span><strong>。</strong></p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc6">SendGrid の仕組みをざっくり理解しよう！</span></h2>



<p>SendGridを使ったメール配信の基本的な流れは以下のようになります。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading has-ex-e-background-color has-background"><span id="toc7">① アプリケーションからSendGridへメールを送信する</span></h3>



<p>SendGridが提供するAPI（HTTPリクエスト）を使ってメールの内容（宛先、件名、本文など）をSendGridに送ります。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading has-ex-e-background-color has-background"><span id="toc8">② SendGridがメールを受け取る</span></h3>



<p>SendGridは受け取ったメールの内容を解析し、適切な処理を行います。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading has-ex-e-background-color has-background"><span id="toc9">③ SendGridがユーザーのメールサーバーへメールを送信する</span></h3>



<p>SendGridは、迷惑メールと判断されないように様々な工夫を凝らしながら、ユーザーが使っているメールサービス（Gmail, Outlookなど）のサーバーへメールを送ります。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading has-ex-e-background-color has-background"><span id="toc10">④ ユーザーのメールサーバーがメールを受信する</span></h3>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading has-ex-e-background-color has-background"><span id="toc11">⑤ ユーザーの受信トレイにメールが届く！</span></h3>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-reference-link is-style-normal-card">
<a href="https://it-bokenki.com/2025/06/11/sendgrid-smtp-setup/" title="SendGrid で自動返信メールを送信する方法" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://it-bokenki.com/wp-content/uploads/2025/06/2-320x180.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/2-320x180.png 320w, https://it-bokenki.com/wp-content/uploads/2025/06/2-120x68.png 120w, https://it-bokenki.com/wp-content/uploads/2025/06/2-160x90.png 160w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">SendGrid で自動返信メールを送信する方法</div><div class="blogcard-snippet internal-blogcard-snippet">SendGridの基本からAPI連携による自動返信メールの実装方法までを徹底解説。Next.jsとの組み合わせで高到達率なメール配信をご説明します。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">it-bokenki.com</div></div></div></div></a>
<p></p>
</div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div style="height:0px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading has-cocoon-white-background-color has-background"><span id="toc12">API連携の実装方法</span></h2>



<p><span class="marker-under"><strong>簡単にメールを送信できる公式APIが提供</strong></span>されています。Java、Python、Ruby、Node.js、PHPなど、主要なプログラミング言語に対応しています。</p>



<p>今回下記のように、お問い合わせ時の自動返信メールを<code>Node.js</code>で実装しました。<br>環境変数は <code>.env</code> ファイルに定義し、以下の2項目を読み込んで使用しています。</p>



<figure class="wp-block-table is-style-stripes"><table class="has-fixed-layout"><thead><tr><th>環境変数項目</th><th>値</th></tr></thead><tbody><tr><td>SENDGRID_API_KEY</td><td>SendGridで発行したAPIキー</td></tr><tr><td>SENDGRID_FROM_EMAIL</td><td>自動返信メールの送信元メールアドレス</td></tr></tbody></table></figure>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>import { NextResponse } from &#8220;next/server&#8221;;
import sgMail from &#8220;@sendgrid/mail&#8221;;

export async function POST(req: Request) {
  const data = await req.json();
  const { name, email, phone, message } = data;

  // 自動送信メールの件名と本文
  const subject = &#8220;お問い合わせありがとうございます&#8221;;
  const mailBody = `${name}様

  このたびはお問い合わせいただき、誠にありがとうございます。
  以下の内容で受付いたしました。
  
  &#8212;&#8212;&#8212;&#8212;&#8212;

  お名前： ${name}
  メール： ${email}
  電話番号： ${phone}
  メッセージ： 
  ${message}

  &#8212;&#8212;&#8212;&#8212;&#8212;

  担当より折り返しご連絡させていただきます。
  今しばらくお待ちください。`;

  try {
    // 自動送信メール
    sgMail.setApiKey(process.env.SENDGRID_API_KEY!);
    await sgMail.send({
      from: process.env.SENDGRID_FROM_EMAIL!,
      to: email,
      subject,
      text: mailBody,
    });

    return NextResponse.json({ message: &#8220;メール送信成功&#8221; });
  } catch (error) {
    return NextResponse.json(
      { message: &#8220;Slack送信に失敗しました&#8221; },
      { status: 500 }
    );
  }
}
</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">NextResponse</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">next/server</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">sgMail</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">@sendgrid/mail</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">function</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">POST</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">req</span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> Request</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">data</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">req</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">json</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">name</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">email</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">phone</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">message</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">data</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// 自動送信メールの件名と本文</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">subject</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">お問い合わせありがとうございます</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mailBody</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">`</span><span style="color: #81A1C1">${</span><span style="color: #D8DEE9">name</span><span style="color: #81A1C1">}</span><span style="color: #A3BE8C">様</span></span>
<span class="line"></span>
<span class="line"><span style="color: #A3BE8C">  このたびはお問い合わせいただき、誠にありがとうございます。</span></span>
<span class="line"><span style="color: #A3BE8C">  以下の内容で受付いたしました。</span></span>
<span class="line"><span style="color: #A3BE8C">  </span></span>
<span class="line"><span style="color: #A3BE8C">  ---------------</span></span>
<span class="line"></span>
<span class="line"><span style="color: #A3BE8C">  お名前： </span><span style="color: #81A1C1">${</span><span style="color: #D8DEE9">name</span><span style="color: #81A1C1">}</span></span>
<span class="line"><span style="color: #A3BE8C">  メール： </span><span style="color: #81A1C1">${</span><span style="color: #D8DEE9">email</span><span style="color: #81A1C1">}</span></span>
<span class="line"><span style="color: #A3BE8C">  電話番号： </span><span style="color: #81A1C1">${</span><span style="color: #D8DEE9">phone</span><span style="color: #81A1C1">}</span></span>
<span class="line"><span style="color: #A3BE8C">  メッセージ： </span></span>
<span class="line"><span style="color: #A3BE8C">  </span><span style="color: #81A1C1">${</span><span style="color: #D8DEE9">message</span><span style="color: #81A1C1">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #A3BE8C">  ---------------</span></span>
<span class="line"></span>
<span class="line"><span style="color: #A3BE8C">  担当より折り返しご連絡させていただきます。</span></span>
<span class="line"><span style="color: #A3BE8C">  今しばらくお待ちください。</span><span style="color: #ECEFF4">`</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">try</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// 自動送信メール</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">sgMail</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">setApiKey</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">process</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">env</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">SENDGRID_API_KEY</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sgMail</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">send</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">from</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">process</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">env</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">SENDGRID_FROM_EMAIL</span><span style="color: #81A1C1">!</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">to</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">email</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #D8DEE9">subject</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">text</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mailBody</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NextResponse</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">json</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">message</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">メール送信成功</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">catch</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">error</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NextResponse</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">json</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">message</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Slack送信に失敗しました</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">status</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">500</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    )</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p></p><p>The post <a href="https://it-bokenki.com/2025/06/11/what-is-sendgrid/">メール配信の強い味方「SendGrid」を徹底解説！</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://it-bokenki.com/2025/06/11/what-is-sendgrid/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>SendGrid で自動返信メールを送信する方法</title>
		<link>https://it-bokenki.com/2025/06/11/sendgrid-smtp-setup/</link>
					<comments>https://it-bokenki.com/2025/06/11/sendgrid-smtp-setup/#respond</comments>
		
		<dc:creator><![CDATA[てんハロ運営者]]></dc:creator>
		<pubDate>Wed, 11 Jun 2025 02:18:18 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[バックエンド]]></category>
		<category><![CDATA[開発事例]]></category>
		<category><![CDATA[make]]></category>
		<category><![CDATA[Next.js]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[SendGrid]]></category>
		<category><![CDATA[SMTP]]></category>
		<category><![CDATA[ローコードツール]]></category>
		<category><![CDATA[自動送信メール]]></category>
		<guid isPermaLink="false">https://it-bokenki.com/?p=2850</guid>

					<description><![CDATA[<p>でじぼうです。 API：SendGridと、ローコードツール：Makeをかけ合わせた自動返信メールを送信する方法についてご説明します。 SendGridとは？ 「メール配信を専門に行ってくれるクラウドサービス（SaaS） [&#8230;]</p>
<p>The post <a href="https://it-bokenki.com/2025/06/11/sendgrid-smtp-setup/">SendGrid で自動返信メールを送信する方法</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<p></p>



<p>でじぼうです。</p>



<p>API：SendGridと、ローコードツール：Makeをかけ合わせた自動返信メールを送信する方法についてご説明します。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="でじぼう" class="speech-icon-image"/></figure><div class="speech-name">でじぼう</div></div><div class="speech-balloon">
<p>この記事は下記の方がおすすめ！<br></p>



<ul class="wp-block-list">
<li style="font-size:15px">SendGridってなに？</li>



<li style="font-size:15px">Makeってなに？</li>



<li style="font-size:15px">API×ローコードツールの実装方法が知りたい！</li>
</ul>
</div></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div style="text-align: center;">
<a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3TB6RG+C3TBLE+4RIG+BYT9D">
<img loading="lazy" decoding="async" border="0" width="468" height="60" alt="" src="https://www26.a8.net/svt/bgt?aid=230629372732&#038;wid=001&#038;eno=01&#038;mid=s00000022228002010000&#038;mc=1"></a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www16.a8.net/0.gif?a8mat=3TB6RG+C3TBLE+4RIG+BYT9D" alt="">
</div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc1">SendGridとは？</span></h2>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="500" height="200" src="https://it-bokenki.com/wp-content/uploads/2025/06/4.png" alt="SendGrid" class="wp-image-2870" style="width:445px;height:auto" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/4.png 500w, https://it-bokenki.com/wp-content/uploads/2025/06/4-300x120.png 300w" sizes="auto, (max-width: 500px) 100vw, 500px" /></figure>



<p><strong>「メール配信を専門に行ってくれるクラウドサービス（SaaS）」</strong> です。</p>



<p>開発したWebサービスやアプリケーションからSendGridにメールを送るように設定するだけで、SendGridがそのメールをユーザーに届けてくれます。</p>



<div class="wp-block-cocoon-blocks-tab-box-1 blank-box bb-tab bb-memo block-box">
<p class="has-small-font-size"><span class="marker">SaaS（サース）</span>：完成されたアプリをインターネット経由で利用できるサービス</p>
</div>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-reference-link is-style-normal-card">
<a href="https://it-bokenki.com/2025/06/11/what-is-sendgrid/" title="メール配信の強い味方「SendGrid」を徹底解説！" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://it-bokenki.com/wp-content/uploads/2025/06/1-320x180.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/1-320x180.png 320w, https://it-bokenki.com/wp-content/uploads/2025/06/1-120x68.png 120w, https://it-bokenki.com/wp-content/uploads/2025/06/1-160x90.png 160w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">メール配信の強い味方「SendGrid」を徹底解説！</div><div class="blogcard-snippet internal-blogcard-snippet">SendGridとは何かを初心者向けにわかりやすく解説。メール配信APIの仕組みや使い方、Webアプリとの連携方法を紹介します。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">it-bokenki.com</div></div></div></div></a>
<p></p>
</div>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc2">Makeとは？</span></h2>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="500" height="200" src="https://it-bokenki.com/wp-content/uploads/2025/06/3.png" alt="make" class="wp-image-2869" style="width:408px;height:auto" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/3.png 500w, https://it-bokenki.com/wp-content/uploads/2025/06/3-300x120.png 300w" sizes="auto, (max-width: 500px) 100vw, 500px" /></figure>



<p>「<strong>ノーコードでさまざまなWebサービスを自動連携できるプラットフォーム（iPaaS）」です。</strong><br><br>Gmail、Slack、Google Sheets、Notionなどと連携し、ワークフローを視覚的に構築可能。<br>エンジニアでなくても効率的な自動化が行えます。<br></p>



<div class="wp-block-cocoon-blocks-tab-box-1 blank-box bb-tab bb-memo block-box">
<p class="has-small-font-size"><span class="marker">iPaaS（アイパース）</span>＝いろんなWebサービスをつなぐ橋渡し役</p>
</div>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc3">なぜ SendGrid × Makeで実装？</span></h2>



<p>もともと <span class="marker-under"><strong>フロントエンド × バックエンドAPI × Make</strong></span> を使ってお問い合わせフォームを実装していました。次のステップとして「お問い合わせをしてくれた方へ自動返信メールを送る機能」を追加することにしました。</p>



<p class="has-text-align-center"><span class="fz-20px"><span class="fz-22px"><span class="fz-24px">前回までの実装内容</span></span></span></p>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="500" height="200" src="https://it-bokenki.com/wp-content/uploads/2025/06/6.png" alt="Make SendGrid" class="wp-image-2899" style="width:704px;height:auto" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/6.png 500w, https://it-bokenki.com/wp-content/uploads/2025/06/6-300x120.png 300w" sizes="auto, (max-width: 500px) 100vw, 500px" /></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h5 class="wp-block-heading"><span>▼ 当初の選択肢：Make × 自前サーバー</span></h5>



<p>まずは自前で契約しているレンタルサーバーを使って実装しようとしましたが、Make のメール送信元である <span class="marker-under"><code>ie.</code><strong>ドメインをそのサーバーが受け付けない仕様であったため、自動返信が正常に動作しないという問題が発生</strong></span>しました。<br></p>



<h5 class="wp-block-heading"><span>▼ 次の選択肢：Make × Googleメール</span></h5>



<p>次に、Gmailを使う方法を検討しましたが、会社独自のドメインでGmailを使うにはGoogle Workspaceの有料契約が必要です。<br>今回はコストをできるだけ抑えたかったため、固定費が発生するこの案は見送りにしました。<br></p>



<h5 class="wp-block-heading"><span>&#x2705; 最終的な選択肢： SendGrid</span></h5>



<p class="has-text-align-center"><span class="fz-20px"><span class="fz-22px"><span class="fz-24px">これから</span>やる実装内容</span></span></p>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="500" height="200" src="https://it-bokenki.com/wp-content/uploads/2025/06/5.png" alt="Make SendGrid" class="wp-image-2900" style="width:700px;height:auto" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/5.png 500w, https://it-bokenki.com/wp-content/uploads/2025/06/5-300x120.png 300w" sizes="auto, (max-width: 500px) 100vw, 500px" /></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>上記のような経緯があり、<span class="marker-under">無料で使えて独自ドメインも対応可能なSendGrid</span>を使うことに決定しました。<br>SendGridであれば、MakeからのSMTP連携も簡単で、自動返信メールも安定して送ることができます。</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><span id="toc4">SendGrid × Make 実装手順</span></h2>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="500" height="200" src="https://it-bokenki.com/wp-content/uploads/2025/06/Make.png" alt="Make SendGrid" class="wp-image-2851" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/Make.png 500w, https://it-bokenki.com/wp-content/uploads/2025/06/Make-300x120.png 300w" sizes="auto, (max-width: 500px) 100vw, 500px" /></figure>



<p>ここからは、実際にSendGridとMakeを使って自動返信メールを実装する手順を紹介していきます。</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc5">① SendGridアカウント作成と会社情報の登録</span></h3>



<p>まずはSendGridのアカウントを作成し、会社情報を登録します。<br>この登録内容の審査には1〜2営業日程度かかるので、余裕を持って申請しておきましょう。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc6">② 承認完了後、マイページにログインする</span></h3>



<p>承認されると、登録したメールアドレス宛に通知が届きます。<br>メールに記載されたリンクから送信者認証を完了させましょう。<br>その後、アカウントIDが発行されるので、事前に設定したパスワードでSendGridにログインします。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc7">③ 送信者情報の登録</span></h3>



<figure class="wp-block-image aligncenter size-full is-resized is-style-default"><img loading="lazy" decoding="async" width="500" height="500" src="https://it-bokenki.com/wp-content/uploads/2025/06/Make-1.png" alt="SendGrid 設定方法" class="wp-image-2853" style="width:478px;height:auto" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/Make-1.png 500w, https://it-bokenki.com/wp-content/uploads/2025/06/Make-1-300x300.png 300w, https://it-bokenki.com/wp-content/uploads/2025/06/Make-1-150x150.png 150w, https://it-bokenki.com/wp-content/uploads/2025/06/Make-1-100x100.png 100w" sizes="auto, (max-width: 500px) 100vw, 500px" /></figure>



<p>左側のDashbord  ＞「Create sender identity」をクリックし、送信者情報を登録します。<br>このとき、<strong><span class="marker-under">送信先・送信元のメールアドレスは同じでも問題ありません</span></strong>。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc8">④ APIキーの作成</span></h3>



<p>左メニューの「<strong><code>Settings ＞ API Keys</code></strong>」から「<strong><code>Create API Key</code></strong>」を選択し、新しいAPIキーを発行します。</p>



<figure class="wp-block-image size-large has-custom-border"><img loading="lazy" decoding="async" width="1024" height="726" src="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-16.56.40-1024x726.png" alt="SendGrid 設定方法" class="wp-image-2855" style="border-width:1px" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-16.56.40-1024x726.png 1024w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-16.56.40-300x213.png 300w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-16.56.40-768x545.png 768w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-16.56.40.png 1390w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-table is-style-stripes"><table class="has-fixed-layout"><thead><tr><th>設定項目</th><th>設定内容</th></tr></thead><tbody><tr><td>API Key Name</td><td>任意の名前（例：Make用自動返信）</td></tr><tr><td>API Key Permissions</td><td><code>Full Access</code><br>（または&nbsp;<code>Restricted Access</code>&nbsp;→&nbsp;<code>Mail Send</code>&nbsp;にチェック）</td></tr></tbody></table></figure>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p>「<code>Create &amp; View Key</code>」をクリックするとAPIキーが表示されます。<br><strong><span class="marker-under">このタイミングでしかコピーできない</span></strong>ので、忘れずに控えておきましょう。<br>後ほどMakeのSMTP接続設定で、このAPIキーをパスワードとして使います。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc9">⑤ MakeでのSMTP接続設定方法</span></h3>



<p>Makeで「<code>Send an Email</code>」モジュールを追加し、以下の情報で新規<code>Connection</code>を作成します。</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="800" height="882" src="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-17.04.46.png" alt="Make Email設定方法" class="wp-image-2856" style="width:376px;height:auto" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-17.04.46.png 800w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-17.04.46-272x300.png 272w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-17.04.46-768x847.png 768w" sizes="auto, (max-width: 800px) 100vw, 800px" /></figure>



<figure class="wp-block-table is-style-stripes"><table class="has-fixed-layout"><thead><tr><th>設定項目</th><th>設定内容</th></tr></thead><tbody><tr><td>Connection type</td><td>Other（SMTP)</td></tr><tr><td>Connection name</td><td>任意の名前（例：SendGrid SMTP）</td></tr><tr><td>Email provider</td><td>Other</td></tr><tr><td>Email address</td><td>自動送信メールを送る主のメールアドレス</td></tr><tr><td>Your full name</td><td>会社名等</td></tr><tr><td>SMTP server</td><td>smtp.sendgrid.netを入力</td></tr><tr><td>Port</td><td><code>587</code>（推奨）または&nbsp;<code>465</code>（SSL）</td></tr><tr><td>Use a secure connection (TLS)</td><td>YES</td></tr><tr><td>Use explicit TLS</td><td>NO</td></tr><tr><td>User name</td><td>apikeyと文字を入力</td></tr><tr><td>Password</td><td>SendGridで生成したAPIキーを入力</td></tr></tbody></table></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc10">⑥ Fromアドレスの設定（詳細設定）</span></h3>



<p>SMTP設定が完了したら、次に<span class="marker-under"><strong>送信元メールアドレス（From）を設定</strong></span>します。<br>これはMakeの「<strong><code>Show advanced settings</code></strong>」をONにすることで表示される詳細設定欄にあります。<br>ここに正しいFromアドレスを入力しないと、メールが正しく送信できなかったり、送信者名が表示されなかったりします。<br><br>下記の写真は「<code>Show advanced settings</code>」がOFFになっている状態</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img loading="lazy" decoding="async" width="617" height="1024" src="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-17.09.54-617x1024.png" alt="Make Email設定方法" class="wp-image-2858" style="width:357px;height:auto" srcset="https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-17.09.54-617x1024.png 617w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-17.09.54-181x300.png 181w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-17.09.54-768x1275.png 768w, https://it-bokenki.com/wp-content/uploads/2025/06/スクリーンショット-2025-06-10-17.09.54.png 884w" sizes="auto, (max-width: 617px) 100vw, 617px" /></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc11">⑦ コードの実装</span></h3>



<p>今回下記のように、<ruby><code><rt>Node.js</rt></code></ruby>で実装しました。<br>環境変数は <code>.env</code> ファイルに定義し、以下を読み込んで使用しています。</p>



<figure class="wp-block-table is-style-stripes"><table class="has-fixed-layout"><thead><tr><th>環境変数項目</th><th>値</th></tr></thead><tbody><tr><td>SLACK_WEBHOOK_URL</td><td>Makeとの連携URL</td></tr></tbody></table></figure>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Makeとの連携URLを設定して、Makeに送りたいお問い合わせ情報（name , email , phone, message)を設定します。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>await fetch(process.env.SLACK_WEBHOOK_URL!, {
  method: &#8220;POST&#8221;,
  headers: {
    &#8220;Content-Type&#8221;: &#8220;application/json&#8221;,
  },
  body: JSON.stringify({
    name,
    email,
    phone,
    message,
  }),
});
</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">fetch</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">process</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">env</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">SLACK_WEBHOOK_URL</span><span style="color: #81A1C1">!</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">method</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">POST</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">headers</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Content-Type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">application/json</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">body</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">JSON</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">stringify</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">name</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">email</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">phone</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">message</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc12">⑧ 設定完了</span></h3>



<p>送信者認証とSMTPの接続設定がすべて完了すると、Make上で自動返信メールが送信できるようになります。<br>これで、お問い合わせをしてくれた方に、即座に確認メールを送る仕組みが完成です。</p><p>The post <a href="https://it-bokenki.com/2025/06/11/sendgrid-smtp-setup/">SendGrid で自動返信メールを送信する方法</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://it-bokenki.com/2025/06/11/sendgrid-smtp-setup/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Linuxコマンド一覧</title>
		<link>https://it-bokenki.com/2023/05/25/linux-command/</link>
					<comments>https://it-bokenki.com/2023/05/25/linux-command/#respond</comments>
		
		<dc:creator><![CDATA[てんハロ運営者]]></dc:creator>
		<pubDate>Thu, 25 May 2023 01:07:44 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[バックエンド]]></category>
		<guid isPermaLink="false">https://it-bokenki.com/?p=797</guid>

					<description><![CDATA[<p>Linuxの基礎を学びたい方や効率的なコマンドの使い方を知りたい方にとって必読です。コマンド操作の力を身につけて、Linuxのパワフルな機能を最大限に活用しましょう。</p>
<p>The post <a href="https://it-bokenki.com/2023/05/25/linux-command/">Linuxコマンド一覧</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>こんにちは、でじぼうです。</p>



<p>この記事では、<strong>Linuxでよく使われるコマンド</strong>をまとめました。</p>



<p>Linuxの基礎を学びたい方や効率的なコマンドの使い方を知りたい方にとって、この記事は必読です。コマンド操作の力を身につけて、Linuxのパワフルな機能を最大限に活用しましょう。</p>



<div style="text-align: center;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=457GS5+AI29WY+E0Q+1BPOF5">
<img loading="lazy" decoding="async" border="0" width="468" height="60" alt="" src="https://www24.a8.net/svt/bgt?aid=250611125635&#038;wid=001&#038;eno=01&#038;mid=s00000001817008014000&#038;mc=1"></a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www11.a8.net/0.gif?a8mat=457GS5+AI29WY+E0Q+1BPOF5" alt=""></div>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc1">コマンドとは</span></h2>



<p><strong>コマンドは、オペレーティングシステムで使われる命令のこと</strong>です。</p>



<p>詳しくはこちらの記事をご覧ください。</p>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-related">
<a href="https://it-bokenki.com/2023/06/29/%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e5%85%a5%e9%96%80/" title="ターミナル初心者のためのコマンド入門ガイド" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://it-bokenki.com/wp-content/uploads/cocoon-resources/blog-card-cache/2a4ac94c3ab58a282f9d9cda62d777c9.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">ターミナル初心者のためのコマンド入門ガイド</div><div class="blogcard-snippet external-blogcard-snippet">ターミナルは初心者にとって少し怖い存在かもしれませんが、このガイドでは基本的なコマンドの使い方を丁寧に解説します。</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com/2023/06/29/command-introduction/" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">it-bokenki.com</div></div></div></div></a>
</div>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc2">最低限覚えたいLinuxコマンド</span></h2>



<h3 class="wp-block-heading"><span id="toc3">ディレクトリ・ファイル操作コマンド</span></h3>



<p><span class="marker-blue"><span class="bold">rm</span></span> &#8211; ファイルやディレクトリを削除する </p>



<p><span class="marker-blue"><span class="bold">cp</span></span> &#8211; ファイルやディレクトリをコピーする </p>



<p><span class="bold"><span class="marker-blue">mv</span></span> &#8211; ファイルやディレクトリを移動する </p>



<p><span class="marker-blue"><span class="bold">diff</span></span> &#8211; ファイルやディレクトリの差分を表示する</p>



<p><span class="marker-blue"><span class="bold">tar</span></span> &#8211; ファイルやディレクトリをアーカイブする</p>



<p><span class="bold"><span class="marker-blue">zip</span></span> &#8211; ファイルやディレクトリをZIP形式で圧縮する</p>



<p><span class="bold"><span class="marker-blue">find</span></span> &#8211; ファイルやディレクトリを検索する</p>



<p><span class="bold"><span class="marker-blue">locate</span></span> &#8211; ファイルやディレクトリのパスを高速に検索する</p>



<h3 class="wp-block-heading"><span id="toc4">ディレクトリ操作コマンド</span></h3>



<p><span class="marker-blue"><span class="bold">ls</span></span> &#8211; ディレクトリの内容を表示する </p>



<p><span class="marker-blue"><span class="bold">cd</span></span> &#8211; ディレクトリを移動する </p>



<p><span class="marker-blue"><span class="bold">pwd</span></span> &#8211; 現在のディレクトリのパスを表示する </p>



<p><span class="marker-blue"><span class="bold">mkdir</span></span> &#8211; ディレクトリを作成する</p>



<p><span class="bold"><span class="marker-blue">rmdir</span></span> &#8211; ディレクトリを削除する（中身が空の場合に限る）</p>



<p><span class="marker-blue"><span class="bold">tree</span></span> &#8211; ディレクトリのツリー構造を表示する</p>



<p><span class="marker-blue"><span class="bold">du</span></span> &#8211; ディスク使用量を表示する</p>



<div style="text-align: center;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=457GS5+AI29WY+E0Q+1BPOF5">
<img loading="lazy" decoding="async" border="0" width="468" height="60" alt="" src="https://www24.a8.net/svt/bgt?aid=250611125635&#038;wid=001&#038;eno=01&#038;mid=s00000001817008014000&#038;mc=1"></a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www11.a8.net/0.gif?a8mat=457GS5+AI29WY+E0Q+1BPOF5" alt=""></div>



<p class="has-text-align-center"><img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www16.a8.net/0.gif?a8mat=3T8UQ0+1E0FLE+3TVC+I05C1" alt=""></p>



<h3 class="wp-block-heading"><span id="toc5">ファイル操作コマンド</span></h3>



<p><span class="bold"><span class="marker-blue">head</span></span> &#8211; ファイルの先頭部分を表示する</p>



<p><span class="bold"><span class="marker-blue">tail</span></span> &#8211; ファイルの末尾部分を表示する</p>



<p><span class="bold"><span class="marker-blue">less</span></span> &#8211; ファイルの内容をページ単位で表示する</p>



<p><span class="marker-blue"><strong>wc</strong></span> &#8211; ファイルの行数や単語数、バイト数を数える</p>



<p><span class="marker-blue"><strong>file</strong></span> &#8211; ファイルの種類を判別する</p>



<p><span class="marker-blue"><span class="bold">touch</span></span> &#8211; 空のファイルを作成する </p>



<p><span class="bold"><span class="marker-blue">cat</span></span> &#8211; ファイルの内容を表示する </p>



<p><span class="bold"><span class="marker-blue">grep</span></span> &#8211; ファイル内からパターンにマッチする行を検索する</p>



<p><span class="marker-blue"><strong>sed</strong></span> &#8211; テキストの置換や編集を行う</p>



<p><span class="marker-blue"><strong>awk</strong></span> &#8211; テキスト処理のためのパターンスキャンと操作を行う</p>



<p><span class="marker-blue"><strong>sort</strong></span> &#8211; ファイルの行をソートする</p>



<p><span class="marker-blue"><strong>uniq</strong></span> &#8211; ソートされたファイルから重複した行を削除する</p>



<h3 class="wp-block-heading"><span id="toc6">パーミッションと所有者の操作コマンド</span></h3>



<p><span class="bold"><span class="marker-blue">chmod</span></span> &#8211; ファイルやディレクトリのパーミッション（アクセス権限）を変更する </p>



<p><span class="bold"><span class="marker-blue">chown</span></span> &#8211; ファイルやディレクトリの所有者を変更する</p>



<p><span class="marker-blue"><strong>chgrp</strong></span> &#8211; ファイルやディレクトリのグループを変更する</p>



<p><span class="marker-blue"><strong>umask</strong></span> &#8211; 新しく作成されるファイルのパーミッションの既定値を設定する</p>



<p class="has-cyan-bluish-gray-color has-text-color" style="font-size:15px">※パーミッション : コンピュータやオペレーティングシステムでのアクセス権限や許可を指す</p>



<h3 class="wp-block-heading"><span id="toc7">リモート接続と管理コマンド</span></h3>



<p><span class="bold"><span class="marker-blue">ssh</span></span> &#8211; リモートサーバーにセキュアシェル接続する </p>



<p><span class="bold"><span class="marker-blue">sudo</span></span> &#8211; スーパーユーザー権限でコマンドを実行する</p>



<p><span class="marker-blue"><strong>scp</strong></span> &#8211; ローカルとリモート間でファイルをコピーする</p>



<p><span class="marker-blue"><strong>rsync</strong></span> &#8211; ファイルやディレクトリをローカルとリモート間で同期する</p>



<p><span class="marker-blue"><strong>sftp</strong></span> &#8211; ファイルの転送や操作を行うために安全なFTPセッションを確立する</p>



<p><span class="marker-blue"><strong>ssh-keygen</strong></span> &#8211; SSH鍵の生成や管理を行う</p>



<p><span class="marker-blue"><strong>systemctl</strong></span> &#8211; サービスの管理と制御を行う</p>



<p><strong><span class="marker-blue">ifconfig</span></strong> &#8211; ネットワークインターフェースの情報を表示する</p>



<p><strong><span class="marker-blue">ping</span></strong> &#8211; ネットワークホストに対してICMPエコーリクエストを送信し、応答を確認する</p>



<p><span class="marker-blue"><strong>traceroute</strong></span> &#8211; パケットがネットワーク上をたどる経路を表示する</p>



<div style="text-align: center;"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T91U0+CZYQ9E+529E+5ZMCH">
<img loading="lazy" decoding="async" border="0" width="300" height="250" alt="" src="https://www23.a8.net/svt/bgt?aid=230529672786&#038;wid=001&#038;eno=01&#038;mid=s00000023621001006000&#038;mc=1"></a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www13.a8.net/0.gif?a8mat=3T91U0+CZYQ9E+529E+5ZMCH" alt=""></div>



<p class="has-text-align-center"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T8UPY+FDP5DE+50+2HCY6Q">【早い者勝ち！】 あなたのお名前、残ってる？</a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www12.a8.net/0.gif?a8mat=3T8UPY+FDP5DE+50+2HCY6Q" alt=""></p>



<h3 class="wp-block-heading"><span id="toc8">その他のコマンド</span></h3>



<p><span class="bold"><span class="marker-blue">man</span></span> &#8211; コマンドのマニュアルページを表示する</p>



<p><span class="marker-blue"><strong>curl</strong></span> &#8211; URLからデータを取得する</p>



<p><span class="marker-blue"><strong>wget</strong></span> &#8211; ファイルをWebからダウンロードする</p>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc9">おわりに</span></h2>



<p>これらは一般的によく使われるLinuxコマンドの一部です。</p>



<p>それぞれのコマンドの詳細な使用方法やオプションについては、manページを参照することをおすすめします。</p>



<p class="has-text-align-center"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T8UQ0+HV0XE+3GWO+6C9LD"><br></a> <img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www10.a8.net/0.gif?a8mat=3T8UQ0+HV0XE+3GWO+6C9LD" alt=""></p><p>The post <a href="https://it-bokenki.com/2023/05/25/linux-command/">Linuxコマンド一覧</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://it-bokenki.com/2023/05/25/linux-command/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>コマンドラインシェル入門：LinuxとWindowsシェルの違い</title>
		<link>https://it-bokenki.com/2023/07/01/shell-introduction/</link>
					<comments>https://it-bokenki.com/2023/07/01/shell-introduction/#respond</comments>
		
		<dc:creator><![CDATA[てんハロ運営者]]></dc:creator>
		<pubDate>Sat, 01 Jul 2023 09:10:18 +0000</pubDate>
				<category><![CDATA[シェル]]></category>
		<category><![CDATA[バックエンド]]></category>
		<guid isPermaLink="false">https://it-bokenki.com/?p=2110</guid>

					<description><![CDATA[<p>シェル入門！LinuxとWindowsの違いと開発例を紹介。シェルの基本を学び、開発に役立つ具体的なコマンドを探求しよう。</p>
<p>The post <a href="https://it-bokenki.com/2023/07/01/shell-introduction/">コマンドラインシェル入門：LinuxとWindowsシェルの違い</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>こんにちは、でじぼうです。</p>



<p>コマンドラインシェル入門として、LinuxとWindowsシェルの違いについてご説明します。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="でじぼう" class="speech-icon-image"/></figure><div class="speech-name">でじぼう</div></div><div class="speech-balloon">
<p>この記事は下記の方がおすすめ！<br></p>



<ul class="wp-block-list">
<li style="font-size:15px">コマンドラインシェルってなに？</li>



<li style="font-size:15px">シェルって種類あったような、、</li>



<li style="font-size:15px">LinuxとWindowsシェルの違いがいまいち分からない、、</li>
</ul>
</div></div>



<p class="has-text-align-center"></p>



<p class="has-text-align-center"></p>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc1">コマンドラインシェルとは</span></h2>



<p>コマンドラインシェルは、ユーザーがテキストベースの<span class="bold">インターフェースを通じてPCシステムと対話するためのプログラム</span>です。</p>



<p>ユーザーはコマンドを入力し、コマンドラインシェルはそのコマンドを受け取り、解釈して実行します。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="でじぼう" class="speech-icon-image"/></figure><div class="speech-name">でじぼう</div></div><div class="speech-balloon">
<p>コマンドラインシェル＝シェル</p>



<p>同じものを指していると考えてOK！</p>
</div></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="has-text-align-center"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T8UPY+FDP5DE+50+2HCY6Q">【早い者勝ち！】 あなたのお名前、残ってる？</a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www13.a8.net/0.gif?a8mat=3T8UPY+FDP5DE+50+2HCY6Q" alt=""></p>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc2">コマンドとシェルは意味同じ？違う？</span></h2>



<p><strong><span class="marker-under">コマンドとシェルは同じではありません。</span></strong>コマンドはシェル内で使用されます。</p>



<p class="has-watery-blue-background-color has-background"><strong>コマンド</strong> : 個々の操作やタスクを実行するための命令<br><br><strong>シェル</strong> : コマンドの入力と実行を受け付けるインターフェースや環境のプログラム</p>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="badge-grey"><strong>コマンドの場合</strong></span></p>



<figure class="wp-block-table is-style-regular"><table><tbody><tr><td class="has-text-align-center" data-align="center">　<span class="badge">コマンド</span>　　　</td><td><span class="red">ls</span></td></tr><tr><td class="has-text-align-center" data-align="center"><span class="badge">意味</span></td><td>ディレクトリ内のファイルとディレクトリの一覧を表示する</td></tr><tr><td class="has-text-align-center" data-align="center"><span class="badge">使用例</span></td><td><span class="red">ls </span>-l</td></tr><tr><td class="has-text-align-center" data-align="center">　  <span class="badge">解説</span>　　</td><td>&#8220;ls&#8221;はコマンドであり、現在のディレクトリ内のファイルとディレクトリの一覧を表示します。オプション &#8220;-l&#8221; は詳細な情報（所有者、サイズなど）を表示するための引数です。</td></tr></tbody></table></figure>



<p><span class="badge-grey"><span class="bold">シェルの場合</span></span></p>



<figure class="wp-block-table"><table><tbody><tr><td class="has-text-align-center" data-align="center"><span class="badge">シェル</span></td><td>Bash</td></tr><tr><td class="has-text-align-center" data-align="center"><span class="badge">使用例</span></td><td>$ <span class="red">echo</span> &#8220;<span class="green">Hello, World!</span>&#8220;</td></tr><tr><td class="has-text-align-center" data-align="center">　　<span class="badge">解説</span>　　　　</td><td>Bashシェルを使用してコマンドライン上で &#8220;echo&#8221; コマンドを実行しています。&#8221;echo&#8221; コマンドは引数として与えられたテキストを表示します。この場合、&#8221;Hello, World!&#8221; というテキストが表示されます。</td></tr></tbody></table></figure>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="has-text-align-center"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3TB6RG+CLOBQQ+2PEO+1I4AW1"><br><img loading="lazy" decoding="async" border="0" width="300" height="250" src="https://www29.a8.net/svt/bgt?aid=230629372762&amp;wid=001&amp;eno=01&amp;mid=s00000012624009090000&amp;mc=1" alt=""></a><br><img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www15.a8.net/0.gif?a8mat=3TB6RG+CLOBQQ+2PEO+1I4AW1" alt=""></p>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc3">Linuxシェルの種類</span></h2>



<h3 class="wp-block-heading"><span id="toc4">多機能で柔軟性が高い「Bash」</span></h3>



<p>Bash（Bourne Again Shell）は、Linuxで<strong>最も一般的なシェル</strong>です。Bashはシンタックスが豊富で柔軟性が高く、多くのスクリプトやコマンドが利用できます。</p>



<p class="has-cyan-bluish-gray-color has-text-color" style="font-size:15px">※シンタックス：コンピュータプログラミングや形式言語における文法</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc5">カスタマイズ性がある「Zsh」</span></h3>



<p>Zsh（Z Shell）は、<strong>Bashの拡張版として開発されたオープンソースのUnixシェル</strong>です。Zshには自動補完やテーマのカスタマイズなど、便利な機能が多く組み込まれています。カスタマイズ性が高く、パワーユーザー向けのシェルとして人気があります。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc6">使いやすさに重点を置いた「Fish」</span></h3>



<p>Fish（Friendly Interactive Shell）は、シンプルで使いやすいインタラクティブシェルです。自動補完や予測入力、カラフルな出力など、<strong>ユーザーフレンドリーな機能が特徴</strong>です。<strong>特に初心者におすすめ</strong>です。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="でじぼう" class="speech-icon-image"/></figure><div class="speech-name">でじぼう</div></div><div class="speech-balloon">
<p>それぞれのシェルには異なる特徴があり、使用目的や好みによって選ぶことができる！</p>
</div></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="has-text-align-center"> <img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www18.a8.net/0.gif?a8mat=3TB6RG+D15LGY+2P76+644DT" alt=""></p>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc7">Windowsシェルの種類</span></h2>



<h3 class="wp-block-heading"><span id="toc8">シンプルな「コマンドプロンプト」</span></h3>



<p>コマンドプロンプトは、<strong>Windowsのデフォルトのシェル</strong>です。古くから存在し、基本的なWindowsコマンドやバッチスクリプトを実行するために使用されます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><span id="toc9">機能豊富な「PowerShell」</span></h3>



<p>PowerShellは、<strong>高度なタスクの自動化やスクリプト作成に適した強力なシェル</strong>です。Windowsの管理や自動化に広く使用されています。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc10">各シェルの表現の違い</span></h2>



<p>シェルの種類があるように（Bash・コマンドプロンプトなど）、各シェルには固有のコマンド表現が存在する場合があります。</p>



<p>下記の<span class="marker-blue"><strong> ls </strong></span>コマンドは、ディレクトリ内のファイルやディレクトリの一覧を表示するためのコマンドです。それぞれのシェルの表現の違いを見てみましょう。</p>



<p class="has-ex-c-background-color has-background"><span class="badge-grey"><strong>ファイルやディレクトリの一覧を表示するためのコマンド</strong></span><br><br><strong>Bashの場合</strong>：<span class="red">ls</span><br><br><strong>Zshの場合</strong>：<span class="red">ls</span><br><strong><br>Fishの場合</strong>：<span class="red">ls</span><br><br><strong>コマンドプロンプトの場合</strong>：<span class="red">dir</span><br><br><strong>PowerShellの場合</strong>：<span class="red">Get-ChildItem</span></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc11">LinuxとWindowsのシェルの利用割合</span></h2>



<h3 class="wp-block-heading"><span id="toc12">Linuxシェルの割合</span></h3>



<p class="has-ex-c-background-color has-background"><span class="badge-grey"><strong>利用率割合</strong></span>　<span class="fz-12px">※これらの割合はあくまで推定値です。</span><br><br><strong>Bash</strong> : 約90% <br><br><strong>Zsh</strong> : 約7% <br><br><strong>Fish</strong> : 約3%</p>



<p><span class="badge">理由</span><br>Bashが依然として最も一般的なシェルであり、Linuxのほとんどがデフォルトのシェルとして使用されています。</p>



<p>Zshはカスタマイズ性の高さや拡張性のため、一部のユーザーや開発者によって選択されています。</p>



<p>Fishは初心者にも使いやすいシェルとして人気がありますが、まだ一般的なユーザーにはあまり利用されていません。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="has-text-align-center"><img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www19.a8.net/0.gif?a8mat=3T8UPZ+FPLTGY+4R90+614CY" alt=""></p>



<h3 class="wp-block-heading"><span id="toc13">Windowsシェルの割合</span></h3>



<p class="has-ex-c-background-color has-background"><strong><span class="badge-grey">利用率割合</span></strong>　<span class="fz-12px">※これらの割合はあくまで推定値です。</span><br><br><strong>コマンドプロンプト</strong> : 約80%<br><br><strong>PowerShell</strong> : 約20% </p>



<p><br><span class="badge">理由</span><br>Windowsにおいて、コマンドプロンプトが最も一般的なシェルであり、古いバージョンのWindowsや一般的なユーザーに広く使用されています。</p>



<p>PowerShellは最新のWindowsでデフォルトのシェルとして採用されており、システム管理者や開発者の間で人気がありますが、全体的な割合はまだ低いと考えられます。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc14">初心者のためのシェル学習方法</span></h2>



<p><strong><span class="marker-under">ネット上のリソースを利用する</span></strong><br> インターネット上にはシェルのチュートリアルや動画がたくさんあります。これらのリソースを利用して使い方を学びましょう。</p>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-reference">
<a href="https://it-bokenki.com/2023/06/29/%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e5%85%a5%e9%96%80/" title="ターミナル初心者のためのコマンド入門ガイド" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://it-bokenki.com/wp-content/uploads/cocoon-resources/blog-card-cache/2a4ac94c3ab58a282f9d9cda62d777c9.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">ターミナル初心者のためのコマンド入門ガイド</div><div class="blogcard-snippet external-blogcard-snippet">ターミナルは初心者にとって少し怖い存在かもしれませんが、このガイドでは基本的なコマンドの使い方を丁寧に解説します。</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com/2023/06/29/command-introduction/" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">it-bokenki.com</div></div></div></div></a>
</div>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="marker-under"><strong>実際にコマンドを使って操作する</strong></span><br>ローカルのコンピューターでシェルを起動し、実際にコマンドを入力して操作してみましょう。基本的なコマンドから始めてみましょう。</p>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="marker-under"><strong>プロジェクトや課題に取り組む</strong></span><br>経験を積むことが大切です。ファイルの一括処理や自動化スクリプトの作成など、ニーズに合わせてシェルを活用してみましょう。</p>



<p>課題を自分でどうやって作ればいいか分からないという方は、思い切ってスクール見学するのもいいかもしれません。<strong><span class="bold-red">体験無料</span></strong>、<strong><span class="bold-red">オンラインスクールで格安</span></strong>など良いポイントがありますのでぜひ。</p>



<p><br>↓おすすめスクール</p>



<p class="has-text-align-left"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T91U0+CZYQ9E+529E+60OXE">まずは無料体験・説明会に参加を♪【Winスクール】</a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www18.a8.net/0.gif?a8mat=3T91U0+CZYQ9E+529E+60OXE" alt=""></p>



<p><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T8UQ0+1E0FLE+3TVC+HYFLU">3ヶ月間のプログラミングスクール【Tech Boost】</a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www17.a8.net/0.gif?a8mat=3T8UQ0+1E0FLE+3TVC+HYFLU" alt=""></p>



<p><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T8UQ0+HV0XE+3GWO+656YQ">現役エンジニアから学ぶならテックアカデミー</a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www14.a8.net/0.gif?a8mat=3T8UQ0+HV0XE+3GWO+656YQ" alt=""></p>



<p><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T91U0+CYRV1U+408S+5YJRM">様々な資格学習が1078円でウケホーダイ！【オンスク.JP】</a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www13.a8.net/0.gif?a8mat=3T91U0+CYRV1U+408S+5YJRM" alt=""></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc15">シェル開発の具体例</span></h2>



<h3 class="wp-block-heading"><span id="toc16">バックアップの自動化（Linux、Bash）</span></h3>



<p>バックアップ自動化を、Linuxの「Bash」を利用して開発してみましょう。<br>rsyncコマンドや tarコマンドなどを使用して、ファイルやディレクトリのバックアップを作成します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>【rsyncコマンドの場合】 ファイルやディレクトリを同期・バックアップ</strong></p>



<p><span class="badge-grey">詳細説明</span><br><strong><span class="marker-blue">rsync</span></strong>コマンドでファイルやディレクトリを同期・バックアップを作成します。<strong><span class="marker-blue">source_directory</span></strong>にソースのディレクトリパスを、<strong><span class="marker-blue">destination_directory</span></strong>にバックアップ先のディレクトリパスを指定します。<span class="marker-blue"><strong>-av</strong></span>オプションは、再帰的に同期を行い、ファイル属性やパーミッションも保持します。</p>



<p class="has-white-color has-black-background-color has-text-color has-background"><span class="badge-grey">Bash</span><br><span class="red">rsync</span> -av source_directory/ destination_directory/ </p>



<div style="height:61px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>【tarコマンドの場合】 ファイルやディレクトリを同期・バックアップ</strong></p>



<p><span class="badge-grey">詳細説明</span><br><strong><span class="marker-blue">tar</span></strong>コマンドでファイルやディレクトリをアーカイブ化し、バックアップファイルを作成します。<em><span class="marker-blue"><strong>backup.tar.gz</strong></span></em>に作成されるバックアップファイル名を指定し、<span class="marker-blue"><strong>source_directory</strong></span>にバックアップ対象のディレクトリパスを指定します。<span class="marker-blue"><strong>-czvf</strong></span>オプションは、圧縮してアーカイブを作成し、詳細情報を表示します。</p>



<p class="has-white-color has-black-background-color has-text-color has-background"><span class="badge-grey">Bash</span><br><span class="red">tar</span> -czvf backup.tar.gz source_directory/ </p>



<p class="has-cyan-bluish-gray-color has-text-color" style="font-size:15px">※アーカイブ化：複数のファイルやディレクトリを一つの単位にまとめて保存すること</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="has-text-align-center"> <img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www18.a8.net/0.gif?a8mat=3T911P+D2CGOI+4H2M+6BEQ9" alt=""></p>



<h3 class="wp-block-heading"><span id="toc17">ファイルの一括処理（Windows、コマンドプロンプト）</span></h3>



<p>ファイルの一括処理を、Windowsの「コマンドプロンプト」を利用して開発してみましょう。<br>copyコマンドや renameコマンド、findstrコマンドなどを使用して、ファイルのコピー、リネーム、検索・置換などを実行します。</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>【STEP１】 ファイルのコピー</strong></p>



<p><span class="marker-blue"><strong>source_file</strong></span>を<strong><span class="marker-blue">destination_file</span></strong>にコピーします。</p>



<p class="has-white-color has-black-background-color has-text-color has-background"><span class="badge-grey">コマンドプロンプト</span><br><span class="red">copy</span> source_file destination_file </p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>【STEP２】</strong> <strong>ファイルのリネーム</strong></p>



<p><strong><span class="marker-blue">current_name</span></strong>のファイルを<span class="marker-blue"><strong>new_name</strong></span>にリネームします。</p>



<p class="has-white-color has-black-background-color has-text-color has-background"><span class="badge-grey">コマンドプロンプト</span><br><span class="red">rename</span> current_name new_name </p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong>【STEP３】</strong> <strong>ファイルの検索・置換</strong></p>



<p><strong><span class="marker-blue">input_file</span></strong>内で<span class="marker-blue"><strong>search_string</strong></span>を検索し、該当する行を<strong><span class="marker-blue">output_file</span></strong>に出力します。</p>



<p class="has-white-color has-black-background-color has-text-color has-background"><span class="badge-grey">コマンドプロンプト</span><br><span class="red">findstr</span> /C:&#8221;search_string&#8221; input_file &gt; output_file </p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc18">おわりに</span></h2>



<p>今回LinuxとWindowsのシェルの違いや、具体的な開発例を紹介しました。</p>



<p>両者の特徴や利用方法を理解し、ファイル操作やバックアップ、テストスクリプトの実行などのさまざまな開発をしてみてください。シェルのパワフルな機能を活用し、効率的な開発を実現しましょう。</p>



<p class="has-text-align-center"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T911P+D2XWAA+4VDC+661TT"><br></a> <img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www19.a8.net/0.gif?a8mat=3T911P+D2XWAA+4VDC+661TT" alt=""></p>



<p></p><p>The post <a href="https://it-bokenki.com/2023/07/01/shell-introduction/">コマンドラインシェル入門：LinuxとWindowsシェルの違い</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://it-bokenki.com/2023/07/01/shell-introduction/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>ターミナル初心者のためのコマンド入門ガイド</title>
		<link>https://it-bokenki.com/2023/06/29/command-introduction/</link>
					<comments>https://it-bokenki.com/2023/06/29/command-introduction/#respond</comments>
		
		<dc:creator><![CDATA[てんハロ運営者]]></dc:creator>
		<pubDate>Thu, 29 Jun 2023 10:46:55 +0000</pubDate>
				<category><![CDATA[コマンド]]></category>
		<category><![CDATA[バックエンド]]></category>
		<guid isPermaLink="false">https://it-bokenki.com/?p=806</guid>

					<description><![CDATA[<p>このガイドでは基本的なコマンドの使い方を丁寧に解説します。コマンドの実行方法やファイルの移動、ディレクトリの作成など、初めてターミナルを使う方に役立つ情報が満載です。これを読んで、ターミナルの世界への第一歩を踏み出しましょう！</p>
<p>The post <a href="https://it-bokenki.com/2023/06/29/command-introduction/">ターミナル初心者のためのコマンド入門ガイド</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>こんにちは、でじぼうです。</p>



<p>ターミナルは初心者にとって少し怖い存在かもしれませんが、この<strong>ガイドでは基本的なコマンドの使い方を丁寧に解説</strong>します。</p>



<p>コマンドの実行方法やファイルの移動、ディレクトリの作成など、初めてターミナルを使う方に役立つ情報が満載です。これを読んで、ターミナルの世界への第一歩を踏み出しましょう！</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="でじぼう" class="speech-icon-image"/></figure><div class="speech-name">でじぼう</div></div><div class="speech-balloon">
<p style="font-size:15px">この記事は下記のような方におすすめ！</p>



<p style="font-size:15px"><br>・ターミナルってなに？</p>



<p style="font-size:15px">・コマンドってなに？</p>



<p style="font-size:15px">・ターミナルの使い方がわからない</p>
</div></div>



<p class="has-text-align-center"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T8UPZ+FPLTGY+4R90+5ZMCH"></a></p>



<p class="has-text-align-center"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T8UPZ+FH9R02+CO4+15OK2A">格安ドメイン名取得サービス『Xserverドメイン』</a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www18.a8.net/0.gif?a8mat=3T8UPZ+FH9R02+CO4+15OK2A" alt=""></p>



<p class="has-text-align-center"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3TB6RG+CLOBQQ+2PEO+1I4QBL"><img loading="lazy" decoding="async" border="0" width="300" height="250" src="https://www25.a8.net/svt/bgt?aid=230629372762&amp;wid=001&amp;eno=01&amp;mid=s00000012624009092000&amp;mc=1" alt=""></a> <img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www12.a8.net/0.gif?a8mat=3TB6RG+CLOBQQ+2PEO+1I4QBL" alt=""></p>



<p class="has-text-align-center"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T8UQ0+HV0XE+3GWO+6IWSI">はじめての副業コース</a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www13.a8.net/0.gif?a8mat=3T8UQ0+HV0XE+3GWO+6IWSI" alt=""></p>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc1">コマンドとは</span></h2>



<p><span class="marker-under"><strong>コマンドは、オペレーティングシステムで使われる命令のこと</strong></span>です。</p>



<p>ちなみに、オペレーティングシステムは、コンピュータ上でソフトウェアとハードウェアを結びつけ、ユーザーがコンピュータを操作するための基盤を提供しているシステムです。</p>



<p>コマンドはテキストを入力することで、<strong><span class="marker-under">コンピュータを操作したり情報を取得したりするために使用</span></strong>されます。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="でじぼう" class="speech-icon-image"/></figure><div class="speech-name">でじぼう</div></div><div class="speech-balloon">
<p>ユーザーがコンピュータを操作するための基盤を、操作するのがコマンド。テキストベースで指示操作できる。</p>
</div></div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-pickup">
<a href="https://it-bokenki.com/2023/06/28/%e3%82%a2%e3%83%b3%e3%83%81%e3%83%91%e3%82%bf%e3%83%bc%e3%83%b3/" title="アンチパターン入門 : ソフトウェア開発の陥りやすい罠とその解決法！ - てんハロ｜未経験エンジニアのIT学習ログ" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://it-bokenki.com/wp-content/uploads/cocoon-resources/blog-card-cache/2259cefeb0e54bd51f4247fb98a3f1c1.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">アンチパターン入門 : ソフトウェア開発の陥りやすい罠とその解決法！ - てんハロ｜未経験エンジニアのIT学習ログ</div><div class="blogcard-snippet external-blogcard-snippet">「アンチパターン」とは、ソフトウェア開発における悪習や問題の典型的なパターンです。コードの可読性や保守性を損ね、開発プロジェクトを混乱させる要因となります。 今回は、その特徴や具体的な例を挙げながら、どのようにそれらを解決するかお伝えします。</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://it-bokenki.com/2023/06/28/anti-patterns/" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">it-bokenki.com</div></div></div></div></a>
</div>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc2">コマンドの基礎</span></h2>



<p>下記はコマンドを利用する際に、よく耳にするワードです。</p>



<figure class="wp-block-table"><table><tbody><tr><td><span class="badge">用語</span></td><td><span class="badge">用途</span></td></tr><tr><td><strong>コマンド</strong></td><td>システムを操作するための命令のこと。コマンドはテキストベースで指示し、特定の動作を実行する。</td></tr><tr><td><strong>コマンドラインインタフェース</strong>（CLI）</td><td>コマンドでシステムに命令する方法のこと。CLIは、コマンドプロンプトを提供し、そこでユーザーはコマンドを入力して命令を伝える。</td></tr><tr><td><strong>引数</strong></td><td>コマンドに渡される追加の情報のこと。引数はコマンドの動作や対象を指定するために使用される。</td></tr><tr><td><strong>オプション</strong></td><td>コマンドの振る舞いを変更するための追加の設定のこと。オプションは通常、ハイフン（-）または二重ハイフン（&#8211;）で始まり、特定の機能を有効にしたり無効にしたりする。</td></tr><tr><td><strong>パイプ</strong></td><td>コマンドを連結して使用するための仕組み。パイプは、コマンドの間に「｜」を記載することによって、1つのコマンドの出力を別のコマンドの入力として渡すことができる。</td></tr><tr><td><strong>ファイルシステム</strong></td><td>ディレクトリ（フォルダ）とファイルからなる階層構造のファイルシステムを使用している。コマンドは、ファイルやディレクトリの作成、表示、移動、削除など、ファイルシステム上での操作を行う。</td></tr></tbody></table></figure>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc3">コマンドラインインターフェースの利点</span></h2>



<p>CLIを使用すると、テキストベースでコマンドや文字を入力するだけで、コンピューターと対話できます。これにより、さまざまなタスクを簡単に自動化することができます。</p>



<p>また、コンピューターのリソース（能力やメモリなど）をあまり使用しません。そのため、<span class="marker-under"><strong>処理が迅速に行われ、システムのパフォーマンスが向上</strong></span>します。</p>



<p>また、言語に依存せずに使用できるため、異なるオペレーティングシステムや環境で利用することができます。<span class="marker-under"><strong>特定の言語に依存しないため、様々なプラットフォームで同じコマンドやスクリプトを使用できます</strong></span>。</p>



<p>CLIは学習に時間がかかる場合もありますが、一度学習すれば、タスクの実行が効率的に行えます。シンプルなコマンドやパラメータを使用するため、小学生でも使い方を覚えやすいです。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://it-bokenki.com/wp-content/uploads/2023/05/名称未設定のデザイン-1-1-150x150.png" alt="でじぼう" class="speech-icon-image"/></figure><div class="speech-name">でじぼう</div></div><div class="speech-balloon">
<p>CLI以外にも、GUI・プログラミング言語・インターフェースなどもコマンド操作ができるよ！</p>
</div></div>



<p class="has-text-align-center"> <img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www19.a8.net/0.gif?a8mat=3TB6RG+D15LGY+2P76+65U41" alt=""></p>



<p class="has-text-align-center"><a rel="nofollow" href="https://px.a8.net/svt/ejp?a8mat=3T8UPZ+3I7X0Y+45OW+60WN6">ITフリーランス専門の案件・求人 | 常時５０００件を超える優良案件</a>
<img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www15.a8.net/0.gif?a8mat=3T8UPZ+3I7X0Y+45OW+60WN6" alt=""></p>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc4">ターミナルの基本操作</span></h2>



<h3 class="wp-block-heading"><span id="toc5">ターミナルとは</span></h3>



<p>ターミナルは、コンピューターの画面に表示される特殊なウィンドウのようなものです。<span class="marker-under"><strong>一般的には黒い背景に白いテキストが表示される画面を指します</strong></span>。</p>



<p>そこには、テキストを入力してコンピューターに命令を伝えたり、コンピューターからの応答を見たりすることができます。</p>



<h3 class="wp-block-heading"><span id="toc6">ターミナルの起動</span></h3>



<p><span class="badge">Windowsの場合</span><br>スタートメニューから「コマンドプロンプト」または「PowerShell」を選択する。</p>



<p><span class="badge">macOSの場合</span><br>Launchpadから「ターミナル」を選択する。</p>



<p><span class="badge">Linuxの場合</span><br>ディストリビューションによって異なるが、一般的には「ターミナル」や「コンソール」といったアプリケーションを起動する。</p>



<h3 class="wp-block-heading"><span id="toc7">コマンドの入力と実行（例：windows）</span></h3>



<p>ターミナルでコマンドを入力するには、プロンプト（$や&gt;など）の後ろにコマンドを入力し、Enterキーを押す。</p>



<p>コマンドの引数やオプションを指定する場合は、スペースを使って入力する。</p>



<p><span class="badge">例_part①</span><br>例題：新しいディレクトリを作成する<br>① <strong><span class="marker-blue">midir fail_test</span></strong>コマンドで、「fail_test」というディレクトリを作成<br>② <span class="marker-blue"><strong>dir</strong></span>コマンドで、現在地のディレクトリやファイル一覧を表示して、「fail_test」を確認</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="658" height="410" src="https://it-bokenki.com/wp-content/uploads/2023/06/スクリーンショット-2023-06-29-180956.png" alt="" class="wp-image-2038" style="width:788px;height:491px" srcset="https://it-bokenki.com/wp-content/uploads/2023/06/スクリーンショット-2023-06-29-180956.png 658w, https://it-bokenki.com/wp-content/uploads/2023/06/スクリーンショット-2023-06-29-180956-300x187.png 300w" sizes="auto, (max-width: 658px) 100vw, 658px" /></figure>



<div style="height:34px" aria-hidden="true" class="wp-block-spacer"></div>



<p><span class="badge">例_part②</span><br>例題：一階層下に移動する<br>① <span class="marker-blue"><strong>cd</strong></span>コマンドで、現在地を確認<br>② <span class="marker-blue"><strong>cd fail_test</strong></span>コマンドで、一階層下のディレクトリ「fail_test」に移動<br>③ <strong><span class="marker-blue">cd</span></strong>コマンドで、移動した場所を確認</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="753" height="337" src="https://it-bokenki.com/wp-content/uploads/2023/06/スクリーンショット-2023-06-29-183820.png" alt="" class="wp-image-2040" style="width:787px;height:353px" srcset="https://it-bokenki.com/wp-content/uploads/2023/06/スクリーンショット-2023-06-29-183820.png 753w, https://it-bokenki.com/wp-content/uploads/2023/06/スクリーンショット-2023-06-29-183820-300x134.png 300w" sizes="auto, (max-width: 753px) 100vw, 753px" /></figure>



<h3 class="wp-block-heading"><span id="toc8">ターミナルの終了</span></h3>



<ol class="wp-block-list">
<li><strong>コマンドの実行を終了</strong>する方法
<ul class="wp-block-list">
<li>実行中のコマンドを終了するには、一般的には「Ctrl+C」を押します。これにより、現在実行中のコマンドが停止します。</li>
</ul>
</li>



<li><strong>ターミナルを閉じる</strong>方法
<ul class="wp-block-list">
<li>ターミナルウィンドウの右上にある「閉じる」ボタン（×）をクリックすると、ターミナルを終了することができます。</li>
</ul>
</li>



<li><strong>コマンドでターミナルを終了する</strong>方法
<ul class="wp-block-list">
<li><strong><span class="marker-blue">exit</span></strong>コマンドを入力してEnterキーを押すと、ターミナルを終了することができます。このコマンドを実行すると、ターミナルセッションが終了し、ターミナルウィンドウが閉じられます。</li>
</ul>
</li>
</ol>



<p><span class="badge">注意点</span></p>



<ul class="wp-block-list">
<li>ターミナルを終了する前に、作業内容の保存やプロセスの終了を忘れないようにしましょう。</li>



<li>ターミナルを終了すると、未保存の作業や実行中のプロセスが終了される場合があります。必要な場合は事前に保存やプロセスの終了を行ってください。</li>
</ul>



<h2 class="wp-block-heading has-black-color has-text-color"><span id="toc9">おわりに</span></h2>



<p>今回は、初心者向けのターミナルの使い方をご紹介しました。</p>



<p>ターミナルはコマンドを通じて操作するため、最初は戸惑うこともあるかもしれません。しかし、ターミナルを使いこなすことで、より効率的な作業が可能になります。一緒に頑張っていきましょう! <img loading="lazy" decoding="async" border="0" width="1" height="1" src="https://www16.a8.net/0.gif?a8mat=3T8UPZ+3I7X0Y+45OW+5ZU29" alt=""></p><p>The post <a href="https://it-bokenki.com/2023/06/29/command-introduction/">ターミナル初心者のためのコマンド入門ガイド</a> first appeared on <a href="https://it-bokenki.com">てんハロ｜未経験エンジニアのIT学習ログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://it-bokenki.com/2023/06/29/command-introduction/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
