<?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/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>まとめ系 | みんたく</title>
	<atom:link href="https://mintaku-blog.net/category/develop/summary/feed/" rel="self" type="application/rss+xml" />
	<link>https://mintaku-blog.net</link>
	<description>みんたくの技術ブログ</description>
	<lastBuildDate>Sun, 11 Jan 2026 08:06:41 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.11</generator>

<image>
	<url>https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2018/06/cropped-ipad-820272_640.jpg?fit=32%2C32&#038;ssl=1</url>
	<title>まとめ系 | みんたく</title>
	<link>https://mintaku-blog.net</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">144480658</site>	<item>
		<title>個人開発のWebサービスがSQLインジェクション攻撃を受けた話と対策まとめ</title>
		<link>https://mintaku-blog.net/attack-sql-injection/</link>
					<comments>https://mintaku-blog.net/attack-sql-injection/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Sun, 11 Jan 2026 08:06:41 +0000</pubDate>
				<category><![CDATA[まとめ系]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=2632</guid>

					<description><![CDATA[<p>個人開発で運営しているWebサービスが攻撃を受けたので、その内容と対策をまとめました。 攻撃を受けた経緯 ある日、サーバーのログを確認していたところ、不審な …</p>
The post <a href="https://mintaku-blog.net/attack-sql-injection/">個人開発のWebサービスがSQLインジェクション攻撃を受けた話と対策まとめ</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>個人開発で運営しているWebサービスが攻撃を受けたので、その内容と対策をまとめました。</p>
<h2>攻撃を受けた経緯</h2>
<p>ある日、サーバーのログを確認していたところ、不審なリクエストを発見しました。</p>
<p>お問い合わせフォームの「姓」フィールドに、以下のような文字列が入力されていたのです。</p>
<p><code></code><code><br />
-1" OR 5*5=25 --<br />
</code><code></code></p>
<p>これはSQLインジェクション攻撃と呼ばれるもので、データベースを不正に操作しようとする攻撃手法です。</p>
<h2>SQLインジェクションとは</h2>
<p>SQLインジェクションは、入力フィールドに悪意のあるSQL文を注入して、データベースを操作しようとする攻撃です。</p>
<p>例えば、ログイン処理で以下のようなSQLを使っていたとします。</p>
<p><code></code><code>sql<br />
SELECT * FROM users WHERE name = '入力値'<br />
</code><code></code></p>
<p>ここに <code>' OR '1'='1</code> のような文字列を入力されると、</p>
<p><code></code><code>sql<br />
SELECT * FROM users WHERE name = '' OR '1'='1'<br />
</code><code></code></p>
<p>となり、条件が常にTRUEになってしまいます。これにより、認証をバイパスされたり、データを不正に取得されたりする可能性があります。</p>
<p>今回の攻撃で使われた <code>-1" OR 5*5=25 --</code> も同様の原理で、<code>5*5=25</code> は常にTRUEになるため、データベースの挙動を変えようとしていたものと思われます。</p>
<h2>攻撃者の情報を分析してみた</h2>
<p>ログに残っていた情報から、攻撃者について分析してみました。</p>
<p>| 項目 | 内容 |<br />
|&#8212;&#8212;|&#8212;&#8212;|<br />
| IPアドレス | VPNプロバイダーの帯域 |<br />
| ブラウザ | Chrome（Windows） |<br />
| メールアドレス | <code>sample@email.tst</code>（明らかにダミー） |<br />
| 入力パターン | 最小限の値 + 攻撃コード |</p>
<h3>攻撃の特徴から分かったこと</h3>
<p>いくつかの特徴から、この攻撃について考察してみました。</p>
<p>1. 汎用的なペイロードが使われていた</p>
<p>使われていた攻撃コードは非常に一般的なもので、特定のサービスを狙ったものではありませんでした。サイトのDB構造を知っているような痕跡もなく、「とりあえず試してみた」という印象です。</p>
<p>2. 入力が機械的だった</p>
<p>名前欄に「e」、メールに「sample@email.tst」など、明らかに自動化ツールで生成したような値が使われていました。SQLMap等の脆弱性スキャンツールの特徴に似ています。</p>
<p>3. VPN経由でアクセスしていた</p>
<p>IPアドレスを調べると、VPNプロバイダーがよく使用する帯域でした。身元を隠しながら多くのサイトをスキャンする際の典型的な手法です。</p>
<h2>結論：無差別スキャンの可能性が高い</h2>
<p>これらの特徴から、特定のサービスを狙った標的型攻撃ではなく、脆弱なサイトを探すボットによる無差別スキャンだったと判断しました。</p>
<p>個人開発の小規模なサービスでも、こういった攻撃は普通に来るんだなと実感しました。</p>
<h2>実施した対策</h2>
<p>今回の攻撃を受けて、以下の対策を実施しました。</p>
<h3>1. IPブラックリストの実装</h3>
<p>攻撃元のIPアドレスを即座にブロックする仕組みを追加しました。</p>
<p><code></code><code>typescript<br />
// IPブラックリスト<br />
const IP_BLACKLIST: Set&lt;string&gt; = new Set([<br />
'178.16.55.xxx', // 攻撃元IP<br />
])</p>
<p>export function checkIpBlacklist(event: H3Event): void {<br />
const ip = getClientIp(event)</p>
<p>if (IP_BLACKLIST.has(ip)) {<br />
console.log(</code>[BLOCKED] Blacklisted IP: ${ip}<code>)<br />
throw createError({<br />
statusCode: 403,<br />
message: 'Access denied'<br />
})<br />
}<br />
}<br />
</code><code></code></p>
<p>シンプルな実装ですが、同じIPからの継続的な攻撃には効果的です。</p>
<h3>2. 既存の対策が機能しているか確認</h3>
<p>改めて既存のセキュリティ対策を確認しました。</p>
<p>| 対策 | 状態 | 説明 |<br />
|&#8212;&#8212;|&#8212;&#8212;|&#8212;&#8212;|<br />
| パラメータ化クエリ | <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> | ORMを使用しており、SQLインジェクション対策済み |<br />
| レート制限 | <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> | 1分間に数回までに制限 |<br />
| reCAPTCHA v3 | <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> | ボット判定を実施 |<br />
| 入力長制限 | <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> | 追加で実装 |</p>
<p>重要なのは、パラメータ化クエリを使用していたため、今回の攻撃は実際には成功していなかったという点です。</p>
<p>Supabaseのクライアントライブラリを使っていたので、入力値は自動的にエスケープされており、SQLインジェクションは成立しませんでした。</p>
<p><code></code><code>typescript<br />
// Supabaseはパラメータ化クエリを使用するため安全<br />
const { error } = await client<br />
.from('inquiries')<br />
.insert({<br />
last_name, // 値は安全にエスケープされる<br />
email,<br />
message,<br />
})<br />
</code><code></code></p>
<h3>3. 入力値の長さ制限を追加</h3>
<p>説明欄などに大量のテキストを送りつけられるのを防ぐため、文字数制限を追加しました。</p>
<p><code></code><code>typescript<br />
const MAX_DESCRIPTION_LENGTH = 1000</p>
<p>if (description &amp;&amp; description.length &gt; MAX_DESCRIPTION_LENGTH) {<br />
throw createError({<br />
statusCode: 400,<br />
message: </code>説明は${MAX_DESCRIPTION_LENGTH}文字以内で入力してください<code><br />
})<br />
}<br />
</code><code></code></p>
<h2>reCAPTCHA v3がボットを検出できる仕組み</h2>
<p>せっかくなので、reCAPTCHA v3がどうやってボットを検出しているのかも調べてみました。</p>
<p>v3は「私はロボットではありません」のチェックボックスがなく、ユーザーの**行動パターン**を分析してスコア（0.0〜1.0）を算出します。</p>
<p>| 分析要素 | 人間の特徴 | ボットの特徴 |<br />
|&#8212;&#8212;&#8212;-|&#8212;&#8212;&#8212;&#8212;|&#8212;&#8212;&#8212;&#8212;&#8211;|<br />
| マウスの動き | 曲線的、不規則 | 直線的、または動きなし |<br />
| キー入力 | タイミングにばらつき | 均一で高速 |<br />
| ページ滞在時間 | 入力に時間がかかる | 瞬時に送信 |<br />
| スクロール | 自然な速度変化 | 一定または無し |</p>
<p>スコアが閾値（例: 0.5）を下回ると、ボットと判定されてブロックされます。自動化ツールはこういった「人間らしさ」を再現するのが難しいようです。</p>
<h2>多層防御の考え方</h2>
<p>今回の経験で改めて実感したのは、多層防御の重要性です。</p>
<p>一つの対策に頼るのではなく、複数の防御層を設けることで、どれか一つが突破されても他の層で防げるようになります。</p>
<p><code></code><code><br />
[攻撃]<br />
→ IPブラックリスト（既知の攻撃元をブロック）<br />
→ レート制限（大量リクエストを防止）<br />
→ reCAPTCHA（ボットを検出）<br />
→ 入力検証（不正な値を拒否）<br />
→ パラメータ化クエリ（SQLインジェクションを無効化）<br />
</code><code></code></p>
<p>今回は最後の砦である「パラメータ化クエリ」で攻撃が無効化されていましたが、他の層も機能していたことで、より安心できる状態でした。</p>
<h2>学んだこと</h2>
<p>今回の攻撃を通じて、いくつかのことを学びました。</p>
<h3>1. 基本的な対策が重要</h3>
<p>ORMやクエリビルダーを正しく使っていれば、SQLインジェクションは基本的に防げます。フレームワークの機能をちゃんと使うことが大切だなと思いました。</p>
<h3>2. ログは必ず残す</h3>
<p>攻撃を検知できたのは、リクエストのログを残していたからです。以下の情報は記録しておくと、分析に役立ちます。</p>
<p>&#8211; IPアドレス<br />
&#8211; User-Agent<br />
&#8211; リクエスト内容（個人情報の取り扱いには注意）<br />
&#8211; タイムスタンプ</p>
<h3>3. 小規模サービスでも攻撃は来る</h3>
<p>「うちは小さいから大丈夫」は通用しないんだなと実感しました。ボットは無差別にスキャンしているので、サービスの規模は関係ありません。</p>
<h3>4. 定期的なログ確認の習慣</h3>
<p>普段からログを確認する習慣をつけておくと、異常に気づきやすくなります。今回も定期的なログ確認で発見できました。</p>
<h2>まとめ</h2>
<p>今回の攻撃は、おそらく脆弱なサイトを探す自動スキャンでした。幸い対策済みだったため実害はありませんでしたが、個人開発でも普通に攻撃が来るんだなという良い経験になりました。</p>
<p>Webサービスを運営している方は、ぜひ以下の点を確認してみてください。</p>
<p>&#8211; SQLインジェクション対策ができているか（パラメータ化クエリの使用）<br />
&#8211; ログを確認する習慣があるか<br />
&#8211; 多層防御を意識した設計になっているか</p>
<p>何かの参考になれば幸いです。</p>The post <a href="https://mintaku-blog.net/attack-sql-injection/">個人開発のWebサービスがSQLインジェクション攻撃を受けた話と対策まとめ</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/attack-sql-injection/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2632</post-id>	</item>
		<item>
		<title>SupabaseのRow Level Security（RLS）について整理する</title>
		<link>https://mintaku-blog.net/supabase-rls/</link>
					<comments>https://mintaku-blog.net/supabase-rls/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Fri, 29 Aug 2025 00:47:54 +0000</pubDate>
				<category><![CDATA[まとめ系]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=2626</guid>

					<description><![CDATA[<p>RLSとは何か？ Row Level Security（RLS）は、データベースの各行に対してアクセス権限を細かく制御する仕組みです。 簡単に言うと、「誰が …</p>
The post <a href="https://mintaku-blog.net/supabase-rls/">SupabaseのRow Level Security（RLS）について整理する</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<h2>RLSとは何か？</h2>
<p>Row Level Security（RLS）は、データベースの各行に対してアクセス権限を細かく制御する仕組みです。</p>
<p>簡単に言うと、「誰がどのデータを見たり編集したりできるか」をデータベースレベルで決められる機能です。</p>
<p>例えば、SNSアプリを作る場合を想像してください。ユーザーAの投稿はユーザーAだけが編集できて、他のユーザーは閲覧のみ可能にしたいですよね。RLSを使えば、そのようなルールをデータベース側で自動的に適用できるのです。</p>
<h2>従来の方法との違い</h2>
<h3>従来のアプローチの問題点</h3>
<p>これまでのWebアプリケーション開発では、セキュリティ制御をアプリケーションのコード内で行うのが一般的でした。しかし、この方法には以下のような問題がありました。</p>
<h4>1. ヒューマンエラーのリスク</h4>
<p>開発者がセキュリティチェックを書き忘れると、他のユーザーのデータが見えてしまう可能性があります。特に大規模なアプリケーションでは、すべてのエンドポイントで完璧なセキュリティを実装するのは困難です。</p>
<h4>2. 開発・保守の負担</h4>
<p>新しい機能を追加するたびに「このユーザーはこのデータにアクセスできるのか？」を毎回考える必要があり、コードも複雑になりがちです。</p>
<h4>3. 一貫性の欠如</h4>
<p>チーム開発では、開発者によってセキュリティの実装方法が異なる場合があり、アプリケーション全体で一貫したセキュリティポリシーを維持するのが難しくなります。</p>
<h3>RLSの利点</h3>
<p>RLSを使用することで、これらの問題を根本的に解決できます。</p>
<p><strong>データベースレベルでの保護</strong>：アプリケーションコードにバグがあっても、データベース側でアクセスを制限するため、データ漏洩のリスクが大幅に減少します。</p>
<p><strong>開発効率の向上</strong>：一度ポリシーを設定すれば、アプリケーション側でいちいちセキュリティチェックを書く必要がなくなります。</p>
<p><strong>自動適用</strong>：Supabaseクライアントを通じてデータにアクセスする際、RLSポリシーが自動的に適用されるため、開発者が意識しなくても適切なアクセス制御が行われます。</p>
<h2>RLSの仕組み</h2>
<p>RLSは「ポリシー」という仕組みで動作します。ポリシーとは、「特定の条件を満たした場合のみ、データへのアクセスを許可する」というルールのことです。</p>
<h3>ポリシーの基本構造</h3>
<p>ポリシーを作成する際は、以下の要素を定義します。</p>
<ul>
<li>対象テーブル：どのテーブルに適用するか</li>
<li>操作種類：SELECT（読み取り）、INSERT（作成）、UPDATE（更新）、DELETE（削除）のどの操作に適用するか</li>
<li>条件：どのような条件の時にアクセスを許可するか</li>
</ul>
<p>例えば「ユーザーは自分が作成した投稿のみ編集できる」というルールを作りたい場合、「投稿テーブルのUPDATE操作において、現在ログインしているユーザーのIDと投稿の作成者IDが一致する場合のみ許可する」というポリシーを定義します。</p>
<h2>実際の活用例</h2>
<h3>ブログアプリケーションでの活用</h3>
<p>ブログアプリケーションを例に、RLSの実際の活用方法を説明します。</p>
<p>まず、ユーザーテーブルと投稿テーブルがあるとします。投稿テーブルには、タイトル、内容、作成者ID、公開フラグが含まれています。</p>
<p>このようなアプリケーションでは、以下のようなアクセス制御が必要になるでしょう。</p>
<h4>閲覧に関するルール</h4>
<ul>
<li>すべてのユーザーが公開済みの投稿を見ることができる</li>
<li>作成者は自分の投稿（下書き含む）をすべて見ることができる</li>
<li>他のユーザーの下書きは見ることができない</li>
</ul>
<h4>編集に関するルール</h4>
<p>ユーザーは自分の投稿のみ作成・編集・削除できる</p>
<p>他のユーザーの投稿は編集できない</p>
<p>これらのルールをRLSで実現することで、アプリケーション側で複雑なセキュリティロジックを書く必要がなくなります。</p><pre class="crayon-plain-tag">-- 例：誰でも公開された投稿を閲覧可能
CREATE POLICY "Anyone can view published posts" ON posts
FOR SELECT USING (is_published = true);

-- 例：ユーザーは自分の投稿のみ編集可能
CREATE POLICY "Users can update own posts" ON posts
FOR UPDATE USING (auth.uid() = user_id);</pre><p></p>
<h2>組織やチーム単位でのアクセス制御</h2>
<p>個人ユーザーだけでなく、組織やチーム単位でのアクセス制御も可能です。</p>
<p>例えば、プロジェクト管理ツールを作る場合を考えてみましょう。このツールでは</p>
<ul>
<li>同じ組織のメンバーは組織内のプロジェクトを閲覧できる</li>
<li>プロジェクトの作成は組織の管理者のみが可能</li>
<li>プロジェクトの削除は組織のオーナーのみが可能</li>
</ul>
<p>といったルールが必要になります。</p>
<p>RLSを使えば、これらの複雑なアクセス制御もデータベースレベルで実現できます。ユーザーと組織の関係、ユーザーの役割（メンバー、管理者、オーナー）などの情報を基に、適切なポリシーを設定することで、安全で柔軟なアクセス制御システムを構築できます。</p>
<h2>パフォーマンスとベストプラクティス</h2>
<h3>パフォーマンスへの配慮</h3>
<p>RLSを使用する際は、パフォーマンスも考慮する必要があります。ポリシーの条件が複雑になると、データベースの処理が重くなる可能性があります。</p>
<h4>インデックスの活用</h4>
<p>ポリシーで使用する条件に対して適切なインデックスを設定することで、パフォーマンスの向上が期待できます。例えば、ユーザーIDで絞り込む条件が多い場合は、user_idカラムにインデックスを設定します。</p>
<h4>効率的なポリシー設計</h4>
<p>よく使用される条件を先に評価するようにポリシーを設計することで、不要な処理を減らすことができます。</p>
<h3>開発時のベストプラクティス</h3>
<h4>明確な命名規則</h4>
<p>ポリシーには分かりやすい名前を付けることが重要です。「users_select_own_posts」のように、誰が何に対してどの操作を行えるかが名前から分かるようにしましょう。</p>
<h4>段階的な実装</h4>
<p>すべてのテーブルに一度にRLSを適用するのではなく、重要なテーブルから段階的に導入することをお勧めします。これにより、問題が発生した際の影響範囲を限定できます。</p>
<h4>十分なテスト</h4>
<p>RLSポリシーは、異なる権限を持つユーザーでテストすることが重要です。管理者、一般ユーザー、ゲストユーザーなど、さまざまな立場からアクセスを試して、期待通りの動作をするか確認しましょう。</p>
<h2>まとめ</h2>
<p>SupabaseのRLSは、アプリケーションのセキュリティを根本的に向上させる強力な機能です。従来のアプリケーションレベルでのセキュリティ制御と比較して、より安全で保守性の高いシステムを構築できます。</p>
<p>適切に設計・実装されたRLSポリシーは、開発者の負担を軽減し、データ漏洩のリスクを最小限に抑えます。また、複雑な組織構造やロールベースのアクセス制御にも対応できる柔軟性を持っています。</p>
<p>RLSを活用して、ユーザーが安心して使える、セキュアなアプリケーションを構築していきましょう。</p>The post <a href="https://mintaku-blog.net/supabase-rls/">SupabaseのRow Level Security（RLS）について整理する</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/supabase-rls/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2626</post-id>	</item>
		<item>
		<title>Claude AIを活用したWebアプリ開発事例まとめ</title>
		<link>https://mintaku-blog.net/claude-ai/</link>
					<comments>https://mintaku-blog.net/claude-ai/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Fri, 25 Jul 2025 04:42:35 +0000</pubDate>
				<category><![CDATA[まとめ系]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=2621</guid>

					<description><![CDATA[<p>最近、Claude AIを使った開発の話をよく聞くようになり、実際に事例を調べてみると、想像以上に実用的な使われ方をしていることがわかりました。 今回は具体 …</p>
The post <a href="https://mintaku-blog.net/claude-ai/">Claude AIを活用したWebアプリ開発事例まとめ</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>最近、Claude AIを使った開発の話をよく聞くようになり、実際に事例を調べてみると、想像以上に実用的な使われ方をしていることがわかりました。</p>
<p>今回は具体的な事例を通して、現在のClaude AI活用の実態を整理してみます。</p>
<h2>Claude 4で何が変わったのか</h2>
<p>2025年5月にリリースされたClaude 4は、従来のバージョンから大きく進化しています。特に注目すべきは並列でのツール使用と、推論中にリアルタイムでWeb検索ができるようになった点です。</p>
<p>これまでのAIチャットツールは「聞かれたことに答える」だけでしたが、Claude 4は「考えながら必要な情報を取りに行く」ということができるようになりました。開発中に「このライブラリの最新の使い方がわからない」となった時、自分で調べて最新情報を踏まえた回答をしてくれるのは、かなり実用的です。</p>
<h3>Web検索機能</h3>
<p>3月に追加されたWeb検索機能も地味に便利です。従来は「GPTに聞く→Googleで調べる→また戻ってGPTに聞く」みたいな往復が必要でしたが、Claudeは一つの会話の中で最新情報を調べて回答してくれます。</p>
<p>ただし、検索結果をそのまま返すのではなく、Claudeが解釈して会話形式で返してくれるのが特徴的です。情報の信頼性については相変わらず注意が必要ですが、開発中のちょっとした調べ物には重宝しそうです。</p>
<h3>Claude Artifacts</h3>
<p>個人的に面白いと思ったのがArtifacts機能です。15行以上のコードや構造化されたコンテンツを独立して管理し、リアルタイムでプレビューできます。</p>
<p>従来だとVSCodeで作って、ローカルサーバー立てて、ブラウザで確認して&#8230;という手順が必要でしたが、すべてClaude上で完結できるのは確かに便利です。</p>
<p>何より、「ちょっとしたツールが欲しい」と思った時のハードルが劇的に下がります。社内の小さな業務効率化ツールとかには、かなり使えそうな印象です。</p>
<h2>Claude Codeという新しいアプローチ</h2>
<p>Claude Codeはターミナルベースで動作し、プロジェクト全体のコンテキストを理解してくれるという点が新しいです。従来のAIコーディングツールは「このファイルの中でこの機能を実装して」みたいな局所的な支援でしたが、Claude Codeはプロジェクト全体を見渡した提案ができるようです。</p>
<p>事例ではダッシュボードを数時間で作り上げていて、リアルタイム統計表示、ドキュメント管理、WebSocket対応、レスポンシブデザイン、ダークモード対応まで含んでいます。従来なら数週間かかる作業を数時間でやってのけるのは、確かにインパクトがあります。</p>
<p>ただ、こういう「すごく早い」系の事例を見る時は、要件定義や設計の時間が含まれているのか、品質はどの程度なのか、という点は気になります。</p>
<p>&nbsp;</p>
<h2>現在の制限事項</h2>
<p>調べてみると、現在のClaude Artifactsにはいくつかの制限があります：</p>
<p>&#8211; 外部APIとの連携ができない<br />
&#8211; 永続的なストレージがない<br />
&#8211; テキストベースの完了APIのみ</p>
<p>つまり、実際のWebサービスで必要な「データベースとの連携」「外部サービスとの認証」「ファイルアップロード」みたいな機能は、まだ自分で実装する必要があります。現状は「プロトタイプやモックアップの作成」「簡単なツールの開発」あたりが現実的な用途でしょう。</p>
<p>&nbsp;</p>
<h3>コスト面</h3>
<p>開発速度の向上は確実にコストメリットがあります。特にプロトタイプ作成やMVP開発では、大幅な時間短縮が期待できます。</p>
<p>一方で、生成されたコードのレビューや品質向上に追加工数がかかることも考慮する必要があります。結果的には「初期開発は早くなるが、品質担保に別の時間がかかる」という構造になりそうです。</p>
<p>&nbsp;</p>
<h3>スキルセットの変化</h3>
<p>Claude AIが普及すると、開発者に求められるスキルも変わってきそうです。純粋な「コードを書く能力」よりも、「問題を整理する能力」「AI生成コードの品質を評価する能力」「プロダクト全体を設計する能力」の重要性が高まりそうです。</p>
<p>特に、プロンプトエンジニアリングのスキルは今後重要になるでしょう。AIに適切な指示を出して、期待する結果を得る技術は、従来のプログラミングスキルとは異なる新しい能力です。</p>
<h2>開発プロセスの変化</h2>
<p>従来の「要件定義→設計→実装→テスト」という流れが、「アイデア→プロトタイプ→反復改善→本格実装」という形に変わる可能性があります。</p>
<p>特に初期段階でのアイデア検証が格段に早くなるため、より多くの選択肢を試行錯誤できるようになります。これは、プロダクト開発全体にとってプラスの変化だと思います。</p>
<h3>新しい役割の出現</h3>
<p>AIとペアプログラミングをする新しい働き方や、AI生成コードの品質を担保する専門職みたいな役割が生まれるかもしれません。また、技術的な実装よりもビジネス価値の創出により重点を置いた開発者の役割も増えそうです。</p>
<h2>まとめ</h2>
<p>Claude AIを使ったWebアプリ開発は、確実に実用的なレベルに達していると感じました。特にプロトタイプ作成や小規模ツール開発では、大幅な効率化が期待できます。</p>
<p>一方で、本格的なプロダクション環境で使うには、まだ課題も多く残っています。セキュリティ、パフォーマンス、保守性といった観点では、引き続き人間の開発者の役割が重要です。</p>
<p>重要なのは、AIを「開発者の代替」として見るのではなく、「開発プロセスを加速するツール」として捉えることだと思います。適切に活用すれば、より創造的で価値の高い仕事に集中できるようになるはずです。</p>
<p>今後もClaude AIの進化は続くでしょうし、開発現場での活用事例も増えてくると思います。早めにキャッチアップして、自分なりの活用方法を見つけていくことが大切になりそうです。</p>The post <a href="https://mintaku-blog.net/claude-ai/">Claude AIを活用したWebアプリ開発事例まとめ</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/claude-ai/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2621</post-id>	</item>
		<item>
		<title>Gemini API の新機能「URL Context」でWebページ情報抽出を実装してみた</title>
		<link>https://mintaku-blog.net/gemini-url-context/</link>
					<comments>https://mintaku-blog.net/gemini-url-context/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Sat, 07 Jun 2025 02:12:28 +0000</pubDate>
				<category><![CDATA[まとめ系]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=2614</guid>

					<description><![CDATA[<p>2025年のGoogle I/Oで発表されたGemini APIの新機能「URL Context」を使って、Webサイトから自動で情報を抽出するシステムを構 …</p>
The post <a href="https://mintaku-blog.net/gemini-url-context/">Gemini API の新機能「URL Context」でWebページ情報抽出を実装してみた</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>2025年のGoogle I/Oで発表されたGemini APIの新機能「URL Context」を使って、Webサイトから自動で情報を抽出するシステムを構築しました。</p>
<p>「URLを投げるだけで中身をAIが理解してくれる」という魔法のような機能に見えましたが、実際に実装してみると様々な課題に直面しました。最終的に安定したシステムを構築するまでの試行錯誤をまとめます。</p>
<h2>URL Context機能とは</h2>
<p>従来のWebスクレイピングでは、HTMLを取得してパースし、CSSセレクターやXPathで特定の要素を抽出する必要がありました。</p><pre class="crayon-plain-tag">// 従来のスクレイピング
const response = await fetch(url);
const html = await response.text();
const $ = cheerio.load(html);
const title = $('.page-title').text();
const content = $('.main-content').text();
// ... 各要素を個別に抽出</pre><p>URL Context機能を使えば、これらの作業をAIに丸投げできます。</p><pre class="crayon-plain-tag">// URL Context使用
const response = await fetch('https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:generateContent', {
  body: JSON.stringify({
    contents: [{
      parts: [{ text: `${url}から情報をJSON形式で抽出して` }]
    }],
    tools: [{ "url_context": {} }]  // これが重要
  })
});</pre><p>&nbsp;</p>
<h2>最初の実装と失敗</h2>
<p>当初、以下のようなシンプルな実装から始めました。</p><pre class="crayon-plain-tag">export async function POST(request: NextRequest) {
    const { url } = await request.json();
    
    const response = await fetch(geminiApiUrl, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            contents: [{
                parts: [{ text: `${url}の情報を抽出して` }]
            }]
        })
    });
}</pre><p></p>
<h3>発生した問題</h3>
<h4>間違った情報が返ってくる</h4>
<ul>
<li>入力: とあるWebサイトのページURL</li>
<li>出力: 全く関係ない別のサイトの情報</li>
</ul>
<h4>動作が不安定</h4>
<ul>
<li>同じURLでも結果が変わる</li>
<li>明らかに学習データから推測した内容</li>
</ul>
<h2>URL Context機能が動作していなかった</h2>
<p>最大の原因はtools設定の不備でした。URL Context機能を使うには明示的に指定する必要があります。</p><pre class="crayon-plain-tag">// 間違った実装
body: JSON.stringify({
    contents: [{ parts: [{ text: `URL: ${url}` }] }]
    // tools設定なし → 通常のテキスト生成として処理される
})</pre><p></p><pre class="crayon-plain-tag">// 正しい実装
body: JSON.stringify({
    contents: [{ parts: [{ text: `URL: ${url}` }] }],
    tools: [{ "url_context": {} }],                    // 重要！
    model: "gemini-2.5-flash-preview-05-20"           // 対応モデル
})</pre><p>また、URL Context機能は新しい機能のため、対応モデルが限定されていました。</p>
<h3>原因分析</h3>
<p>Webページが膨大だったのが大きな要因でした。</p><pre class="crayon-plain-tag">元のHTML: 208,922文字
↓
Gemini内部処理: 6,377トークン
↓
制限オーバー: 4,096トークン制限を超過</pre><p>一般的なWebサイトには以下の要素が大量に含まれていました。</p>
<ul>
<li>JavaScript（数万行）</li>
<li>CSS（複雑なスタイル定義）</li>
<li>広告・関連コンテンツ・ナビゲーション</li>
<li>アナリティクス用のdata属性</li>
</ul>
<p>&nbsp;</p>
<h2>解決策：ハイブリッドアプローチ</h2>
<p>最終的に、従来のスクレイピング + AI分析のハイブリッドアプローチを採用しました。</p>
<h3>実装フロー</h3>
<ol>
<li>自前でHTMLを取得</li>
<li>不要要素を徹底的に削除</li>
<li>プレーンテキスト化</li>
<li>Geminiで構造化データに変換</li>
</ol>
<h3>HTML軽量化の実装</h3>
<p></p><pre class="crayon-plain-tag">async function preprocessHTML(url) {
    // 1. HTMLを取得
    const response = await fetch(url, {
        headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }
    });
    const html = await response.text();
    
    // 2. 不要要素を削除
    let cleanHtml = html
        .replace(/&lt;script[^&gt;]*&gt;[\s\S]*?&lt;\/script&gt;/gi, '') // JavaScript
        .replace(/&lt;style[^&gt;]*&gt;[\s\S]*?&lt;\/style&gt;/gi, '')   // CSS
        .replace(/&lt;!--[\s\S]*?--&gt;/g, '')                  // コメント
        .replace(/class="[^"]*"/gi, '')                   // class属性
        .replace(/id="[^"]*"/gi, '')                      // id属性
        .replace(/style="[^"]*"/gi, '')                   // style属性
        .replace(/data-[^=]*="[^"]*"/gi, '');             // data属性
    
    // 3. HTMLタグを完全除去
    cleanHtml = cleanHtml
        .replace(/&lt;[^&gt;]+&gt;/g, ' ')                         // 全タグ削除
        .replace(/\s+/g, ' ')                             // 空白正規化
        .trim();
    
    // 4. 文字数制限
    return cleanHtml.substring(0, 8000);
}</pre><p>&nbsp;</p>
<h3>Gemini APIへの送信</h3>
<p></p><pre class="crayon-plain-tag">const response = await fetch(geminiApiUrl, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        contents: [{
            parts: [{
                text: `以下のWebページテキストから必要な情報をJSON形式で抽出：

${preprocessedText}

出力形式:
{
  "title": "タイトル",
  "category": "カテゴリ",
  "description": "説明",
  "details": "詳細情報"
}`
            }]
        }],
        // URL Contextは使わない（前処理済みテキストのため）
        generationConfig: {
            temperature: 0.1,
            maxOutputTokens: 4096
        }
    })
});</pre><p>&nbsp;</p>
<h2>学んだこと</h2>
<p>「URLを渡すだけ」という説明に惑わされ、tools設定を見落としており、公式ドキュメントをよく読むべきでした。</p>
<p>また、基本的にWebページは非常に重く、軽量化なしではAI APIの制限にすぐ引っかかるので考慮する必要がありそうです。</p>
<p>「AIですべて解決」ではなく、現状は従来技術と組み合わせることで、より確実で効率的なシステムを作ることを目指すのが良さそうです。</p>
<p>現在、一部の項目で「N/A」が出力される場合があり、サイト構造の分析と、より適切な文字数制限の設定が今後必要になりそうです。</p>The post <a href="https://mintaku-blog.net/gemini-url-context/">Gemini API の新機能「URL Context」でWebページ情報抽出を実装してみた</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/gemini-url-context/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2614</post-id>	</item>
		<item>
		<title>Model Context Protocol (MCP) を理解してみる</title>
		<link>https://mintaku-blog.net/about-mcp/</link>
					<comments>https://mintaku-blog.net/about-mcp/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Tue, 20 May 2025 09:18:23 +0000</pubDate>
				<category><![CDATA[まとめ系]]></category>
		<category><![CDATA[その他]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=2610</guid>

					<description><![CDATA[<p>最近よく聞くMCPについてよくわかっていないので、どんなものなのか理解するために整理してみました。 MCPって何？ Model Context Protoc …</p>
The post <a href="https://mintaku-blog.net/about-mcp/">Model Context Protocol (MCP) を理解してみる</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>最近よく聞くMCPについてよくわかっていないので、どんなものなのか理解するために整理してみました。</p>
<h2>MCPって何？</h2>
<p>Model Context Protocol（MCP）は、簡単に言うとAIモデルと外部ツールが連携するときの標準的なルールを定めたものです。</p>
<p>今まで、GPTやClaude等のAIモデルにWebスクレイピングやデータベース操作などの機能を追加しようとすると、それぞれ独自の方法で実装する必要がありましたが、MCPはこの問題を解決します。</p>
<p>要するにAIと外部ツールが話し合うための「共通言語」のようなものだと思います。</p>
<p>今まで、AIに「Webで検索して」とか「データベースから情報を取得して」とお願いするとき、それぞれ別々の方法で実装する必要がありましたが、MCPであれば一度覚えた方法でいろんなツールとAIを連携させることができるようになります。</p>
<h2>技術的にはどういう仕組みなのか</h2>
<p>MCPは、WebSocketやgRPCなどの通信プロトコルの上で動く、メッセージベースのシステムのようです。JSON形式でメッセージをやり取りして、AIとツールが情報を交換します。</p>
<p>特に重要だと思うのは「コンテキスト」の管理です。普通のAPIだと、一回一回のリクエストは独立していますが、MCPでは会話の流れやこれまでの処理結果を適切に管理してくれるようです。</p>
<p>これにより、AIが複数のツールを連続して使ったり、前回の結果を踏まえて次の行動を決めたりすることができるのではないでしょうか。</p>
<h2>実際の開発現場でどう使えそうか</h2>
<p>現在のAI開発で困っていることを考えると、MCPの恩恵は大きそうです。</p>
<h3>チャットボット開発での活用</h3>
<p>例えば、顧客サポートのチャットボットを作る場合</p>
<ul>
<li>CRMシステムから顧客情報を取得</li>
<li>注文履歴をデータベースから検索</li>
<li>在庫確認システムで商品状況をチェック</li>
<li>メール送信システムで返答を送信</li>
</ul>
<p>これらを全て統一的な方法で連携できれば、開発がかなり楽になります。</p>
<h3>開発者向けAIアシスタント</h3>
<p>コーディング支援AIの場合</p>
<ul>
<li>GitHubから最新のコードを取得</li>
<li>静的解析ツールでコード品質をチェック</li>
<li>テスト実行環境でコードを実行</li>
<li>ドキュメントを自動生成</li>
</ul>
<p>これらのツールを組み合わせたワークフローが、MCPで簡潔に記述できるかもしれません。</p>
<h2>実装の難しさと課題</h2>
<p>MCPを実際に使う際の課題もあるかと思います。</p>
<h3>学習コスト</h3>
<p>新しいプロトコルを覚える必要があります。特に、コンテキスト管理やメッセージ形式など、従来のAPI開発とは異なる概念を理解する必要があります。</p>
<h3>デバッグの困難さ</h3>
<p>AIとツールの連携が複雑になると、どこで問題が発生しているかを特定するのが難しくなりそうです。適切なログ機能やデバッグツールが重要になるでしょう。</p>
<h3>パフォーマンスの懸念</h3>
<p>抽象化レイヤーが増えることで、多少のオーバーヘッドは必要になりそうです。高負荷なシステムでは、この影響を考慮する必要がありそうです。</p>
<h2>まとめ</h2>
<p>Model Context Protocolは、AI開発における「配管工事」の部分を大幅に簡略化してくれそうです。標準化により、AI開発者はより創造的で付加価値の高い部分に時間を使えるようになるでしょう。</p>
<p>まだ新しい技術なので、全てが確定しているわけではありませんが、AI開発に携わる者として注目していくべき技術だと思います。</p>
<p>実際のプロジェクトで使えるレベルになるまでには、もう少し時間がかかるかもしれませんが、早めにキャッチアップしておけば、将来的に大きなアドバンテージを得られるかもしれないです。</p>The post <a href="https://mintaku-blog.net/about-mcp/">Model Context Protocol (MCP) を理解してみる</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/about-mcp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2610</post-id>	</item>
		<item>
		<title>【実体験】個人開発でサービス運営を始める前に知っておくべきこと</title>
		<link>https://mintaku-blog.net/before-personal-dev/</link>
					<comments>https://mintaku-blog.net/before-personal-dev/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Sun, 02 Feb 2025 04:51:21 +0000</pubDate>
				<category><![CDATA[まとめ系]]></category>
		<category><![CDATA[サイト運営]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=2573</guid>

					<description><![CDATA[<p>個人開発において「技術的な学習が目的の個人開発」と「実際にユーザーに使ってもらうことを目指す個人開発」では、考えるべきことが大きく違います。 今回は実際にユ …</p>
The post <a href="https://mintaku-blog.net/before-personal-dev/">【実体験】個人開発でサービス運営を始める前に知っておくべきこと</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>個人開発において「技術的な学習が目的の個人開発」と「実際にユーザーに使ってもらうことを目指す個人開発」では、考えるべきことが大きく違います。</p>
<p>今回は実際にユーザーに使われるサービスを作りたい方に向けて、大学生の頃から現在まで10個以上の個人開発のサービスを作ってきた経験から得た知見をお伝えします。</p>
<p><strong>なお、単純に技術力向上が目的の場合は、この記事で紹介する「集客」や「マネタイズ」といった観点は気にする必要はありません。</strong></p>
<p>まずは自分の目的を明確にすることから始めましょう！</p>
<h2>個人開発の目的を明確にする</h2>
<p>個人開発には大きく分けて3つの目的があります。</p>
<h3>1. 技術的な学習</h3>
<ul>
<li>新しい言語やフレームワークの習得</li>
<li>アーキテクチャの理解</li>
<li>技術的チャレンジ</li>
</ul>
<p>→ この場合は以降で説明する「ユーザー獲得」や「マネタイズ」は気にする必要なし</p>
<h3>2. ポートフォリオ作成</h3>
<ul>
<li>転職や就職の際のアピール</li>
<li>技術力の可視化</li>
<li>コーディングスキルの証明</li>
</ul>
<p>→ この場合も「収益化」よりも「技術の見せ方」を重視</p>
<h3>3. サービス運営・収益化</h3>
<ul>
<li>実際のユーザーに使ってもらう</li>
<li>継続的な収益の獲得</li>
<li>サービス運営の経験を得る</li>
</ul>
<p>→ この場合は以降で説明する内容が重要</p>
<p>&nbsp;</p>
<h2>サービス運営から得られる学び</h2>
<p>実際にユーザーに使われるサービスを作ると、会社員エンジニアとして働いているだけでは得られない多くの学びがあります。</p>
<p>これらの経験は、エンジニアとしての視野を大きく広げてくれます。</p>
<h3>1. 収益の仕組みの理解</h3>
<p>広告収入の仕組みについて、実際に運用してみて初めて細かい部分が見えてきました。</p>
<ul>
<li>インプレッション単価は季節や時間帯でかなり変動する</li>
<li>クリック単価は業界によって大きく違う（金融系は高め、エンタメ系は低めなど）</li>
<li>成果報酬型広告は条件が合えば収益性が高い</li>
<li>純広告は安定収入になるけど、営業力が必要</li>
<li>動画配信型広告など新しい媒体が出てくる</li>
</ul>
<p>正直、これらは実際にやってみないと分からないことばかりでした。</p>
<h3>2. 運用コストの現実</h3>
<p>サービスの運用には意外と多くのコストがかかることを、実際に運営してみて初めて実感します。</p>
<p>特に自分の場合、最初は「無料枠でなんとかなるだろう」と思っていたのですが、ユーザーが増えるにつれて様々なコストが発生してきました。</p>
<p>サーバー費用はアクセス数と比例して増加し、最初は無料枠で収まっていても、徐々にコストが発生してきました。</p>
<p>他にもドメイン代、データベースやストレージなどの費用が発生します。</p>
<p>急なアクセス増に対応するための余裕を持たせる必要がある場合は、それに伴うコストも考慮が必要です。例えば、SNSで拡散された時の一時的なアクセス増にも耐えられる設計が必要です。</p>
<h3>3. ユーザー対応の重要性</h3>
<p>サービスを運営する上で、ユーザーとの関係構築は重要です。</p>
<p>サービスを運営していくと問い合わせが発生してきます。ユーザーからのバグ報告はしっかりと受け止め、迅速に対応する必要があります。</p>
<p>お問い合わせに対して真摯に対応していくことでユーザー価値を届けることの大切さを学ぶことができます。</p>
<p>また、同じような質問が多いため、FAQ作成など効率化が必要になります。</p>
<p>機能要望について全ての要望に応えることはできませんが、優先順位をつけて計画的に対応することが重要です。</p>
<h2>アイデアの見つけ方</h2>
<p>自分の経験から言えば、最も取っ掛かりやすいのは自分自身が本当に必要としているものです。</p>
<p>自分が実際に困っている問題など、毎日の生活や仕事で「これ、面倒だな」と感じることをメモしておくと良いです。また、同僚や友人の愚痴や相談の中にも、サービスのタネは隠れています。</p>
<p>他にもよく使うサービスの「ここが使いづらい」という点も、新しいサービスのヒントになります。</p>
<p>アイデアが思いついたら、実際に需要があるか確認します。XなどのSNS検索で「〜できない」「〜めんどくさい」などのネガティブなキーワードで検索すると、潜在的なニーズが見つかります。</p>
<h2>アイデアの検証ステップ</h2>
<p>アイデアが固まったら、本格的な開発に入る前に必ず検証を行います。ここでの検証が甘いと、後々大きな手戻りの原因となります。</p>
<h3>1. 競合分析</h3>
<p>競合サービスの機能を一覧表にまとめ、どの機能が本当に必要とされているのかを見極めます。</p>
<p>例えば、私の場合は競合を全てスプレッドシートにまとめ、本当に使われている機能を洗い出しました。</p>
<p>差別化ポイントとして「より良い」ではなく「異なる」アプローチを見つけることが重要です。例えば、競合が機能の豊富さを売りにしているなら、あえてシンプルさを極めるという選択肢もあります。</p>
<h3>2. ユーザーヒアリング</h3>
<p>実際のユーザーの声を聞くことで、思い込みに気づくことができます。</p>
<p>知人や同僚など最初は身近な人に協力してもらいましょう。「このサービスがあったら使う？」ではなく、「現在どうやってこの問題を解決しているか」を聞くのがポイントです。</p>
<p>サブスクや買い切りなどの場合は「いくらなら払えるか」を具体的に聞きます。この時、「月額いくら？」ではなく「この問題を解決するためにいくらまでなら払えるか」という聞き方をすると、より正確な答えが得られます。</p>
<p>また「いつ」「どこで」「どんな時に」使うのかを具体的にイメージしてもらいます。これにより、見落としていた機能要件が見つかることもあります。</p>
<h2>MVP（最小機能）の設計</h2>
<p>ここからが実際の開発フェーズです。MVPは「必要最小限の機能を持つ製品」という意味ですが、重要なのは「最小限」であることです。</p>
<p>例として、以下の3つの質問全てに「YES」と答えられる機能のみを実装します。</p>
<h3>1. 必要最低限の機能か？</h3>
<p>「あったら便利」と「なければ困る」は明確に区別します。</p>
<p>例えばタスク管理アプリなら、タスクの追加・編集・削除は必須ですが、タグ付けは必ずしも最初から必要ではないです。</p>
<p>なくても代替可能な機能は後回し、例えば、カレンダー連携は便利ですが、最初は手動で日付を入力してもらうことで代替できます。</p>
<p>ヒアリングで得た情報をもとに、ユーザーが本当に必要な機能を見極めます。</p>
<h3>2. 2週間以内に実装可能か？</h3>
<p>開発期間が長くなると、モチベーション維持が難しくなります。</p>
<p>未経験の技術を使う場合は、学習時間も含めて見積もります。機能ごとに必要な作業を細かく分解し、現実的な工数を見積もります。</p>
<p>特に外部サービスとの連携や、初めて使う技術については、予期せぬ問題が発生する可能性を考慮します。</p>
<h3>3. 検証可能な価値を提供できるか？</h3>
<p>特に最初はユーザーからフィードバックが得られる機能を考慮します。</p>
<p>ユーザーの課題をどの程度解決できるのか、具体的に説明できる必要があります。</p>
<p>また、ユーザーの行動や反応を測定できる機能であることが重要です。この辺りはGoogle AnalyticsやSearch Console、Clarityなどを導入すると良いかと思います。</p>
<p>フィードバックをもとに、どのように改善できるかが具体的にイメージできるとなお良いです。</p>
<h2>運用コストを考える</h2>
<p>個人開発では、運用コストの管理が特に重要です。</p>
<p>最初は無料枠の範囲内で始められるサービスを選ぶと良いと思います。例えば、Vercel + Supabase、Firebase、Herokuなど。</p>
<p>また自動化できる部分は最大限自動化し、運用の手間を減らします。</p>
<h2>マネタイズプランの検討</h2>
<p>個人開発でのサービス運営でよく見かける失敗の一つが、マネタイズプランを後回しにすることです。なぜなら運用コストが発生すると赤字になり続けるので、サービス運営をすることが困難になるからです。</p>
<p>最低でも運営コストを稼げるくらいのマネタイズを考えておくと良いでしょう。</p>
<p>個人開発の開始前から以下の点を検討しておく必要があります。</p>
<h3>1. 収益モデルの選択</h3>
<p>サービスの性質に合わせて、適切な収益モデルを選択します。例えば以下などがあります。</p>
<h4>広告収入</h4>
<ul>
<li>メリット：ユーザーの金銭的負担がなく、導入が容易</li>
<li>デメリット：安定した収益を得るには大量のPVが必要</li>
<li>具体例：月間10万PVで1-2万円程度の収入が目安</li>
<li>向いているサービス：情報提供系、メディア系</li>
</ul>
<h4>サブスクリプション（月額課金）</h4>
<ul>
<li>メリット：安定した収益が見込める、売上予測がしやすい</li>
<li>デメリット：継続的な価値提供が必要、解約率の管理が重要</li>
<li>具体例：月額500円×継続ユーザー100人で月5万円の収入</li>
<li>向いているサービス：ツール系、サービス系</li>
</ul>
<h4>プラットフォーム手数料</h4>
<ul>
<li>メリット：取引規模に応じて収益が増加、ユーザー同士の取引から収益化</li>
<li>デメリット：両面市場の運営が必要、初期の流動性確保が課題</li>
<li>具体例：取引額の3-15%程度を手数料として徴収</li>
<li>向いているサービス：マッチングサービス、マーケットプレイス</li>
<li>補足：出品手数料、決済手数料、プレミアム掲載料など複数の収益源を組み合わせることも</li>
</ul>
<h4>ライセンス販売</h4>
<ul>
<li>メリット：一度の開発で複数回販売可能</li>
<li>デメリット：継続的なアップデートやサポートが必要</li>
<li>具体例：永続ライセンスを1-5万円で販売</li>
<li>向いているサービス：デスクトップアプリ、専門的なツール</li>
</ul>
<h4>フリーミアム</h4>
<ul>
<li>メリット：導入障壁が低く、優良ユーザーの囲い込みが可能</li>
<li>デメリット：無料ユーザーのコスト負担、機能分けの難しさ</li>
<li>具体例：基本機能は無料、高度な機能は月額課金</li>
<li>向いているサービス：SaaS、モバイルアプリ</li>
<li>補足：無料プランと有料プランの機能差を明確に</li>
</ul>
<h4>アフィリエイト/紹介料</h4>
<ul>
<li>メリット：初期投資が少なく、成果に応じた収益</li>
<li>デメリット：提携先の選定や関係維持が重要</li>
<li>具体例：商品紹介による成果報酬、ユーザー紹介料</li>
<li>向いているサービス：情報メディア、比較サイト</li>
<li>補足：主要な収益源として、または副収入として活用可能</li>
</ul>
<p>個人開発の場合、最初は1つのモデルからスタートして、サービスの成長に合わせて他のモデルを追加していくのがおすすめです。</p>
<p>例えば、最初は広告収入からスタートし、ユーザーが増えてきたらプレミアム機能を追加してサブスクリプションを導入する、といった具合です。</p>
<p>個人開発では、全てを完璧にする必要はないです。まずは最小限の体制を整え、サービスの成長に合わせて徐々に改善していきましょう。</p>
<p>特に初期は、自動化できる部分は積極的に自動化し、人的リソースはサービスの改善や新機能の開発に集中することをおすすめします。</p>
<p>&nbsp;</p>
<h2>結果はそんな重要じゃない</h2>
<p>色々書きましたが、これらをやるのはぶっちゃけめんどくさいです。ここまでしてユーザーが集まらなかったらとか1円も稼げなかったらどうしようとかやってて思いがちですが、個人的にあまり意識しすぎない方が良いと思ってます。</p>
<p>これらに挑戦したこと自体に価値があり、それぞれ実践してアウトプットすることで確実に自分の経験となり、キャリアップや想定外のところで活きてきます。</p>
<p>つまり、やること自体、自分にプラスになっていると意識すると良いと思ってます。結果的にダメでも学びや気づきがあるので、過程を楽しむと良いと思います。</p>
<h2>まずはやってみよう！</h2>
<p>この記事に書いたことは、あくまでも私の経験からの「こうじゃないかな」という考えで、人によって正解は違うと思います。<br />
正直、最初から全部完璧にやろうとする必要はありません。</p>
<p>この記事に書いてあることを頭の片隅に置きつつ、まずは自分で何かアクションを起こしてみることをおすすめします。</p>
<p>例えば、気になる技術でとりあえず何か作ってみる、小さなツールでもいいので公開してみる、広告を入れてみて収益の仕組みを体験するなど実際に動いてみると、必ず何かしらの気づきがあります。</p>
<p>私も最初は全然うまくいきませんでしたが、少しずつ試行錯誤する中で、だんだんコツが掴めてきました。</p>
<p>大事なのは、完璧を目指すことではなく、実際に動いて学びを得ること。この記事が、皆さんの最初の一歩を踏み出すきっかけになれば嬉しいです！</p>The post <a href="https://mintaku-blog.net/before-personal-dev/">【実体験】個人開発でサービス運営を始める前に知っておくべきこと</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/before-personal-dev/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2573</post-id>	</item>
		<item>
		<title>マイクロサービスにおけるCDCについて</title>
		<link>https://mintaku-blog.net/cdc/</link>
					<comments>https://mintaku-blog.net/cdc/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Sun, 05 Feb 2023 00:35:50 +0000</pubDate>
				<category><![CDATA[まとめ系]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=2324</guid>

					<description><![CDATA[<p>マイクロサービスにおけるCDCについて色々腑に落ちてきたのでちょっと整理しておきます。 マイクロサービスにおけるE2Eの問題 マイクロサービス化したアプリケ …</p>
The post <a href="https://mintaku-blog.net/cdc/">マイクロサービスにおけるCDCについて</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>マイクロサービスにおけるCDCについて色々腑に落ちてきたのでちょっと整理しておきます。</p>
<h2>マイクロサービスにおけるE2Eの問題</h2>
<p>マイクロサービス化したアプリケーションにおいていくつものAPIなどが作られるかと思いますが、それぞれのマイクロサービスのモジュールE2Eを実行する際に、関連するマイクロサービスを立ち上げてテストをすることになるかと思います。</p>
<p>その場合、関連するAPIやDBなどを起動する必要があり、重くて時間がかかったり、そのマイクロサービスをテストしている間は他のmicroserviceをテストすることができないなどデメリットが出てきます。</p>
<p>そこで、関連する他のマイクロサービスをwiremockにすることで、作業がシンプルかつ軽くなり素早いテストが実現できます。</p>
<p>ただその場合だと、マイクロサービスの仕様が変わった場合、変更による影響を検知できなくなる可能性があります。つまり、テストで通ったのにいざ本場にデプロイしたら落ちるといったことが起こります。</p>
<p>これまでの話をまとめると、以下のようになります。</p>
<h3>関連するマイクロサービスを全て起動してテストする</h3>
<p><img data-attachment-id="2326" data-permalink="https://mintaku-blog.net/cdc/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2023-02-03-19-05-37/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/28e7db7604ea5dde146b3a12b4cdafbb.jpg?fit=1180%2C856&amp;ssl=1" data-orig-size="1180,856" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2023-02-03 19.05.37" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/28e7db7604ea5dde146b3a12b4cdafbb.jpg?fit=300%2C218&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/28e7db7604ea5dde146b3a12b4cdafbb.jpg?fit=800%2C580&amp;ssl=1" loading="lazy" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/28e7db7604ea5dde146b3a12b4cdafbb.jpg?resize=800%2C580&#038;ssl=1" alt="" width="800" height="580" class="aligncenter size-large wp-image-2326" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/28e7db7604ea5dde146b3a12b4cdafbb.jpg?resize=1024%2C743&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/28e7db7604ea5dde146b3a12b4cdafbb.jpg?resize=300%2C218&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/28e7db7604ea5dde146b3a12b4cdafbb.jpg?resize=768%2C557&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/28e7db7604ea5dde146b3a12b4cdafbb.jpg?w=1180&amp;ssl=1 1180w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>起動の手間や時間がかかるなどあるが、確実にテストすることができます。</p>
<p>&nbsp;</p>
<h3>関連するマイクロサービスをWiremockにしてテストする</h3>
<p><img data-attachment-id="2325" data-permalink="https://mintaku-blog.net/cdc/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2023-02-03-19-05-55/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/5c47e86cb301afb707ecac1d429d27fe.jpg?fit=940%2C694&amp;ssl=1" data-orig-size="940,694" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2023-02-03 19.05.55" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/5c47e86cb301afb707ecac1d429d27fe.jpg?fit=300%2C221&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/5c47e86cb301afb707ecac1d429d27fe.jpg?fit=800%2C591&amp;ssl=1" loading="lazy" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/5c47e86cb301afb707ecac1d429d27fe.jpg?resize=800%2C591&#038;ssl=1" alt="" width="800" height="591" class="aligncenter size-full wp-image-2325" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/5c47e86cb301afb707ecac1d429d27fe.jpg?w=940&amp;ssl=1 940w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/5c47e86cb301afb707ecac1d429d27fe.jpg?resize=300%2C221&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/5c47e86cb301afb707ecac1d429d27fe.jpg?resize=768%2C567&amp;ssl=1 768w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>手間がかからず素早く実行できるが、仕様の変更の影響などによりテストの挙動が担保することができない場合があります。</p>
<p>&nbsp;</p>
<p>それぞれのメリット・デメリットがあるなかで一つの解決策としてCDCがあります。</p>
<p>&nbsp;</p>
<h2>CDC(Consumer Driven Contract testing)とは</h2>
<p>CDCとは<span>APIやマイクロサービスの開発において、サービス間の契約を定義し、各サービスが契約に従って動作することを保証するための手法のことです。</span></p>
<p><span>サービス間の契約を明確にし、各サービスが互いに依存していることを考慮することで、サービスの信頼性を向上させることができます。</span></p>
<p>例えば、A社のあるAPIの口にリクエストしたら、こういったレスポンスを返して欲しい場合、A社にそのAPIの口のinputとoutputのテストを書いてもらい、その挙動を担保してもらうといったイメージかと思います。</p>
<p>先程の例だと、テスト対象のマイクロサービスと関連するマイクロサービスにCDCを結び、関連したマイクロサービスにinputとoutputのテストをしっかり書き、その挙動を担保します。</p>
<p>それぞれのマイクロサービスにCDCを結んでおくことで、モジュールE2Eを実行する際に関連するマイクロサービスをWiremockとすることができます。</p>
<p>図のイメージだとこんな感じです。</p>
<p><img data-attachment-id="2327" data-permalink="https://mintaku-blog.net/cdc/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2023-02-03-19-06-10/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/ae9ed35f6ef86365f773b3b9f07738a9.jpg?fit=1274%2C720&amp;ssl=1" data-orig-size="1274,720" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2023-02-03 19.06.10" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/ae9ed35f6ef86365f773b3b9f07738a9.jpg?fit=300%2C170&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/ae9ed35f6ef86365f773b3b9f07738a9.jpg?fit=800%2C452&amp;ssl=1" loading="lazy" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/ae9ed35f6ef86365f773b3b9f07738a9.jpg?resize=800%2C452&#038;ssl=1" alt="" width="800" height="452" class="aligncenter size-large wp-image-2327" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/ae9ed35f6ef86365f773b3b9f07738a9.jpg?resize=1024%2C579&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/ae9ed35f6ef86365f773b3b9f07738a9.jpg?resize=300%2C170&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/ae9ed35f6ef86365f773b3b9f07738a9.jpg?resize=768%2C434&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2023/02/ae9ed35f6ef86365f773b3b9f07738a9.jpg?w=1274&amp;ssl=1 1274w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>それぞれのマイクロサービスにCDCを結ぶ手間はありますが、テストがしやすくなりました。</p>
<p>ここまで書いて思ったのですが、それぞれのマイクロサービスでちゃんとモジュールE2Eを書いていれば、自然とCDCが結べていることになるのかとも思いましたが、CDCを結ぶという観点を持ってテストを書くと書かないとでは意味合いが違うような気もします。</p>
<p>CDCを結ぶことになると、変更をしたマイクロサービスはCDCを結んでいるマイクロサービスとの契約を守る必要があるため、影響範囲に気付くことになるのかなと思いました。</p>The post <a href="https://mintaku-blog.net/cdc/">マイクロサービスにおけるCDCについて</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/cdc/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2324</post-id>	</item>
		<item>
		<title>Kubernetesのクラスタやリソースを整理する</title>
		<link>https://mintaku-blog.net/kubernetes-cluster/</link>
					<comments>https://mintaku-blog.net/kubernetes-cluster/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Sun, 07 Aug 2022 11:10:36 +0000</pubDate>
				<category><![CDATA[まとめ系]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=2236</guid>

					<description><![CDATA[<p>業務で普段使っているKubernetesにおけるクラスタやリソースについて改めて調べ整理することで、イメージと理解をより深めることを目的に書いています。 ク …</p>
The post <a href="https://mintaku-blog.net/kubernetes-cluster/">Kubernetesのクラスタやリソースを整理する</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>業務で普段使っているKubernetesにおけるクラスタやリソースについて改めて調べ整理することで、イメージと理解をより深めることを目的に書いています。</p>
<h2>クラスタ(Cluster)</h2>
<p><img data-attachment-id="2238" data-permalink="https://mintaku-blog.net/kubernetes-cluster/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2022-07-16-12-58-30/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/796cc7a9ac0072075631b382790ae140.jpg?fit=1310%2C614&amp;ssl=1" data-orig-size="1310,614" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2022-07-16 12.58.30" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/796cc7a9ac0072075631b382790ae140.jpg?fit=300%2C141&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/796cc7a9ac0072075631b382790ae140.jpg?fit=800%2C375&amp;ssl=1" loading="lazy" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/796cc7a9ac0072075631b382790ae140.jpg?resize=800%2C375&#038;ssl=1" alt="" width="800" height="375" class="aligncenter size-large wp-image-2238" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/796cc7a9ac0072075631b382790ae140.jpg?resize=1024%2C480&amp;ssl=1 1024w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/796cc7a9ac0072075631b382790ae140.jpg?resize=300%2C141&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/796cc7a9ac0072075631b382790ae140.jpg?resize=768%2C360&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/796cc7a9ac0072075631b382790ae140.jpg?w=1310&amp;ssl=1 1310w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>クラスタは、コンテナ化されたアプリケーションを実行するためのノードマシンの集合です。クラスタには少なくとも、1 つのコントロールプレーン(マスターノードとも呼ばれている？)と、1 つ以上のノードと呼ばれるコンピューティングマシンが含まれます。</p>
<ul>
<li>コントロールプレーン：どのアプリケーションが実行されているかといった、クラスタの望ましい状態を維持</li>
<li>ノード：実際にアプリケーションとワークロードを実行</li>
</ul>
<p>以下のコマンドで、configの設定で指定されている接続先クラスター情報を確認できます。</p><pre class="crayon-plain-tag">$ kubectl config get-clusters

NAME
docker-desktop</pre><p>&nbsp;</p>
<h2>コンテキスト(Context)</h2>
<p>コンテキストはクラスタとユーザの組み合わせです。同一クラスタでも接続ユーザが異なれば、別のコンテキストとして扱われます。</p>
<p>以下のコマンドでコンテキストを取得できます。同じクラスタでもコンテキストが違っています。</p><pre class="crayon-plain-tag">$ kubectl config get-contexts

CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* docker-desktop docker-desktop docker-desktop
docker-desktop-2 docker-desktop docker-desktop</pre><p>&nbsp;</p>
<h2>名前空間(Namespace)</h2>
<p>名前空間とは、クラスタの分離機能のことで、複数のチームやユーザーでクラスターリソースを分割することができます。</p>
<p>名前空間を使うことで、Kubernetes内の環境に名前を付けて利用することができます。他の環境と分離させることができ、ユーザーによって権限を変えることも可能です。</p><pre class="crayon-plain-tag">$ kubectl get namespace

NAME STATUS AGE
default Active xxd
kube-node-lease Active xxd
kube-public Active xxd
kube-system Active xxd
sample Active xxd</pre><p>&nbsp;</p>
<h2>Pod</h2>
<p>Podは、1つまたは複数のコンテナのグループです。ストレージやネットワークの共有リソースを持ち、コンテナの実行方法に関する仕様を持っています。</p>
<p>Podとは、Kubernetesで実行できるアプリケーションの最小単位です。</p><pre class="crayon-plain-tag">$ kubectl get pod

NAME READY STATUS RESTARTS AGE
sample-78d9c99bd4-kdbwx 1/1 Running 0 xxd
sample-78d9c99bd4-m7mk2 1/1 Running 0 xxd</pre><p>&nbsp;</p>
<h2>Service</h2>
<p>Serviceとは、Podとの通信を容易に行うためにエンドポイントの提供を行ってくれる機能です。</p>
<p>通常、NodeのIPアドレスは一定ではないため、通信するにはその都度IPアドレスを指定する必要があります。</p>
<p>Serviceという機能があることで、通信するためのDNSラベルが発行され、アプリケーションが他のPodとの通信が簡単にできるようになります。</p><pre class="crayon-plain-tag">$ kubectl get service

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
sample-service NodePort 10.102.100.87 &lt;none&gt; 80:31512/TCP xxd</pre><p>&nbsp;</p>
<h2>Deployment</h2>
<p>DeploymentはPodやReplicaSetの宣言的なアップデート機能を提供します。</p>
<p>Kubernetesでは、Podを単独で起動することはほとんどなく、大抵の場合は、ReplicaSetやJobなどの管理用オブジェクトを通してPodを利用します。</p>
<p>ReplicaSetは、複数のPodのレプリカをセットで作成する機能で、DeploymentはさらにそのReplicaSetを管理します。</p>
<h3>ローリングアップデート</h3>
<p><img data-attachment-id="2237" data-permalink="https://mintaku-blog.net/kubernetes-cluster/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2022-07-16-12-43-03/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/0f3d7403024c66382a3b042485d97b68.jpg?fit=934%2C666&amp;ssl=1" data-orig-size="934,666" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="スクリーンショット 2022-07-16 12.43.03" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/0f3d7403024c66382a3b042485d97b68.jpg?fit=300%2C214&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/0f3d7403024c66382a3b042485d97b68.jpg?fit=800%2C570&amp;ssl=1" loading="lazy" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/0f3d7403024c66382a3b042485d97b68.jpg?resize=800%2C570&#038;ssl=1" alt="" width="800" height="570" class="aligncenter size-full wp-image-2237" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/0f3d7403024c66382a3b042485d97b68.jpg?w=934&amp;ssl=1 934w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/0f3d7403024c66382a3b042485d97b68.jpg?resize=300%2C214&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2022/07/0f3d7403024c66382a3b042485d97b68.jpg?resize=768%2C548&amp;ssl=1 768w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>Deploymentは、作成したPodの仕様が変更されると、自動的にReplicaSetを再作成します。</p>
<p>Deploymentのアップデート方法は、デフォルトでローリングアップデートとなっており、新しいReplicaSetを生成し、順に古いPodを新しいPodに入れ替えていきます。</p>
<p>そのため、ダウンタイムが発生しないというメリットがある代わりに、切り替えに多少時間がかかるというデメリットがあります。</p>
<p>上の図の例だと、下の新しいReplica Setが作成され、上の古いReplica Setで作成されたPodが、新しいReplica Setで作成されたPodに徐々に切り替わっていく感じです。</p><pre class="crayon-plain-tag">$ kubectl get deployment

NAME READY UP-TO-DATE AVAILABLE AGE
sample 2/2 2 2 xxd</pre><p>&nbsp;</p>
<h2>参考記事</h2>
<p><a href="https://kubernetes.io/ja/docs/concepts/overview/components/" target="_blank" rel="noopener">https://kubernetes.io/ja/docs/concepts/overview/components/</a></p>
<p><a href="https://udemy.benesse.co.jp/development/system/kubernetes.html" target="_blank" rel="noopener">https://udemy.benesse.co.jp/development/system/kubernetes.html</a></p>
<p><a href="https://kubernetes.io/ja/docs/concepts/workloads/pods/" target="_blank" rel="noopener">https://kubernetes.io/ja/docs/concepts/workloads/pods/</a></p>The post <a href="https://mintaku-blog.net/kubernetes-cluster/">Kubernetesのクラスタやリソースを整理する</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/kubernetes-cluster/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2236</post-id>	</item>
		<item>
		<title>TypeScriptの型とクラスについて学び直す</title>
		<link>https://mintaku-blog.net/ts-class/</link>
					<comments>https://mintaku-blog.net/ts-class/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Mon, 07 Feb 2022 13:34:13 +0000</pubDate>
				<category><![CDATA[まとめ系]]></category>
		<category><![CDATA[TypeScript]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=2146</guid>

					<description><![CDATA[<p>TypeScriptハンズオンとTypeScript Deep Diveを読んでTypeScriptの型とクラスについて学び直しました。 TypeScrip …</p>
The post <a href="https://mintaku-blog.net/ts-class/">TypeScriptの型とクラスについて学び直す</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>TypeScriptハンズオンとTypeScript Deep Diveを読んでTypeScriptの型とクラスについて学び直しました。</p>
<h2>TypeScriptの型システム</h2>
<p>型は、コードの品質と読みやすさを高めることができます。</p>
<p>また、型はリファクタリングをする際の開発スピードを高め、型があることによって、コードを書いている時点でエラーに気づくことができます。開発中に早い段階でエラーに気づけるのは大きなメリットです。</p>
<h2>暗黙的な型推論</h2>
<p>型推論とは、TypeScriptがソースコードを解析し、そのコードの流れから変数や関数などの型を推測してくれる仕組みのことです。</p>
<p>TypeScriptは型を推論することによって、不明確なコードに対しエラーを表示してくれます。</p>
<h2>明示的な型指定</h2>
<p>TypeScriptは型を推論しますが、型推論の結果が正しくない場合や正確でない場合は、開発者が、明示的にコード上で、型を指定する(型アノテーションを書く)ことができます。</p>
<p>型アノテーションを書くことによって、開発者にとってのドキュメントにもなります。</p>
<h2>TypeScriptの型の深堀り</h2>
<h3>型エイリアス</h3>
<p>指定した型に別名を設定することができます。エイリアスという名の通り、新しい型というよりかは既にある型に別の名前をつけているといった感じです。</p>
<p><mark>type 新型名 = 型名</mark></p><pre class="crayon-plain-tag">type name = string
type age = number

type person = [name, age]

const taro: person = ['taro', 20]</pre><p></p>
<h3>リテラル型</h3>
<p>リテラルというのは直接ソースコードに書かれる値のことです。以下のようにokだけしか値がない型が作れます。</p>
<p><mark>type ok = &#8216;ok&#8217;</mark></p>
<h3>条件型(Conditional Types)</h3>
<p>複数の型を許容する新しい型エイリアスが作成できます。</p>
<p><mark>type 型名 = 型1 | 型2 | …</mark></p>
<p>リテラル型と条件型を組み合わせることで、複数の値のいずれかを許容するenumのような働きをする型が作れます。</p>
<p><mark>type msg = &#8216;hello&#8217; | &#8216;bye&#8217;</mark></p>
<h3>ユーティリティ型</h3>
<p>変数のさまざまな性質を付加する特殊な型が用意されており、これらをユーティリティ型といいます。以下のようなユーティリティ型があります。</p>
<p><mark>Partial&lt;T&gt;</mark></p>
<ul>
<li>Partial&lt;T&gt;はTの全てのプロパティをOptional(任意)のプロパティにしてくれる</li>
</ul>
<p><mark>Required&lt;T&gt;</mark></p>
<ul>
<li>Required&lt;T&gt;はTの全てのプロパティを必須のプロパティにしてくれる</li>
</ul>
<p><mark>Readonly&lt;T&gt;</mark></p>
<ul>
<li>Readonly&lt;T&gt;はTの全てのプロパティをreadonlyのプロパティにしてくれる</li>
</ul>
<p>他のユーティリティ型などは以下を参照してください。</p>
<p><a href="https://qiita.com/k-penguin-sato/items/e2791d7a57e96f6144e5" target="_blank" rel="noopener">https://qiita.com/k-penguin-sato/items/e2791d7a57e96f6144e5</a></p>
<h3>総称型(ジェネリクス)</h3>
<p>総称型は値の型を特定せずに使用するための仕組みです。</p>
<p>&lt;T&gt;というのが、ここで使われている総称型の指定です。総称型は&lt;&gt;の中に抽象的な型を表す名前を指定します。このTは別にTでなくても良いが、TypeScriptではTから始まるアルファベットを使う習慣があるそうです。</p>
<p>複数の総称型を指定したい場合は&lt;T, U, V…&gt;という具合でカンマ区切りで記述します。</p>
<p><mark>function 関数 &lt;T&gt; (引数) : 戻り値</mark></p>
<p>ジェネリクスでUnitテストで使うmockを作ると以下のように書けそうです。</p><pre class="crayon-plain-tag">function mock&lt;T&gt;(): T {
  return ({} as unknown) as T
}</pre><p>&nbsp;</p>
<h2>TypeScriptのクラスの深堀り</h2>
<h3>インターフェース</h3>
<p>インターフェースはオブジェクト構造を記述するための仕組みです。インターフェースではオブジェクトに用意するプロパティやメソッドを用意できます。</p>
<p>ただあくまでインターフェースは構造の定義をするもので、そのまま使ってオブジェクトを作ることはできません。</p>
<p><mark>interface 名前 {</mark><br />
<mark>  プロパティ: 型</mark><br />
<mark>  メソッド(引数): 型</mark><br />
<mark>  …</mark><br />
<mark>}</mark></p>
<h3>インターフェースの実装</h3>
<p>用意されたインターフェースは、クラスに指定することで利用されます。クラス名の後にimplementsというキーワードを付けます。</p>
<p>このようにimplementsするとそのクラスでは組み込まれたインターフェースに用意されているプロパティやメソッドを全て用意しなければならないです。</p>
<p>つまりインターフェースはクラスにプロパティやメソッドの実装を保証するものです。</p>
<p><mark>class 名前 implementes インターフェース</mark></p>
<p>クリーンアーキテクチャで考えると、Portレイヤーにインターフェースを定義し、Gatewayレイヤーで実装する感じになりそうです。</p><pre class="crayon-plain-tag">interface SamplePort {
  find(): Promise&lt;number&gt;
}

export class SampleGateway implements SamplePort {
  async find(): Promise&lt;number&gt; {
    …
  }

}</pre><p></p>
<h3>インターフェースの継承</h3>
<p>インターフェースを定義するときに「extends インターフェース」と指定することで、既にあるインターフェースを継承した新たなインターフェースを作成できます。</p>
<p>継承して作られたインターフェースはimplementesする際に継承もとのインターフェースに用意されているプロパティやメソッドまで含めて全て実装する必要があります。</p>
<h3>抽象クラス</h3>
<p>インターフェースと似たような働きをするものに抽象クラスがあります。抽象クラスは具体的な処理を持たない抽象的な存在としてのクラスです。</p>
<p>クラス定義の冒頭にabstractを付けることで抽象クラスになります。またメソッドもabstractをつけることで抽象メソッドになります。</p>
<p><mark>abstract class クラス名 {</mark><br />
<mark>  abstract メソッド(): 型</mark><br />
<mark>  …</mark><br />
<mark>}</mark></p>
<h3>抽象クラスとインターフェースの違い</h3>
<p>抽象クラスとインターフェースはかなり似ています。ほぼimplementesするかextendsするかの違いですが、それでも以下のような違いがあります。</p>
<h4>他にクラスを継承する必要があるか</h4>
<p>もし他のクラスを継承するのであれば、抽象クラスは使えません。extendsで継承できるのは1つのクラスのみであるため、抽象クラスと他のクラスを同時に継承できません。</p>
<h4>プロパティを義務付けるか</h4>
<p>抽象クラスは基本的にメソッドを定義するものです。抽象プロパティはないため実装クラスに必ずプロパティを用意させたければインターフェースを使う必要があります。</p>
<h3>静的メンバー</h3>
<p>基本的にプロパティやメソッドはインスタンスを作成して利用するという共通点があります。クラスは基本的にインスタンスを作って利用するものであるため当然とも言えます。</p>
<p>ただ場合によってはインスタンスが必要ないクラスもあります。こうした場合クラスのプロパティやメソッドを静的メンバーとして用意することで、クラスから直接使えるようにできます。</p>
<p>この静的メンバーは「static」というキーワードを使って作成します。</p>
<p><mark>static プロパティ: 型</mark><br />
<mark>static メソッド(引数): 型</mark></p>
<h3>パラメータプロパティ</h3>
<p>読み取りのみのプロパティを扱う場合、パラメータプロパティと呼ばれる機能を使う方法があります。</p>
<p>パラメータプロパティはコンストラクタの引数をそのままプロパティとして扱えるようにする機能です。コンストラクタにreadonlyを指定したプロパティを用意するとそれは「変更不可のプロパティ」として使えるようになります。</p><pre class="crayon-plain-tag">class People {
  constructor(
    readonly name: string
  ) {}
}</pre><p>&nbsp;</p>The post <a href="https://mintaku-blog.net/ts-class/">TypeScriptの型とクラスについて学び直す</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/ts-class/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2146</post-id>	</item>
		<item>
		<title>Vue.jsの特徴やライフサイクル、Vuexなどについて整理する</title>
		<link>https://mintaku-blog.net/about-vuejs/</link>
					<comments>https://mintaku-blog.net/about-vuejs/#respond</comments>
		
		<dc:creator><![CDATA[みんたく]]></dc:creator>
		<pubDate>Sun, 11 Jul 2021 01:25:39 +0000</pubDate>
				<category><![CDATA[Vue.js]]></category>
		<category><![CDATA[まとめ系]]></category>
		<guid isPermaLink="false">https://mintaku-blog.net/?p=2022</guid>

					<description><![CDATA[<p>Vue.jsの特徴やライフサイクル、Vuexなどについて改めて理解を深めるためにも自分なりに整理しました。 Vue.jsの特徴 Progressive Fr …</p>
The post <a href="https://mintaku-blog.net/about-vuejs/">Vue.jsの特徴やライフサイクル、Vuexなどについて整理する</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></description>
										<content:encoded><![CDATA[<p>Vue.jsの特徴やライフサイクル、Vuexなどについて改めて理解を深めるためにも自分なりに整理しました。</p>
<h2>Vue.jsの特徴 Progressive Framework</h2>
<p><img data-attachment-id="2023" data-permalink="https://mintaku-blog.net/about-vuejs/the-progressive-framework/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/The-Progressive-Framework.png?fit=960%2C720&amp;ssl=1" data-orig-size="960,720" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="The Progressive Framework" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/The-Progressive-Framework.png?fit=300%2C225&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/The-Progressive-Framework.png?fit=800%2C600&amp;ssl=1" loading="lazy" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/The-Progressive-Framework.png?resize=800%2C600&#038;ssl=1" alt="" width="800" height="600" class="aligncenter size-full wp-image-2023" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/The-Progressive-Framework.png?w=960&amp;ssl=1 960w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/The-Progressive-Framework.png?resize=300%2C225&amp;ssl=1 300w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/The-Progressive-Framework.png?resize=768%2C576&amp;ssl=1 768w" sizes="(max-width: 800px) 100vw, 800px" data-recalc-dims="1" /></p>
<p>Vue.jsの特徴として、Progressive Frameworkという概念に基づいて開発されています。</p>
<p>ビルドシステムを利用せずにVue.js単体で使うことやVuexやvue-routerを使って動的なWebアプリケーションの構築もできます。</p>
<h3>Declative Rendering 宣言的なDOMレンダリングに関する領域</h3>
<p>テンプレートにレンダリングする対象を宣言的に記載することでDOMレンダリングやユーザによる入力データの同期が可能になります。Vue.jsでは本体自体でこの領域をサポートしているため、LPのようなシンプルなWebサイトはじめ、小規模的なものはこの領域で解決できます。</p>
<h3>Component System UIをモジュール化して再利用する必要がある領域</h3>
<p>Vue.js本体自体にコンポーネント化する機能があるため、それによって開発効率を向上させることが可能になります。</p>
<h3>Client-side Routing WebサイトがSPAとして必要とされるWebアプリケーションの領域</h3>
<p>Vue.jsが提供しているルーティングライブラリのvue-routerを利用することで、これまでに作成したコンポーネントでSPAに対応することが可能になります。</p>
<h3>Large-scale State Management コンポーネント間で状態の共有方法が必要となる領域</h3>
<p>Vue.jsが提供している状態管理ライブラリのVuexを利用することで、既存のコンポーネントを拡張する形で状態を集中管理することが可能になります。</p>
<h3>Build System コンポーネント管理やプロジェクト構成などの領域</h3>
<p>Vue.jsが提供しているvue-cliやvue-loaderなどを利用することで、プロジェクトの環境構築や構成管理の手間が省略かされ、継続的な開発を持続できるようになります。</p>
<p>&nbsp;</p>
<p>参考：<br />

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://vuex.vuejs.org/ja/">Vuex とは何か？ | Vuex</a>
			</p>
							<div class="ys-blog-card__dscr">
					Vue.js のための集中状態管理				</div>
										<div class="ys-blog-card__domain">vuex.vuejs.org</div>
					</div>
	</div>
</div>
<br />

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
					<figure class="ys-blog-card__image">
				<img src="https://i0.wp.com/gihyo.jp/assets/images/ICON/2016/1522_vuejs.png?w=800&#038;ssl=1" alt="" data-recalc-dims="1">			</figure>
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://gihyo.jp/dev/serial/01/vuejs/0001?page=2">第1回　プログレッシブフレームワーク Vue.js | gihyo.jp</a>
			</p>
							<div class="ys-blog-card__dscr">
					Vue.js（ビュージェイエス）は、インタラクティブなUIを構築するためのJav&hellip;				</div>
										<div class="ys-blog-card__domain">gihyo.jp</div>
					</div>
	</div>
</div>
<br />

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
					<figure class="ys-blog-card__image">
				<img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Farticle-ogp-background-afbab5eb44e0b055cce1258705637a91.png%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkYwJTJGMjc5NzMlMkZwcm9maWxlLWltYWdlcyUyRjE1ODUxOTM3Mjk_aXhsaWI9cmItNC4wLjAmYXI9MSUzQTEmZml0PWNyb3AmbWFzaz1lbGxpcHNlJmJnPUZGRkZGRiZmbT1wbmczMiZzPTYzNmU3NDRlNzg4MDMxM2NjZDVmMTJlODJhZThkNDM1%26blend-x%3D120%26blend-y%3D467%26blend-w%3D82%26blend-h%3D82%26blend-mode%3Dnormal%26s%3D83413c28100a79c361c9eb154280a278?ixlib=rb-4.0.0&amp;w=1200&amp;fm=jpg&amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9VnVlLmpzJTIwUHJvZ3Jlc3NpdmUlMjBGcmFtZXdvcmslMjAmdHh0LWFsaWduPWxlZnQlMkN0b3AmdHh0LWNvbG9yPSUyMzFFMjEyMSZ0eHQtZm9udD1IaXJhZ2lubyUyMFNhbnMlMjBXNiZ0eHQtc2l6ZT01NiZ0eHQtcGFkPTAmcz04ZWY3OTEzNWJjMGE3NjMzNGNmODdhMmFiMDAxMzBjNQ&amp;mark-x=120&amp;mark-y=112&amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDBtaWtha2FuZSZ0eHQtY29sb3I9JTIzMUUyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTM2JnR4dC1wYWQ9MCZzPWVhYTUxZDEzZjFhZmM5ZjU2OTk4YTM0MTE2MjBmMWEz&amp;blend-x=242&amp;blend-y=480&amp;blend-w=838&amp;blend-h=46&amp;blend-fit=crop&amp;blend-crop=left%2Cbottom&amp;blend-mode=normal&amp;s=3023216ec89ed77c2258ebed1b790de4" alt="">			</figure>
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://qiita.com/mikakane/items/3bd6af69259f5af6fecb">Vue.js Progressive Framework  #Vue.js - Qiita</a>
			</p>
							<div class="ys-blog-card__dscr">
					Vue.js の作者Evan氏によるVue.jsの紹介スライドで触れられていた「&hellip;				</div>
										<div class="ys-blog-card__domain">qiita.com</div>
					</div>
	</div>
</div>
<br />
<a href="https://amzn.to/3k4ooBe" target="_blank" rel="noopener">Hello!! Vue.js　最新プログレッシブフレームワーク入門</a></p>
<p>&nbsp;</p>
<h2>ライフサイクル</h2>
<p><img data-attachment-id="2024" data-permalink="https://mintaku-blog.net/about-vuejs/lifecycle/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/lifecycle.png?fit=1200%2C3039&amp;ssl=1" data-orig-size="1200,3039" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="lifecycle" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/lifecycle.png?fit=118%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/lifecycle.png?fit=404%2C1024&amp;ssl=1" loading="lazy" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/lifecycle.png?resize=404%2C1024&#038;ssl=1" alt="" width="404" height="1024" class="aligncenter size-large wp-image-2024" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/lifecycle.png?resize=404%2C1024&amp;ssl=1 404w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/lifecycle.png?resize=118%2C300&amp;ssl=1 118w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/lifecycle.png?resize=768%2C1945&amp;ssl=1 768w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/lifecycle.png?resize=809%2C2048&amp;ssl=1 809w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/lifecycle.png?w=1200&amp;ssl=1 1200w" sizes="(max-width: 404px) 100vw, 404px" data-recalc-dims="1" /></p>
<h3>ライフサイクルフック</h3>
<p>Vueのインスタンスは、インスタンスを生成時やDOM要素へのマウント時、データ更新時など、ある特定のタイミングでユーザが処理を行えるようにいくつかのライフサイクルフックが実行されます。</p>
<h4>beforeCreate</h4>
<p>インスタンスの初期化時に実行されます。dataなどのプロパティは生成前のためアクセスできません。</p>
<h4>created</h4>
<p>インスタンスの初期化後に実行されます。この時点でプロパティへのアクセスが可能になります。</p>
<h4>beforeMount</h4>
<p>マウント前に実行されます。この時点ではDOM要素にはアクセスできません。</p>
<h4>mounted</h4>
<p>マウント後に実行されます。この時点でDOM要素へのアクセスが可能になります。</p>
<h4>beforeUpdate</h4>
<p>DOM更新前に実行されます。</p>
<h4>update</h4>
<p>DOM更新後に実行されます。</p>
<h4>beforeDestroy</h4>
<p>インスタンスの破棄の前に実行されます。この時点ではプロパティへのアクセスは可能です。</p>
<h4>destroyed</h4>
<p>インスタンスが破棄された後に実行されます。この時点からプロパティへのアクセスはできません。</p>
<p>&nbsp;</p>
<h3>ライフサイクルフックの動きを確認する</h3>
<p>実際にいくつかのライフサイクルフックを使って動きを確認してみました。</p>
<h4>beforeCreate</h4>
<p>インスタンス初期化時に実行されます。このタイミングでは、インスタンスは初期化前ですので、msgは呼ばれません。</p><pre class="crayon-plain-tag">&lt;script&gt;
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  beforeCreate () {
    console.log('beforeCreate：' + this.msg)
  }
}
&lt;/script&gt;</pre><p></p><pre class="crayon-plain-tag">// beforeCreate：undefined</pre><p></p>
<h4>created</h4>
<p>インスタンス生成後に実行されるため、msgが呼び出されます。</p><pre class="crayon-plain-tag">&lt;script&gt;
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  created () {
    console.log('created：' + this.msg)
  }
}
&lt;/script&gt;</pre><p></p><pre class="crayon-plain-tag">// created：Welcome to Your Vue.js App</pre><p>&nbsp;</p>
<h4>beforeMount</h4>
<p>インスタンスが作成された後、elementへのマウントされる前で実行されます。</p>
<p>そのためmsgは更新されず、「Welcome to Your Vue.js App」と表示されます。</p><pre class="crayon-plain-tag">...

  &lt;h1&gt;{{ msg }}&lt;/h1&gt;

...

&lt;script&gt;
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  beforeMount () {
    this.msg = 'Update Your Vue.js App'
  }
}
&lt;/script&gt;</pre><p></p><pre class="crayon-plain-tag">// Welcome to Your Vue.js App</pre><p>&nbsp;</p>
<h4>mounted</h4>
<p>elementへのマウントがされた後に実行されるため、msgが更新され「Update Your Vue.js App」と表示されます。</p>
<p>createdとの違いとしてmountedは、elementへのマウントが行われた後処理されます。また、mountedはSSRの場合は使えないので注意が必要です</p><pre class="crayon-plain-tag">...


  &lt;h1&gt;{{ msg }}&lt;/h1&gt;

...

&lt;script&gt;
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  mounted () {
    this.msg = 'Update Your Vue.js App'
  }
}
&lt;/script&gt;</pre><p></p><pre class="crayon-plain-tag">// Update Your Vue.js App</pre><p>&nbsp;</p>
<p>参考：<br />

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
					<figure class="ys-blog-card__image">
				<img src="https://i0.wp.com/jp.vuejs.org/images/logo.png?w=800&#038;ssl=1" alt="" data-recalc-dims="1">			</figure>
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://jp.vuejs.org/v2/guide/instance.html">Vue インスタンス — Vue.js</a>
			</p>
							<div class="ys-blog-card__dscr">
					Vue.js - The Progressive JavaScript Fram&hellip;				</div>
										<div class="ys-blog-card__domain">jp.vuejs.org</div>
					</div>
	</div>
</div>
<br />

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
					<figure class="ys-blog-card__image">
				<img src="https://i.vimeocdn.com/video/699168105-5c72ea3b44769bd02e93b27405737287cc7693eeda72cc92346b2c7d02382d9e-d_1280x720?r=pad" alt="">			</figure>
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://vueschool.io/lessons/understanding-the-vuejs-lifecycle-hooks?friend=vuejs">Understanding the Vue.js Lifecycle Hooks</a>
			</p>
							<div class="ys-blog-card__dscr">
					Each Vue instance has many lifecycle hoo&hellip;				</div>
										<div class="ys-blog-card__domain">vueschool.io</div>
					</div>
	</div>
</div>
</p>
<p>&nbsp;</p>
<h2>Vuex</h2>
<p><img data-attachment-id="2025" data-permalink="https://mintaku-blog.net/about-vuejs/vuex/" data-orig-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/vuex.png?fit=701%2C551&amp;ssl=1" data-orig-size="701,551" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="vuex" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/vuex.png?fit=300%2C236&amp;ssl=1" data-large-file="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/vuex.png?fit=701%2C551&amp;ssl=1" loading="lazy" src="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/vuex.png?resize=701%2C551&#038;ssl=1" alt="" width="701" height="551" class="aligncenter size-full wp-image-2025" srcset="https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/vuex.png?w=701&amp;ssl=1 701w, https://i0.wp.com/mintaku-blog.net/mintaku/wp-content/uploads/2021/07/vuex.png?resize=300%2C236&amp;ssl=1 300w" sizes="(max-width: 701px) 100vw, 701px" data-recalc-dims="1" /></p>
<p>VuexとはVue.js アプリケーションのための 状態管理パターン + ライブラリです。</p>
<p>Vuexを使うことで、複雑に構成されたコンポーネントでのデータ管理の難しさを解決することができます。</p>
<p>Vuexという一つの入れ物にデータを入れることで、どのコンポーネントからでもVuex内に保持するデータへのアクセスが可能になります。</p>
<h3>Actions</h3>
<p>API等と非同期通信を行い、データを取得します。取得後はデータをコミットし、Mutationsを呼び出します。</p>
<h3>Mutations</h3>
<p>Actionsやコンポーネントからデータがコミットされた時に呼び出されます。唯一State内のデータを変更することが出来ます。</p>
<h3>State</h3>
<p>各コンポーネントで使用するデータはここに集約します。</p>
<h3>Vuexの使いどころ</h3>
<p>Vuexの使いどころについては以下の記事がとても参考になりました。</p>
<p>そもそもVuexを使うべきか、使うとしてもOrganismレベル以上のコンポーネントからのみStoreの参照、変更を許可するなど、どういったルールで運用すべきかを考慮することが大切です。</p>
<p>参考：<br />

<div class="ys-blog-card">
	<div class="ys-blog-card__container">
				<div class="ys-blog-card__text">
			<p class="ys-blog-card__title">
				<a class="ys-blog-card__link" href="https://python.ms/vuex/#vuex-%E4%BB%A5%E5%A4%96%E3%81%AE%E3%82%A2%E3%83%95%E3%82%9A%E3%83%AD%E3%83%BC%E3%83%81">なんで Vuex はなるべく避けるの？ | 民主主義に乾杯</a>
			</p>
							<div class="ys-blog-card__dscr">
					副作用を持ち、意識する範囲が広がるから。				</div>
										<div class="ys-blog-card__domain">python.ms</div>
					</div>
	</div>
</div>
</p>The post <a href="https://mintaku-blog.net/about-vuejs/">Vue.jsの特徴やライフサイクル、Vuexなどについて整理する</a> first appeared on <a href="https://mintaku-blog.net">みんたく</a>.]]></content:encoded>
					
					<wfw:commentRss>https://mintaku-blog.net/about-vuejs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2022</post-id>	</item>
	</channel>
</rss>
