TECH PLAY

ニフティ株式会社

ニフティ株式会社 の技術ブログ

487

はじめまして。 ニフティ株式会社の出口です。 今回は、私が所属している業務支援チームで行ったちょっとした工夫についてご紹介します。 自己紹介 まずは私の自己紹介です。 入社後、インフラ運用を、長く担当してきました。 入社当時は、小型冷蔵庫の様なサーバでしたが、徐々に小型化され、仮想化環境の導入、クラウド移行、マルチクラウド化と様々な経験をさせてもらいました。 今は、24時間365日、運用監視(サービス、システムの正常性確認)、システム業務支援 (オペレーション代行)を担っているチームでサブチームリーダーをさせてもらっています。 背景 依頼元から提示されたドキュメントの記載内容に沿って作業することが多いため、特定の分野において専門的な知識がなくても、業務を遂行する上で問題がない様になっていますが、 日々の作業で気づいた点はチーム内で共有し、効率化を図っています。 例えば、メッセージ検知後に依頼元へメール報告する際、メール本文のフォーマットを用意していましたが、メッセージが出力されたサービス・システムによって、メール報告先が多岐に渡ります。 このメッセージのメール送信先は?と確認している間に時間が過ぎてしまい、メッセージ出力からメール報告までに時間が掛かりすぎと依頼元から指摘されることもあります。 GASを利用したメール送信 メッセージ出力した際のメール送信先は、依頼元から指定されているので、メール本文とセットになっていれば迷うことなく、短時間で送信できるのにといったチームメンバの何気ない一言がきっかけです。 Google Formsはアンケートなどに利用する場合が多いですが、GASを利用して複数メールアドレスを送信先に指定できることは分かっていたので、試みることにしました。 1.送信メールのテンプレートを決めます。 2.Google Formsでフォームを作成します。 3.スクリプトエディタのコードに記入していきます。 ※「メッセージ出力システム・サービス」選択肢毎にメール送信先を指定します 4.スクリプトエディタのトリガーを設定します。 5.動作確認を実施して、問題なければリリースになります。 さいごに 社内でGASを利用した事例や、ネット公開されているブログを参考にさせてもらいました。 昔と違い、今は欲しい情報が直ぐに入手できますので、困ったことや実施してみたいことがあれば、参考にさせてもらっており、便利な世の中になったとつくづく感じています。 自発的に行った課題解決策に対して、依頼元やチームメンバから前向きな反応があればモチベーションも維持され、更なる要望にも応えたいと次の一手を模索しているところです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは!新卒入社4年目の小松です。主にお客様が初めて@niftyをご利用になる際の無料ID会員登録システム、いろいろなサービスをご利用になる際のログインシステムの開発・運用を担当しています。 今回はリモート会議のリアクションわかりづらい問題を解消するツール「もじこえ」を作ってみたので、紹介したいと思います。社内でも一部の会議では実際に使われています。 リモート会議はリアクションがわかりづらい 対面での会議と違って、参加者のリアクションがわかりづらいと感じたときはありませんか。 カメラ・マイクがオフの時はもちろん、うなずきや笑い声など些細なリアクションがわかりづらく、伝わっているのか不安になることがあります。 また実際にはワイワイとしている会議も、コメントを拾い忘れたり、盛り上がりに欠けるなと感じたこともあります。 そこで「もじこえ」を作りました。 もじこえ AI音声でコメント読み上げてくれる匿名チャットツールWebアプリです。 使い方は、リモート会議時に参加者が「もじこえ」をブラウザで開いてチャットします。 読み上げ音声は現在3種類で、コメント投稿ごとに切り替えできます。 実際に使ってみないと伝わりづらいかと思いますが、画面はこんな感じです。 まだデザインを考え中なので、プロトタイプになっています。 ちなみに名前の由来は、 GoogleMeet拡張機能の「こえもじ」 というものがありまして、Meetで話した内容を文字起こしして、コメント欄に追加してくれるものです。 その逆(テキスト→音声)もあればと思ったのが始まりでした。 試しに社内に公開してみましたが、意外と反応があり、社内のLT大会や勉強会などでも使われています。ちなみに私が所属する サービスインフラチーム では、毎日使っています。 もじこえ の中身 構成 バックエンドはNode.js + Expressで、Socket.IOを使ってリアルタイムチャットできるようにしています。音声変換はAWS SDKのPollyを使っています。 フロントは生HTMLとJQueryです。デザインはあとまわしにしているので、のちのちReactなどで作り直したいと思っています。 これらをAWSのFargateで動かしています。 後ほど紹介するSlack連携では、Slack Appを作成し、 Lambdaも使用しています。 読み上げ音声はAWSのAmazon Pollyを使用 Amazon Polly はテキストを音声に変換してくれるAWSのサービスです。様々な言語に対応し、日本語にも対応しています。 料金は、100万文字ごとに4ドルなので、そこまで気にせず使えるかなと思っています。今までで最高でも3ドル未満でした。 もじこえ には、3種類の音声を採用 日本語が話せる3種類の音声を採用しました。結構リアルです。 一番人気はマシューです。 ミズキ(女性) タクミ(男性) マシュー(外国籍で日本語も話せる男性) マシューの音声サンプル ソース紹介 まだリポジトリを公開できる状態ではないため、一部を紹介していきます。 テキスト→音声変換 部分 Node.js + Expressのサーバ側で、AWS SDKでPollyを使用します。 import AWS from "aws-sdk"; // この形式のファイルを作って、各自の値で埋める。 // { "accessKeyId": "", "secretAccessKey": "", "region": "" } AWS.config.loadFromPath('config.json'); const textToSpeakUrl = async (text, voiceId) =>{ // 決めた文字数以降は「省略」に変換 text = omitLongText(text); // URLは「URL省略」に変換 text = replacementUrl(text); // Create the JSON parameters for getSynthesizeSpeechUrl const speechParams = { OutputFormat: "mp3", SampleRate: "16000", // 読ませるテキスト Text: text, TextType: "text", // "Mizuki"などが入る。 VoiceId: voiceId }; let speakUrl; // Polly準備 const polly = new AWS.Polly({apiVersion: '2016-06-10'}); const signer = new AWS.Polly.Presigner(speechParams, polly); // 音声URLに変換 signer.getSynthesizeSpeechUrl(speechParams, function(error, url) { if (error) { return "" } else { speakUrl = url; } }); return speakUrl; } getSynthesizeSpeechUrl を使って、テキストを音声URLに変換します。 テキストの省略は、長すぎる文章と、URLは考慮して行っています。 そのままだと、URLは律儀に1文字ずつ読み上げてくれます。 ただし、各クライアント側で表示されるテキストは省略せずそのままで、音声変換時のみ省略されたテキストを使います。 チャット部分 Socket.IOを使ったチャット自体はよくある使い方です。単純にテキストと、音声変換した音声URLを各部屋のクライアント側に送信しているだけです。 サーバー側 io.on('connection',function(socket){ // 部屋入室 socket.on('enterTheRoom', function({roomId: roomId}){ socket.join(roomId); }) // テキストを受信したら、テキストと音声URLを送信 socket.on('speakTextRoom',async function(speakInfo){ const {speakText, voiceId, roomId, channelId} = speakInfo; // テキストを音声URLに変換 const speakUrl = await textToSpeakUrl(speakText, voiceId); const speakData = {speakText: speakText, speakUrl: speakUrl}; console.log(JSON.stringify({roomId: roomId, speakData: speakData})); // channelId があれば、Slack送信します。 if (channelId !== '') { // Slackに送信 postSlackMsg(channelId, voiceId, speakData); } io.to(roomId).emit('speakData', speakData); }); }); ここはシンプルですが、受け取ったテキストを音声URLに変換して、クライアント側に送信します。 channelId があれば、Slackにも送信します。 クライアント側 var socketio = io(); $(function () { // 部屋番号取得 const pathname = location.pathname; const roomId = pathname.split("room/").pop(); let channelId = ""; // 部屋入室 socketio.emit("enterTheRoom", {roomId: roomId}); // 送信 $("#message_form").submit(function () { // 空白、空文字は送信しない。 if ($("#input_msg").val().trim().length == 0 ) { $("#input_msg").val(""); return false; } // Slack連携flgがcheckedなら、channel_idを渡す。 if ((document.getElementById('slack_link')).checked) { // 先頭がCではないと、""に(channelId) if (roomId.slice(0, 1) === 'C') { channelId = roomId; } } else { channelId = ""; } // サーバに送信 socketio.emit("speakTextRoom", { speakText: $("#input_msg").val(), voiceId: $("#voiceId").val(), roomId: roomId, channelId: channelId} ); $("#input_msg").val(""); return false; }); // テキストと音声URLを受信 socketio.on("speakData", function (speakData) { $("#messages").append($("<li>").text(speakData["speakText"])); const music = new Audio(speakData['speakUrl']); // 音量 music.volume = Number($("#volume").val()); music.play(); // 自動スクロールにチャックなければ、 スクロールしない if ((document.getElementById('auto_scroll_flg')).checked) { $('.message_area').animate({scrollTop: $('.message_area')[0].scrollHeight}, 'fast'); } }); }); URLパス( /room/{各部屋番号} )ごとに部屋を分けるようにしているので、各部屋に入室させます。 Slack連携については、後述します。 音声URLの再生はシンプルで、 Audio() を使っています。 Slack連携 Slack連携をするようにした背景は、ニフティでは特定のリモート会議(大人数が参加するイベントなど)ではSlack実況チャンネルというものが存在していて、実況の分断をなくすためです。 現時点では、「もじこえ」、Slackの双方向にコメントがそれぞれのコメントが流れるようにしました。 もじこえ → Slackのチャンネル 部屋番号をSlackのチャンネルIDにすることで、( /room/{SlackのチャンネルID} )でチャンネルIDを取得します。Slack連携にチェックをつければ、サーバ側でwebhookを使ってSlackチャンネルに送信します。 SlackにPOSTするデータは以下です。現状おそらくSlackで音声再生はできないのですが、再生ボタンの絵文字を押せば、音声URLが開く仕組みにしています。 const payload = JSON.stringify({ channel: channelId, username: username, icon_emoji: iconEmoji, attachments: [ { color: "#ffdbb7", text: `${speakText}\n<${speakUrl}|:arrow_forward:>`, footer: `<{ドメイン}/room/${channelId}|fromもじこえ>`, }, ], }); Slackのチャンネル → もじこえ こちらは、Slack Appを作成して、メッセージデータを取れるようにしました。 データの受取先は手軽なAWS Lambda + API Gatewayにしました。 Lambda + API Gateway APIGatewayはLambdaのAPI化に使っただけで、特に珍しいこともしていないので、説明は省きます。 Lambdaソースは以下になります。 import json import logging import urllib.request import urllib.parse logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(data, context): logger.info(json.dumps(data)) if ('challenge' in data): return { "statusCode": 200, "body": json.dumps({'challenge': data['challenge']}) } # もじこえ用 if data.get("event") is not None: subtype = data["event"].get("subtype") # もじこえ など、botから送信されたメッセージは何もせずreturn if subtype == "bot_message": return text = data["event"].get("text") roomId = data["event"].get("channel") mojikoe_direct_posting(roomId, text) return { "statusCode": 200 } def mojikoe_direct_posting(roomId, text): params = urllib.parse.urlencode({'room': roomId, 'text': text}) url = '{ドメイン}/api/direct-posting?%s' %params req = urllib.request.Request(url) urllib.request.urlopen(req) return "ok" SlackのRequestを受け取るにはSlack Appで承認される必要があります。リクエストデータに challenge が含まれていたら、特定のレスポンスを返すようにします。 また双方向の実装するにあたり、考慮する必要があったのが、「もじこえ」→Slackに送信された場合、Slack AppのEventが発火され、「もじこえ」→ Slack → 「もじこえ」のように再び送信しようとすることです。 以下のように、SlackからPOSTされるデータの event の subtype を見ると、 bot_message になっているのがわかったので、ここで判別するようにしました。ちなみに、普通にSlackに投稿した場合は "type": "message" になります。 ~~~ "event": { "type": "message", "subtype": "bot_message", "text": "もじこえ から Slack に", "ts": "1661256966.757159", "username": "Mizuki", "icons": { "emoji": ":woman:" }, ~~~ 「もじこえ」に送信する部分については、「もじこえ」のサーバ側で簡単なAPIを作成したので、それを呼ぶだけです。 まずサーバ側で部屋名とメッセージを受け取り、音声はランダムにして、音声URLを作成し、対象の部屋に送信します。 サーバ側のソース // API app.get('/api/direct-posting' , async function(req, res){ const roomId = req.query.room; const voiceIds = ["Mizuki", "Matthew", "Takumi"] const voiceId = voiceIds[Math.floor(Math.random() * voiceIds.length)]; const speakUrl = await textToSpeakUrl(req.query.text, voiceId); const speakData = {speakText: req.query.text, speakUrl: speakUrl} io.to(roomId).emit('speakData', speakData); console.log(roomId, speakData); res.status(200); res.send("ok"); }); Slack Appの設定 Subscribe to bot events で message.channels を追加すると、作成したSlack Appが追加されているチャンネルでメッセージが投稿されたときに、連携したURLにデータをPOSTしてくれます。 ※外部にSlackメッセージが送信されるので、扱いには気をつける必要があります。 Lambda + API Gatewayで受け取る Request URL に追加して連携します。上で説明した、特定のレスポンスを返す用に実装しておくと承認されます。 準備ができたので、あとは連携したいチャンネルにSlack Appを招待。 「もじこえ」のURLを /room/{SlackのチャンネルID} にして、Slack連携のチェックをいれれば、完成です。 今後やること もともと勉強で作り始めたもので、まだまだやることがいっぱいあります。 フロントをReactなどで書き換える Slack連携のオンオフ制御 社内SSO連携 現在匿名でのコメントになるので、チームで相談してログ整備は必要ということになりました。 Meetの拡張機能にできないか調査 などなど またなにか進展があれば、ブログに書こうかと思ってます! 【告知】NIFTY Tech Dayで「もじこえ」について話すかもしれません! NIFTY Tech Day 2022 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは!新卒入社6年目の添野です。@niftyトップページシステムの開発・運用を担当しています。 先日「レガシーシステムからの脱却」に登壇しましたので、その様子を紹介していきます! イベント概要 NIFTY Tech Talk は、ニフティ株式会社の社員が主催するトークイベントです。 本イベントではニフティ社員が業務を通じて学んだことを発信しています。 第四回目となる今回は、「レガシーシステムからの脱却」に関するテーマで開催しました。 ニフティではさまざまなシステムの刷新やリプレースなどを行っています。今までのレガシーなシステムからモダンなシステムにどんどん切り替えていこうという流れが全社的に強くなっています。 イベントの詳細については こちら の記事でも紹介しておりますので、ぜひご覧ください。 また、今回の Tech Talk のアーカイブを YouTube にアップロードしております。 こちらもご覧いただけますと幸いです。 内容レポート オープニングからディスカッションに至るまでの各セッションにおいて一部抜粋して、どのような内容だったかご紹介したいと思います。 オープニング 今回も前回に引き続きYouTube Liveで開催しました。 はじめにニフティの会社紹介、登壇者の自己紹介から始まりました。 今回も最後にニフティポイントのプレゼントがありました! 今回の登壇者 小松 勇貴:会員システムグループ グループ長 島田 大徳:基幹システムグループ 課金システムチーム 村松 啓寛:会員システムグループ 第2開発チーム 添野 翔太:会員システムグループ 第1開発チーム 清水 利音:基幹システムグループ サービスインフラチーム 固定IP受付システム刷新 まず1つ目は、 @nifty 固定IPサービス の事例紹介です。 Kubernetesを活用してマイクロサービス化を図りながら新環境を構築を進めた話がありました。 レガシー脱却の背景 あるタイミングで新規のIPを払い出す話が浮上した際、前任者がチームを離れてしまったため改修に注力できない状況が生まれたとの話がありました。@nifty固定IPサービスのシステムはモノリスでブラックボックスとなっていたため、作るべきものを見定めた上でイチから作ることにしたそうです。 新環境の紹介 申込受付部分にフォーカスして説明がありました。新環境はEKS、NGINX、Djangoをベースに、 Argo CD なども組み合わせて構築したそうです。 新環境構築を通じて 構築を進めていく中でブラックボックスとなっていたシステムに関して要件が明らかになり、改修がしやすくなったそうです。また開発者のスキルが向上し、モチベーションも上がったそうです。 ニフティニュースの夜明け〜32万超のページをレガシーシステムから救出!〜 2つ目は、 @niftyニュース の事例紹介です。 ストラングラーパターンを利用し、モダンなアーキテクチャーへの段階的な移行について話がありました。 レガシー脱却の背景と目的 コア機能をニフティ独自のモノリスフレームワークで提供しているため、属人化が進みやすい、クラウドのスケーリングメリットなどの恩恵を受けられないという課題に加えて、@niftyニュース特有の課題についても触れられていました。 新環境の紹介 移行方針ストラングラーパターンについて説明がありました。またモダンな開発言語を採用し、オートスケーリングなどクラウドメリットを享受できるようなシステム構成にした話がありました。そして事前のページ出力に関してはSEOを意識してSSRを利用したそうです。 新環境構築を通じて 老舗ポータルサイトの新たなシステムへの挑戦 〜@niftyトップページ〜 3つ目は、筆者のセッションである @niftyトップページ の事例紹介です。 @niftyニュース と同様にストラングラーパターンを利用し、Next.js、AWSを使ってPC版ページの刷新を進めた話をしました。 レガシー脱却の背景と目的 長大なJavaScriptファイルや未使用なコードがあるなどの課題を解決することが目的であるという話をしました。 新環境の紹介 APIデータ連携を実施し、レガシーシステムからの脱却を着々と進めているという話をしました。 Serverless Framework 、改修対象を迅速に把握するために Atomic Design を駆使したアプリケーションの再構築、GitHub Actionsを用いたデプロイを実施していることを紹介しました。 他のGitブランチ戦略の記事 を参考にして策定した、新環境でのブランチ戦略を紹介しました。 新環境構築を通じて 内製で構築を進めたので、システムへの理解が進み、ドキュメントを新しくできていること、また最新技術に触れたことでメンバーのモチベーションが向上したという話をしました。 レガシーなシングルサインオンシステムを完全内製で作り直した話 最後は、ニフティシングルサインオン(SSO)システムの事例紹介です。 100を超えるサービスと連携する状況で、マネージドサービスを活用して問題に立ち向かった話をしていただきました。 レガシー脱却の背景 SSOシステムはスケールイン/アウトしにくいインフラ構成でバージョンアップも厳しいシステムであるという話がありました。またドキュメントが少なくブラックボックス化しているという話がありました。 新環境の紹介 メンバー一丸となり、コードリーディングを進め仕様を把握し、基本設計から作り直したそうです。またインフラはCDKを用いてIaC管理を進め、CloudWatchなどAWSサービスを用いた監視機構を導入したそうです。 新環境構築を通じて 完全内製で進めたことによりナレッジが残せたこと、インフラコストを削減できたことについて話がありました。 ディスカッション 今回は各システムの事例紹介後、登壇者間でディスカッションをする時間を設けました。 以下のテーマに沿って深堀りを進めました。 テーマ1:そもそもレガシーって何?(レガシーへのイメージ) テーマ2:皆さんのシステム、どれくらいレガシーなんですか?(レガシー度合いの自慢) テーマ3:レガシー脱却で苦労した話 テーマ4:レガシー脱却の対応状況 テーマ1:レガシーへのイメージ 今回のテーマである「レガシー」に関して、各自イメージを話しました。 気軽に変更できない、チーム離脱に伴い前任者が持っていた知見が失われている状態などが話に挙がりました。また新環境への構築を進めた我々が未来に負債を残さないという話も挙がりました。 テーマ2:レガシー度合いの自慢 レガシー脱却を進めていた中での苦しみを存分に話しました。何か変更を行う際に影響範囲がしっかりと分からない、何かあってもシステムを再構築できない、そして中にはテストも仕様書もないという悲しみを持つシステムがありました。 テーマ3:レガシー脱却で苦労した話 汎用的なシステムを利用しているがゆえの苦しみ、また知見が失伝されていることによる要件漏れ、連携先や連携要素の多さによるものが挙がっておりました。 テーマ4:レガシー脱却の対応状況 事例紹介の中では触れなかった進捗度合いについて話しました。各システムはおおむね道半ばという状況ですが、新環境での明るい未来の実現に向けてこれからも突き進んでいきたいという話がありました。 まとめ 今回の Tech Talk では、ニフティでのレガシー脱却について事例を交えて紹介しました。 1 時間という短い枠だったので、今回話しきれなかった内容もありますが、参考にできるものがあれば幸いです。 また後半ではディスカッションを行いました。社内の雰囲気を少しでも感じていただけたらありがたいです。 そして今回も質問やコメントをくださった方もいました。ありがとうございました。 今後も NIFTY Tech Talk は継続して実施していきますので、ぜひご参加ください。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
■始めに 初めまして。下屋敷と申します。 ニフティ株式会社に中途入社して5年目になります。 弊社では今AWSのサービスを次々と取り入れてシステム開発をしています。 ニフティでは回線接続サービスを提供していますが、私が担当しているシステムで回線申込時に特定オプションを申し込んだお客様に対して使用可になった際にSMS通知をしたいという要望があったため、Amazon SNSのSMSを用いて対象者へのSMS送信を導入、実装した話をお伝えしようと思います。 単にSMS送信をしたいだけなのですが、ネット検索をしてみてもトピック機能などの記事に寄ってしまっていたり、後述するサポート申請に関する記述が無かったりと、意外とそういった記事が無かったというのも書いてみようと思った理由です。 ■前提として オプションが使用可になった申込ユーザに対しては、ECSクラスターのタスクスケジューリングにて定期バッチ起動をして対象者へのSMS送信をします 特定オプションの申込は月500件想定なので、SMSを500件/月送信する予定です ■AWSコンソール上からSMS送信を試してみる テスト送信してみます ログイン後Amazon SNS(SMS)サービスへ移動 デフォルトはサンドボックス内になっている(詳細は後述)と思うので、先に電話番号を登録して認証します。※登録に関する手順詳細は割愛 ちなみに検証してみたところ「+810X0」形式でも「+81X0」形式でも送信できるみたいです。(boto3経由でも同様でした賢い!) 電話番号認証完了したら「テキストメッセージの発行」から発行してみます 既に登録された電話番号が送信先選択できるので選択して「送信者ID」も指定 届きました! ちなみに送信者ID指定しないと「NOTICE」として送信されます これで送信テストできました! ■Amazon SNS(SMS) を用いたメッセージ送信のソース(Python) awsコンソール上からのSMS送信は確認できました。 バッチからAmazon SNS(SMS)を呼び出して送信をしたいので、実装方法を確認します。 boto3のpublishを用いると送信が可能です( 機能詳細 ) boto3は実行環境にpip installしておきましょう 事前にAWSコンソール上のIAMよりIAMユーザーを作成し、 AmazonSNSFullAccess のアクセス許可を設定しておきます。その際に生成された アクセスキーID と シークレットアクセスキー を控えておきます サンプルソース(Python) 単にSMS送信を実行するだけなら以下のソースで行けるはずです。 実際は複数の電話番号にお送りすることになると思うので、対象の電話番号分client.publishをループする形になるかと思います。 import boto3 client = boto3.client( 'sns', aws_access_key_id='[アクセスキーID]', aws_secret_access_key='[シークレットアクセスキー]', region_name='[リージョン]' ) res = client.publish( PhoneNumber='[電話番号]', Message='[送信するメッセージ本文]', MessageAttributes={ 'AWS.SNS.SMS.SenderID': { 'DataType': 'String', 'StringValue': '[送信者ID]' } } ) こちらのソースでも同じように送信できました! ですが、色々実装・確認をしながらマニュアル等を確認していたところ、後述の制限などがあることが分かったので、 その制限を確認しつつサポートへの申請をしています。 次はそちらを確認していきます。 ■Amazon SNS(SMS) を利用するにあたっての注意 単に特定の電話番号にSMSメッセージ送信をしたかっただけなのですが、実装導入するにあたり、何点か気を付けなければいけないことがありました。 デフォルトの状態ですと、以下の制約があります。 アカウントの毎月毎のSMSの使用料上限が決まっている。デフォルトは$1.00 USD  ( https://docs.amazonaws.cn/en_us/sns/latest/dg/sms_preferences.html ) デフォルトはAmazon SNS サンドボックス内にあるので、SMS内で認証した電話番号(最大10件)以外に送ろうとする場合はアカウントをサンドボックス外に移動申請する必要がある ( https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sns-sms-sandbox.html ) こちらの制約について確認します。 アカウントのSMSメッセージングの使用料上限について ▼日本国内でのコストと上限 執筆時点での日本国内でSMSメッセージを送信しようとしたときのコストは $0.07451 です。 各国のSMS料金 デフォルトの上限は$1.00 USDとのことでした。これは1か月ごとの上限のようです。 アカウントの請求ダッシュボードを参照した際に「Amazon Simple Notification Service APN1-SMS-Price-ROW」が1.00 USDに到達していると、SMS送信不可となります ▼どのくらいのコストがかかるか試算してみる SMS 使用クォータの計算式  大体要約すると以下のような計算式になります。 (1日のメッセージ送信量 × 30日【1か月】) × $0.07451 USD × 【メッセージが長文になって分 割される想定の時何パート分割されるか】 = 1か月の使用量 デフォルトですと、日本国内では短いメッセージでも大体13件くらいまでしか送信できない想定です 余談ですが、日本の大手通信キャリアのSMSの文字上限は1メッセージは670文字(全角)くらいのようなので動作検証は必ず必要ですが、大体のメッセージは1パートで送れる想定です 1か月送信件数 SMS金額 パート * コスト 判定 500 $0.07451 1 $37.2550 × 100 $0.07451 1 $7.45100 × 50 $0.07451 1 $3.72550 × 14 $0.07451 1 $1.04314 × 13 $0.07451 1 $0.96863 〇 12 $0.07451 1 $0.89412 〇 … 2 $0.07451 1 $0.14902 〇 1 $0.07451 1 $0.07451 〇 今回はさほど長文を送るわけではないので、1パートのみのメッセージを想定して試算すると… 月500件くらい送る想定 × $0.07451 × 1パート = $37.255 ▼確認結果 $37 USDと試算が出ました。切り上げて$38とし、こちらを上限として申請しないとダメそうです。 申請後はAWSコンソール上で自分で上限値を上げる必要があるとのこと。 SMS サンドボックス ▼何でサンドボックスがあるの? 過去はSMSのサンドボックス機能は実装されていなかったようです。 ここ最近は新規でアカウント作成するとサンドボックス状態になっています。 サンドボックスは個人的な見解ですが、こういった意図があるのかなと思っています。 最初から不特定多数にSMS送信できる仕組みはサービスとして良くない 最初のうちは本当に送りたい先を登録&認証してその送信先にSMSを送って内容を検証すべき 一旦遊び場(試験場)のような場所を設けておいて、検証できたらそのサービスを公開(サンドボックスからの移動)することで安全を保障する ▼サンドボックス内の機能制限 デフォルトはこのような表記になっていると思います。 サンドボックス内でも大体機能は使えますが以下制限があるようです。 SMS メッセージは、認証済みの送信先電話番号にのみ送信できます。 最大 10 個の認証済みの送信先電話番号を持つことができます。 送信先の電話番号を削除できるのは、認証または最後の認証の試行から 24 時間以上経過後に限られます。 ▼そのままサンドボックス内で要件を満たせるか? 送り先が完全に決まっていて定期送信するような用途でしたらそのままでも良さそうですが、今回はオプション申込されたユーザそれぞれにSMSメッセージお送りしなければいけないので、そのままでは良くなさそうです。 毎度毎度バッチ実行の度に、電話番号登録 → 認証するのは流石にNG(お客様に認証をしていただく手段が無い) しかも認証できたとしても最大10個までしか登録できない 一度登録した電話番号は認証してから24時間以上経たないと削除できない ▼確認結果 サンドボックス内での利用では要件を満たせません。 というわけでAWSサポートに連絡して上記の撤廃申請を出すことにしました。 ■AWSサポートへの申請 デフォルトのままですと、制限により実装機能を満たす使い方ができないということが分かったので、AWSサポートへの申請を出します。 サポートページからの申請 ログイン後  サポートページ  へ Service limit increaseを選択 【 Case details 】 Limit type:SNS Text Messagingを選択し、optionalはどういう用途で制限を撤廃したいのかを記載 【Requests】 「 SMSアカウント使用量のしきい値の増加 」、「 アカウントのサンドボックス外への移動 」が目的なので Requests からそれぞれ追加 【 Case description 】どういう用途・目的で申請を出しているのかを記載 記述内容が不明だったり、情報不備などあればサポートから返信されるので、とりあえず自分がやりたいことを記載してみて申請を出してみるといいと思います。 大体数日以内にはサポートからお返事いただけると思います。(結構早かった) 申請が通るとこのような感じでサポートからお返事を頂けました。 申請通ったのでアカウント情報確認 申請が通ったので変更されているはずです。確認します。 1USD → 38USD AmazonSNSサンドボックスから移動 ▼アカウントのSMSメッセージングの使用料上限 「テキストメッセージングの優先設定」より「アカウントの使用制限」が設定したい上限値になっているか確認(変更されていました) 設定したい上限値になっていなければ変更 ▼SMS サンドボックス ステータスが変わりました これでSMS メッセージを任意の電話番号に送信できるようになりました 「サンドボックスの送信先電話番号」の項目は消えます 変更前はこちらでした ■まとめ これでAmazon SNS(SMS)を活用できるようになりました。 成功、失敗等をもっと詳細に知る必要がある場合は、cloud watch logsに出力する必要がありますが、 今回は簡易的な実装なのでここまでとなります。 AWSの技術、UIは移り変わりが激しいので、ここで共有させていただいた内容も数か月後、数年後には古くなっている可能性がありますが、誰かのお役に立てれば幸いです! ■We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
概要 サービス開始から35年、ニフティは常に技術者やIT技術と共にありました。 高い好奇心で新しい技術トレンドをいち早く導入し、システムやサービスへの活用を常に模索しています。ニフティが創業時から変わらないのは、好奇心と挑戦し続けること。 この”NIFTY Tech Day”を通じて、私たちの今と未来をお伝えします。 詳細 公式サイト 日程 11月22日(火)13:00〜18:00 配信URL 準備次第掲載いたします 視聴環境 インターネット接続が可能なPC/スマートフォン 参加方法 connpass にて参加登録をお願いします! タイムテーブル 準備次第掲載いたします。 ニフティグループでは一緒に働く仲間を募集中です ニフティ株式会社 新卒採用、キャリア採用を実施しています。ぜひ リクルートサイト をご覧ください。 ニフティエンジニアが業務で学んだことやイベント情報を エンジニアブログ にて発信しています! ニフティライフスタイル株式会社 想像以上を、みつけよう。 をコーポレートメッセージに、“一人ひとり”のライフスタイルを便利で豊かにするため、ニフティライフスタイルのエンジニアは日々開発をしています。 採用情報 や ニフティライフスタイル Tech Blog をご覧ください。 ニフティエンジニアのTwitterアカウントを作りました NIFTY Tech Talkのことや、ニフティのエンジニアの活動を発信していきます。 https://twitter.com/NIFTYDevelopers
アバター
はじめに はじめまして。新卒3年目の南と申します。 ニフティではSlackを利用しており、絵文字リアクションも多く利用されています。日々の連絡や相談はもちろんのこと、出退勤連絡やレビュー依頼などでもSlackを利用しています。 そして私はふと思いました。 毎日当たり前に利用しているSlackですが、Slackの機能を活用しきれてないのでは? 入社当時から既にSlackを使い始めているので、改めてSlackの使い方や機能について学ぶ機会がなく案外知らない機能や使ったことのない機能が多いのではないだろうか? Slackを使って、何か業務効率化できないだろうか? そこで今回は、Slackの機能の一つであるワークフロービルダーを活用して日々の業務連絡を少しだけ効率化させた事例をご紹介します。 ワークフロービルダーとは ワークフロービルダーは、定型的なプロセスを自動化して Slack ワークスペースのワークフローに変換できるツールです。コーディングの必要はありません。Slack でのワークフローは簡単なものから複雑なものまで自由に作れます。仕事に使用しているほかのアプリやサービスを連携させることもできます。 https://slack.com/intl/ja-jp/help/articles/360035692513-%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%95%E3%83%AD%E3%83%BC%E3%83%93%E3%83%AB%E3%83%80%E3%83%BC%E3%82%AC%E3%82%A4%E3%83%89 上記の通りコーディングなしで定型的なプロセスを自動化できる非常に便利なツールです! ワークフロービルダーには6つ(2022年9月現在)のテンプレートが存在しています。まずはそれぞれ何ができるテンプレートなのか簡単にご紹介します。設定方法や使い方については ワークフロービルダーガイド をご覧ください。 新しくチームに参加するメンバーに送る心温まる歓迎メッセージのテンプレート 新しいメンバーがチャンネルに参加するタイミングで自動でメッセージを送信するテンプレートです。 ニフティでも歓迎してくれるチャンネルがたくさんあります! リクエストのトリアージ方法 メンバーがチャンネルにリクエストを簡単に送信できるように、ショートカットを追加するテンプレートです。 ニフティでも問い合わせフォームなどで多く利用されています。 毎日のスタンドアップ・ミーティングとチェックイン 日時のスケジュールを使用してチームのリマインダーを設定し、通知するテンプレートです。日付、時間、頻度、繰り返す間隔、終了タイミングなどが設定可能です。 ニフティでも定期的な打ち合わせを知らせたり、定期的に行う作業を忘れないよう知らせたりするリマインダーとして多く利用されています。 情報を簡単に送る方法 誰かが会話に 特定の絵文字 で反応した時にメッセージが自動送信されるテンプレートです。 よく使われる絵文字を指定してしまうとその度に自動送信されるので注意が必要です。 チームのステータス更新 いつオフィス不在であるか、リモートで作業するかといった最新情報をチームが公開できるショートカットを追加するテンプレートです。 ショートカットを追加するテンプレートなので、2つ目に紹介したリクエストのトリアージ方法と同じような設定手順になります。 ゼロから始める 名前の通り、ゼロから自分で設定していく必要があります。まず、ワークフローを開始させる方法から選択していきます。ワークフローの開始方法は下記から選ぶことができます。 ショートカット 「 リクエストのトリアージ方法 」「 チームのステータス更新 」と同じような開始方法です チャンネルの新しいメンバー 「 新しくチームに参加するメンバーに送る心温まる歓迎メッセージのテンプレート 」と同じような開始方法です 絵文字リアクション 「 情報を簡単に送る方法 」と同じような開始方法です スケジュールされた日付と時間 「 毎日のスタンドアップ・ミーティングとチェックイン 」と同じような開始方法です Webhook URLが生成されるので、アプリや他サービスがリクエストを送信すると開始します ワークフローのステップ追加でできること ここまで説明した各テンプレートでは、下記のようなステップの追加も可能です。 ※3つ目以降は、各種アプリと連携することで利用が可能になります。 メッセージを送信 フォームを送信する Add a spreadsheet row スプレッドシートに追記します Delete a spreadsheet row スプレッドシートの特定の行を削除します Select a spreadsheet row スプレッドシートの特定の行の内容を取得します Update a spreadsheet row スプレッドシートの特定の行の内容を更新します More Steps by Zapier Zapier では、Zap というカスタムワークフローを使用して、毎日使うツールの間で情報を自動的に移動します。Zapier アプリをインストールすると、ワークスペースをさまざまなサービスに連携させて、作成した Zap を Slack で直接使用できます。 https://slack.com/intl/ja-jp/help/articles/360002074228-Slack-%E7%94%A8-Zapier 活用事例 ここまでワークフロービルダーについて簡単にご紹介しましたが、ここからが本題です! ニフティでは、出社/在宅のハイブリッドな働き方を導入しており場所が離れていて直接顔を合わせない日もあるので、私が所属するチームではSlackのワークフローを活用して出退勤連絡や残業申請などを行っています。これまでの課題も交えて実際に活用しているワークフローをご紹介します。 出勤連絡 これまでの課題 毎日スレッドに勤務場所と業務内容を手入力する必要があり、業務内容記入以外で毎回同じ記載をしている部分がありました。 改善 業務内容記入は必須ですが、毎回同じ記載をしている「〇〇勤務開始します。」などは絵文字リアクションで自動送信できるようにしたいという思いがありました。全体で利用しているワークフロービルダーのテンプレートは下記の2つです。 毎日のスタンドアップ・ミーティングとチェックイン(元々利用していたテンプレート) 情報を簡単に送る方法 ステップの追加でフォームの送信を追加しました 在宅か出社によって文章が変わるため、それぞれ特定の絵文字で動くワークフローを設定しています。 業務内容入力は毎日異なるためフォーム入力できるようにしてあり、その内容と特定の文章を組み合わせてこれまで動いていたリマインダーのスレッドにメッセージを自動投稿するようにしています。 毎日異なる業務内容の入力まで自動化することは困難でしたが、毎回同じ記載をしていた「在宅勤務開始します。」や「【主な業務内容】」など固定の文章については入力不要となったため、少し手間を省くことができました。 退勤連絡 これまでの課題 明日の勤務状況が2パターンあるだけで、それ以外の「退勤します。明日も〇〇です。」は固定化され毎日スレッドに手入力する必要がありました。 改善 絵文字リアクションで退勤連絡ができるようにしたいという思いがありました。全体で利用しているワークフロービルダーのテンプレートは下記の2つです。 毎日のスタンドアップ・ミーティングとチェックイン(元々利用していたテンプレート) 情報を簡単に送る方法 在宅か出社によって文章が変わるため、それぞれ特定の絵文字で動くワークフローを設定しています。 絵文字リアクションのみで退勤連絡が可能となりました。 残業連絡 これまでの課題 残業する際、スレッドに上司へのメンションや作業内容、残業時間や申請済みかどうかを手入力する必要があり、作業内容や残業時間は変わるものの上司へのメンションや申請済みかどうかは毎回同じ記載をしていました。 メンションすることを忘れてしまったり、作業内容や残業時間の入力を忘れる恐れがありました。 改善 作業内容や残業時間は必須で入力するようにして、上司へのメンションなどは記載漏れがないよう絵文字リアクションで自動送信できるようにしたいという思いがありました。全体で利用しているワークフロービルダーのテンプレートは下記の2つです。 毎日のスタンドアップ・ミーティングとチェックイン(元々利用していたテンプレート) 情報を簡単に送る方法 ステップの追加でフォームの送信を追加しました 作業内容や残業時間はフォーム入力を必須とするように設定し、残業時間についてはリストとして一定間隔で時間を設定して一覧から選択できるようにしました。 フォームに入力された内容を元に自動でメッセージをスレッドに投稿することが実現できたので、全て手入力する手間を省くことができました。 レビュー依頼フォーム これまでの課題 レビュー依頼のショートカットにより投稿されたメッセージに対して、レビュアーは対応のチケットにコメントを記載した上で同じような内容をSlackでも連絡をしているので、二度手間になってしまっていました。 改善 レビューをいつ始めてもらえたかを把握したいという思いや、レビュー結果が問題ない、もしくは、チケットに記載している指摘内容を確認して欲しいという文章を絵文字リアクションで自動送信できるようにしたいという思いがありました。全体で利用しているワークフロービルダーのテンプレートは下記の2つです。 リクエストのトリアージ方法(元々利用していたテンプレート) 情報を簡単に送る方法(2つ) まず、レビューをいつ始めてもらえたかを把握するためにワークフローを設定しました。レビュアーがどの絵文字を使ってリアクションすればよいかも明記しています。 指摘ありかなしによって文章が変わるため、それぞれ特定の絵文字で動くワークフローを設定しています。 レビュアーの二度手間を無くすことができ、レビューの状況も依頼者が把握できるようになりました。 運用作業の時間計測 これまでの課題 チェックやリカバリにかかった時間を自分でスプレッドシートに追記していく必要がありました。 改善 対応者はSlackのみで時間を登録できるようにして、自動でスプレッドシートに追記/集計をできるようにしたいという思いがありました。全体で利用しているワークフロービルダーのテンプレートは下記の2つです。 毎日のスタンドアップ・ミーティングとチェックイン(元々利用していたテンプレート) ゼロから始める 絵文字リアクションでワークフローを開始するようにして、ステップの追加でフォームの送信とAdd a spreadsheet rowを追加しました かかった時間をフォームで入力できるようにして、スプレッドシートにはフォームの入力を行った日付とフォームの入力者、そして入力された時間を追記するように設定しています。 スプレッドシートに移動して追記する手間が無くなり、日付や確認者も別途フォーム入力する必要はなく自動で追記してくれるためとても便利です。 スプレッドシートだと、グラフ化させる設定を入れていれば自動でグラフに追加されていくので可視化できました。 最後に ニフティではSlackの絵文字リアクションを多く活用していることに着目し、絵文字リアクションで開始できるワークフローを活用してみました。 まだまだ有効活用できる方法はたくさんあると思いますし、使い道はたくさんあります。ノーコードで誰でも簡単に設定できるので、是非毎日当たり前に行っている作業を自動化して効率化させてみてはいかがでしょうか? 私も、ワークフロービルダーを使いこなして業務効率化に繋げていきたいと思います! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
イベント概要 NIFTY Tech Talkは、ニフティ株式会社の社員が主催するトークイベントです。 本イベントではニフティグループの社員が業務を通じて学んだことを発信しています! 第5回目のテーマは「iOS/Androidアプリ開発」。現在、ニフティおよびニフティライフスタイルではさまざまなiOS/Androidアプリアプリが展開されています。 今回はそれぞれのサービスのiOS/Androidエンジニアから、新規アプリの立ち上げからアーキテクチャ選定、チーム開発の難しさなどをLT形式で語っていただきます。 本イベントは ニフティ株式会社 と ニフティライフスタイル株式会社 の共催でお届けします。 概要 日程:9月26日(月)12:00〜13:00 配信方法:YouTube Live 視聴環境:インターネット接続が可能なPC/スマートフォン 参加方法 YouTube Live connpass にて参加登録をお願いします! こんな方におすすめ iOS/Android関連技術およびすべてのソフトウェアエンジニア iOSのCI/CDなどのDevOpsに興味がある方 AndroidアプリへJetpack Composeを導入検討している方 アプリエンジニアのチーム作りに興味がある方 ニフティの現場でどのような技術が使われているか興味のある方 タイムテーブル 時間 コンテンツ 12:00-12:05 オープニング+会社紹介 12:05-12:10 登壇者紹介 12:10-12:25 ニフティライフスタイルのiOSアプリ開発での課題と解消に向けた取り組み 12:25-12:40 マイ ニフティ Android版におけるJetpack Composeの導入と課題 12:40-12:55 マイ ニフティ アプリ開発チームにおける開発スタイルの紹介 12:55-13:00 クロージング テーマ 各プロダクトに携わっている方々に登壇していただき、それぞれLT形式で発表していただきます。 ニフティライフスタイルのiOSアプリ開発での課題と解消に向けた取り組み 累計900万DLの不動産アプリを始めとする「ニフティライフスタイル株式会社」のiOSアプリ開発現場では、「在宅勤務下でのプロダクトレビューが大変」「施策が多く改善活動に時間を割けない」など複数の課題がありました。これらの課題に対して「CI/CD(Bitrise)導入」などの改善を行なってきた経緯など、我々が課題に対してどのように取り組んでいるかをお話しします! マイ ニフティ Android版におけるJetpack Composeの導入と課題 今年リリースしたニフティ会員向けアプリ「マイ ニフティ」Android版では開発当初より画面実装にJetpack Composeを全面的に採用し開発を行っています。 まだ登場して間もないJetpack Composeですが、実際に取り入れてどう良くなったか、また現状抱えている課題などについてお話しします。 マイ ニフティ アプリ開発チームにおける開発スタイルの紹介 ニフティ会員向けアプリ「マイ ニフティ」の開発チームでは、API・インフラのバックエンドを含めたiOS/Androidアプリの開発・運用を行なっています。幅広いタスクを行う中で「アプリ経験が浅い新規メンバーへの技術共有」「タスクの属人化解消」「品質管理」が重要になっています。これらに対する取り組みについて、アーキテクチャなども交えて開発スタイルをお話しいたします! 登壇者プロフィール 中村 伊吹(ファシリテータ) ニフティ株式会社 会員システムグループ 第二開発チーム 新卒入社4年目。ニフティニュースの開発・運用を担当し、最近はモダンなフロントエンド開発を学習中。男女混成チアリーディング元日本代表。 山田 良介(登壇者) ニフティ株式会社 会員システムグループ 第一開発チーム 新卒入社六年目。Web検索(@search)の運用を担当しつつ、社内でのアプリ開発に協力。マイ ニフティではテックリード兼Androidエンジニアとして参加。 川上 倫人(登壇者) ニフティ株式会社 会員システムグループ 第二開発チーム 新卒入社4年目。マイ ニフティアプリの開発・運用を担当し、モダンなアプリ開発の実践に向けて学習中。 齋藤 圭祐(登壇者) ニフティライフスタイル株式会社 システム開発部 アプリ開発チーム 新卒入社4年目。主にニフティ不動産のiOSアプリの開発・運用を担当しつつ、Androidも勉強中。 ニフティグループでは一緒に働く仲間を募集中です ニフティ株式会社 新卒採用、キャリア採用を実施しています。ぜひ リクルートサイト をご覧ください。 ニフティエンジニアが業務で学んだことやイベント情報を エンジニアブログ にて発信しています! ニフティライフスタイル株式会社 想像以上を、みつけよう。 をコーポレートメッセージに、“一人ひとり”のライフスタイルを便利で豊かにするため、ニフ ティライフスタイルのエンジニアは日々開発をしています。 採用情報 や ニフティライフスタイル Tech Blog をご覧ください。 ニフティエンジニアのTwitterアカウントを作りました NIFTY Tech Talkのことや、ニフティのエンジニアの活動を発信していきます。 https://twitter.com/NIFTYDevelopers アンチハラスメントポリシー 私たちは下記のような事柄に関わらずすべての参加者にとって安全で歓迎されるような場を作ることに努めます。 社会的あるいは法的な性、性自認、性表現(外見の性)、性指向 年齢、障がい、容姿、体格 人種、民族、宗教(無宗教を含む) 技術の選択 そして下記のようなハラスメント行為をいかなる形であっても決して許容しません。 不適切な画像、動画、録音の再生(性的な画像など) 発表や他のイベントに対する妨害行為 これらに限らない性的嫌がらせ 登壇者、主催スタッフもこのポリシーの対象となります。 ハラスメント行為をやめるように指示された場合、直ちに従うことが求められます。ルールを守らない参加者は、主催者の判断により、退場処分や今後のイベントに聴講者、登壇者、スタッフとして関わることを禁止します。 もしハラスメントを受けていると感じたり、他の誰かがハラスメントされていることに気がついた場合、または他に何かお困りのことがあれば、すぐにご連絡ください。 ※本文章はKotlinFest Code of Conductとして公開された文章( https://github.com/KotlinFest/KotlinFest2018/blob/master/CODE-OF-CONDUCT.md )を元に派生しています。 ※本文章はCreative Commons Zero ライセンス( https://creativecommons.org/publicdomain/zero/1.0/ ) で公開されています。
アバター
初めに こんにちは!Flutterエンジニア(自称)の柴田です。 Flutterは、UIレンダリングエンジンとしてSkiaを採用しています。 しかし、Skiaにはパフォーマンスの問題があり、Flutterはバージョン3.0.0で「Impeller」というUIレンダリングエンジンを実験的に導入しました。 今回はこの「Impeller」を試してみます。 「Skia」とは Skiaは2Dグラフィックスライブラリーです。 特徴として以下の点があげられます。 オープンソース Googleが開発 C++を使用 マルチプラットフォームに対応 Chrome、Android、.NET MAUI(Xamarin.Forms)、Compose Multiplatformなど多くの環境で採用されています。 余談: Xamarinは今後サポート終了し.NET MAUIに引き継がれる予定です。 https://dotnet.microsoft.com/ja-jp/platform/support/policy/xamarin FlutterでもUIレンダリングエンジンとしてSkiaを採用しています。(Flutter WebはSkiaのWebAssembly版であるCanvasKitを使用) https://skia.org/ Skiaの問題点 初回起動時のパフォーマンスが悪い Skiaでは、アプリ初回起動時にシェーダーコンパイルが行われるため、初回起動時のパフォーマンスが良くありません。(60FPSを下回るなど) Andoridはコンパイルの結果が永続化されるため、パフォーマンスが悪いのはアプリインストール後の起動時のみですが、iOSはタスクキルすると廃棄されるため、アプリを起動するたびにパフォーマンスが悪くなります。 Skiaにはこのシェーダーコンパイルを事前にしておくSkSL(Skia Shader Language) warmupという機能があります。これは、事前にSkSL でシェーダーをキャプチャし、それをアプリにパッケージ化することで初回起動時のコンパイルを軽減するものです。しかし、これはアプリを変更するたびに全てのシェーダーをキャプチャする必要があり、開発者の負担が大きいという問題があります。また、キャプチャしたシェーダーが他の端末で使用できる保証がありません。 https://docs.flutter.dev/perf/shader 新しいエンジン「Impeller」とは これらSkiaのパフォーマンス問題はFlutter公式でも認識しており、グラフィックバックエンドの書き換えをおこなっています。それが「Impeller」です。 「Impeller」はFlutterのためのレンダリングランタイムです。 特徴としては以下の点があげられます。 全てのシェーダーのコンパイルをビルド時にオフラインで実行 モダンなグラフィックスAPIを効果的に使用 MetalやVulkanなどの利用可能な機能を使用する(依存はしない) 並行処理を効果的に使用 必要なら単一フレームワークロードを複数スレッドに分配して処理する 現在Impellerが使用できるのはiOSとAndroidのみです。 https://github.com/flutter/engine/tree/main/impeller 「Impeller」を使ってみる 重いと噂のアプリでパフォーマンスの比較を行います。ページ遷移時のレンダリング速度をDevToolsで計測します。 https://github.com/flutter/gallery/releases/tag/v2.9.2 実行環境 MacBook Pro (13-inch, M1, 2020) Flutter 3.0.4 Simulator Version 13.4.1 (977.2) iPhone 13 Pro (iOS15.5) 結果 シェーダーコンパイルにかかる時間の結果です。 Skiaは162.5msかかってるのに対し、Impellerは22.1msとSkiaに比べ7倍以上高速になっています。 体感でもカクつきが明らかに減っています。 しかし、なお60FPSを出すのに必要な16msを上回っています。 今回の計測はdebug buildなのでrelease buildにすればもっとパフォーマンスが良くなると思います。 # Skia flutter run # Impeller flutter run --enable-impeller 終わりに 今回は新たなシェーダーレンダリングエンジンのImpellerを試してみました。Impellerを用いることで、Skiaに比べ7倍以上のパフォーマンスが出ることを確認できました。ImpellerがStableになることを楽しみに今後のアップデートに注目します。 みなさんもFlutterで快適な開発体験を!! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは。サービスインフラチームの清水と申します。 ニフティではスクラム開発が様々なチームやプロダクトに導入されています。私も現在のチームに配属されてから開発メンバーとして4年ほどスクラム開発を行ってきました。 社内でスクラム開発を導入するチームが増えていく中、スクラムマスターも増やそうといった動きがあり、2021年12月、機会にも恵まれ Scrum Alliance 社主催の認定スクラムマスター研修に参加し、認定スクラムマスターの資格を取得することができました。以来チームのスクラムマスターとして活動しています。 今回は一般エンジニアがスクラムマスターになって、どんなことを考えながら取り組んでいるか、自分のケースを取り上げて学びや試行錯誤についてお話したいと思います。まだまだ新米スクラムマスターですが、少しでも参考になれば幸いです。 サービスインフラチームでは、ID管理・決済・サービス申し込みといったシステムの開発・運用を行っています。詳しくは 基幹システムグループ サービスインフラチームの紹介です – NIFTY engineering をご覧ください! チームを見つめ直そう まずは、スクラムチームがいまどのような状態かを見つめ直すことから始めました。 いち開発メンバーの視点から見ると、私の属するスクラムチームはうまく機能しているように感じていました。各種イベントの実施や定期的なリリース、イテレーションによるチームの成長……。しかし4年という歳月の間にはスクラムガイドの改定も行われ、メンバー間でスクラムに対する認識のズレが生まれていました。そして、メンバーにとって居心地の良い我流のスクラムとなっていきました。 もちろんスクラムガイドには具体的な方法が書かれていないので、チームにフィットするやり方でスクラムを適用するのはむしろ望ましいことです。しかし、私のチームには以下の問題がありました。 マネージャーがスクラムマスターを兼任しすべてやってしまいがち プロダクトオーナーが不在 マネージャーがスクラムマスターを兼任すると、メンバーに声が届きやすくチームビルディングが行いやすい反面、マネージャーに一極集中しやすいという問題があります。これについてはスクラムマスターの権限委譲をしてもらうことで形式上解消されました。その後自分がスクラムマスターとしてうまくチームを機能させられるかどうかについては別の話ですが……。 一方、プロダクトオーナーがいないという点について、これはスクラムガイドに則っていないチーム体制であり、メスをいれるべきものです。 以前よりビジネス部門と連携を取りながら開発を進めていましたが、開発者とビジネス担当者での1対1のコミュニケーションになりがちで、部署間のコミュニケーションにどうしても隔たりが発生していました。そして開発側の調整役はしばしばマネージャーであり、マネージャーがチームにビジネス側の要件を共有するという形になっていました。ビジネスの観点からプロダクトの成長について考えられる人がいない状態、といったところでしょうか。 スーパーマンのマネージャーによって決定や調整、問題解決が行われており、チームとしてうまく機能しているように感じていても、実際は自己管理の意識が弱かったのかもしれません。 スクラムについて学び直す場を設けよう 認定スクラムマスター研修の中で印象的だった話に、LeSS の創始者の1人であるクレイグ・ラーマンが提唱する「 ラーマンの法則 」というものがあります。 組織構造と文化に関する内容ですが、スクラムに当てはめてみると次のようになると言っていました。 「今やっている仕事をスクラムの用語で置き換えてしまい、本来あるべきスクラムチームの形ではなくなってしまう。」 私のチームも、スクラムに対する認識のズレを感じていたものの、それがチーム内の共通認識となっていました。研修でこの話を聞いたとき、まさに自分たちのことのように感じました。 そこで、改めてスクラムを学び直す機会を設けました。具体的には、改定後のスクラムガイドを読んでもらう、認定スクラムマスター研修で学んだ内容を「スクラム再入門」と題してチームメンバーへのアウトプットを行うなどです。 あわせてインプットも積極的に行いました。SCRUMMASTER THE BOOK やアジャイルレトロスペクティブズといったスクラム関連の書籍を読み、研修の内容と照らし合わせながら理解を深めるとともに、スクラム・アジャイル系の勉強会に参加して他社のスクラム事例やノウハウを学ぶ、といった具合です。 ただ、これらは一度やれば良いというものではなく、定期的に行うことが重要に感じています。単純にスクラムについての理解を深めるだけでなく、自分たちの都合のいいようにスクラムを解釈していないか?チームの組織構造はどうか?といった点に気づける機会にもなります。新しいメンバーがジョインしたら勉強会を開いたり、数ヶ月に1回スクラムガイドの輪読会を行うなど、慣れてきたタイミングで改めて学び直すようにしたいですね。 プロダクトオーナーを立てよう 私のチームの問題としてあったプロダクトオーナー不在問題を解消するべく、ビジネス部門の中で以前からメインにやり取りしている方にプロダクトオーナーの打診をしました。お願いをするにあたり スクラムの概要 プロダクトオーナーの役割 具体的にやってほしいこと を説明し、プロダクトのこれからについて一緒に考えていきませんか?といったことを伝えました。 スクラムの各種イベントに時間が取られたり新しい概念を取り入れる必要があるため、いきなりプロダクトオーナーの仕事をすべて任せるのは難しいと考え、まずはレビューやレトロスペクティブなどからイベントに参加してもらうなど段階的にチームにジョインしてもらうことにしました。 話を進めていくと、ビジネス部門も私たちが感じていた組織感でのコミュニケーションなどについて課題を感じていたことがわかりました。プロダクトのこれからの方向性やビジネス側のビジョンなどについても話したいと、ありがたいことにスクラムについて理解を示していただき、プロダクトオーナーも快諾していただけました。 まだプロダクトオーナーがジョインして時間もあまり経っていませんが、プロダクトオーナーの意見をもらえる場ができたことで、今まではなかったビジネスの視点についてチーム全体で考えられるようになっていると実感しています。 私のチームがそうだったように、ニフティの他スクラムチームもプロダクトオーナーが不在という問題を耳にします。ビジネス部門の中にはまだスクラムが浸透できていない部分もあるため、他チームのスクラムマスターと協力して組織の体制なども変えられるよう活動していく必要がありそうです。 スクラムマスターのスキルセットを意識しよう スクラムマスターに必要なスキルでよく言われるものとして、以下の5つがあげられます。 ティーチング ファシリテーリング メンタリング コーチング シチュエーショナリング いわゆるソフトスキルと呼ばれるものですが、エンジニアのキャリアとしてこうしたスキルに触れる機会が少なく感じます。それぞれなんとなく理解できるのですが、いざ実践しようとすると非常に難しく試行錯誤の連続です。 たとえばスクラムイベント1つを取っても、参加する側からファシリテーションする側になったことで、メンバーが発言しやすい場にするにはどうすればよいか考えなければなりません。また、タイムボックス内でスムーズにミーティングを終わらせるために、ミーティングの事前準備がいかに重要か身をもって感じるようになりました。 ほかにも、チームの透明性が担保されているか俯瞰して見る必要があります。今までは、自分たちが作る成果物 (ソースコード・機能など) について集中していましたが、チームが自己管理できている状態にあるのか、チームの障害となっているものは無いかなど、成果物だけでなくチーム全体を見るように意識が変わりました。 このあたりは新米スクラムマスターにとってはなかなか難しいと感じていますが、幸いチームにこういった視点を持ったメンバーがいるため、相談しながら考えることができており非常に助かっています。 今までとは違った能力が要求され大変なことも多いですが、その分今までとは違った分野での成長を実感しています。チームビルディングやマネジメントといった方向のキャリアパスにも興味を持ち始めてきました。個人の選択肢が広がったように感じます。 相談できる場を作ろう スクラムマスターはひとりになりがちです。問題に直面したとき常に明確な答えがあることは少なく、特に新米スクラムマスターは経験も浅いため、一人ではどうすることもできない状況がしばしばあります。 そのため、スクラムマスターとしての悩みを相談できる場を確保しておくことが重要です。 スクラムチームというとチーム内で完結してしまうようにイメージしがちですが、スクラムマスター同士のつながりは非常に大切で、スクラムマスターの協働によって組織が変わっていく、と研修で教わりました。 他のスクラムマスターの経験を知ることもまた自分の経験に繋がります。知り合いのスクラムマスターに相談するのも良いですし、社内外のスクラムコミュニティに参加して他チームの事例などを知るだけでも非常に学びがあります。 ニフティでは社内のスクラムマスターが集まって良かったことの共有や悩みを相談する「スクラムマスター共有会」というものが月に1度開催されています。私もこの会には非常に助けられています。自分の悩みを相談するだけでなく、他のスクラムマスターがどのような悩みを抱えているのかを知る機会にもなるため、ニフティのスクラムマスター全体として集合知、経験が培われる非常に良い循環となっていると感じています。 おわりに 約半年スクラムマスターを経験して感じたのは、これらは一朝一夕で習得できるものではなく、常に意識しながら実践と経験を積み重ねることで培われるということです。 スクラムが経験主義のフレームワークであるように、スクラムマスターもチームとともに経験して成長していくものだと感じました。 新米スクラムマスターの私の経験が、どこか他のスクラムチームの一助となれば嬉しい限りです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
初めに こんにちは、インフラシステムグループの佐藤です。 皆様は問い合わせ窓口に電話をした際、オペレーターとのやり取りが長引きイライラする、といった経験はないでしょうか? 今回、受電時間を削減するために電話認証番号という仕組みを導入しましたので紹介します。 電話認証番号とは? こちらで告知されています↓ 会員サポート >「電話認証番号」による本人確認運用を開始 : @nifty 簡単に要約すると、 本人確認をIVR(自動音声応答システム)上で行うことで通話時間やオペレーターに繋がるまでの待ち時間を削減しよう という取り組みです。本人確認には事前に登録した4桁の番号を利用します。 既存の本人確認方法 氏名や生年月日、電話番号などを電話口でヒアリングして確認しています。 本人確認後、お客様情報を確認するWEBシステムから契約情報などを閲覧することで問い合わせの対応を行っていました。 IVR上での必要なフロー IVRに電話認証番号用のフローを作成、追加します。 必要なフローは下図の通りです。 電話認証番号の仕組みを導入しても、即座に全てのお客様が利用するわけではありません。 そのため、まずは電話認証番号を持っているか否かで分岐します。 持っていない場合は既存のIVRに復帰します。 持っている場合はそのまま自身の電話認証番号を入力し、認証を行います。 認証では下記のようなSQLを実行します。 SELECT [@niftyID] FROM [テーブル名] WHERE [登録されている電話認証番号] = '[入力した電話認証番号]' [登録されている電話番号] = '[架電している電話番号]' GROUP BY [@niftyID] @nifty IDが返ってくれば認証成功です。 認証に成功した旨のアナウンスを流し、@nifty ID情報を保持します。 認証に失敗した場合、もしくは一定時間電話認証番号を入力しなかった場合は認証に失敗した旨のアナウンスを流します。 その後、成功失敗ともに既存のIVRに復帰します。 オペレーター視点での挙動の違い IVRの終端ではアナウンス後切断するか、オペレーターに繋がります。 オペレーターに繋がった時、CTI連携を行います。 CTI連携とは電話とコンピュータを連携させることで、ニフティの場合はお客様情報を確認するWEBシステムページが起動します。 オペレーターはCTI連携後に電話口で本人確認を行い、お客様情報を検索して契約情報などを確認していました。 電話認証に成功した場合は、本人確認が取れた状態であるため、CTI連携時に@nifty IDのURLパラメータを追加した状態で起動します。 すると@nifty IDに紐づいた情報が表示されるため、オペレーターは初めからお客様の契約情報などを確認することが可能になります。 上図は実際に開くURLの例です。 右側のマスクされた部分に@nifty IDが入ります。 コールフローを作成する 前項までで電話認証番号を実現するために、電話システム上で必要な機能についてまとめました。 ここからは実際にコールフローを作成していきます。 コールフローとは、お客様からの入電を適切に振り分ける流れのことです。 ニフティではコンタクトセンターサービスとして、NTTコミュニケーションズの Arcstar Contact Center を利用しています。 ストラテジを作成する まずは、ストラテジという動作の骨組みにあたる部分を作成します。 下図は先ほどのフロー図での、[電話認証番号_認証]に該当するストラテジ例です。 ストラテジはウィザードというアイコンが結びついて構成されています。 内、下記の中央部分に絞って簡単に解説します。 まず、左のデータベースアイコンの部分でDBに接続、SQLを実行します。 実行に成功した場合は右の緑色、失敗した場合は下の赤色に分岐します。 緑色に進んだ場合は、クリップマークのアイコンにてSQLの実行結果を変数に格納しています。 格納したのち、矢印がクロスしているアイコンで変数を元に分岐させます。 分岐先のFアイコンでは、このストラテジが終了したとき、次に遷移する先を記載します。 上のFアイコンでは認証成功時の遷移先に、下のFアイコンでは認証失敗時の遷移先が指定されています。 値の定義 先ほどFアイコンで遷移先を指定している、と言いましたが、ストラテジはあくまで骨組みなので直接遷移先を記載してはいません。 今回の例では上のFアイコンは遷移先1、下のFアイコンは遷移先2を見に行く、といった形で記載されています。 そのため、実際の遷移先をリストにして定義する必要があります。 [〇〇窓口用の電話認証番号] 遷移先1=XXX 遷移先2=YYY [××窓口用の電話認証番号] 遷移先1=aaa 遷移先2=bbb その他にもアナウンス用の音声ファイルなど、固有のパラメータは同様に定義する必要があります。 利用時の流れ 全てのストラテジを作成、値を定義すれば電話認証番号用フローの完成です。 コールフローに電話認証番号用フローを追加すればそのコールフロー内で電話認証番号が使えるようになります。 電話認証番号を実際に利用する場合は、下記3ステップで行えます。 自身の@nifty IDに電話番号、電話認証番号を登録する 本人確認用の電話認証番号を登録したい Q&A(よくあるご質問) 登録した電話番号から架電し、電話認証番号を入力する オペレーターに繋がった際、電話認証が成功していれば自動的に本人確認が終了している 効果 現在スタートしたばかりのため効果は測定中ですが、一月当たり40万ほどのコスト削減を見込んでいます。 さいごに 今回は電話での受電時間を削減するための取り組みについて紹介しました。 ニフティに問い合わせの電話をかける際は、電話認証番号を登録してみてはいかがでしょうか?   # We are hiring ! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! [ ニフティ株式会社採用情報 ] Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! [ Event – NIFTY engineering ]                    
アバター
はじめに こんにちは!新卒3年目の加藤です。普段は社内システムの運用・開発を担当しています。 一番好きな社内ツールはSlackです。 Slackには単純にメッセージを投稿するだけではなく、APIを利用してアプリを作ることが可能です。 その中でも、何かのトリガーを元に処理を行う Slack Events API というものがあります。 今回は試しに、そのSlack Events APIを利用し、「Timesチャンネルが開設されたときに通知をしてくれるアプリ」の作り方をご紹介します。 SlackのTimesチャンネルとは?? いわゆる「分報」と呼ばれるものです。 (別名「社内Twitter」とも) 今何をしているか、何に困っているかといった業務のことから、ちょっとした雑談など、個人個人が開設し、自由に利用することができるチャンネルです。 他の人のTimesチャンネルに参加しておけば、業務の合間の雑談やその人が何の業務をしているのかがわかるので、コミュニケーションの活性化に繋がります。 ニフティでもこのTimesチャンネルが活発に活用されていて、自身も、開発で詰まってしまった部分を呟いた際に、部署の垣根を超えて他のエンジニアの方が教えてくれた経験もよくあります。 また、配属1年目の新人の方には先輩のトレーナーがついてOJTを行いますが、リモートワーク全盛の昨今、常に隣に座って相談に乗るということが出来ません。 また新人の方も先輩の顔が見えないなか遠慮してしまい、積極的に先輩社員に質問するというのも難しかったりします。 そこで、Slackを使って今の自分自身の進捗や困ったことをどんどん自身のTimesに載せて、トレーナーがアドバイスをしてくれるような新しい働き方など、様々な使われ方がされています。 (中には、トレーナーを呼び出すボタンをTimesチャンネルに設置している新人もいるとか…?) 今回は、このTimesチャンネルを誰かが開設した際に、いち早く参加するために、その開設のお知らせをチャンネルにするアプリを作ってみます。 事前に準備するもの 次のものは事前に準備されていることを想定しています。 Python(手元ではver 3.8で実行) Node.js(手元ではver 16で実行) AWSアカウント AWS CLIのインストールとプロファイルの設定 なお、手元ではMacを利用しています。 サービスの構成 今回はSlack APIから来たデータをAmazon API Gatewayを介してAWS Lambdaで処理するという、とてもシンプルな構成で作りたいと思います。 なお、AWSのサービスをGUIで設定するのは大変なので、今回は Serverless Framework を用いてInfrastructure as Code(IaC)も組んでみたいと思います。 手順 では早速アプリを作っていきましょう! 作業はすべて適当なディレクトリにて行います。 最終的には、次のようなファイル・ディレクトリ構成になります。 . ├── .serverless ← 自動生成 ├── Pipfile ← 自動生成 ├── Pipfile.lock ← 自動生成 ├── lambda_function.py ← 手順4内にて作成 ├── node_modules ← 自動生成 ├── package-lock.json ← 自動生成 ├── package.json ← 自動生成 └── serverless.yml ← 手順3内にて作成 1. Slackアプリの設定 まずはSlack APIを利用するためにSlackアプリの設定をします。 https://api.slack.com/ の「Create an app」からSlack アプリを作成しましょう。 その際、以下のような画面が出ると思います。 これは、Slackアプリをどうやって設定するか選択する画面です。 From scratch で画面からポチポチ設定していってもいいですが、少し大変なので、今回は manifest を使ってみましょう。 ワークスペースを選んで、YAMLには下記をコピペします。 display_information: # アプリの設定 name: NofityNewTimes description: Notify new times channels features: app_home: home_tab_enabled: true messages_tab_enabled: false messages_tab_read_only_enabled: true bot_user: # Botの設定 display_name: Notify New Times always_online: true oauth_config: # 許可するscopeの設定 scopes: bot: - channels:read # channel_createdのイベントを受け取るのに必要 - chat:write # Slackにメッセージを投稿するのに必要 - chat:write.public # チャンネルにアプリを追加しなくても投稿できるようにする settings: event_subscriptions: # イベントを受信する設定 request_url: https://example.com # イベント送信先。後で変えるので一旦適当 bot_events: # 受信するイベント。今回はチャンネルが作られたら発火します。 - channel_created org_deploy_enabled: false socket_mode_enabled: false token_rotation_enabled: false これで「Create」をし、アプリができたら「Install to Workspace」をクリックしてワークスペースにインストールしておきましょう。 2. 環境構築系 実際のアプリを作っていく前にアプリを構築するための環境を整備しましょう。 まずは、デプロイに利用するServerless Frameworkと、デプロイパッケージにPythonの依存パッケージを自動で含めてくれる便利なプラグインをインストールします。 % npm init (npm initの設定はすべて何も入力せずEnterでOK) % npm i -g serverless # Serverless Frameworkインストール % npm i --save serverless-python-requirements # デプロイパッケージに自動でPythonパッケージを含めてくれるプラグイン 次にPython関連の準備です。 今回は、仮想環境として pipenv を使うので、そのインストールと仮想環境の作成をします。 % pip install pipenv==2022.8.5 # pipenvインストール % pipenv --python=3.8 # pipenv仮想環境作成 最後に、作成した仮想環境に対して、今回の開発に必要なPythonパッケージをインストールしましょう。 % pipenv install slack-bolt # Slack Boltインストール 3. Serverless Frameworkの整備 AWSのリソースを自動で作成してくれるServerless Frameworkの設定ファイルを作ります。 serverless.yml service: notify-new-times frameworkVersion: '3' custom: pythonRequirements: # Pythonの依存パッケージを自動でデプロイに含めてくれるプラグインの設定 usePipenv: true # pipenvを使うためtrue provider: name: aws # AWSにデプロイ runtime: python3.8 # LambdaのランタイムにPython3.8を利用する region: ap-northeast-1 # デフォルトのAWSリージョン(東京) iam: # デプロイするLambda関数に与えるロールの設定 role: statements: - Effect: "Allow" Action: # Slack Boltでは下記が必要 - "lambda:InvokeFunction" - "lambda:GetFunction" Resource: "*" environment: # Lambda関数に設定する環境変数 SLACK_BOT_TOKEN: ${env:SLACK_BOT_TOKEN} # SlackアプリのAPIトークン SLACK_SIGNING_SECRET: ${env:SLACK_SIGNING_SECRET} # Slackアプリのシークレット(リクエストが正当なものか検証するのに必要) CHANNEL_ID: ${env:CHANNEL_ID} # 通知をするSlackチャンネルのチャンネルID package: # デプロイパッケージに含めるファイル patterns: # lambda_function.pyのみ必要なので、全部を除いたあとにlambda_function.pyのみ追加 - '!**' - 'lambda_function.py' functions: # Lambda関数の設定 notify-new-times: handler: lambda_function.lambda_handler # 最初に実行されるファイルと関数名 timeout: 10 # Lambda関数のタイムアウト(10秒) events: # Lambda関数のトリガー - httpApi: # API Gateway(自動でデプロイ時にAPI Gatewayも作成してくれる) method: POST path: /notify-new-times plugins: # 利用するプラグイン - serverless-python-requirements 4. Lambda関数の準備 では、実際にLambdaで動かすスクリプトを作ります。 lambda_function.py from slack_bolt import App from slack_bolt.adapter.aws_lambda import SlackRequestHandler import os # Slack Boltのappの初期化 app = App(token=os.environ.get("SLACK_BOT_TOKEN"), signing_secret=os.environ.get("SLACK_SIGNING_SECRET"), process_before_response=True) # LambdaのようなFaaSでSlack Boltを利用するときはTrue # Slack APIにackを返す関数 def respond_ack(ack): ack() # 指定されたチャンネルにTimesチャンネルの開設者とそのリンクを送信する関数 def notify_created_times(body, client): channel_info = body["event"]["channel"] if channel_info["name"].startswith('time'): # チャンネル名が「time」で始まっていれば notify_text = f'<@{channel_info["creator"]}>さんが<#{channel_info["id"]}>を開設しました:partying_face:' client.chat_postMessage(channel=os.environ.get( 'CHANNEL_ID'), text=notify_text) # channel_createdのイベントが来た時に実行される関数 # Ref:https://api.slack.com/events/channel_created app.event('channel_created')( ack=respond_ack, # Slack APIに3秒以内にackを返さないといけないので、それを行う関数 lazy=[notify_created_times] # 時間がかかりそうな関数はすべてこっちに載せる ) # 最初に実行される関数 def lambda_handler(event, context): slack_handler = SlackRequestHandler(app=app) return slack_handler.handle(event, context) 5. 環境変数の設定 デプロイに必要な環境変数を設定します。 APIトークンは「OAuth & Permissions」に、Signing Secretは「Basic Information」にそれぞれ書かれています。 % export SLACK_BOT_TOKEN=xoxb-xxxxxxxxx # SlackアプリのAPIトークン % export SLACK_SIGNING_SECRET=xxxxxxxxxxxx # SlackアプリのSigning Secret % export CHANNEL_ID=xxxxxxx # 通知先のSlackチャンネルID 6. デプロイ ではデプロイしましょう! % sls deploy --aws-profile プロファイル名 # Serverless Frameworkでデプロイする 7. イベント通知先のURLを設定する デプロイに成功すると、ターミナルの最後の方にendpoint URLが記載されているはずです。 これが、今回のデプロイで作成されたAPI GatewayのURLになるので、これをSlack APIに設定しましょう。 これで、チャンネルが作成された場合に、Lambdaが起動するようになります。 動作確認 Timesチャンネルを作成してみると… 無事に通知されました! 最後に ニフティではTimesチャンネルを多く活用しており、コミュニケーションの活性化に繋げています。 近年ではリモートワークによりコミュニケーションが希薄になりがちですが、そんな中でもSlackを通じてコミュニケーションを維持し、困ったことや雑談に対して誰かがすぐに反応をくれる文化は、ニフティの良い文化かなと個人的に思っています。 今回は、そんなTimesチャンネルのメリットを最大限に活かすために、Slack Events APIを用いて、Timesチャンネルの開設を通知してくれるアプリを作ってみました。 もし、Slackを活用していらっしゃれば、ぜひ参考にしてみてください。 また、今回はAPIのイベントトリガーとして「チャンネルが作られたら」というトリガーのみ利用しましたが、それ以外にもたくさんのトリガーで処理をさせることができるので、ぜひ試してみてください! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに はじめまして。 中廣と申します。 ニフティ株式会社に中途入社して4年目になります。 私が所属しているチームでは、日々の運用作業をこなしつつ、並行して開発作業も行っていますが、開発作業に時間を取りたいので、運用作業はなるべく自動化若しくは簡易化を進めています。今回は、AWS Chatbot + AWS Lambda + Slackを利用して運用作業を簡易化した話を書きたいと思います。 とある運用作業の手順(簡易化前) これまで手運用で実施していた運用作業の手順を以下に記します。 ※ 実際の手順より簡略化しています。また、テーブル名・項目名は適当な値にしています。 依頼元より作業依頼を受ける 他部署より作業依頼をメールで受けます。 依頼内容と、対象データのキー(受付番号:HOGE_NO)が連携されます。 SQLを順番に実行する 作業用サーバからSQL実行環境へログインし、以下SQLを実行します。 -- テーブルAのデータを依頼元から連携された受付番号で検索し、 -- 現在登録されているデータを確認する&後続処理に必要な値を取得する SELECT HOGE_ID, HOGE_A, HOGE_B, HOGE_C, LAST_UPDATE FROM TABLE_A WHERE HOGE_NO = &HOGE_NO; -- テーブルAの値を更新する -- HOGE_A,HOGE_B の設定値は HOGE_C の値によって決まるため、手作業で設定する UPDATE TABLE_A SET HOGE_A = &VAL1, HOGE_B = &VAL1, LAST_UPDATE = SYSDATE WHERE HOGE_NO = &HOGE_NO; -- 更新後の値を確認するため、再度SELECT文を実行し、目視で確認する SELECT HOGE_ID, HOGE_A, HOGE_B, HOGE_C, LAST_UPDATE FROM TABLE_A WHERE HOGE_NO = &HOGE_NO; -- テーブルBのデータを受付番号で検索し、データがないことを確認する SELECT HOGE_NO,FUGA_A,FUGA_B,LAST_UPDATE FROM TABLE_B WHERE HOGE_NO = &HOGE_NO; -- テーブルBへデータを投入する -- FUGA_A, FUGA_B の値は HOGE_C の値によって決まるため、手作業で設定する INSERT INTO TABLE_B (HOGE_NO ,FUGA_A,FUGA_B,LAST_UPDATE) VALUES (&HOGE_NO, &VAL_3, &VAL_4, SYSDATE); -- テーブルBのデータを受付番号で再検索し、データが投入されていることを確認する SELECT HOGE_NO,FUGA_A,FUGA_B,LAST_UPDATE FROM TABLE_B WHERE HOGE_NO= &HOGE_NO; -- 問題なければコミットする COMMIT; APIを実行し、外部システムへ連携する SQL更新後、APIを実行して外部システムへの連携を行います。 # HOGE_IDはテーブルA.HOGE_IDの値を設定する # VAL1, VAL2, VAL3 の値はテーブルA.HOGE_Cの値によって決まる curl "http://hogehoge/renkei?HOGE_ID=XXXXX&VAL1=XXX&VAL2=YYY&VAL3=ZZZ" …いかがでしょうか。 手順が決まっているとはいえ、なかなか面倒です。 また、すべて手作業なので作業漏れ・ミスにもつながります。 運用作業手順をもっと簡単にする 上記の手順を見ると、以下のことが分かります。 受付番号があればテーブルAのデータを特定できる 更新時に設定する値は、テーブルAを見ればわかる API連携する値はテーブルAを見ればわかる …ということは、受付番号さえわかれば自動化できちゃいそうですね。 ① 一連の作業を Lambda関数化する ということで、上記の作業手順をLambda関数(hogehoge_operation)にまとめました。 (以下はサンプルなのでデータチェック・エラーハンドリングなどは一切考慮していません!!) from lib.settings import session from lib.models import TableA,TableB import requests def lambda_handler(event, context): """ ほげほげ運用作業用Lambda関数(サンプル) """ # 受付番号を取得 hoge_no = event.get("hoge_no", "") # テーブルAのデータを取得 data = session.query(TableA).filter(TableA.hoge_no == hoge_no ).one_or_none() id = data.id hoge_c = data.hoge_c # テーブルAのデータを更新しつつ、テーブルBへ追加する値・API連携値を設定する if hoge_c == '1': data.hoge_a = 'hoge_a_1' data.hoge_b = 'hoge_b_1' fuga_a = 'fuga_a_1' fuga_b = 'fuga_b_1' val1 = 'val_1_1' val2 = 'val_2_1' val3 = 'val_3_1' else: data.hoge_a = 'hoge_a_0' data.hoge_b = 'hoge_b_0' fuga_a = 'fuga_a_0' fuga_b = 'fuga_b_0' val1 = 'val_1_0' val2 = 'val_2_0' val3 = 'val_3_0' data.last_update = dt.now() session.add(data) # テーブルBにデータ挿入 data2 = TableB( hoge_no= data.hoge_no, fuga_a = fuga_a, fuga_b = fuga_b, last_update = dt.now() ) session.add(data2) # コミット session.commit() # APIを叩いて外部連携する requests.get("http://hogehoge/renkei", params={"ID" : id, "VAL1" : val1, "VAL2" : val2, "VAL3" : val3,}) # 結果を返す return {"result" : "0"} この関数に引数 hoge_no を設定し実行することで、上述の運用作業を自動でやってくれるようになりました。これだけでだいぶ楽になりましたね。早速実行してみます。 PS C:hogehoge> aws lambda invoke --function-name hogehoge_operation --payload '{ "hoge_no": "xxxxxx" }' --cli-binary-format raw-in-base64-out response.json --profile profile_name { "StatusCode": 200, "ExecutedVersion": "$LATEST" } PS C:hogehoge> cat response.json {"result": 0 } 応答結果がresponse.json に出力されています。問題なさそうですね。 …ただし、aws-cliがインストールされていない環境では実行できません。 さらに手軽に実行できるように、Lambda関数をSlack経由で呼び出せるようにしたいと思います。 ② AWS Chatbot を利用してLambda関数をSlack経由で呼び出す WebコンソールからAWS Chatbotを開き、Slack ワークスペースを追加します チャットクライアントで「Slack」を選択し、「クライアントを設定」を押下すると、 認証画面へ遷移しますので、そのまま進めてください。 Slackワークスペースが作成されますので、「新しいチャネルを設定」ボタンを押下します。 設定画面から各種設定を行います。 チャネルID には、利用するSlackチャンネルのIDを入力します。 SlackのリンクURLを入力すると、チャネルID部分だけ切り取ってくれます。(便利) アクセス許可には、適切なロールを設定しましょう。 チャネルロールは「テンプレートを使用してIAMロールを作成する」を選択し、 ポリシーテンプレートは「通常のアクセス許可」「Lambda呼び出しコマンドのアクセス許可」を選択します。 ここまで設定したら、利用するSlackチャンネルで以下を入力します。 /invite @aws 入力後、以下が表示されればOKです! 続けて、以下のコマンドを入力します。 @aws lambda invoke –payload {“hoge_no” : “xxxxx”} –function-name hogehoge_operation –region ap-northeast-1 実行確認のメッセージが通知されますので、「[Run] command」 を押下します。 押下すると、コマンドを実行した旨の通知と実行結果が返ってきました! aws-cli を使わずに、SlackからLambda関数を呼び出すことができるようになりました!! …が、毎回コマンドを入力するのも正直面倒ですよね。 更に運用を楽にするため、Slackワークフローを利用してみましょう! ③ Slackワークフローを利用してコマンドを実行する Slackワークフロービルダーにて、以下のようなフローを作成します。 チャンネルのショートカットから起動する フォームを作成し、受付番号(hoge_no)を入力できるようにする チャンネルにコマンドを送信する hoge_no は引数に指定する 送信するメッセージはこんな感じです。ほぼ入力していたコマンドそのままですが、 hoge_no は「変数を挿入する」からフォームの入力値を設定します。 公開をしたら早速ワークフローを実行してみます。 チャンネルから「てすと」ショートカットを選択します。 フォームが表示されますので、受付番号を入力し、「Submit」ボタンを押下します。 ワークフローからコマンドが送信され、引数付きでLambdaを実行することができました! とある運用作業の手順(簡易化後) 上記①~③の対応を行ったことで、運用作業手順は以下になりました。 依頼元から作業依頼を受ける Slackのショートカットからワークフローを起動し、受付番号を入力して送信 結果を確認して終わり 簡易化前・後を比較するとだいぶやることが減りましたね♪ おわりに いかがでしたか? 面倒な運用作業もAWS・Slackを利用することによって簡易化することができました。 是非参考になればと思います。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
こんにちは。最近PCを買い替えましたたけろいどです。 Nuxt3にStorybookとTailWindCSSを入れるまで はじめに Nuxt3、RC1おめでとうございます。 本リリースまでが待ち遠しいです。 ちょうど社内用ツールの開発があったのでNuxt3を導入しStoryBookなどのエコシステムを入れてみました。 Nuxt2であればモジュールが存在しますので簡単にセットアップできますがNuxt3はまだその辺りが充実していません。そのため手動でセットアップしていくこととなります。 その備忘録を残しておきます。だれかの参考になれば幸いです。 Nuxt3のインストール まずはNuxt3をインストールしましょう sample-project部分はご自身のプロジェクトに合わせましょう npx nuxi init sample-project Storybook パッケージインストール 必要なパッケージをインストールします。 yarn add -D @storybook/vue3 @storybook/addon-essentials storybook-builder-vite .storybookディレクトリ作成 storybookの設定を行うディレクトリを作成します mkdir .storybook touch .storybook/main.js touch .storybook/preview.js main.jsとpreview.jsも書いておきます。 // main.js module.exports = { stories: [ "../components/stories/**/*.stories.mdx", "../components/stories/**/*.stories.@(js|jsx|ts|tsx)", ], addons: ["@storybook/addon-essentials"], framework: "@storybook/vue3", core: { builder: "storybook-builder-vite", } }; // preview.js export const parameters = { } 次はpackage.jsonにstorybookを立ち上げるコマンドを書きましょう "storybook": "storybook-start -p 6006" その後実際に yarn storybook などでstorybookを立ち上げてみましょう 以下のような画面が表示されます。 まだstoriesがないのでその旨のエラーが吐かれていることがわかります。 storiesの作成 storiesを作成していきます。 まずは必要なディレクトリを切っていきましょう。 mkdir components touch components/Button.vue mkdir components/stories touch components/stories/Button.stories.ts 今回は以下のようなButton.vueを作成しました。 <script setup lang="ts"> interface PropType { type?: "button" | "submit" | "reset"; } withDefaults(defineProps<PropType>(), { type: "button", }); </script> <template> <button :type="type"> <slot></slot> </button> </template> <style scoped> button { font-size: 24pt; } </style> storiesも一緒に作成しましょう。 import Button from "../Button.vue"; export default { title: "Button", component: Button, }; const Template = (args: any) => ({ components: { Button }, setup() { return { args, }; }, template: ` <Button v-bind="args">Button</Button> `, }); export const Primary: any = Template.bind({}); Primary.args = { type: "button", }; 再度 yarn storybook などでstorybookを立ち上げてみます 無事Buttonが表示されています。 Storybookの導入ができました。 一方でTailWindCSSをStorybook上で使うことはまだできません。 次の章でTailWindCSSを導入していきます。 TailWindCSS パッケージインストール StorybookにTailWindCSSを動かす前にまずはNuxt3上で動作するようにしていきましょう。 必要なパッケージをインストールします。 yarn add -D @nuxtjs/tailwindcss 初期化処理 Tailwindが入ったら初期化します。 tailwind.config.jsが作られていることを確認してください npx tailwindcss init これでTailwindCSSがVueファイル内で使えようになりました。 class=”p_10” などを指定して確かめてみましょう。 StorybookとTailwindCSSをつなぐ 以上の設定によりStorybook起動とNuxt3上でのTailwindCSSの適応は確認できました。 一方でStorybook上でTailwindCSSが反映されておらずレビュー時に混乱を招く可能性があります。 このセクションではこれを解決していきます。 assetsの作成 tailwindCSSのbaseなどを読み込むためにassetsを作成します mkdir assets mkdir assets/css touch assets/css/tailwind.css tailwind.cssは以下のようにします @tailwind base; @tailwind components; @tailwind utilities; tailwind.config.jsの修正 tailwind.config.jsのcontentに設定を追加します。 /** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./app.{vue,js,ts,jsx,tsx}", "./components/**/*.{vue,js,ts,jsx,tsx}", "./layouts/**/*.{vue,js,ts,jsx,tsx}", "./pages/**/*.{vue,js,ts,jsx,tsx}", "./plugins/**/*.{js,ts}", ], theme: { extend: {}, }, plugins: [], } StorybookにpostCSSの設定を追加 まずはpostCSSをStorybookに設定していきましょう。 そのためにアドオンをinstallしましょう。 npm install -D @storybook/addon-postcss まずはStorybookのmain.jsを変更していきます。 addonsにpostCSSを追加します module.exports = { stories: [ "../components/stories/**/*.stories.mdx", "../components/stories/**/*.stories.@(js|jsx|ts|tsx)", ], addons: [ "@storybook/addon-essentials", { name: "@storybook/addon-postcss", options: { cssLoaderOptions: { importLoaders: 1, }, postcssLoaderOptions: { implementation: require("postcss"), }, }, }, ], framework: "@storybook/vue3", core: { builder: "storybook-builder-vite", }, }; 次はpreview.jsを修正していきます。 修正内容は簡単でtailwind.cssをimportするだけです。 import '../assets/css/tailwind.css' export const parameters = { } 以上のことをやったのち npm run storybook とすることでtailwindCSSがStorybookに適応されていることが確認できました。 終わりに 今回はNuxt3でStorybookとtailwindCSSを導入してみました。 Nuxt3はTSがしっかりとサポートされており、触っていてとても楽しかったです。 useFetchやserverディレクトリなどの新機能も非常に使い勝手がよく、これからの開発もワクワクしてくるよいフレームワークです。 ぜひみなさんもお試しください 参考 https://github.com/nuxt-community/storybook/issues/330 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに ニフティでエンジニアをしている添野 翔太です。 ここ最近、 @niftyトップページ システム基盤の刷新を進めていく中で、ニフティの様々なサービスのデータを取得するために、APIをGoで作成していました。 そして、API仕様ドキュメントの管理をどうするか悩む中で、 こちらの記事 (@pei0804さんに感謝)を見つけ、Swagというツールに着目しました。 本稿ではAPI仕様ドキュメントを生成するSwagを導入した際にハマったことを紹介します。 Swagとは API仕様定義に基づくツールセット Swagger に関連するツールであり、Go向けのものとなります。 SwaggerにはYAML形式やJSON形式で記述したAPI仕様定義に基づいてHTMLドキュメントを生成する機能があります。Swagを使うと、コードコメントからYAML形式とJSON形式で記述したAPI仕様定義を生成できます。 コード内に記述するため、ドキュメントの更新漏れリスクを低減させることが可能となります。なお、詳しい記述ルールは Swag公式リポジトリにあるREADME を参照してください。 実際にSwagを使ってみる 実際にコードコメントからYAML形式とJSON形式のAPI仕様定義を生成してみます。 そのために適当なユーザーの一覧を返却するサンプルAPIを用意しました。 以下は、抽出したいユーザーが所属するサービスの識別子をもとに、ユーザー一覧を返却するAPIのコードです。import文の下とhandler関数の下に、Swagで使用されるコードコメントを記載しています。 package main import ( "bytes" "encoding/json" "fmt" "log" "net/http" "time" ) // @title ブログ記事用サンプルAPI // @version 1.0 // @description ブログ記事用サンプルAPI // @host localhost:8081 type User struct { ID json.Number `json:"id"` Name string `json:"name"` LastUpdateDate time.Time `json:"last_update_date"` } type Error struct { ID string `json:"id"` Message string `json:"message"` } var users = []User{{ ID: "1", Name: "太郎", LastUpdateDate: time.Now(), }, { ID: "2", Name: "花子", LastUpdateDate: time.Now(), }, { ID: "3", Name: "次郎", LastUpdateDate: time.Now(), }} var error_400 = Error{ ID: "ERROR-001", Message: "リクエストパラメータが不足しています", } // handler godoc // @Summary users // @Description get the users list // @Accept json // @Produce json // @Param service query string true "Service you want to get the users list" // @Success 200 {object} main.User // @Failure 400 {object} main.Error // @Router /users [get] func handler(w http.ResponseWriter, r *http.Request) { var buf bytes.Buffer enc := json.NewEncoder(&buf) service := r.URL.Query().Get("service") fmt.Println("service =>", service) if service == "" { if err := enc.Encode(&error_400); err != nil { log.Fatal(err) } fmt.Println(buf.String()) http.Error(w, buf.String(), 400) return } if err := enc.Encode(&users); err != nil { log.Fatal(err) } fmt.Println(buf.String()) _, err := fmt.Fprint(w, buf.String()) if err != nil { return } } func main() { // GET /users http.HandleFunc("/users", handler) log.Fatal(http.ListenAndServe(":8081", nil)) } さて、API仕様ドキュメントを生成するための準備が揃いましたので生成します。 APIのコード(main.go)が存在するディレクトリで以下のコマンドを入力すると、 $ go install github.com/swaggo/swag/cmd/swag@latest $ swag init 構文解析エラーが表示されました。これが本稿の題名にあるハマりポイントでした。 Generate swagger docs.... Generate general API Info, search dir:./ Generating main.User ParseComment error in file ./main.go :cannot find type definition: json.Number ここでエラーメッセージをもとに調べると、 こちらのissue や こちらのissue がヒットし、モジュール依存を解決するためのオプションが必要だと判明しました。 そこで、 $ swag init --parseDependency --parseInternal --parseDepth 1 を実行してみると、今度は上手く行ったようです。 Generate swagger docs.... Generate general API Info, search dir:./ Generating main.User Generating main.Error create docs.go at docs/docs.go create swagger.json at docs/swagger.json create swagger.yaml at docs/swagger.yaml 生成されたYAMLファイルを https://editor.swagger.io/ で確認してみると、API仕様ドキュメントを閲覧できました。 おわりに 本稿では、Swagとそれを初めて使ったときにハマったことを紹介しました。 Swagの記述ルール は個人的には分かりやすいと感じていて、導入してみてAPI仕様ドキュメントをすぐに生成できることに感動しました。 皆さんもぜひSwagを使うことを検討してみましょう。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは!新卒入社4年目の小松です。主にお客様が初めて@niftyをご利用になる際の無料ID会員登録システム、いろいろなサービスをご利用になる際のログインシステムの開発・運用を担当しています。 先日「マルチクラウド管理ノウハウ公開(AWS、ニフクラ)」に登壇しましたので、その様子を紹介していきます! イベント概要 NIFTY Tech Talk は、ニフティ株式会社の社員が主催するトークイベントです。 本イベントではニフティ社員が業務を通じて学んだことを発信しています。 第三回目となる今回は、「クラウドコスト」に関するテーマで開催しました。 ニフティでは、主にAWSとニフクラ、少しGCPを利用したマルチクラウドを管理しています。 テーマ1:「コストダウンの取り組み」 テーマ2:「コスト可視化の取り組み」 テーマ3:「コスト管理の取り組み」 イベントの詳細については こちら の記事でも紹介しておりますので、ぜひご覧ください。 また、今回の Tech Talk のアーカイブを YouTube にアップロードしております。 こちらもご覧いただけますと幸いです。 内容レポート 各テーマから一部抜粋して、どのような内容だったかご紹介したいと思います。 オープニング 今回はTech Talk初のYouTube Liveで開催しました。 はじめにニフティの会社紹介、登壇者の自己紹介から始まりました。 今回は最後にニフティポイントのプレゼントもありました! 今回の登壇者 小松 勇貴:会員システムグループ グループ長 福田 紫穂:インフラシステムグループ マネージャー 河野 曜平:インフラシステムグループ インフラチーム 小松 初:基幹システムグループ サービスインフラチーム 深田 健太:会員システムグループ メールチーム ニフティでのクラウド利用状況 ニフティでは現在、AWS・ニフクラ・GCPを利用しています。アカウント数は、AWS約240、ニフクラ約150、GCPが少数あり、これを社員のエンジニア150人で管理しています。 過去3年分のクラウドコストを見てみると増加傾向にあるのと、クラウドの予算と実績の乖離も増加傾向であったため、全社的にクラウドコストダウンとコスト管理強化に取り組みました。 テーマ1:「コストダウンの取り組み」 まず1つ目のテーマは、「コストダウンの取り組み」です。 実際に社内で取り組んだAWS、ニフクラのクラウドコストダウン方法を一部紹介しました。 初歩的なものから紹介しているので、何か参考になるものがあれば幸いです。 紹介した取り組み一覧です。 不要サーバ停止 スペック見直し(サーバ、ディスク) 料金プランの変更 利用時間外のリソース停止 Fargate Spotの利用 AWSによる推奨事項の活用 AWS RI/SPの適用 Amazon CloudFront Security Savings Bundleの適用 AWSの通信量の節減 CloudWatchログの保持期間設定 例えば、全クラウド共通でコストダウン効果が大きいものとしては、利用時間外のリソース停止があります。ここではAWS Lambdaとニフクラ、AWSのそれぞれのSDKを用いて、スケジューリングを行う方法を紹介しました。なおニフクラの場合は月額課金ではなく、従量課金にしておく必要があります。 工夫した点 工夫したことの一部にはチーム全員でクラウドコストダウンを取り組む方法として、スクラム開発で行った話を紹介しました。 ニフティでは、スクラム開発を導入するチームも増えてきています。 テーマ2:「コスト可視化の取り組み」 2つ目のテーマでは、「コスト可視化の取り組み」です。 継続的にクラウドコストダウンをするために、マルチクラウドのコスト可視化に取り組んだ話を紹介しました。 各ベンダーから提供されている生データをそのまま分析するのは手間なので、AWSとニフクラの請求情報をRedashでグラフ表示させた話をしました。 AWS、ニフクラ、それぞれの請求データ収集方法も話していますので、気になる方はアーカイブの方をご覧いただけますと幸いです。 さらに、フィルターを充実させることにより、期間ごと、プロダクトごと、部署ごとにフィルターをかけることができて、分析しやすくなりました。 今後は機械学習など用いて、予測額の精度を上げていく取り組みを行っていきます。 またGCPなどにも対応予定になっています。 工夫した点 AWS為替レートの取得で工夫した点を紹介しました。 フォーマット変更に弱い、AWSのPDFベースの請求書からデータ取得をやめ、AWS CURからデータを取得するようにしました。 このためにAWS Lambdaを実行する必要がありますが、さらにSlackワークフローを用いるように工夫したことにより、アカウントにログインせずとも、誰でも請求データを作成できるようになりました。 テーマ3:「コスト管理の取り組み」 最後のテーマは「コスト管理の取り組み」です。 適正なコストを維持するための、コスト管理の仕組みを紹介しました。 各アカウント単位で月次のクラウドコスト見通し額を立て、月末実績と一定以上の乖離があれば、差額と理由を報告する仕組みを導入した話をしました。 アカウントごとに見通しと実績に一定以上の乖離があれば、アラートが飛ぶ仕組みもあり、コスト見直しのきっかけになっています。 見通し額などの修正をする場合は現在Slackワークフローで申請するようになっていますが、もっと申請の手間をなくすためのプラットフォームを開発しています。 利用者側からの感想 アラートによって実際に誤請求に気づけた AWS、ニフクラの全アカウントにアラート設定をしてくれているので、手間がかからず助かっている アラートが来た場合は原因調査もするためクラウドコスト意識は上がった などの感想があり、実際にクラウドコスト意識向上に役立っています。 大変だった点 経理が円で管理しているのに合わせて、AWSも円で管理していたが、円安影響を受けアラートが大量に出てしまった話をしました。 これにより、「円安影響のため」といった無意味な見通し額修正の申請が大量にされてしまい、AWSはドルで受け付けるようにシステムの改修をしました。 まとめ 今回の Tech Talk では、ニフティでのマルチクラウドコスト管理方法、クラウドコストダウン方法を紹介しました。 1 時間という短い枠だったので、今回話しきれなかったものもありますが、参考にできるものがあれば幸いです。 初のYouTube Liveで開催でしたが、コメントくださった方もいました。ありがとうございました。 今後も NIFTY Tech Talk は継続して実施していきますので、ぜひご参加ください。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに はじめまして。会員システムグループでメールシステムの担当をしている鹿野です。 みなさまは、担当されているシステムの監視アラート対応はどうされていますか? 弊社のメールシステムはメールサービスを提供しているというその特性もあり、緊急度の高いアラートは電話で担当者に通知を行う構成を採用しています。 今回はそのアラート発生から担当者に電話で通知するまでのフローを Alertmanager と Amazon Connect を使って構成したお話です。 この記事で使用している構成コードのサンプルは こちら システム構成 構成はとてもシンプルです。 アラートが発生するとAlertmanagerがSNSトピックにメッセージを発行し、メッセージを受けたSNSトピックはサブスクライブしているLambda関数を呼び出します。 呼び出されたLambda関数がAmazon ConnectのStartOutboundVoiceContact APIをコールします。 Amazon Connectが電話で通知を行います。 Lambda関数のコードサンプルを以下に抜粋しておきます。 import os import boto3 DEST_PHONE_NUMBER = "+81xxxxxxxxxx" connect = boto3.client("connect") def lambda_handler(event, context) -> None: contact = connect.start_outbound_voice_contact( DestinationPhoneNumber=DEST_PHONE_NUMBER, ContactFlowId=os.getenv('CONNECT_CONTACT_FLOW_ID'), InstanceId=os.getenv('CONNECT_INSTANCE_ID'), SourcePhoneNumber=os.getenv('SOURCE_PHONE_NUMBER'), Attributes={"message": "This is alert notification system."}, ) 今回使用するサンプルでは発信先電話番号を定数(DEST_PHONE_NUMBER)として定義していますが、環境変数で渡してあげたり、またはDBで管理するなどお好みで拡張ができます。 また、着信時に流れる機会音声の内容についてはAttributesパラメータに渡すmessage属性の内容がそのまま適用されるようになっています。 構成してみる 以下のステップで構成していきます。 通知システムの構成 Alertmanagerのアラート通知設定 通知システムの構成 ここでの通知システムとは、構成図のAWSリソース群のことを指します。 構成するには、以下の要素が満たされていることが前提です。 Terraformクライアントがインストール済み AWS IAM認証情報が設定済み 実行計画を確認して、 terraform plan 構成を反映します。 terraform apply outputsに出力された以下項目はAlertmanagerのアラート通知設定で使用するので、値を控えておきます。 iam_assumable_role_arn sns_topic_arn terraform outputs また、SNSトピックへメッセージを発行するIAMユーザーのアクセスキーが必要です。 コンソールまたはCLI等から取得しておきましょう。 Alertmanagerのアラート通知設定 Alertmanagerのバージョンは 0.23.0 以降が必須です。 Prometheus及びAlertmanager自体の構成は済んでいるものとし、Alertmanagerのバージョンは 0.23.0 を使用しています。 以下のステップで構成していきます。 IAM認証プロファイルの作成 Alertmanager設定ファイルにAWS SNSレシーバーを追加 IAM認証プロファイルの作成 Alertmangerのホスト上にIAM認証プロファイルを作成しておきます。 このサンプルでは、プロファイル名を共に alertmanger  とします。 Alertmanager設定ファイルにAWS SNSレシーバーを追加 Alertmanager設定ファイルにAWS SNSレシーバーを追加します。 route: receiver: 'snsreceiver' receivers: - name: 'snsreceiver' sns_configs: - api_url: 'https://sns.ap-northeast-1.amazonaws.com' topic_arn: '<sns_topic_arn>' subject: 'optional string' sigv4: region: 'ap-northeast-1' profile: 'alertmanager' role_arn: '<iam_assumable_role_arn>' topic_arn に前の項目で控えておいた sns_topic_arn の値を入力します。 sigv4.role_arn に iam_assumable_role_arn の値を入力します。 設定ファイルを保存後、Alertmanager を再起動、または設定を再読み込みさせれば Alertmanager の通知設定は完了です。 構成後の注意点 AWSリソースを構成して、Alertmanagerにも通知設定を反映したからはい終わり! となればいいのですが、電話でアラート通知を受けるにはあともう2ステップ必要です。 発信元電話番号の取得とコンタクトフローへの紐づけ 発信先電話番号の制限解除 発信元電話番号の取得とコンタクトフローへの紐づけ この記事を執筆した時点では、発信元電話番号の取得や、取得した電話番号をコンタクトフローへ紐づけするリソースが、TerraformのAWSプロバイダーに存在していなかったため構成内に組み込むことができませんでした。 本サンプルではコンソール上から紐づけ作業を行いますが、CLIでも同様のこと(claim-phone-number, associate-phone-number-contact-flow)ができるので構成フローに組み込もうと思えばできると思います。 発信元電話番号の取得とコンタクトフローへの紐づけは、Amazon Connectインスタンスの管理画面から行います。 取得と紐づけができたら、terraform.tfvarsファイルを作成して、 connect_source_phone_number に取得した発信元電話番号(E.164)を設定します。 connect_source_phone_number = "+1xxxxxxxxxx" 構成を更新します。 terraform apply 発信先電話番号の制限解除 地味なハマりポイントです。 これで発信できるようになったと思いきや、試しにアラート通知テストをしてみると以下のエラーに遭遇します。 [ERROR] DestinationNotAllowedException: An error occurred (DestinationNotAllowedException) when calling the StartOutboundVoiceContact operation: None エラー文だけだとさっぱり分かりません。 原因は、日本の携帯電話番号が デフォルトでは許可されていないプレフィックス として、サービス側で制限されていたからでした。 リストに載っているプレフィックスから始まる電話番号に発信したい場合は、AWSサポートからサービスクォータ引き上げ申請を行います。 内容に問題がなければ、数日程度で受理されます。 ここまでやることで、アラート通知を電話に発信できるようになります。 カスタマイズするとしたら 大きく二分すると、カスタマイズ先は以下の2つが挙げられます。 Lambda関数 コンタクトフロー 「発信先電話番号の指定」は前者でしかできませんが、それ以外のことはどちらでも可能です。 しかし、StartOutboundVoiceContact をコールしてから電話が切断されるまでのフローはコンタクトフローで制御されているため、フローの制御はできることならコンタクトフローに任せてしまったほうが楽かと思います。 例えばですが、「電話を受信して対応を開始したか?」に基づいてSlackに通知したければ、以下のようなフローを組み込めば実現できるかもしれません。 「顧客の入力を取得する」+「顧客の入力を保存する」 or 「コンタクト属性の設定」 -> 「コンタクト属性を確認する」 -> 「Slack通知するLambda関数を呼び出す」 まとめ Amazon Connect を使って電話アラート通知の仕組みを構成できる 発信先電話番号に制限がある点には注意が必要 以上がAlertmanagerとAmazon Connectで構成する電話アラート通知についてのお話でした。 Terraformのアップデートで、将来的にはTerraformだけで構成作業が完結できるようになることを期待しています。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
イベント概要 NIFTY Tech Talkは、ニフティ株式会社の社員が主催するトークイベントです。 本イベントではニフティ社員が業務を通じて学んだことを発信しています! 第4回目のテーマは「レガシーシステムからの脱却」。現在、ニフティではさまざまなシステムの刷新やリプレースなどを行っています。今までのレガシーなシステムからモダンなシステムにどんどん切り替えていこうという流れが全社的に強くなっています。 今回は、レガシーシステムから脱却したプロダクトに携わっている現場のエンジニアを中心に、パネルディスカッション形式でリアルな現場の声をお伝えします。 概要 日程:8月23日(火)19:00〜20:00 配信方法:YouTube Live 視聴環境:インターネット接続が可能なPC/スマートフォン 参加方法 YouTube Live connpass にて参加登録をお願いします! こんな方におすすめ レガシーシステムからの脱却を検討している方 モダンな技術を現場で導入したいと考えている方 ニフティの現場でどのような技術が使われているか興味のある方 タイムテーブル 時間 コンテンツ 19:00-19:05 オープニング+会社紹介 19:05-19:15 登壇者紹介 19:15-19:20 固定IP受付システム刷新 19:20-19:25 老舗ポータルサイトの新たなシステムへの挑戦 〜@niftyトップページ〜 19:25-19:30 ニフティニュースの夜明け 〜32万超のページをレガシーシステムから救出!〜 19:30-19:35 レガシーなシングルサインオンシステムを 完全内製で作り直した話 19:35-19:55 ディスカッション & 質疑応答 19:55-20:00 クロージング テーマ 各プロダクトに携わっている方々に登壇していただき、それぞれLT形式で発表していただきます。 その後、発表していただいた内容についてディスカッションしていただきます。 固定IP受付システム刷新 ニフティ接続サービスで利用できるIPv4固定IPサービスの刷新について話していただきます。中でKubernetesが使われており、モダンな作りになっています! 老舗ポータルサイトの新たなシステムへの挑戦 〜@niftyトップページ〜 @niftyトップページの刷新について話していただきます。外注で作られた複雑なシステムをNext.jsとAWSを使って刷新しました! ニフティニュースの夜明け〜32万超のページをレガシーシステムから救出!〜 月間1億PV、32万記事超の規模であるニフティニュースを、レガシーシステムから段階的に移行しています。大規模システムの移行中で得られた知見や学びに関して紹介します! レガシーなシングルサインオンシステムを完全内製で作り直した話 各サービスで使われているSSOシステムの刷新について話していただきます。より安全に、互換性を持って前のバージョンから移行し、完全内製で刷新しました! 登壇者プロフィール 島田 大徳 (登壇者 & ファシリテータ) ニフティ株式会社 基幹システムグループ 課金システムチーム 新卒4年目。資料発送システムを中心に課金系、入会系システムを扱っています。好きなものはコンテナ技術。 添野 翔太(登壇者) ニフティ株式会社 会員システムグループ 第1開発チーム 新卒入社6年目。@niftyトップページの開発・運用を担当。AWS認定資格9冠達成、電気通信主任技術者資格を所持し、電気通信主任技術者に選任。 村松 啓寛(登壇者) ニフティ株式会社 会員システムグループ 第2開発チーム 新卒入社4年目。ニフティニュースの開発・運用を担当し、最近はモダンなフロントエンド開発を学びながら、実践中。 清水 利音(登壇者) ニフティ株式会社 基幹システムグループ サービスインフラチーム 新卒入社6年目。シングルサインオンシステムのスクラムマスターとして刷新・開発・運用などの活動をしています。 一緒に働く仲間を募集中です 新卒採用、キャリア採用を実施しています。ぜひ リクルートサイト をご覧ください。 ニフティエンジニアが業務で学んだことやイベント情報を エンジニアブログ にて発信しています! ニフティエンジニアのTwitterアカウントを作りました NIFTY Tech Talkのことや、ニフティのエンジニアの活動を発信していきます。 https://twitter.com/NIFTYDevelopers
アバター
初めに こんにちは!ニフティ新卒1年目の柴田です。研修が終わり、会員システムグループに配属されました。 配属先では、US配列のMacを使用しています。US配列を使用すると、JIS配列に慣れているため、英数/かなの切り替えが不便に感じます。そこで、US配列でもJIS配列のように英数/かなを切り替えられるよう設定しました。この記事ではその方法をまとめます。 不便な点 JIS配列のMacはスペースキーの左右に英数/かなを切り替えるキーがあり、左側のキーを押すと「英数」、右側のキーを押すと「かな」に切り替えることができます。 これがとても便利です。(Windowsを使用していた時も変換キー、無変換キーを英数/かなに割り当てて使用していました。) しかし、US配列のMacには英数/かなキーがありません。そのため、US配列のMacでは「Control + Space」での切り替えになってしまい、とても不便に感じます。 そこで、スペースキーの左右にある⌘COMMANDキーをそれぞれ英数/かな切り替えに割り当ててJIS配列のようにします。 設定方法 karabiner-elementsをインストール 画面に出てくる指示に従いインストールを完了させます karabiner-elements.pqrs.org karabiner-elementsでキーを割り当てる 今回はスペースキーの左右にある⌘COMMANDキーをそれぞれ英数/かな切り替えに割り当てます。 v14.5.0以降は  Swift UIに移行して UIが大幅に変わっているので過去の情報に注意してください https://karabiner-elements.pqrs.org/docs/releasenotes/#karabiner-elements-1450 Karabiner-Elementsを開く (Karabiner-EventViewerではない) サイドバーにある「Complex Modifications」をクリック 「Add rule」をクリック 「コマンドキーを単体で押したときに、英数・かなキーを送信する。(左コマンドキーは英数、右コマンドキーはかな) (rev 3)」の Enableをクリック 完了! これで左側の⌘COMMANDキーを押すと「英数」、右側の⌘COMMANDキーを押すと「かな」に切り替えることができます。 終わりに 今回は、US配列のMacをJIS配列のように英数/かなを切り替えらるように設定しました。 生まれて初めてUS配列を使用していますが、英数/かなの切り替え以外にはUS配列に不便を感じず、むしろcontrol, option, commandが並んでいるのがJIS配列に比べて使いやすく感じています。今後JIS配列とUS配列を選べる場合はUS配列にしようと思うくらい気に入っています! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは。ニフティ株式会社に入社して新卒四年目の佐々木です。 今回は、業務で触れる機会のあった「NextAuth.js」について紹介したいと思います。 この記事の内容 NextAuth.jsの特徴 NextAuth.jsの実装方法 NextAuth.jsとは NextAuth.js とは、Next.jsで認証機能を実装するためのライブラリです。 特徴 NextAuth.jsの 特徴 としては以下になります。 セッションデータの保存をデータベースなしでも使用できる サーバーレス環境向けに設計されている(それ以外の環境でも利用はできる) デフォルトの設定でセキュアになるように設計されている ログインのセッションについては、データベースを使用せずにJWTで管理することができます。 例えばユーザー情報をアプリケーション側に保持しなくても良い場合は、「ログイン機能のためにデータベースを用意する」といった手間も省くことが可能です。 認証を行うコンポーネントを自前で実装する方法もありますが、NextAuth.jsといったライブラリを利用した方が、自前で実装したときと比較してアプリケーション以外にかけるコスト(運用やセキュリティ面のリスク)を下げることができると思います。 実装してみる 次に、NextAuth.jsを利用した際の実装例について紹介したいと思います。 NextAuth.jsでの認証の実装で作成するファイルは以下になります。 pages/api/auth/[…nextauth].js:認証プロバイダーやセッション保存方法を指定するために必要 pages/_app.js:Sessionオブジェクトを取得できるようにするために必要 pages/index.js: ログイン処理の実装を埋め込むために必要 next.config.js: 本番環境で外部の環境変数を参照するために必要 前提条件 技術:NextAuth.js(v4) + Next.js + React セッション格納方法:JWT Next.jsのアプリケーションは作成済み (NextAuth.jsはv3系からv4系へのアップデートで大きな変更が入ったため、今回は最新版である v4系 での紹介となります。詳細は こちら をご参照ください。) インストール まずは必要なパッケージのインストールを行います。 yarn add next-auth pages/api/auth/[…nextauth].js NextAuth.jsを組み込むには、pages/api/auth配下に[…nextauth].jsというファイルを用意する必要があります。 認証プロバイダー 認証プロバイダーを指定するため、providerオプションを追加します。認証プロバイダーに関しては、clientId、clientSecretなどの指定を行います。 認証プロバイダーには 組み込みのプロバイダー も用意されており、Google、Twitter、Githubといった有名なプロバイダーであればこちらから利用が可能です。 例として、Googleをプロバイダーとして指定する場合は以下のようになります。 import NextAuth from "next-auth" import GoogleProvider from 'next-auth/providers/google'; export default NextAuth({ providers: [ GoogleProvider({ clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, }), ], }) ちなみに、指定するプロバイダーについては、自前で用意した任意のカスタムプロバイダーを指定することもできます。詳細は NextAuth.jsの公式ドキュメント をご参照ください。 セッション 次に、セッションの保存方法を指定するため、sessionオプションを追加します。 NextAuth.jsは、デフォルトでDBを使用せずJWTのみでセッション管理とユーザ情報の管理を行います。しかし、公式のFAQ(  https://next-auth.js.org/faq#databases  )の例にあるようなDBへのユーザ情報の保存が必要なケースでは、strategyをdatabaseに指定しDBに接続するためのadapterを別途用意します。 今回はJWTでセッション管理を行うため、strategyをjwtに指定します。 providers: { ... }, session: { strategy: "jwt", maxAge: 30 * 24 * 60 * 60, }, pages/_app.js SessionProviderの設定 後ほど設定するuseUsession()でSessionオブジェクトを取得できるようにするために、<SessionProvider>を設定する必要があります。取得したセッションは同じアプリケーションが動くすべてのブラウザタブ/ウインドウで同期されるようになります。 pages/_app.jsに以下を追加します。 import { SessionProvider } from "next-auth/react" export default function App({ Component, pageProps: { session, ...pageProps }, }) { return ( <SessionProvider session={session}> <Component {...pageProps} /> </SessionProvider> ) } pages/index.js NextAuth.jsには Client API といったものが用意されており、これらのフック関数を使用することでログイン処理や、セッション情報の判定といった操作を簡単に行うことができます。 ログイン・ログアウト pages/index.js内でログインボタンを設置し、クリックした際に サインイン処理 が実行されるようにします。 signiIn()関数を使用すると、NextAuth.jsのサインインの中間ページにリダイレクトされます。 import { signIn } from "next-auth/react" export default () => <button onClick={() => signIn()}>Sign in</button> signIn()関数の第1引数にGoogleなどのプロバイダー名を指定することで、NextAuth.jsの中間ページをスキップして直接ログインさせることもできます。 また、第2引数にcallbackUrlを指定すると、ユーザーがサインイン後にリダイレクトで戻ってくるページを任意のURLに変更もできます。ログイン後に別ページにリダイレクトさせたい場合には使えそうですね。 import { signIn } from "next-auth/react" export default () => <button onClick={() => signIn('google', { callbackUrl: 'http://localhost:3000/bar' })}>Sign in</button> ログアウトさせたい場合は signout()関数を使用します。 import { signOut } from "next-auth/react" export default () => <button onClick={() => signOut()}>Sign out</button> セッション情報の利用 NextAuth.jsでログインすると、sessionにユーザー情報が格納されます。 それらを利用して、ログイン後に別のコンポーネントを表示させたり、ユーザーごとにクライアント側の処理を変更させる、というように簡単にクライアント側のみで動作のカスタマイズが可能です。 クライアント側からsession情報にアクセスするにはuseSession()を利用します。useSession()はクライアントアプリケーションのどの階層からでも呼び出すことができます。 以下がその利用例です。 import { useSession, signIn, signOut } from "next-auth/react" export default function Component() { const { data: session } = useSession() if (session) { return ( <> Signed in as {session.user.email} <br /> <button onClick={() => signOut()}>Sign out</button> </> ) } return ( <> Not signed in <br /> <button onClick={() => signIn()}>Sign in</button> </> ) } 環境変数の設定 ローカル環境で試す場合 先程[…nextauth].jsに記述した、clientId や callbackUrl などの値を env.local に環境変数として設定します。 GOOGLE_CLIENT_ID=xxx GOOGLE_CLIENT_SECRET=xxx 本番環境にデプロイする場合 本番環境にデプロイする場合は、ローカル環境で設定した値に加えて以下の環境変数を追加します。 NEXTAUTH_URL NEXTAUTH_SECRET NEXTAUTH_URL NEXTAUTH_URL にはサイトの正規URLを指定します。 NEXTAUTH_SECRET NEXTAUTH_SECRET にはデフォルトのシークレットの値を指定します。この値はJWTを暗号化しトークンをハッシュするために使用します。 (本番環境ではNEXTAUTH_SECRETの値が定義されていないと エラー が発生するため) また、シークレットにはopensslコマンドでランダムな文字列を生成すると便利です。 openssl rand -base64 32 環境変数の追加方法 本番環境などにデプロイする際には env.local だと環境変数として利用できないので、外部から値を参照できるようにする必要があります。 next.config.js というファイルを作成し、外部の環境変数を参照できるようにします。 require("dotenv").config(); module.exports = { env: { GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET, NEXTAUTH_URL: process.env.NEXTAUTH_URL, NEXTAUTH_SECRET: process.env.NEXTAUTH_NEXTAUTH_SECRET, }, }; さいごに 導入としては簡単になりますが、今回はNextAuth.jsのライブラリについて紹介しました。 NextAuth.jsには他にもオプションや機能などが充実しているので、もし興味があるという方は使ってみてください! 参考記事 https://next-auth.js.org/ https://nextjs.org/ We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
この記事は、ニフティのエンジニア組織を知っていただくための一環としての、チーム紹介記事です。 はじめに はじめまして、三国と申します。 私はニフティに入社して二十数年、様々なシステム部門を巡り巡ってきましたが、今回は、現在マネージャーとして担当している会員システムグループの第三開発チームを紹介します。 まず、当チームは以下2つのサブチームから構成されています。 メールチーム データ基盤チーム 「第三開発」だけでは何を担当しているチームか全く分からなかったと思いますが、これで多少のイメージはつきましたでしょうか。以下、順にご紹介します。 メールチームの紹介 メールチームでは@niftyのメールサービスを支えるシステムの運用・開発を行っています。 @niftyのメールサービスは歴史が長く、始まりを辿るとパソコン通信NIFTY-Serveの誕生までさかのぼることになってしまいますが、ここを割愛したとしても、インターネットの電子メールサービスを二十数年に渡って提供し続けています。 お客さまと共にサービス35周年 | @nifty この記事を読まれているみなさんも、友人・知人とメールをやり取りする際、「〇〇〇@nifty.com」というアドレスを一度は見た事がありますよね?(無かったらすみません)これのことです! @niftyメール このようなサービスですので、システムの規模、利用されているお客様の規模、いずれもニフティ内で随一です。そのためメールチームだけで全てを賄っている訳ではなく、システム監視の部門やお客様サポートの部門などと協力して、日々、サービスの維持に努めています。 直近のメールチームのお仕事は@niftyメールのリニューアルです。 @niftyメール リニューアルのお知らせ 長年積み重なった複雑な仕組みや仕様を解きほぐしながら、新たなシステムを構築するのは骨の折れる作業ですが、やりがいはあります。(チームメンバーもそう感じてくれているはず。。) 現在は登山で言うとまだ五~六合目と先はまだ長いですが、様々な課題をチーム一丸で解決しながら進めています。 最後に、メールチームのメンバーに仕事のやりがいを聞いてみましたので、いくつか紹介します。 メールシステムのベテラン Aさん 「非常に大規模なシステムの開発&運用を経験できる。コンシューマ向けのサービスであり、リアルな利用者の声を聞ける。関わることができる範囲が広く、システム担当でも機能提案が可能。このような点にやりがいを感じています。」 中途入社〇年目 Bさん 「システム構成が一般的なWeb系のサービスとは異なっており、知識・経験の幅を広げるという意味合いでも価値があると思います。」 入社〇年目の若手エンジニア Cさん 「〇〇万人ものユーザーがいるシステムを支えているため、責任感とやりがいがあります!」 データ基盤チームの紹介 上記ご紹介した通り、メールチームではお客様が直接ご利用されるサービスを提供していましたが、データ基盤チームではニフティ社内向けに「データ基盤」を提供しています。 みなさま「データ基盤」とは何なのかご存じでしょうか。 ニフティではお客様に、光ファイバー回線やモバイル回線などのネットワークサービスを始めとして、メールやセキュリティなどのオプションサービス、ニュースやポイントサイトなどのWEBサービスを提供しています。 事業紹介 | ニフティ株式会社 これら様々なサービスの情報を一元的に集約し、社内に共有しているのが「データ基盤」です。これにより社員であれば誰でも、事業の状況をすぐに参照したり、サービス横断的なデータ分析をすることができるようになります。ニフティの縁の下を支えているシステムなのです! ニフティには、特定の分野で突出した知識とスキルを持って活躍している社員を「N1!(nifty No.1)」として任命する制度があり、この第一期メンバーに名を連ねるデータアーキテクトが在席しています。データ基盤に興味を持たれた方はこちらもご覧ください。 N1! 制度 | ニフティ株式会社 データ基盤チームのメンバーにも仕事のやりがいを聞いてみていますので、いくつか紹介します。 N1!データアーキテクト Dさん 「様々な理由で分断されていたデータを集めて触れられ、利活用がバッチリハマったときは特に面白い。日々進歩している業界の知識を得られる点も楽しいです。」 入社〇年目の若手エンジニア Eさん 「社内のデータを集約しているので、様々なシステムについての知見を深められる!」 以上、簡単でしたが第三開発チームの紹介でした。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター