fincode

Product Blog

CloudWatch Logs Insightsでログを抽出・分析する

fincode開発チームです! 今回は、fincodeでも利用しているAmazon Web Services(AWS)のCloudWatch Logs Insightsを使用して、アプリケーションのログを簡単に抽出し、分析する方法を紹介したいと思います。 はじめに アプリケーションの運用や開発において、ログデータは貴重な情報源です。エラーや警告、トランザクションの記録など、アプリケーションの挙動や状態を理解するために不可欠な要素です。 しかし、アプリケーションが成長し、複雑化するにつれて、ログデータの量も増加し、その分析はますます困難になっています。 ここで登場するのが、Amazon Web Services(AWS)の提供するCloudWatch Logs Insightsです。このサービスは、ログデータを簡単に抽出し、リアルタイムで効果的に分析するための強力なツールです。 ログデータから価値ある情報を引き出し、アプリケーションのパフォーマンスを向上させる手助けをしてくれます。 CloudWatch Logs Insightsとは CloudWatch Logs Insightsは、AWSのモニタリングおよび管理サービスであるCloudWatchの一部として提供されています。このサービスを使用することで、アプリケーションのログデータをリアルタイムで簡単にクエリし、分析することができます。 従来のログの探索や分析では手間がかかっていた作業が、CloudWatch Logs Insightsを使用することで迅速かつ効率的に行えるようになります。 ログの重要性 ログデータは、アプリケーションがどのように動作しているか、ユーザーやシステムとのインタラクションがどのように進行しているかを記録する貴重な情報源です。特に、以下のような状況でログの分析が重要となります。 エラーのトラブルシューティング: エラーメッセージやスタックトレースを分析することで、アプリケーションの不具合を特定し、修正する手助けをします。 パフォーマンスの最適化: レスポンスタイムやリソース使用量などの情報を分析することで、アプリケーションのボトルネックを特定し、パフォーマンスを向上させる施策を打つことができます。 セキュリティ監視: 不正アクセスや異常なアクティビティを検知するために、アクセスログや認証イベントを監視することが重要です。 CloudWatch Logs Insightsは、これらの課題に取り組むためのツールとして優れた機能を提供しており、ログの分析作業を効率化し、アプリケーションの品質向上に寄与します。 次に、CloudWatch Logs Insightsの基本的な概念や操作方法について探求していきましょう。 実際に使ってみる 1.Logs Insights(ログのインサイト)を開く AWSコンソールからCloudWatchを開きログ>ログのインサイトを選択。 2.ロググループを選ぶ 抽出したいログが出力されてるロググループを選ぶ。(複数選択できる) 3.ログを抽出するクエリを書いて実行する クエリを書くことでログの表示ができる。(SQLみたいな感じ) @messageに1レコードのログが入っている。 そこからfilterを使って不要なログのレコードは取り除いたり、PARSEを使って欲しい情報のみを抽出してフィルタリング(filter)に使ったり並び替え(sort)に使ったりできる。 今回はAPI Gatewayのログを見てみることにします。 参考 CloudWatch Logs Insights のクエリ構文 - Amazon CloudWatch Logs API Gateway での CloudWatch による REST API のログの設定 CloudWatch Logs Insights は、さまざまなタイプのログをサポートします。Amazon CloudWatch Logs に送信されるすべてのログについて、CloudWatch Logs Insights は 5 つのシステムフィールドを自動的に生成しています。 フィールド名 備考 @message 生の未解析のログイベント。要はアプリで出力したログの中身 @timestamp ログイベントの timestamp フィールドに含まれるイベントタイムスタンプ。 @ingestionTime CloudWatch Logs によって受信された時間。 @logStream ログイベントの追加先のログストリームの名前を示します。ログストリームは、生成時と同じプロセスでログをグループ化します。 @log ロググループ識別子。 API Gatewayのログを見てみましょう。 下記のようなクエリを書いて実行することで、集計したデータを取得することができます。 fields@message # 単純に表示するとき | display@timestamp,path,httpMethod,status,authorizererror,dataProcessed,integrationErrorMessage,integrationLatency,sourceip # path毎に集計 | stats avg(integrationLatency) as avg_integrationLatency , sum(integrationLatency) as sum_integrationLatency , count(*) as count_path by path as path | sort count_path desc すると下記のように結果を出力できます。処理時間によってソート出来ていて、かつ各情報を簡潔に確認できますね。 @単純に表示するとき @path毎に集計 count(*) as path by pathのように記述することで、エンドポイント単位で集計することもできます。 4.使用したクエリを保存して他の人にも使ってもらう。 作ったクエリはAWSに保存できます。汎用性のあるものはできたら保存しておけば同一環境の他の人たちも気軽に使えて便利です。 まとめ この記事では、AWSのCloudWatch Logs Insightsを使ってアプリケーションのログをスマートに抽出し、リアルタイムで分析する方法をご紹介しました。 ログデータの探索や分析が面倒だった過去とは違い、CloudWatch Logs Insightsはその手間を劇的に削減してくれる頼もしいツールです。 fincodeではこのようなサービスを活用しながら継続的なサービスの改善に取り組んでいます! ご意見・ご要望もお待ちしております!  

開発チーム

UIコンポーネントのデモページを作成しました

fincode開発チームです! UIコンポーネントの「コーディングを始める」というページを作成したのでそのご紹介です。 https://docs.fincode.jp/payment/ui_component/demo fincodeでは、UIコンポーネントというWebサイトに埋め込めるカード情報入力フォームを提供しています。 詳しくはこちら UIコンポーネントは利用者が自由にカスタマイズできるようになっていて、 文字色や背景、ラベルの内容...などを任意の値に指定できるようにしています。 今回はdocs上に実際にUIコンポーネントのカスタマイズを試してどんなUIになるのか?をインタラクティブに試せるページを作成しました。 1.初期表示 ページを開くとこの画面が表示されます。 2.各パラメータを変更 今回はテキストを変えてみようと思います。 ラベルテキストの各項目を英語にし、 プレースホルダーテキストのカード名義人を変更し、「更新」を選択します。 すると... 3.更新後画面 UIコンポーネントが更新され、変更したパラメータ通りの表示になっていますね! また、左に記載されているコードブロックはUIコンポーネントのサンプルコードです。 このページでお好みの文字や色に調整したあと、コードをコピーすればローカルでも利用できます! 今回はdocsに追加したUIコンポーネントの「コーディングを始める」ページの紹介でした。

開発チーム

fincodeの構築方法~UIコンポーネント編~

fincode開発チームです! fincodeを使ってみた 第四弾・UIコンポーネント編をご紹介します! 今回は、UIコンポーネントを使って決済画面を構築してみました。 htmlにformを埋め込み、fincodeJSを使ったコードを書くだけで簡単にカード入力フォームを配置することができたので、ぜひ使ってみてください! UIコンポーネントを使った決済フローは以下になります。 まず、[UI初期化]・[入力フォーム作成]・[UIマウント]を行うことで決済画面にカード入力フォームを配置します。 その後ユーザーが入力したカード情報を[入力フォーム情報取得]で取得します。 取得したカード情報と決済実行APIのレスポンスをもとに、[決済実行JS]を呼び出し決済を実行します。 以下で画面にカード入力フォームを埋め込んだコードを掲載します。フロントはVue.jsで実装しました。 実装メモ: ・htmlにformを挿入 ・fincodeJSの[UI初期化]・[入力フォーム作成]・[UIマウント]を実行 htmlタグ <form id="fincode-form"> <div id="fincode"> </div> <button v-on:click="payment" class="fincode-button"> <span>お支払い</span> </button> </form> JS <script src="https://js.test.fincode.jp/v1/fincode.js"></script> <script> const app = new Vue({ el: '#app', mounted() { setUiComponent() { const fincode = Fincode('p_prod_XXXXXXXXXXXXXXXX'); const appearance = { layout: "vertical", hideLabel: false, hideHolderName: false, hidePayTimes: true, labelCardNo: "カード番号", labelExpire: "有効期限", labelCvc: "セキュリティコード", labelHolderName: "カード名義人", cardNo: "1234 5678 9012 3456", expireMonth: "01", expireYear: "25", cvc: "001", holderName: "TARO YAMADA", colorBackground: "f7f6e7", colorBackgroundInput: "ecebd9", colorText: "333", colorPlaceHolder: "9a9a9a", colorLabelText: "314e52", colorBorder: "314e52", colorError: "990c02", colorCheck: "000054", } const ui = fincode.ui(appearance) ui.create("payments", appearance) ui.mount("fincode", "400") }, }, }); </script> 上記実装で構築した決済画面はこちらです↓ フォームのデザインを考える際にはDocsの[コーディングを始める]ページを使うのがおすすめです! UIコンポーネントのDocs 好きなカラーやレイアウトを選ぶだけで簡単にコードが生成できるようになっています。 皆さんも是非試してみてください!

開発チーム

fincodeの構築方法~リダイレクト型編~

fincode開発チームです! fincodeを使って決済実行してみた 第三弾・リダイレクト型決済編をご紹介します! (第一弾・決済JS編、第二弾・トークンJS編) リダイレクト型決済では、決済JS・トークンJSを用いた決済方法とは異なり fincodeが提供する決済画面を使用して決済が実行されます。 リダイレクト型決済のフローは以下になります。 まず、サーバから決済URL作成APIを実行し、決済URLを取得します。 取得したURLに遷移させることで、fincodeの決済画面での決済が可能となります。 オーソリ後に決済結果画面に遷移して完了です。 今回フロントはVue.js、バックエンドはnode.js(+ Express)で実装しました。 実装メモ: ■フロント ・axiosでバックエンドのAPIを呼び出す。 ・決済URL作成APIで取得したURLに遷移する。 ■バックエンド ・決済URL作成APIを実行する。 ※[success_url]→fincodeの決済画面で[お支払い]ボタン押下後、オーソリ完了時の遷移先を設定 [cancel_url]→fincodeの決済画面で[戻る]ボタン押下時の遷移先を設定 Vue.js <template> 省略 </template> <script> import axios from "axios"; export default { name: "redirectTest", data() { return { amount: "1000", }; }, methods: { redirect() {   //axiosでリクエストデータ送信   axios.post("http://localhost:3000/redirect", { amount: this.amount, }) .then((res) => { console.log(JSON.stringify(res)); //リダイレクト型リンクに遷移 window.location.href = res.data.link_url; }) .catch((err) => { console.log(err); }); }, }, }; </script> node.js var express = require('express'); var router = express.Router(); /* 決済URL作成呼び出しAPI * http://localhost:3000/redirect にPOSTを投げると、 * 決済URL作成APIのレスポンスをJSON形式で返す。 */ router.post('/', function (req, res, next) { "use strict"; const console = require("console"); const request = require("request"); const API_KEY = "Bearer m_prod_XXXXXXXXXXXXXXXX“”; const BASE_URL = "https://api.fincode.jp"; const endpoint = "/v1/sessions"; const DATA = { success_url: "http://localhost:3000/success", cancel_url: "http://localhost:3000/cancel", transaction: { amount: req.body.amount, }, }; const options = { url: BASE_URL + endpoint, proxy: PROXY_URL, headers: { "Content-Type": "application/json; charset=utf-8", Authorization: API_KEY, }, json: DATA, } main(); function main() { // 決済URL作成API呼び出し request.post(options, (error, response, body) => { if (200 != response.statusCode) { console.log("ERROR"); console.log(body); } else { console.log("SUCCESS"); console.log(body); res.header('Content-Type', 'application/json; charset=utf-8') res.send(body); } } ); } }); module.exports = router; ■画面イメージ 上記を実行するとサンプルの商品選択画面からfincodeの決済画面に遷移させることができました。 ・商品選択画面(サンプル) ↓ [購入画面へ]押下 ・fincodeが提供する決済画面 ※決済画面デザインは変更になる可能性があります

開発チーム

fincodeの構築方法~トークン決済編~

fincode開発チームです! fincodeを使って決済実行してみた 第二弾・トークン決済編をご紹介します! 今回は、fincodeが提供している決済フローのうち、トークンJSを使って構築してみました。 (第一弾・決済JS編はこちら)   トークンJSを使った決済フローは以下になります。 ■決済登録API + トークンJS + 決済実行APIのフロー まず決済登録APIを呼び出し、オーダーIDや取引IDを取得します。 次にフロント側でトークンJSを実行し、カード情報(カード番号・有効期限など)のトークン化を行います。 最後に決済実行APIを呼び出し、オーソリを実行します。 今回もフロントはVue.js、バックエンドはnode.js(+ Express)で実装しました。   実装メモ: ■フロント ・axiosでバックエンドのAPIを呼び出し、決済登録API・決済実行APIのレスポンスを受け取っている ・カード情報を引数に設定してトークンJSを呼び出す ・トークンJSでエラーの場合はエラーコードがリスト形式で複数返る ・APIキーはパブリックキーを使う Vue.js <script src="https://js.fincode.jp/v1/fincode.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <script> let fincode = Fincode('p_prod_XXXXXXXXXXXXXXXX'); const app = new Vue({ el: '#app', data() { return { card: { card_no: '', expire: '', holder_name: '', security_code: '' }, expire_mm: '', expire_yy: '', amount: "500", id: '', access_id: '', } }, methods: { submit() { this.card.expire = this.expire_yy + this.expire_mm; //axiosでリクエストデータ送信(①fincode決済登録呼び出しAPI) axios.post("http://localhost:3000/payment", { amount: this.amount }) .then((res) => { console.log(res); //決済登録APIのレスポンスを設定 this.id = res.data.id;; this.access_id = res.data.access_id; //トークンJS実行 fincode.tokens(this.card, (status, response) => { if (200 === status) { // トークンJS リクエスト正常時の処理 console.log(response); // 決済実行APIのリクエストパラメータを設定 const transaction = { id: this.id, access_id: this.access_id, token: response.list[0].token, //トークンJSで取得した値 }; //axiosでリクエストデータ送信(②fincode決済実行呼び出しAPI) axios.post("http://localhost:3000/execute", { data: transaction }).then((res) => { // リクエスト正常時の処理 console.log(res); alert("決済が完了しました"); }) .catch((err) => { console.log(err); }); } else { // トークンJS リクエストエラー時の処理 console.log(response); response.errors.forEach(error => { alert(error.error_message + "(" + error.error_code + ")"); }); } }, () => { // トークンJS 通信エラー処理。 alert("通信エラーが発生しました。しばらく経ってから再度お試しください。"); } ); }) .catch((err) => { console.log(err); }); }, } }); </script> ■バックエンド 2つのAPIを作成し、fincodeのAPIを呼び出す。 ①決済登録呼び出しAPI ・requestモジュールでfincode(決済登録API)にPOST通信 ・決済登録APIのレスポンスをフロントに渡す   ②決済実行呼び出しAPI ・requestモジュールでfincode(決済実行API)にPUT通信 ・決済実行APIのレスポンスをフロントに渡す ※①②とも、fincodeと通信する際のAPIキーはシークレットキーを使う。 node.js(①決済登録呼び出しAPI) var express = require('express'); var router = express.Router(); /* ①fincode決済登録呼び出しAPI * http://localhost:3000/payment にPOSTを投げると、 * 決済登録APIのレスポンスをJSON形式で返す。 */ router.post('/', function (req, res, next) { "use strict"; const console = require("console"); const request = require("request"); const API_KEY = "Bearer m_prod_XXXXXXXXXXXXXXXX"; const BASE_URL = "https://api.fincode.jp"; const endpoint = "/v1/payments"; const DATA = { pay_type: "Card", job_code: "CAPTURE", amount: req.body.amount, }; const options = { url: BASE_URL + endpoint, proxy: PROXY_URL, headers: { "Content-Type": "application/json; charset=utf-8", Authorization: API_KEY, }, json: DATA, } main(); function main() { request.post(options, (error, response, body) => { if (200 != response.statusCode) { console.log("ERROR"); console.log(body); } else { console.log("SUCCESS"); console.log(body); res.header('Content-Type', 'application/json; charset=utf-8') res.send(body); } } ); } }); module.exports = router; node.js(②決済実行呼び出しAPI) var express = require('express'); var router = express.Router(); /* ②fincode決済実行呼び出しAPI * http://localhost:3000/execute にPOSTを投げると、 * 決済実行APIのレスポンスをJSON形式で返す。 */ router.post('/', function (req, res, next) { "use strict"; const console = require("console"); const request = require("request"); const API_KEY = "Bearer m_prod_XXXXXXXXXXXXXXXX"; const BASE_URL = "https://api.fincode.jp"; const ID = req.body.data.id; const DATA = { pay_type: "Card", access_id: req.body.data.access_id, token: req.body.data.token, method: "1", }; console.log(DATA); main(); function main() { var endpoint = "/v1/payments/{id}".replace("{id}", ID); request.put( { url: BASE_URL + endpoint, proxy: PROXY_URL, headers: { "Content-Type": "application/json; charset=utf-8", Authorization: API_KEY, }, json: DATA, }, (error, response, body) => { if (200 != response.statusCode) { console.log("ERROR"); console.log(body); } else { console.log("SUCCESS"); console.log(body); res.header('Content-Type', 'application/json; charset=utf-8'); res.send(body); } } ); } }); module.exports = router; 上記を実行した結果、ダッシュボードから決済成功したことを確認できました。 (参考)決済実行APIからのレスポンス SUCCESS { acs: '0', shop_id: 's_21121014979', id: 'o_0TiOWd3DT5uWD-0nCOiZ4g', pay_type: 'Card', status: 'CAPTURED', access_id: 'a_Jou6XFKoT6KUjHNpG6XXKw', process_date: '2022/04/25 10:16:23.681', job_code: 'CAPTURE', item_code: '0000990', amount: 500, tax: 0, total_amount: 500, customer_group_id: null, customer_id: null, card_no: '************1234', card_id: null, expire: '2411', holder_name: 'Test', card_no_hash: '0e4802a01114169feded374beed5f7d810be72c4aed0118285169b2b57fd55ec', method: '1', pay_times: null, forward: '15250', issuer: '9999999', transaction_id: '2204251016602250501600919723', approve: ' 067736', auth_max_date: null, client_field_1: null, client_field_2: null, client_field_3: null, tds_type: '0', tds2_type: null, tds2_ret_url: null, tds2_status: null, merchant_name: null, send_url: null, subscription_id: null, error_code: null, created: '2022/04/25 10:16:22.771', updated: '2022/04/25 10:16:23.681' }

開発チーム

fincodeの構築方法~決済JS編~

fincode開発チームです! fincodeを使って決済実行してみたのでご紹介します! fincodeが提供している決済フローのうち、今回は決済登録API + 決済実行JSを使って構築しました。 決済登録API + 決済実行JSのフロー フロントはVue.js、バックエンドはnode.js(+ Express)で実装してみました。 バックエンドでは決済登録APIを呼び出して、取引IDなどのレスポンスを受け取っています。 フロント側では、画面入力されたカード情報(カード番号・有効期限・決済手段)と バックエンド側で登録した決済情報を受け取った後、決済実行JSを呼び出しています。 実装メモ ■フロント ・axiosでバックエンドのAPIを呼び出し、決済登録APIで登録した決済情報を受け取っている ・上記とカード情報を引数に設定して決済実行JSを呼び出す ・決済実行JSでエラーの場合はエラーコードが複数返る ・APIキーはパブリックキーを使う ■バックエンド ・requestモジュールでfincode(決済登録API)にPOST通信 ・レスポンスをフロントに渡す ・APIキーはシークレットキーを使う ■Vue.js <script src="https://js.fincode.jp/v1/fincode.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <script> let fincode = Fincode('p_prod_XXXXXXXXXXXXXXXX'); const app = new Vue({ el: '#app', data() { return { transaction: { id: "", pay_type: 'Card', access_id: '', card_no: '', expire: '', method: '1' }, expire_mm: '', expire_yy: '', holder_name: '', security_code: '', amount: "500" } }, methods: { submit() { this.transaction.expire = this.expire_yy + this.expire_mm; console.log(this.transaction); //axiosでリクエストデータ送信 axios.post("http://localhost:3000/payment", { amount: this.amount }) .then((res) => { //決済登録APIのレスポンスを設定 console.log(res); this.transaction.id = res.data.id;; this.transaction.shop_id = res.data.shop_id; this.transaction.access_id = res.data.access_id; //決済実行JS呼び出し fincode.payments(this.transaction, function (status, response) { if (status === 200) { console.log(response); // リクエスト正常時の処理 alert("決済が完了しました") } else { // リクエストエラー時の処理 console.log(response); response.errors.forEach(error => { alert(error.error_message + "(" + error.error_code + ")"); }); } }, function () { // 通信エラー処理。 alert("通信エラーが発生しました。しばらく経ってから再度お試しください。"); }); }) .catch((err) => { console.log(err); }); } } }); </script> ■node.js var express = require('express'); var router = express.Router(); /* fincode決済登録呼び出しAPI * http://localhost:3000/payment にPOSTを投げると、 * 決済登録APIのレスポンスをJSON形式で返す。 */ router.post('/', function (req, res, next) { "use strict"; const console = require("console"); const request = require("request"); const API_KEY = "Bearer m_prod_XXXXXXXXXXXXXXXX"; const BASE_URL = "https://api.fincode.jp"; const endpoint = "/v1/payments"; const DATA = { pay_type: "Card", job_code: "CAPTURE", amount: req.body.amount, }; const options = { url: BASE_URL + endpoint, proxy: PROXY_URL, headers: { "Content-Type": "application/json; charset=utf-8", Authorization: API_KEY, }, json: DATA, } main(); function main() { request.post(options, (error, response, body) => { if (200 != response.statusCode) { console.log("ERROR"); console.log(body); } else { console.log("SUCCESS"); console.log(body); res.header('Content-Type', 'application/json; charset=utf-8') res.send(body); } } ); } }); module.exports = router; 上記を実行した結果、ダッシュボードから決済成功したことを確認できました。 (参考)fincode 決済登録APIからのレスポンス SUCCESS { shop_id: 's_21121014979', id: 'o_m7cH7lzNSfKKHUMI5JxWkw', pay_type: 'Card', status: 'UNPROCESSED', access_id: 'a_0HiqJUxnQ9CSYu5Wxzq3IQ', process_date: '2022/03/23 18:14:30.259', job_code: 'CAPTURE', item_code: '0000990', amount: 1000, tax: 0, total_amount: 1000, customer_group_id: null, customer_id: null, card_no: null, card_id: null, expire: null, holder_name: null, card_no_hash: null, method: null, pay_times: null, forward: null, issuer: null, transaction_id: null, approve: null, auth_max_date: null, client_field_1: null, client_field_2: null, client_field_3: null, tds_type: '0', tds2_type: null, tds2_ret_url: null, tds2_status: null, merchant_name: null, send_url: null, subscription_id: null, error_code: null, created: '2022/03/23 18:14:30.259', updated: '2022/03/23 18:14:30.259' } POST /payment 200 3199.975 ms - 797

開発チーム

fincodeの決済APIの利用する仕組みと方法

fincode開発チームです! 本日は「fincodeの決済APIの利用する仕組みと方法」について話したいと思います。 fincodeの決済APIを利用してクレジットカード決済をする場合、様々な方法が用意されています。 決済を行う方法について大きく分けて3つに分かれているので、自分の使用感などを整理してみました。 方法 説明 リダイレクト型 fincodeが用意している決済画面に遷移して決済処理を行える方法です。 カード情報を入力させる画面を用意する必要ないのが楽です○ 決済実行(トークンJS) カード情報をトークン化して決済処理を行う方法です。 決済実行(決済実行JS) fincodeが公開しているJavaScriptライブラリのfincodeJSを使ってブラウザ上で決済処理を行う方法です。 自前で画面を用意してカスタマイズできます。また、APIを実行する部分はライブラリを利用できるので便利です。 大雑把にまとめるとこのような感じですね。 お手軽さを求めるならリダイレクト型、 ECサイトの中に支払い画面を組み込みたい場合や、デザイン性を高く求める場合は決済実行(決済実行JS)を使うのがベターです。 決済を行う方法ごとのフロー 今までに挙げた方法ごとのフローが下記になります。 リダイレクト型 決済実行(決済実行JS) 決済実行(トークンJS) 決済を行う方法の種類と比較 機能に分けて比較してみましたので、決済方法の選定の参考にしてみてください。 リダイレクト型 決済実行(決済実行JS) 決済実行(トークンJS) 顧客IDの利用 × 〇 〇 開発コスト ◎ ◎ △ カスタマイズ性 △ ◎ ◎ セキュリティ ◎ ◎ ◎ 終わりに 本日はfincodeの決済APIを利用する仕組みや方法について紹介しました。 どの方法がベストプラクティスであるかは、ユーザーごとに違うと思いますが、今回まとめたものが少しでも役に立てば幸いです。

開発チーム