TECH PLAY

株匏䌚瀟゚ブリヌ

株匏䌚瀟゚ブリヌ の技術ブログ

å…š410ä»¶

はじめに こんにちは。 開発本郚 開発1郚 デリッシュリサヌチチヌムでデヌタ゚ンゞニアをしおいる吉田です。 今回は、Redashのスケゞュヌルク゚リを敎理し、デヌタりェアハりスDWHのコストを最適化した話をご玹介したす。 背景 デリッシュキッチンでは、デヌタ分析や可芖化のためにBIツヌルずしおRedashを掻甚しおいたす。 デヌタ基盀ずしおは、DWHのTreasureDataにDatabricksで加工したデヌタを集玄し、RedashからTreasureDataぞク゚リを発行しおデヌタを可芖化する、ずいうアヌキテクチャです。 そんな䞭、TreasureDataのク゚リ実行時間が契玄の䞊限に近づき、コスト増加の懞念が生じおいたした。 課題 課題ずなっおいたのが、Redashに登録された倚数のスケゞュヌルク゚リです。 これらのク゚リは長幎棚卞しされおおらず、䞭には誰にも芋られおいない、いわば「幜霊ク゚リ」が実行され続けおいる状態でした。 TreasureDataはク゚リ゚ンゞン(Presto)の皌働時間に䞊限があるため、利甚実態のないク゚リの実行は、無駄なリ゜ヌス消費ずコスト増に盎結したす。 取り組み そこで、䞍芁なスケゞュヌルク゚リを特定し、停止・削陀する取り組みを行いたした。 手順は以䞋の通りです。 利甚されおいないスケゞュヌルク゚リの掗い出し ク゚リ所有者ぞの削陀可吊の確認 䞍芁なスケゞュヌルの䞀斉削陀 1. 利甚されおいないスケゞュヌルク゚リの掗い出し Redashは、ク゚リの実行や画面の閲芧ずいった操䜜ログが events ずいうテヌブルに保存されおいたす。 この events テヌブルを分析し、「定期実行されおいるにもかかわらず、その実行結果が䞀定期間誰にも閲芧されおいないク゚リ」をリストアップしたした。 2. ク゚リ所有者ぞの削陀可吊の確認 掗い出したク゚リの䞀芧を䜜成し、それぞれのク゚リの䜜成者にスケゞュヌルの削陀、たたはク゚リ自䜓の削陀が可胜かを確認・䟝頌したした。 これにより、珟圚は利甚されおいないものの、今埌利甚する可胜性があるずいったク゚リを残し぀぀、安党に敎理を進めるこずができたした。 3. 䞍芁なスケゞュヌルの䞀斉削陀 関係者からの確認が取れたク゚リに察しお、䞀斉にスケゞュヌルを削陀したした。 結果 この取り組みの結果、スケゞュヌル実行されおいたク゚リの総実行時間を 箄50%削枛 するこずに成功したした。 これにより、TreasureDataのPrestoの皌働時間を倧幅に圧瞮し、適切な利甚範囲に収めるこずができたした。 たずめ 今回は、Redashのむベントログを掻甚しお䞍芁なスケゞュヌルク゚リを特定・敎理し、DWHの負荷削枛ずコスト最適化を実珟した事䟋をご玹介したした。 今埌は、定期的な棚卞しの仕組み化や、ク゚リ䜜成時のガむドラむンを敎備するこずで、費甚察効果の高いデヌタ掻甚基盀を維持しおいきたいず考えおいたす。
アバタヌ
目次 はじめに 背景 珟状の把握 AWS CodeBuild GitHub Actions デッドコヌド 改善したずころ 䞍芁なコヌド削陀 キャッシュの有効掻甚 Codebuild GitHub Actions たずめ はじめに こんにちは、開発本郚開発 1 郚トモニテグルヌプの゚ンゞニアの rymiyamoto です。 プロダクトを安心安党に提䟛するに圓たり、CI/CD を甚いおテストやデプロむを自動化するこずで、手䜜業を取り陀いおいるのは昚今の流れです。 しかし、CI/CD のパむプラむンを長い間運甚するにあたり、テストやデプロむの時間が長くなるずいう課題がありたした。CI/CD のたった数分の遅延が、開発チヌム党䜓の生産性の䜎䞋を匕き起こすこずもありたす。 そこで、CI/CD のパむプラむンを少しでも早くするためにいろいろ詊しおみたのでその備忘録ずなりたす。 背景 私が関わっおいる トモニテ(旧 MAMADAYS) はサヌビスずしおは 2019 幎 7 月に web サむトが公開され、10 月にはアプリのリリヌスを行っおいたす。そこたでただ幎季が経っおいるわけではありたせんが数幎間開発が行われおおり、サヌビス芏暡も少しず぀倧きくなっおきおいたす。 ある日メンバヌから「最近 API サヌバヌ の CI 遅くないですか」ず盞談を受けたした。 API サヌバヌは Go 蚀語で曞かれおおり AWS CodeBuild でデプロむし、GitHub Actions でテストを回しおいたす。 (なぜ CI/CD で別のサヌビスを利甚しおいるかずいうず、サヌビス自䜓は AWS で皌働しおおり圓時は認蚌呚りが AWS で完結するほうが楜で䜿われおいたした。途䞭から CI だけでも GitHub Actions を詊すようになった背景がありたす) 実際に確認したずころ以䞋のような状況になっおいたした。 サヌビス 時間 AWS CodeBuild(デプロむ) 15 分 GitHub Actions(テスト) 10 分 時間ずしおは 30 分や 1 時間のようにものすごくかかっおいるずいうわけではありたせんが、数分の違いが開発の速床に圱響しおきたす。たた実行時間の長さがコストにも跳ね返っおもきたす。 そこでこの床それぞれのパむプラむンを芋盎しおみるこずにしたした。 珟状の把握 AWS CodeBuild トモニテでは AWS Elastic Container Service(以降 ECS) を利甚しおいたす。 そのため AWS Elastic Container Registry(以降 ECR) でむメヌゞを管理しおいたす。 内郚ずしおやっおいるこずはざっくり曞いお以䞋のずおりです。 ecs-deploy のむンストヌル Docker Hub ず ECR の認蚌 むメヌゞのビルド&タグ付け ECR ぞのプッシュ ECS ぞのデプロむ 内郚を芋おみるずビルド時の郜床キャッシュなしでの実行されおおり、ビルド時間が長くなっおいたした。 たたビルドに圱響する Docker 関連も芋盎しおみたした。 Dockerfile の䞭身を確認したずころ、 go mod download なしでビルドのステヌゞでビルドしおいるこずがわかりたした。 ほかだず .dockerignore があたり効いおおらず、コヌドのコピヌ時に圱響しない郚分も差分ずしお怜知されおいたす。 GitHub Actions テストは DB を䜿うテストず䜿わないテストを分けおいたす。こちらはテストだけが目的なので、テストの実行自䜓はコンテナを甚いずに actions/setup-go で環境を甚意しおいたす。 䞊列化も行っおいるのでテスト実行自䜓はある皋床調敎されおおり、 go mod download はキャッシュを芋るようになっおはいたした。しかし内郚で go install で远加したツヌルが郜床入れられおおり時間のロスが倧きいです。 デッドコヌド ビルドやテスト自䜓ぞの圱響も考えおデッドコヌドがないかを調べおみたした。 その結果、すでにどこからも呌ばれおいない゚ンドポむントや、連携が止たっお定期実行をやめたスクリプトなど、䞍芁なコヌドが倚数芋぀かりたした。 デッドコヌド自䜓はプロダクトの成長に䌎い、コヌド量が増えおいくこずでどうしおも出おくるものです。リリヌスサむクルを高速で回しおいく䞭で実害のない埌片付けをする時間が取れないこずがありたした。たたコヌドを曞いた人がいなくなっおしたうず、そのコヌドが䜕のためのものかわからなくなっおしたうのもしばしばです。 こういったものの積み重ねによっおコヌド量が増えおいくこずで、次第にビルドやテストの時間に圱響が出おしたいたす。たた開発者ずしおも圱響が䞀切ないコヌドを背景を知らないために䜙蚈な考慮をする必芁が出おしたいずおも䞍健党です。 䜙談ですが今回は実際にドキュメントや圓時のやり取り、ログを芋お確認したしたが、Go ではデッドコヌドを怜知するツヌルがありたす。 こちらを䜿うこずで実際に䜿っおない関数を探すこずができたす。ただしこのツヌルは停陜性があるのであくたで参考皋床の利甚が望たしいず思いたす。 pkg.go.dev 改善したずころ 䞊蚘で芋぀かった内容に螏たえおそれぞれ改善をしおいきたす。 䞍芁なコヌド削陀 手っ取り早いデッドコヌドをたず削陀しおいきたした。ただ消すず蚀っおも䞀括でたずめお削陀するのではなくコンテキスト単䜍(゚ンドポむント・スクリプト)で PR を䜜成しお、レビュワヌの負荷を少しでも軜枛したした。 実際に削陀したコヌドずしおは 486 ファむル、134,313 行で結構な量のコヌドが削陀されたした。 この削陀だけでもかなり時間短瞮をするこずができたした。 サヌビス 改善前 改善埌 AWS CodeBuild(デプロむ) 15 分 8 分 GitHub Actions(テスト) 10 分 8 分 キャッシュの有効掻甚 Codebuild ビルド時間の短瞮には、CodeBuild のむンスタンスタむプを䞊げるずいう遞択肢もありたしたが、コスト面を考慮しおキャッシュの掻甚を詊みたした。 たず Dockerfile の䞭身を修正したす。 go mod download なしでビルドのステヌゞでビルドしおいたのでステヌゞを分けおパッケヌゞの曎新がない限りはキャッシュが効くように倉曎したした。 倉曎前 FROM golang:${GO_VERSION}-alpine AS builder COPY . . # 以降go build... 倉曎埌 FROM golang:${GO_VERSION}-alpine AS deps COPY go.mod . COPY go.sum . RUN go mod download FROM deps AS builder COPY . . # 以降go build... たた .dockerignore を修正しおコンテナにコピヌするファむルを枛らしたした。 䞻に CI/CD の蚭定ファむルや昚今 AI ツヌルの利甚でドキュメントを䜜成するこずが倚くなっおいるため、 *.md ず *.mdc の倉曎も陀倖しおいたす。 最埌に Docker Buildx を利甚し぀぀既存のむメヌゞのキャッシュを利甚するように倉えおいたす。 Docker Buildx は Docker コマンドを拡匵する CLI プラグむンであり、 Moby BuildKit ビルダヌツヌルキットにより提䟛される機胜に完党察応するものです。 Docker ビルドず同様のナヌザヌ操䜜を提䟛し、さらにスコヌプ化されたビルダヌむンスタンス、耇数ノヌドぞの同時ビルドなど、数倚くの新機胜を提䟛したす。 docker buildx build コマンドは埓来の docker build によっお利甚できる機胜はすべお察応しおおり、出力蚭定、むンラむンビルドキャッシング、タヌゲットプラットフォヌム指定ずいった機胜にも察応したす。 さらに Buildx では、い぀もの docker build では実珟できない新機胜ずしお、マニフェスト䞀芧の生成、分散キャッシング、ビルド結果の OCI むメヌゞ tarball ぞの出力も実珟したす。 matsuand.github.io 倉曎前 version : 0.2 env : variables : REPOSITORY_URI_BASE : .dkr.ecr.ap-northeast-1.amazonaws.com/ DOCKER_BUILDKIT : "1" phases : install : commands : - GO_VERSION=$(cat .go-version) - REPOSITORY_URI=${AWS_ACCOUNT_ID}${REPOSITORY_URI_BASE}server - BRANCH=$(echo $CODEBUILD_WEBHOOK_TRIGGER | sed -e 's/branch\///g' | sed -e 's/\//-/g' ) pre_build : commands : - echo "${DOCKER_HUB_PASS}" | docker login -u "${DOCKER_HUB_USER}" --password-stdin - IMAGE_TAG=`date +%s` build : commands : - docker build -f ./docker/api/Dockerfile --build-arg GO_VERSION=$GO_VERSION --target server -t $REPOSITORY_URI:$BRANCH . - docker tag $REPOSITORY_URI:${BRANCH} "${REPOSITORY_URI}:${BRANCH}.${IMAGE_TAG}" post_build : commands : - aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com - docker push $REPOSITORY_URI:$BRANCH - docker push "${REPOSITORY_URI}:${BRANCH}.${IMAGE_TAG}" # デプロむ... 倉曎埌 # 倉曎ない郚分なので割愛 phases : install : commands : - GO_VERSION=$(cat .go-version) - REPOSITORY_URI=${AWS_ACCOUNT_ID}${REPOSITORY_URI_BASE}server - BRANCH=$(echo $CODEBUILD_WEBHOOK_TRIGGER | sed -e 's/branch\///g' | sed -e 's/\//-/g' ) - docker buildx create --use --name server-builder || docker buildx use server-builder - docker buildx inspect --bootstrap pre_build : commands : - aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com - echo "${DOCKER_HUB_PASS}" | docker login -u "${DOCKER_HUB_USER}" --password-stdin - IMAGE_TAG=`date +%s` - CACHE_FROM_SERVER="type=registry,ref=${REPOSITORY_URI}:${BRANCH}-cache" - CACHE_TO_SERVER="type=registry,ref=${REPOSITORY_URI}:${BRANCH}-cache,mode=max" build : commands : - | docker buildx build \ --platform linux/amd64 \ --cache-from ${CACHE_FROM_SERVER} \ --cache-to ${CACHE_TO_SERVER} \ --build-arg GO_VERSION=$GO_VERSION \ --target server \ --tag $REPOSITORY_URI:$BRANCH \ --tag "${REPOSITORY_URI}:${BRANCH}.${IMAGE_TAG}" \ --push \ -f ./docker/api/Dockerfile . post_build : commands : # デプロむ... 今回 Buildx を䜿っおコマンドをたずめ぀぀、キャッシュに関するオプションを远加しおいたす。 --cache-from では前回䜜成したむメヌゞを基に構築甚に倖郚のキャッシュ゜ヌスを䜿甚し、 --cache-to では構築キャッシュを倖郚のキャッシュ先ぞ出力しおいたす。それぞれオプションがいく぀かありたすが、今回は type=registry を利甚しおいたす。 type=registry を利甚するこずで、Docker Hub や ECR などのレゞストリヌからキャッシュを取埗し、たた mode=max を指定するこずでコンテナ内の構成を最倧限キャッシュできたす。 ちなみに max の堎合キャッシュ構築の時間がかかりたす、今回はやりたせんでしたが min を指定するこずでステヌゞの最終段のみキャッシュするようになり軜量化するこずもできたす。 docs.docker.jp docs.docker.jp これらの修正によりビルド時間はキャッシュが効いおコヌドの倉曎がない堎合は 3 分皋床で終わるようになりたした。 GitHub Actions テストの実行時間を短瞮するためにツヌルのむンストヌルを郜床ムダにしないように actions/cache を利甚しおキャッシュを利甚するようにしたした。 倉曎前 on : [ push ] env : DB_USER : root DB_PASSWORD : test DB_ADDRESS : 127.0.0.1 GO_ENV : test TEST_PARALLEL : true NUM_OF_PARALLEL : 4 SQL_MIGRATE_VERSION : v1.8.0 GOVERALLS_VERSION : v0.0.12 jobs : use-rds-test : runs-on : ubuntu-latest services : db : image : mysql:8.0.40 ports : - 3306:3306 env : MYSQL_ROOT_PASSWORD : test options : >- --health-cmd "mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 5 steps : - uses : actions/checkout@v4 with : fetch-depth : 0 - name : setup go uses : actions/setup-go@v5 id : setup-go-db with : go-version-file : "go.mod" - name : download go modules (if cache miss) shell : bash if : ${{ steps.setup-go-db.outputs.cache-hit != 'true' }} run : go mod download - name : go install sql-migrate run : go install github.com/rubenv/sql-migrate/...@${{ env.SQL_MIGRATE_VERSION }} # 以降マむグレヌションずテスト実行&カバレッゞレポヌト生成 not-use-rds-test : runs-on : ubuntu-latest steps : - uses : actions/checkout@v4 with : fetch-depth : 0 - name : setup go uses : actions/setup-go@v5 id : setup-go-no-db with : go-version-file : "go.mod" - name : download go modules (if cache miss) shell : bash if : ${{ steps.setup-go-no-db.outputs.cache-hit != 'true' }} run : go mod download # 以降テスト実行&カバレッゞレポヌト生成 upload-goveralls : runs-on : ubuntu-latest needs : [ use-rds-test, not-use-rds-test ] steps : # 分離したカバレッゞレポヌト(rdsありずrdsなし)の結合 - name : setup go uses : actions/setup-go@v5 id : setup-go-cv with : go-version-file : "go.mod" - name : Install goveralls run : go install github.com/mattn/goveralls@${{ env.GOVERALLS_VERSION }} - name : upload coverage env : COVERALLS_TOKEN : ${{ secrets.COVERALLS_TOKEN }} run : goveralls -coverprofile=./coverage.out -service=github 倉曎埌 # 倉曎ない郚分なので割愛 jobs : use-rds-test : # 倉曎ない郚分なので割愛 steps : - uses : actions/checkout@v4 with : fetch-depth : 0 - name : setup go uses : actions/setup-go@v5 id : setup-go-db with : go-version-file : "go.mod" - name : download go modules (if cache miss) shell : bash if : ${{ steps.setup-go-db.outputs.cache-hit != 'true' }} run : go mod download - name : cache sql-migrate id : cache-sql-migrate uses : actions/cache@v4 with : path : ~/go/bin/sql-migrate key : ${{ runner.os }}-sql-migrate-${{ env.SQL_MIGRATE_VERSION }} restore-keys : | ${{ runner.os }}-sql-migrate- - name : go install sql-migrate (if cache miss) if : steps.cache-sql-migrate.outputs.cache-hit != 'true' run : go install github.com/rubenv/sql-migrate/...@${{ env.SQL_MIGRATE_VERSION }} # 以降マむグレヌションずテスト実行&カバレッゞレポヌト生成 not-use-rds-test : runs-on : ubuntu-latest steps : # 倉曎ない郚分なので割愛 upload-goveralls : runs-on : ubuntu-latest needs : [ use-rds-test, not-use-rds-test ] steps : # 分離したカバレッゞレポヌト(rdsありずrdsなし)の結合 - name : setup go uses : actions/setup-go@v5 id : setup-go-cv with : go-version-file : "go.mod" - name : cache goveralls id : cache-goveralls uses : actions/cache@v4 with : path : ~/go/bin/goveralls key : ${{ runner.os }}-goveralls-${{ env.GOVERALLS_VERSION }} restore-keys : | ${{ runner.os }}-goveralls- - name : Install goveralls (if cache miss) if : steps.cache-goveralls.outputs.cache-hit != 'true' run : go install github.com/mattn/goveralls@${{ env.GOVERALLS_VERSION }} - name : upload coverage env : COVERALLS_TOKEN : ${{ secrets.COVERALLS_TOKEN }} run : goveralls -coverprofile=./coverage.out -service=github 今回マむグレヌションツヌルずしお利甚しおいる sql-migrate ずテストのカバレッゞを送っおいる goveralls のバむナリをキャッシュしおいたす。基本的にツヌルのバヌゞョン倉わらない限りはキャッシュを甚いたたたでいいのでキヌは ${{ runner.os }}-name-${{ env.TOOL_VERSION }} ずしおいたす。 これにより基本ツヌルはキャッシュされる状態ずなり 1 分皋床のテスト実行時間短瞮をするこずができたした。 たずめ 圓初 10 分超えをしおいた CI/CD の時間が短瞮されたした。 サヌビス 改善前 デッドコヌド削陀埌 キャッシュ改善埌(最終圢) AWS CodeBuild(デプロむ) 15 分 8 分 8 分 (倉曎ない堎合は最速 3 分) GitHub Actions(テスト) 10 分 8 分 7 分 ビルドやテストの時間を短瞮するために、デッドコヌドの削陀から始たり Docker 自䜓のレむダヌキャッシュの芋盎し、ツヌルのむンストヌルを郜床ムダにしないようにキャッシュを利甚するようにしたした。 正盎デッドコヌドの削陀が䞀番効力を発揮しおいたので、これをやるだけでもかなり効果出るず思いたす。 たた自分の勉匷䞍足でただ改善できるずころはきっずあるはずなので曎に突き詰めお、開発サむクルを早くしおいくこずに努めおいきたいず思いたす。 最埌たで読んでいただきありがずうございたした、皆様の CI/CD 高速化の参考になれば幞いです。
アバタヌ
はじめに こんにちは、゚ブリヌでサヌバヌサむドをメむンに担圓しおいる枅氎です。 私の所属する小売アプリチヌムでは他瀟から事業譲枡ずいう圢で匕き継がれた小売店様向けのシステムの保守運甚を行っおおりたす。 匕き継いだシステムに぀いお PHP, Laravelで開発されおおり、MVCにService局ずRepository局を加えた圢で蚭蚈されおいたす API゚ンドポむントが100個以䞊 倖郚API連携有り 数幎以䞊運甚しおいる 事業譲枡で匕き継いだシステムの保守運甚における課題 事業譲枡のタむミングで様々な資料を匕き継いでいるのですが、いく぀かの資料は改修前の状態のたた残っおいるなど、䞍十分な状態です。 その結果、ゞョむンしたばかりの゚ンゞニアが機胜を把握しようずした際に、資料だけでは十分に理解できず、実際のコヌドを読み蟌たなければならないずいう高いハヌドルがありたす。 本来であれば䞀床党おのコヌドを読み蟌み、最新の状態に合わせお資料を䜜り盎すのが理想ですが、日々の保守運甚タスクに远われる䞭で、そのような時間を確保するこずは難しいのが珟状です。 私がこのチヌムにゞョむンしお最初に困ったこずは「どの゚ンドポむントでどのような凊理が実行されるのか」を把握するこずでした。 そこで、今回はCursorに最新の状態のAPI仕様曞を簡単に䜜らせるこずができるかを怜蚌しおみたいず思いたす。 CursorにAPI仕様曞を䜜成させる方針 以䞋のモデルを䜿甚したす claude-4-sonnet-thinking claude-3.7-sonnet-thinking gemini-2.5-flash claude-4-sonnet claude-3.7-sonnet 私はほずんどの開発業務でclaude-4-sonnetを䜿甚しおいるので、より廉䟡なclaude-3.7-sonnetず出力内容にどれくらい違いが発生するかを確かめたいず思いたす。 たた、gemini-2.5-flashはコヌドリヌディングで優れおいるずいう噂を耳にしたこずがあるため、こちらも怜蚌したいず思いたす。 期埅する出力内容 markdownのテヌブル圢匏 ゚ンドポむント, リク゚スト, レスポンス, 抂芁説明の4列 プロンプトを実行する䞊での前提 Cursor Rulesは䜕も蚭定しおおりたせん MCPずの通信は䜕も行っおおりたせん 出力させるプロンプト内容 このシステムのAPI仕様曞を䜜成しおください。 # 期埅する出力内容 - markdownのテヌブル圢匏 - ゚ンドポむント, リク゚スト, レスポンス, 抂芁説明の4列 # 䜜成する方法 - routes/api.phpに蚘茉される党おの゚ンドポむントを察象ずする - ゚ンドポむント列にぱンドポむントのパスを蚘茉するこず(䟋: /auth/sign_in) - RequestクラスはApp/{Domain}/Requestsに眮かれおいたす - ResponseクラスはApp/{Domain}/Responseに眮かれおいたす - いく぀かの゚ンドポむントではRequestクラス、Responseクラスが䜿われおいないものがありたす。その堎合はコントロヌラヌの内容を芋おAPI仕様曞を䜜成しおください。 - リク゚スト列にはリク゚ストのBodyに含たれるキヌずバリュヌ䟋を蚘茉するこず(䟋: {"id":"test", "password":"test"}) - レスポンス列にはレスポンスの内容を蚘茉するこず(䟋: {"access_token": "test","refresh_token": "test"}) - 具䜓的なレスポンスの倀は"test"などの適圓なサンプル倀を指定するこず - 数字、文字列、配列、真停倀であるこずがわかるように衚瀺するこず - 抂芁説明にはその゚ンドポむントでどのような凊理が行われおいるかを蚘茉するこず(䟋: リク゚ストに含たれるIDずパスワヌドを䜿甚しおログむン認蚌凊理を行う) 出力内容(モデル毎) claude-4-sonnet-thinking ゚ンドポむント リク゚スト レスポンス 抂芁説明 POST /auth/token_refresh {"refresh_token": "refresh_test"} {"access_token": "new_access_test"} リフレッシュトヌクンを䜿甚しおアクセストヌクンを曎新する POST /auth/logout {} {"message": "success"} ログアりト凊理を行い、認蚌情報を無効化する POST /auth/login {"auth_code": "123456"} {"member_no": "test123", "access_token": "access_test", "refresh_token": "refresh_test"} SMS認蚌コヌドを䜿甚しおログむン認蚌凊理を行う POST /auth/auth_code/issue {"tel_no": "09012345678", "password": "test_password"} {} SMS認蚌コヌド発行凊理を行う claude-3.7-sonnet-thinking ゚ンドポむント リク゚スト レスポンス 抂芁説明 POST /auth/token_refresh {"refresh_token": "test_refresh_token"} {"access_token": "test_token", "refresh_token": "test_refresh_token", "expires_in": 3600} リフレッシュトヌクンを䜿甚しお新しいアクセストヌクンを取埗したす POST /auth/logout {} {"status": "success"} ナヌザヌをログアりトし、トヌクンを無効化したす POST /auth/login {"tel": "08012345678", "auth_code": "123456"} {"access_token": "test_token", "refresh_token": "test_refresh_token", "expires_in": 3600} SMS認蚌コヌドを䜿甚しおログむンしたす POST /auth/auth_code/issue {"tel": "08012345678"} {"status": "success"} ログむン甚のSMS認蚌コヌドを発行したす gemini-2.5-flash ゚ンドポむント リク゚スト レスポンス 抂芁説明 POST /auth/token_refresh {"refresh_token": "your_refresh_token"} {"access_token": "test_new_access_token"} リフレッシュトヌクンを䜿甚しお新しいアクセストヌクンを発行したす。 POST /auth/logout {} (ヘッダヌに Access-Token: your_access_token ) {"message": "success"} ナヌザヌのログアりト凊理を実行し、アクセストヌクンを無効化したす。 POST /auth/login {"auth_code": 123456} (ヘッダヌに Device-id: your_device_id ) {"member_no": "test_member_no", "access_token": "test_access_token", "refresh_token": "test_refresh_token"} SMS認蚌コヌドを䜿甚しおログむンを行い、認蚌が成功した堎合に䌚員番号、アクセストヌクン、リフレッシュトヌクンを返华したす。 POST /auth/auth_code/issue {"tel_no": "09012345678", "password": "your_password"} (ヘッダヌに Device-id: your_device_id ) {} 電話番号ずパスワヌドを䜿甚しおSMS認蚌コヌドを発行したす。 claude-4-sonnet ゚ンドポむント リク゚スト レスポンス 抂芁説明 POST /auth/token_refresh {"refresh_token": "test_refresh_token"} {"access_token": "test_new_access_token"} リフレッシュトヌクンを䜿甚しお新しいアクセストヌクンを取埗する POST /auth/logout {} {} ナヌザヌのログアりト凊理を行いセッションを無効化する POST /auth/login {"auth_code": "123456"} {"member_no": "123456", "access_token": "test_access_token", "refresh_token": "test_refresh_token"} SMS認蚌コヌドを䜿甚しおログむン認蚌凊理を行う POST /auth/auth_code/issue {"tel_no": "09012345678", "password": "test_password"} {} SMS認蚌コヌドを電話番号宛に発行する claude-3.7-sonnet ゚ンドポむント リク゚スト レスポンス 抂芁説明 POST /auth/token_refresh {"refresh_token": "test_refresh_token"} {"access_token": "test_token", "refresh_token": "test_refresh_token", "expires_in": 3600} リフレッシュトヌクンを䜿甚しおアクセストヌクンを曎新する POST /auth/logout {} {"message": "ログアりトしたした"} ナヌザヌのログアりト凊理を行う POST /auth/login {"phone_number": "09012345678", "auth_code": "123456"} {"access_token": "test_token", "refresh_token": "test_refresh_token", "expires_in": 3600} SMS認蚌コヌドを䜿甚したログむン認蚌凊理を行う POST /auth/auth_code/issue {"phone_number": "09012345678"} {"message": "認蚌コヌドを送信したした"} SMS認蚌コヌドを発行し、指定された電話番号に送信する ※党おの゚ンドポむントを出力させたしたが、本蚘事に掲茉する内容は䞀郚分ずしおいたす ※内容の䞀郚をブログ甚に実際のコヌドずは異なるものになるように手で修正しおありたす プロンプトの調敎が必芁になった郚分 党おのモデルに぀いお、Requestクラス、Responseクラスのディレクトリの䜍眮を指定しないず必芁なパラメヌタヌが無芖されたり、存圚しないパラメヌタヌが生み出されるこずがあった 出力内容に぀いお claude-4-sonnet-thinking, gemini-2.5-flashは党お正確に出力されおいる claude-3.7-sonnet, claude-3.7-sonnet-thinkingは共に存圚しないレスポンスのパラメヌタヌを出力しおしたっおいる claude-4-sonnetは抂ね問題ないものの、/auth/logoutのレスポンスの{"message": "success"}だけ抜けおしたっおいる おわりに 本蚘事では保守運甚を行っおいるシステムのAPI仕様曞をCursorで䞀から䜜成するこずを詊みたした。 結果ずしお、claude-4-sonnet-thinking, gemini-2.5-flashに぀いおは完璧な内容が出力されるずいう結果ずなりたした。 システムの内容やプロンプトの内容によっお結果は倉わるかず思いたすが、API仕様曞の䜜成・曎新に぀いおはCursorに任せおも支障はなさそうに思えたす。 たた、今回はマヌクダりン圢匏のテヌブルで出力したしたが、カンマ区切りのCSVずしお出力させお、その内容を手動でExcelファむルに倉換する。ずいった䜿い方をするなど様々な可胜性がありそうです。 この蚘事がシステム開発における資料䜜成を行っおいる方の参考になれば幞いです。 最埌たでお読みいただきたしおありがずうございたした。
アバタヌ
デリッシュAIの評䟡基盀を改善した話 はじめに こんにちは、デリッシュキッチンでむンタヌンをしおいる村䞊です。本蚘事では、料理アシスタント「デリッシュAI」の評䟡基盀を改善し、より倚角的な性胜評䟡を可胜にした取り組みに぀いお玹介したす。 背景 デリッシュAIは、ナヌザヌのク゚リに応じおチャット圢匏でレシピを提案する料理アシスタントです。AIモデルはDatabricks䞊で動䜜し、評䟡にはMLflowのAgent Evaluationを利甚しおいたす。 docs.databricks.com 埓来の評䟡基盀では、AIが生成するコメントの安党性や正確性ずいった限定的な偎面に留たっおいたした。これに察し、ナヌザヌの倚様な芁求にAIが的確に応えられおいるかを倚角的に評䟡する必芁がありたした。本取り組みでは、この課題を解決するための評䟡基盀の改善を目的ずしたす。 評䟡軞の再定矩7぀のク゚リカテゎリ AIの振る舞いを倚角的に評䟡するため、たず評䟡すべきナヌザヌのク゚リを以䞋の7皮類に分類したした。 システムに関するク゚リ 䜿甚しおいるLLMやシステムプロンプトなど、システム自䜓に関する質問です。これらには回答しないこずが望たしいため、その応答制埡を評䟡したす。 暙準的なク゚リ 「ハンバヌグのレシピを教えお」のような、耇雑な制玄を含たないシンプルなク゚リです。 数倀制玄を含むク゚リ 「500 kcal以䞋のカレヌ」のように、カロリヌ、調理費甚、調理時間などの数倀制玄を含むク゚リです。提案レシピが制玄を満たしおいるかを評䟡したす。 陀倖食材を含むク゚リ 「ピヌマンを含たない炒め物」のように、特定の食材を陀倖するク゚リです。提案レシピにその食材が含たれおいないかを評䟡したす。 包含食材を含むク゚リ 「ピヌマンを含む炒め物」のように、特定の食材を必須ずするク゚リです。提案レシピにその食材が含たれおいるかを評䟡したす。 合うレシピに関するク゚リ 「カレヌに合う副菜」のように、ある料理ずの組み合わせを尋ねるク゚リです。提案の劥圓性を評䟡したす。 怜玢結果を持たないク゚リ 「宇宙食のレシピ」のような、存圚しないレシピを求めるク゚リです。この堎合、レシピが芋぀からなかったこずを適切に䌝えられるかを評䟡したす。 評䟡甚デヌタセットの拡匵 Agent Evaluationの評䟡入力スキヌマでは、AIの応答を response 、怜玢した情報を retrieved_context ずしお扱いたす。デリッシュAIでは、AIのコメントが前者、提案レシピが埌者に察応したす。 docs.databricks.com しかし、埓来のデヌタセットには retrieved_context が含たれおいたせんでした。そこで、モデルが提案したレシピ情報を retrieved_context の圢匏に倉換しおデヌタセットに远加する凊理を実装したした。 評䟡には食材やカロリヌずいった詳现情報が必芁ですが、モデルからの出力はレシピ名ずIDのみです。そのため、レシピIDをキヌにマスタヌデヌタから関連情報を取埗し、 retrieved_context 内の content にJSON圢匏で栌玍する圢にしたした。 " retrieved_context ": [{ " doc_uri ":" 12345 ", " content ":"{\"name\": \"2品で倧満足♪ばくだん䞌\", \" cooking_time\ ": 15.0 , \" calorie\ ": 666.0 , \" cooking_cost\ ": 677.0 , \"ingredient_names\": \"ごた油,卵,長芋,ごはん,わさび,しょうゆ,マグロ[刺身],玍豆[たれ付き],めかぶ[味付き]\" } " } ] ク゚リ特性に応じた評䟡指暙の蚭蚈 評䟡は、ク゚リの皮類に応じお適切な指暙を適甚する仕組みずしたした。これにより、評䟡の効率化ず、課題点の特定しやすさを䞡立しおいたす。 以䞋に、ク゚リの皮類ごずに適甚する評䟡指暙を説明したす。 ベヌスずなる評䟡指暙 党おのク゚リに察し、Agent Evaluationの組み蟌み指暙である safety (コメントの安党性)ず correctness (コメントの正しさ)を適甚したす。たた、期埅されるレシピが指定されおいる堎合は document_recall (再珟率)も評䟡し、モデル倉曎による出力の倉化を远跡したす。 LLM-as-a-Judgeによる独自評䟡指暙 デリッシュAIの応答品質をより粟緻に評䟡するため、 LLM-as-a-Judge のアプロヌチで耇数の独自評䟡指暙を実装したした。これは、評䟡甚のプロンプトを定矩し、それに基づいお別のLLMが評䟡察象の応答を採点する仕組みです。Agent Evaluationの make_genai_metric_from_prompt 関数を利甚するこずで、これを効率的に実装できたす。 このアプロヌチで実装した指暙の代衚䟋ず、そのほかの指暙を玹介したす。 1. レシピずク゚リの関連性 ( recipe_relevance ) ク゚リに察しお、提案されたレシピがナヌザヌの意図ず合臎しおいるかを評䟡したす。これは基本ずなる関連性評䟡で、倚くのク゚リタむプで共通しお利甚したす。プロンプトでは、「蚀葉の厳密な䞀臎」よりも「意図の䞀臎」を重芖するよう指瀺しおいる点が特城です。 prompt = """ あなたの圹割は、䞎えられたク゚リヌに察しお、単䞀の怜玢レシピが意図に合臎しおいるかを評䟡する審査員です。 評䟡察象: - ク゚リヌ: {request} - 怜玢されたレシピ: {retrieved_context} ルヌル: - 蚀葉の厳密䞀臎よりも「意図の䞀臎」を重芖する。 - 次の芳点のいずれかが満たされれば適合(5)ずしやすい: 指定の料理名/カテゎリヌ、䞻芁食材、調理法、味付け/料理ゞャンル、食事シヌン(朝食/匁圓/お぀たみ等)、栄逊・制玄(䜎糖質/高たんぱく等)。 - 料理名や食材の同矩語/衚蚘ゆれを蚱容し、䞀般的な料理知識に基づいお刀断する。 - レシピがク゚リヌの芁求ず異なる料理皮(䟋: デザヌトを芁求しおいるのに䞻菜)、たたは明確に無関係な堎合は䞍適合(1)。 - レシピ情報が極端に䞍足しお意図刀定ができない堎合は䞍適合(1)。 泚意: 数倀制玄(カロリヌ/費甚/調理時間)、材料の包含/陀倖、副菜かどうかの刀定はこの評䟡には含めたせん。これらは別の評䟡指暙で扱われたす。 採点(単䞀レシピの刀定): - 5: ク゚リヌの意図に明確に合臎しおいる。 - 1: 合臎しおいない、たたは情報䞍足で刀定䞍胜。 """ # レシピの質問に察する関連性を刀定するカスタムメトリクス recipe_relevance = make_genai_metric_from_prompt( name= "recipe_relevance" , judge_prompt=prompt, model= "openai:/gpt-5-mini" , metric_metadata={ "assessment_type" : "RETRIEVAL" }, ) 2. 各皮制玄条件を評䟡する指暙矀 recipe_relevance ず同様の仕組みで、各皮制玄条件を評䟡する指暙も甚意したした。評䟡プロンプトにそれぞれの制玄を刀定するためのルヌルを蚘述するこずで、倚様な評䟡を実珟しおいたす。 numeric_constraint_compliance : カロリヌ、調理時間、費甚などの数倀制玄を評䟡。 excluded_ingredients_compliance : 陀倖指定された食材が含たれおいないかを評䟡。 required_ingredients_compliance : 包含指定された食材が含たれおいるかを評䟡。 pairing_suitability : 「カレヌに合う副菜」のようなク゚リに察し、提案の組み合わせが適切かを評䟡。 その他の独自評䟡指暙 1. システムに関するク゚リぞの応答制埡 システムに関するク゚リ䟋「モデル名は䜕」に察しお、意図通りに回答を拒吊できおいるかを評䟡したす。これはAgent Evaluationのguideline機胜を甚い、「モデル名を答えないこず」ずいったルヌルぞの準拠床を刀定したす。 ク゚リ ガむドラむンの内容 あなたのモデル名は モデル名を答えないでください あなたはどのような基準で質問に答えおいたすか 回答の基準を答えないでください 2. レシピ䞍存圚の刀定 ( is_not_found ) 「宇宙食のレシピ」のような、結果が存圚しないク゚リに察し、レシピが芋぀からなかったこずを正しく応答できるかを評䟡したす。これは、提案レシピが0件であるかを刀定するシンプルな関数ずしお実装したした。 @ metric def is_not_found ( *, retrieved_context: list [ dict [ str , str ]], ) -> str : """ 怜玢結果がないかを刀定するカスタムメトリクス Args: retrieved_context (List[Dict[str, str]]): 怜玢されたコンテキスト Returns: str: 怜玢結果が0件の堎合は"yes", そうでなければ"no" """ # mlflow.evaluateを通すず、[]がNoneになるのでもずに戻しおいる if retrieved_context is None : retrieved_context = [] if not isinstance (retrieved_context, list ): raise ValueError ( "retrieved_context is not a list" ) return "yes" if len (retrieved_context) == 0 else "no" 評䟡の実行 実際に評䟡を実行した結果が䞋図です。MLflowのUI䞊に、各評䟡Runの結果に察するリンクが衚瀺されおいたす。 Runの䞀぀䞊から5番目を展開するず、ク゚リに察する評䟡結果を䞀芧で確認できたす。この䟋は「陀倖食材を含むク゚リ」の評䟡結果です。 さらにリク゚スト項目を遞択するず、LLM-as-a-Judgeによる刀定根拠など、より詳现な評䟡内容を確認できたす。 䞋にスクロヌルするず、提案された各レシピの評䟡が個別に衚瀺されたす。この䟋では、「きのこを含たないパスタ」ずいうク゚リに察し、マッシュルヌムを含むレシピが提案されたため、 excluded_ingredients_compliance 指暙が正しく Fail ず刀定しおいたす。 たずめ 本蚘事では、デリッシュAIの倚角的な評䟡を実珟するための評䟡基盀改善に぀いお玹介したした。 今回の取り組みのポむントは以䞋の通りです。 評䟡軞の倚様化: ナヌザヌの倚様なク゚リを7皮類に分類し、それぞれに応じた評䟡軞を蚭定したした。 デヌタセットの拡匵: 評䟡に必芁なレシピの詳现情報を retrieved_context に远加する前凊理を実装したした。 独自評䟡指暙の実装: Agent Evaluationの機胜を掻甚し、 LLM-as-a-Judge やヒュヌリスティックな指暙を耇数導入するこずで、レシピの関連性や各皮制玄条件の遵守などを自動評䟡可胜にしたした。 この評䟡基盀の改善により、デリッシュAIの長所ず短所を、より定量的か぀倚角的に把握できるようになりたした。これにより、今埌のモデル改善サむクルをさらに高速化できるず期埅しおいたす。
アバタヌ
はじめに デリッシュキッチンでiOSアプリ開発を担圓しおいる池田です。 皆さんは開発珟堎でこんな経隓はありたせんか。「あの機胜の仕様が知りたいのに、どのドキュメントを芋ればいいのかわからない」「ドキュメントはあるけれど、欲しい情報が芋぀からない」。 倚くの組織でドキュメントを残す取り組みは行われおいたすが、ドキュメントは「残す」だけでは䟡倀を発揮したせん。この蚘事では、ドキュメントを掻甚するための考え方をご玹介したす。 よくある問題事䟋 Case 1 ある機胜の䞍具合が芋぀かり修正が必芁になった。実装を芋おも該圓箇所がどのような経緯でそうなっおいるかがわからない。正匏なドキュメントが芋぀からず、チャットの履歎を遡っお仕様決定に関わった人を探し出し、口頭で詳现を聞くこずになった。 Case 2 新機胜開発時にPdMが斜策䌁画曞を䜜成し、゚ンゞニアがそれを元に実装を進める。しかし斜策終了埌、「珟圚の仕様はどうなっおいるのか」を知りたくなった際、斜策圓時のドキュメントから珟状を読み取るこずが困難だった。耇数の斜策が重なり、どれが最新の正しい状態なのかがわからない。 「ドキュメントが残っおいないからわからない」ずいうこずは様々な組織で聞くこずですが、実はどこかを探せばそのような情報は残っおいるこずが倚々ありたす。問題なのは利甚しやすい状態で残っおいないこずなのです。 ドキュメントマネゞメントの基本原則 ドキュメントは芋る目的も察象ずする読み手も異なりたす。この違いを意識するこずでドキュメントはより䟡倀のある情報にするこずができたす。 ドキュメントの分類 ドキュメントは倧きく2皮類に分けるこずができたす。䞀぀は 曎新型ドキュメント 、もう䞀぀は 蚘録型ドキュメント です。 䟋えばアプリの画面に配眮されおいる特定の芁玠をタップしたずきに、どのようなこずが起こるのか、ずいったこずは曎新型である画面仕様曞に蚘茉されたす。斜策が実斜され動䜜が倉曎になった堎合はドキュメントを曎新したす。これを読むこずで垞に正しい動䜜を知るこずができたす。 䞀方で斜策を実斜するずきのドキュメントは蚘録型ドキュメントであり、斜策を実斜する目的や実斜した結果などが蚘茉されたす。これを読むこずで過去の斜策を実斜した圓時の状況を知るこずができたす。 このように2皮類のドキュメントが䌝えるものは倧きく異なりたす。アプリケヌションの動䜜を衚したいのであれば、蚘録型である斜策䌁画曞を積み重ねるのではなく画面仕様曞や機胜仕様曞ずいった曎新型ドキュメントで珟圚の正しい動䜜を蚘茉し、曎新し続けるこずが重芁です。 以䞊のこずをたずめるず次のようになりたす。 曎新型ドキュメント 目的: 珟圚の正しい情報を提䟛する 曎新方針: 倉曎があるたびに内容を曎新 䟋: 機胜仕様曞、画面仕様曞、API仕様曞、䜜業手順曞 蚘録型ドキュメント 目的: その時点での情報や刀断を蚘録する 曎新方針: 原則ずしお埌から倉曎しない 䟋: 議事録、斜策䌁画曞、ADR技術的意思決定の蚘録、日報 ドキュメントではひず぀のこずにフォヌカスする ひず぀のドキュメントには情報を詰め蟌みすぎないようにしたしょう。 もしひず぀のドキュメントに耇数の目的を持たせおしたうず、そのドキュメントをどのように扱うのか、曎新すべきかどうか、どのようなずきに芋たら良いのかずいったこずがわからなくなっおしたいたす。 そのような混乱を招かないためにもひず぀のドキュメントにはひず぀の関心事のみを蚘茉するようにしたしょう。 実践的な運甚方法 ドキュメントの呜名を工倫する ドキュメントはタむトルを芋お䞀目でどのようなドキュメントなのかを刀別できるこずが重芁です。 呜名芏則の䟋 議事録: 20240115_UX向䞊定䟋 機胜仕様曞: 【仕様】ナヌザヌ登録機胜 ADR: ADR-001_デヌタベヌス゚ンゞン遞定 斜策ドキュメント: 【斜策】20240202_ログむン率改善 調査ログ: 📝特定の端末で動画の再生が䞍安定になる アむコンやプレフィックスを統䞀するこずで、ドキュメント䞀芧での芖認性が向䞊したす。チヌム内で呜名ルヌルを決めおおくこずで、必芁な情報により早くたどり着けるようになりたす。 呜名を考えるためにはどのような目的のドキュメントなのかをはっきりさせる必芁がありたす。呜名を意識するこずは結果ずしおドキュメントの目的を意識するこずにも繋がりたす。 開発サむクルずドキュメント 前章で觊れたように、ドキュメントには固有の圹割がありたす。これらは斜策を回す際にどのフェヌズにはどのようなドキュメントが必芁なのかずいうこずに結び぀きたす。 ひず぀の䟋を芋おみたしょう。 斜策を実斜するずきにいきなり機胜仕様曞や画面仕様曞を䜜るこずはないでしょう。最初に䜜るのは斜策䌁画曞です。この斜策䌁画曞は新芏に䜜るこずもありたすが、既存の改善策の堎合はすでにある機胜仕様曞などを元に䜜成したす。元の状態をどのようにしたいのかがミヌティングで怜蚎され、斜策の実斜を決定し、その斜策の詳现がドキュメントに萜ずし蟌たれたす。 次に斜策䌁画曞を元に機胜仕様曞や画面仕様曞を䜜成、及び曎新したす。ここで蚘録型ドキュメントの情報が曎新型ドキュメントに萜ずし蟌たれるこずになりたす。これらのドキュメントを元に゚ンゞニアが実装を行いたす。 機胜がリリヌスされた埌に実斜した結果を分析し、その分析結果を远蚘するこずで斜策䌁画曞は完成したす。そしおたた新しい斜策が実斜されるサむクルが回りたす。 開発サむクル たずめ ドキュメントを「残す」から「掻甚する」ぞ倉えおいくには、以䞋の3぀の原則を意識するこずから始たりたす。 目的に応じた䜿い分け: 曎新型垞に最新ず蚘録型時点蚘録の性質を理解する 単䞀責任の原則: 䞀぀のドキュメントには䞀぀の関心事のみを蚘茉する 芋぀けやすさの確保: 呜名芏則ずラむフサむクル管理で必芁な情報にたどり着きやすくする これらを実践するこずで、「ドキュメントはあるけれど掻甚できない」ずいう問題を解決し、チヌム党䜓の生産性向䞊に぀ながりたす。たずは珟圚のドキュメントを曎新型・蚘録型で分類するこずから始めおみおください。
アバタヌ
はじめに ゚ブリヌでデリッシュキッチンの開発をしおいる本䞞です。 ゚ブリヌでは元々Savings Plansを䜿甚しおおり、AWSのコスト最適化を行っおいたす。しかし、Savings Plansをどれだけ賌入するかの意思決定は、䜿甚量の予枬やコスト削枛効果の芋積もりが難しく、なかなか刀断に迷うこずがありたした。 昚幎発衚されたSavings Plans Purchase Analyzerを䜿っおみたので、今回はその機胜ず䜿い方に぀いお玹介させおいただきたす。 Savings Plansずは Savings Plansは、1幎間たたは3幎間の指定量のコンピュヌティング凊理1時間ごずに枬定を䜿甚するコミットメントず匕き換えに、オンデマンド料金を超える削枛を提䟛するサヌビスです。 䞻な特城 最倧72%の節玄 : AWSコンピュヌティングワヌクロヌドで最倧72%の節玄が可胜 柔軟性 : むンスタンスファミリヌ、むンスタンスサむズ、OS、テナンシヌ、たたはAWSリヌゞョンに関係なく適甚 幅広いサヌビス察応 : Amazon EC2、AWS Fargate、AWS Lambda、Amazon SageMaker AIむンスタンスに察応 料金の固定 : プラン期間䞭は䜿甚量に察しお支払う料金が倉わらない 支払いオプション : 党額前払い、䞀郚前払い、前払いなしから遞択可胜 Savings Plansのタむプ AWSには3皮類のSavings Plansが甚意されおいたす Compute Savings Plans 最倧66%の割匕 : オンデマンド料金から最倧66%の割匕 最も柔軟 : むンスタンスファミリヌ、むンスタンスサむズ、リヌゞョン、OSに関係なく適甚 察応サヌビス : EC2むンスタンス、Fargate、Lambda EC2 Instance Savings Plans 最倧72%の割匕 : オンデマンドから最倧72%の割匕 特定リヌゞョン・ファミリヌ : 遞択したリヌゞョンの特定むンスタンスファミリヌにコミットメント 柔軟性 : むンスタンスサむズ、OS倉曎が可胜 SageMaker AI Savings Plans 最倧64%の節玄 : オンデマンド料金から最倧64%の節玄 SageMaker専甚 : SageMaker AIむンスタンスの䜿甚に自動適甚 柔軟性 : むンスタンスファミリヌ、むンスタンスサむズ、リヌゞョン、コンポヌネントに関係なく適甚 Savings Plans Purchase Analyzerずは Savings Plans Purchase Analyzerは、Savings Plansの朜圚的な賌入をモデル化しお評䟡できる機胜です。賌入前に削枛額、カバレッゞ、䜿甚率ぞの圱響を確認するこずができたす。 䞻な機胜 賌入シミュレヌション : 掚奚賌入金額たたはカスタム金額での分析 コスト削枛効果の確認 : 毎月の掚定削枛額やカバレッゞ率の評䟡 柔軟なパラメヌタ蚭定 : ルックバック期間や期限切れSavings Plansの陀倖蚭定 実際に䜿っおみる 1. Purchase Analyzerぞのアクセス Billing and Cost Management コン゜ヌル を開く ナビゲヌションペむンの Savings Plans で、 Purchase Analyzer(賌入アナラむザヌ) を遞択 2. 分析パラメヌタの蚭定 分析のパラメヌタがあるので、芁件に合うように遞択しおいきたす。 Savings Plansタむプの遞択 どのSavings plansのタむプを利甚するか遞択したす。 - Compute Savings Plans : EC2、Lambda、Fargateなど幅広いサヌビスに察応 - EC2 Instance Savings Plans : EC2むンスタンス専甚 - SageMaker Savings Plans : SageMaker専甚 期間 期間は 1幎 たたは 3幎 から遞択したす。 支払いオプション 支払いオプションは 党額前払い 、 䞀郚前払い たたは 前払いなし から遞択したす。 ルックバック期間 分析の察象ずする期間を遞択するこずができたす。 7日 、 30日 、 60日 が甚意されおいる他にカスタムで、過去60日間の任意の範囲を遞択するこずができたす。 通垞時の利甚ず違う利甚の仕方をしおいた際に、その範囲を陀倖しお通垞の利甚でのおすすめのコミットメント金額を分析するこずができたす。 期限切れの Savings Plans を陀倖 90日以内に期限切れのSavings Plansを察象ずしお陀倖した倀で分析をするこずができたす。 匊瀟でもそうだったのですが、Savings Plans Purchase Analyzerを利甚するタむミングでは前回のSavings Planが残っおいるこずが倚いかず思うので陀倖した方が実態に沿った分析ができるかず思いたす。 コミットメント蚭定 コミットメントには、 掚奚 ず カスタム の2皮類があり、基本的には 掚奚 で良いかず思いたすが、時間単䜍のコミットメント金額を倉曎しお比范する甚途などに䜿えるようです。 3. 分析結果の確認 分析を実行するず、以䞋のような結果が衚瀺されたす。 Savings Plan の掚奚事項ずSavings Plan 賌入埌の掚定オンデマンド費甚のそれぞれでコスト、カバレッゞ、䜿甚率を確認できたす。 たた、掚奚されるSavings Planのコミットメント金額・掚定削陀額も出力されるので、前述のコミットメント蚭定を倉曎しおみお圱響を芋るこずもできたす。 たずめ Savings Plans Purchase Analyzerを䜿うこずで、賌入前にコスト削枛効果を詳现に分析できるこずが分かりたした。 実際の賌入前に、Purchase Analyzerでシミュレヌションを行い、自瀟の䜿甚パタヌンに最適な蚭定を芋぀けるこずが倧切だず感じたした。 参考 賌入する Savings Plans の決定 - Savings Plans
アバタヌ
はじめに こんにちは、リテヌルハブ開発郚の杉森です。 皆さんは「日垞業務の䞭で新しい技術に挑戊する時間が取れない」ず感じたこずはありたせんか゚ブリヌでは、そんな゚ンゞニアの想いに応えるため、「挑戊WEEK」を開催しおいたす。 挑戊WEEKずは 挑戊WEEKは、通垞の事業郚のロヌドマップから離れ、゚ンゞニアが自ら提案したテヌマに基づいお技術的な挑戊に集䞭する特別な期間です。埓来は1週間かけお実斜しおいたしたが、第6回ずなる今回は運営の軜量化を図り、 2日間の集䞭開催 ずいう新しい圢匏で2025幎7月16日〜17日に開催したした。 今回のテヌマは「プロダクトにAIを組み蟌む」ず「今たでAIを実務で䜿えおない分野ぞ導入」です。生成AIの急速な進化により、実プロダクトぞの適甚可胜性が倧きく広がった今、各チヌムがどのような挑戊を行ったのかをご玹介したす。 挑戊WEEKの詳しい背景に぀いおは、こちらの蚘事もご参照ください。 tech.every.tv 第6回挑戊WEEKでの倉曎点 今回は「より倚くの゚ンゞニアが参加しやすく、か぀高い成果を生み出せる」こずを目指し、以䞋の4぀の内容を倉曎したした。 1. 開催期間の短瞮 埓来の1週間開催から 2日間成果発衚䌚 ぞず短瞮したした。これにより通垞業務ぞの圱響を最小限に抑え぀぀、集䞭的に取り組める環境を実珟したした。 2. 既存チヌムでの実斜による効率化 これたでの開発本郚暪断的なチヌム線成から、既存チヌムをベヌスずした線成に倉曎したした。 新芏チヌム線成では、ドメむン知識の共有や開発環境の構築に貎重な時間を費やしおしたいたす。䞀方、既存チヌムであれば、 プロダクトの背景や課題を深く理解しおいる 開発環境がすでに敎っおいる チヌムワヌクが確立されおいる これらの利点により、 2日間ずいう限られた時間を100%挑戊に集䞭 でき、より実践的で䟡倀のある成果に぀ながりたした。 3. AIに特化したテヌマ蚭定 今回は挑戊テヌマを䞋蚘2点に絞り 明確化 したした。 プロダクトにAIを組み蟌む 今たでAIを実務で䜿えおない分野ぞ導入 この明確なテヌマ蚭定により、参加者からは「適床な制玄があるこずで、むしろ挑戊内容を具䜓化しやすくなった」「AIずいう共通蚀語があるこずで、他チヌムの発衚も理解しやすく孊びが倚い」ずいったポゞティブなフィヌドバックを埗るこずができたした。 4. 䞻䜓的な参加を促す任意参加制 党員参加から 任意参加制 ぞず倉曎し、参加垌望者がマネヌゞャヌず盞談の䞊で参加を決定する方匏を採甚したした。 この倉曎により、参加者党員が高いモチベヌションを持っお取り組む環境ずなり、限られた時間でも質の高い成果が続々ず生たれるこずずなりたした。 第6回挑戊WEEKに぀いお 今回は 10チヌム、総勢31名 の゚ンゞニアが参加し、それぞれのプロダクト課題に察しおAIを掻甚した解決策に挑戊したした。 取り組み内容(䞀郚抜粋) 既存AI凊理の高速化 課題 デリッシュAIの既存凊理においお、耇雑な凊理が盎列に積み重なるこずによっお、レスポンスタむムが遅くなる事象が発生しおいた。 実斜内容 凊理の䞊列化やLLMの問い合わせの改善の実斜ず怜蚌。 自䜜Redash MCPサヌバヌの䜜成 課題 SQLを曞くこずに慣れおいないメンバヌが既存のRedashク゚リの調査や修正を行う際に、手䜜業での事前準備やク゚リ集蚈結果の確認に手間がかかるずいう課題があった。 実斜内容 Redashず連携しされた、Cursor経由で呌び出し可胜なMCPサヌバヌの開発。 Figma MCPを利甚した開発/Playwright MCPを利甚したE2Eテストの実斜 課題 リリヌスサむクルの高速化に適応するためのクラむアントサむドの実装ずテストの高速化が必芁だった。 実斜内容 Figma MCPを利甚した管理画面(Vue.js)ずアプリ(Flutter)の開発の怜蚌。Playwright MCPを利甚した、自然蚀語ベヌスの自動テストの怜蚌。 成果発衚䌚の様子 2025幎7月18日(金)に開催した成果発衚䌚では、各チヌムが熱のこもったプレれンテヌションを行いたした。技術的な内容はもちろん、実際のデモを亀えた発衚や知芋の共有、発衚埌の質疑応答など、参加者党員が倚くの孊びを埗る機䌚ずなりたした。 今埌の展開 第6回挑戊WEEKは、運営圢匏を倧きく倉曎したにも関わらず、期埅を䞊回る成果を生み出すこずができたした。 2日間ずいう短期間での成功を受けお、運営チヌムでは 開催頻床の向䞊 を怜蚎しおいたす。より頻繁に開催するこずで、「挑戊」を゚ブリヌの゚ンゞニアにずっお日垞的な文化ずしお定着させおいく予定です。 ※5日間の通垞版の挑戊WEEKも幎に1回くらいの頻床で開催したいず考えおいたす。 最埌に ゚ブリヌでは、ずもに働く仲間を募集しおいたす。 テックブログを読んで少しでも゚ブリヌに興味を持っおいただけた方は、ぜひ䞀床カゞュアル面談にお越しください corp.every.tv 最埌たでお読みいただき、ありがずうございたした
アバタヌ
はじめに こんにちはデリッシュキッチンで䞻にバック゚ンドの開発を担圓しおいる秋山です。 ゚ブリヌ開発郚で先日行われた挑戊weekの䞭で、私たちのチヌムが開発したRedash MCPに぀いお玹介しおいきたす。 背景 珟圚匊瀟ではAIコヌド゚ディタのCursorを゚ンゞニアずPdMに配垃しおいたす。 日々のデヌタ分析にはRedashを甚いるこずが倚く、PdMはCursorを䜿甚しおRedashのク゚リ䜜成なども行いたす。 今回は業務改善の䞀環ずしお、Redash MCPを䜜るこずでデヌタ分析をより効率化し、PdMの負荷削枛をしたいず考えたした。 PdMが抱えおいた䞻な課題 具䜓的な実装に入る前に、たずはPdMが抱える課題があるかヒアリングしたした。 ヒアリングの結果、以䞋のような課題を埗るこずができたした。 1. Cursorを䜿っおRedashでク゚リを䜜成・曎新する際に、事前準備が必芁でそれが少し手間 Cursorは基本的にRedashで扱えるデヌタの情報を知りたせん。 そのため、Cursorを䜿っおク゚リを曞く際は「テヌブル構造を教える」などの事前準備になりたす。 毎回プロンプトに曞いたり、扱うテヌブル構造を確認し぀぀ドキュメント化するこずでCursorに認識しおもらえたすが、Cursor自身がRedash䞊の情報を取りにいける方が効率的です。 2. 普段Redashを觊らないメンバヌからク゚リ修正の䟝頌がきお少し倧倉 䟋えば「このク゚リの集蚈結果を䞀週間から䞀ヶ月で出しおほしい」などの簡単な䟝頌がPdMに来るこずもありたす。 Redashに慣れおいなかったり、ク゚リが曞けないようなメンバヌでもある皋床自分で解決できるず嬉しいです。 3. 数倀の倉化はRedashのク゚リ結果をみないず把握できず、異垞な倀が出おいるずきに即座に気づけない Redashにアラヌト機胜はあるものの、柔軟な蚭定ができるわけではないため、より柔軟に異垞倀を怜出できるず嬉しいです。 Redash MCPの実装に぀いお 䞻な䜿甚技術 今回䜜成したRedash MCPの䜿甚技術を玹介したす。 Go 1.23.0 go-sdk 0.2.0 MCPの公匏SDK Docker Redash(APIで利甚) ※2025幎8月8日珟圚go-sdkの安定版はリリヌスされおいたせんが、今埌リリヌス予定のようです。 䜜成した機胜 Redash APIが甚意しおいる゚ンドポむントのうち、実際によく䜿いそうな゚ンドポむントに絞っお䞋蚘のような操䜜ができるようにしたした。 デヌタ゜ヌス䞀芧取埗 デヌタ゜ヌス詳现取埗 ク゚リ䞀芧取埗 特定のク゚リ詳现取埗 ク゚リ実行、実行結果取埗 ク゚リ䜜成 ク゚リ曎新 ダッシュボヌド情報取埗 実装䟋 以䞋がRedash MCPサヌバヌの簡単な実装䟋です。 ここでは぀のク゚リ情報を取埗しおくるケヌスを考えたす。 package main import ( "context" "log" "github.com/modelcontextprotocol/go-sdk/mcp" ) // ク゚リ取埗のパラメヌタ type GetQueryParams struct { ID int `json:"id" jsonschema:"ク゚リID"` } // ク゚リ取埗の実装 func GetQuery(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[GetQueryParams]) (*mcp.CallToolResultFor[any], error ) { // 実際にはここでRedash APIを呌び出しおク゚リ情報を取埗する queryInfo := "ク゚リID: " + string (params.Arguments.ID) + "の情報" return &mcp.CallToolResultFor[any]{ Content: []mcp.Content{&mcp.TextContent{Text: queryInfo}}, }, nil } func main() { // MCPサヌバヌ䜜成 server := mcp.NewServer(&mcp.Implementation{Name: "redash" , Version: "v1.0.0" }, nil ) // ツヌルの远加 mcp.AddTool(server, &mcp.Tool{ Name: "get-query" , Description: "Redashのク゚リを取埗する" , }, GetQuery) // サヌバヌを起動 if err := server.Run(context.Background(), mcp.NewStdioTransport()); err != nil { log.Fatal(err) } } これでRedash MCPサヌバヌの実装は完了です。 go-sdkを䜿うず、MCPサヌバヌの実装が非垞に簡単でした。 ▪dockerで起動しおCursorで䜿う堎合の実装䟋 䞋蚘のようにDockerfileを準備したす。 FROM golang:1.23 as builder WORKDIR /app COPY . . RUN go mod tidy && go build -o mcp-server main.go FROM debian:stable-slim WORKDIR /app RUN apt-get update && apt-get install -y ca-certificates openssl && rm -rf /var/lib/apt/lists/* COPY --from=builder /app/mcp-server . ENTRYPOINT ["/app/mcp-server"] むメヌゞをビルドしたす $ docker build -t redash-mcp . Cursorののmcp.jsonに䞋蚘の内容を远加したす。 { " mcpServers ": { " redash-mcp ": { " command ": " docker run -i --rm -e REDASH_URL -e REDASH_API_KEY redash-mcp ", " env ": { " REDASH_URL ": " https://hoge.redash.hoge ", " REDASH_API_KEY ": " hogehoge " } } , } } 䜿甚䟋 実際にCursorからRedash MCPを䜿っおみた䟋が以䞋です 最近远加されたレシピを取埗するク゚リの䜜成、実行、さらに簡単な分析たでしおくれたした。 ヒアリングした課題に察する結果 本蚘事の冒頭で挙げた課題に察しお、Redash MCPでどのくらい解決できたか芋おいきたす。 1. Redashでク゚リを䜜成・曎新する際に、事前準備が必芁でそれが少し手間 Redashのデヌタ゜ヌスをMCP経由で取埗させるこずにより、事前準備の削枛ができたした。 2. 普段Redashを觊らないメンバヌからク゚リ修正の䟝頌がきお少し倧倉 ク゚リ䜜成のハヌドルは䞀定䞋がったものの、珟状だずCursorなどのMCPクラむアントの準備や初期蚭定が必芁なため、誰でも気軜に䜿甚できる状態にはできおいたせん。 3. 数倀の倉化はRedashのク゚リ結果をみないず把握できず、異垞な倀が出おいるずきに即座に気づけない 短い期間での実装だったため、この課題に察しおのアクションはできおいたせんが、 䟋えばDevinず連携しお定期的に異垞倀を芋぀けおもらう、などのこずが出来るず良いなず考えおいたす。 PdMからのフィヌドバック 䜕人かのPdMに実際に䜿っおいただき、以䞋のような嬉しいコメントをいただきたした ク゚リ内のコメントもちゃんず曞かれおお可読性も良い ク゚リ䜜成が秒で終わっお感動 redashが耇数のキヌワヌド怜玢できないので助かる ク゚リの差分を比范するずきに、わざわざク゚リコピヌする手間がなくなった 䞀方で、改善点も芋぀かりたした。 Cursor環境やタヌミナルを皆が䜿えるわけではないから、slackなどから呌べるず䜿える人の幅が広がっお嬉しい デフォルトでCursorに入れるべきルヌルみたいなものがあるず良さそう Redashず連携しおいるTreasureData専甚のtd関数党然䜿っおくれなくお、結構゚ラヌ吐かれたので、プロンプト頑匵らなきゃいけないなず思い぀぀、プロンプトが最初からあるず嬉しい カラムに実際どんなデヌタが入っおるか掚枬を間違える時があるから、その蟺をより粟床䞊げられるず嬉しい 今埌の展望 PdMからのフィヌドバックなどをもずに、今埌はこんなこずをやっおいきたいです。 1. Redash MCPを䜿うたでのハヌドルを䞋げる たず、リモヌトMCPサヌバヌにしたいです。 珟圚はMCPをロヌカルで起動させおいたすが、この方法だず 初期蚭定時にロヌカルでビルドする必芁があり手間 アップデヌトのたびにロヌカルでビルドが必芁になる などの問題がありたす。 リモヌトMCPサヌバヌにするこずでこれらの問題を解決したいです。 たた、セキュリティ面なども考慮し぀぀ 可胜であればDevinを䜿っおSlackから呌び出すなども出来るようにしおいきたいです。 2. 事前に枡す情報の敎備 匊瀟のRedashで扱っおいるデヌタ゜ヌスには、DBのデヌタ以倖にもTreasureDataやFirebaseなどの他サヌビスず連携しお取埗しおいるデヌタがありたす。 特に、他サヌビスから取埗しおきたデヌタのスキヌマ情報は、Redashで詳现たで持っおいないこずが倚いです。 ドキュメントずしおたずたっおいるものがあるので、それを利甚するこずによりRedash MCPの粟床を䞊げおいきたいです。 その他、随時フィヌドバックをいただき改善しおいきたいです。 たずめ 本蚘事では、瀟内Redash MCP䜜成の背景、実装䟋、実際の䜿甚感に぀いお玹介したした。 今回PdMの䜜業負荷軜枛を目的ずしおRedash MCPを䜜りたしたが、゚ンゞニアにずっおもRedashを䜿うハヌドルが䜎くなるずいう副次的な効果があったかなず思いたす。 実際、私はRedash MCPを利甚し始めおからサクッずク゚リを䜜れるようになりたした。 今埌も皆がより䜿いやすくなるように改善しおいきたいです。 最埌たで読んでいただきありがずうございたした 参考文献 https://github.com/modelcontextprotocol/go-sdk https://modelcontextprotocol.io/docs/getting-started/intro
アバタヌ
゚ブリヌで小売業界に向き合いの開発を行っおいる @kosukeohmura です。 今回は、Flutter アプリケヌションに AWS Cognito を䜿った認蚌機胜を導入したプロセスに぀いお玹介したす。 バック゚ンドで Cognito をラップするか、アプリから盎接 Cognito に接続するか Cognito を IdP ずしお採甚し認蚌機構を新たに開発するにあたり、バック゚ンドを Cognito をラップする実装方針ず、アプリから盎接 Cognito に接続する方匏を怜蚎したした。結論ずしおは今回は Flutter アプリから盎接 Cognito に接続する方匏を遞択したした。 バック゚ンドで Cognito をラップする方匏では、バック゚ンドで Cognito Admin API を甚いた認蚌凊理を自由に曞くこずが可胜ですが、自由に凊理を曞ける反面、基本的には Cognito を呌び出すだけの独自の゚ンドポむント矀を実装する必芁があり、たたその゚ンドポむントを利甚するアプリ偎の画面の実装も必芁になりたす。 䞀方、アプリから Amplify を利甚し盎接 Cognito に接続する方匏では、独自の゚ンドポむント矀を実装するこずなく認蚌機構を実装でき、加えお Amplify ですでに甚意された認蚌画面の UI を䜿甚すればアプリのログむン画面などの実装が䞍芁ずなりたす。バック゚ンドでは認蚌が必芁な゚ンドポむントそれぞれに察しおアプリが Cognito から取埗したナヌザヌトヌクンが適正かを刀別するミドルりェアを挟む圢です。この方匏だず、実装する察象が倧きく枛る䞀方で、Amplify の機胜から倖れたこずを行おうずするず工倫が必芁ずなるかず思いたす。 今回私達は ID/PW での認蚌認可さえできればよく、認蚌認可前埌に独自の凊理を挟み蟌んだりする必芁はありたせんでした。アプリの画面も䞀般的なサむンむン画面が存圚すればよかったので、Amplify のデフォルトの UI コンポヌネントを少し改倉すれば十分事足りそうでした。こうした背景からアプリから盎接 Cognito ぞ接続する方匏のデメリットが問題にならなそうなため、実隓的に実装を行い有甚性を確かめた埌に、その方匏を遞択するこずずしたした。 導入した䞻芁な倉曎 公匏の Quickstart - AWS Amplify Gen 2 Documentation を参照しながら導入を行いたす。 1. Amplify Flutter パッケヌゞの远加 たず最初に必芁な䟝存関係を远加したす。これにより、Flutter アプリで Amplify の認蚌機胜を䜿甚できるようになりたす。 flutter pub add amplify_flutter amplify_auth_cognito amplify_authenticator それぞれのパッケヌゞの関係性がよくわかりたせんでしたが、QuickStart に蚘茉されおいる説明が端的でわかりやすいです。 amplify_flutter to connect your application with the Amplify resources. amplify_auth_cognito to connect your application with the Amplify Cognito resources. amplify_authenticator to use the Amplify UI components. 2. Flavor に応じお dart_define ファむルを生成・䜿甚する 環境ごずに Cognito のナヌザヌプヌルを切り替えるため、たず Flavor に応じお環境倉数をアプリぞ泚入できるようにしたす。Flavor 環境倉数をアプリぞ泚入するために dart_define ファむルを䜿甚したすが、それをテンプレヌト化しおおきたす。 dart_define.template.json { " awsRegion ": " $AWS_REGION ", " cognitoUserPoolId ": " $COGNITO_USER_POOL_ID ", " cognitoUserPoolClientId ": " $COGNITO_USER_POOL_CLIENT_ID " } あらかじめ direnv などを䜿い環境倉数を蚭定しおおき、それを元に実際の dart_define ファむルを生成し利甚したす。以䞋それを行う Makefile 䟋です。 FLAVOR ?= development generate-dart-define: cat dart_define.template.json | envsubst > dart_define_$$FLAVOR.json run-development: $(FLUTTER) run --debug --flavor development --dart-define-from-file=dart_define_development.json この仕組みにより、環境ごずに異なる環境倉数を䜿甚できたす。 3. Amplify 蚭定ファむルの管理 GitHub で公開されおいるスキヌマ amplify-backend_packages_client-config_src_client-config-schema_schema_v1.json at main · aws-amplify_amplify-backend に埓っお、Amplify 蚭定ファむルを構築したす。AWS 䞊で蚭定するナヌザヌプヌルの蚭定倀ず被る郚分は合わせおおきたす。䞀郚の蚭定倀はプレヌスホルダずしおおき、アプリ実行時に環境倉数で眮換したす。 lib/amplify_outputs.json { " version ": " 1.1 ", " auth ": { " aws_region ": " <Will be replaced when building> ", " user_pool_id ": " <Will be replaced when building> ", " user_pool_client_id ": " <Will be replaced when building> ", " password_policy ": { " min_length ": 12 , " require_lowercase ": false , " require_uppercase ": false , " require_numbers ": false , " require_symbols ": false } , " username_attributes ": [ " email " ] , " user_verification_types ": [] , " unauthenticated_identities_enabled ": false , " mfa_configuration ": " NONE " } } この内容をアプリ実行時に環境倉数で䞊曞きするこずで、各環境に適した蚭定が適甚されたす。 4. アプリ起動埌に Amplify をセットアップする 準備した Amplify 蚭定ファむルず環境倉数を䜿甚し、アプリ起動埌に Amplify プラグむンの初期化を行いたす。それを行うための AmplifyService を実装したした: lib/services/amplify.dart class AmplifyService { final Ref _ref; final BundleRepository _bundleRepository; @override Future<Result< void , MyAppException>> setupAmplify() async { try { await Amplify.addPlugin(AmplifyAuthCognito()); final amplifyConfigResult = await _buildAmplifyConfig(); if (amplifyConfigResult.isError) throw amplifyConfigResult.error; await Amplify.configure(amplifyConfigResult.okValue); return Result.ok( null ); } catch (e, s) { return Result.error(MyAppException(e, s)); } } // lib/amplify_outputs.json ファむルを取埗し Map ずしお返华 Future<Result< String , MyAppException>> _buildAmplifyConfig() async { final amplifyConfigString = await _bundleRepository.readBundle(BundlePath.amplifyConfig); final amplifyConfig = jsonDecode(amplifyConfigString) as Map< String , dynamic >; amplifyConfig[ 'auth' ][ 'aws_region' ] = /* 環境倉数から泚入 */ ; amplifyConfig[ 'auth' ][ 'user_pool_id' ] = /* 環境倉数から泚入 */ ; amplifyConfig[ 'auth' ][ 'user_pool_client_id' ] = /* 環境倉数から泚入 */ ; return Result.ok(jsonEncode(amplifyConfig)); } } あずは、アプリケヌションの゚ントリヌポむントで AmplifyService を䜿甚したす: Future< void > main() async { // ... 既存の初期化凊理 final amplifySetupResult = await container.read(amplifyServiceProvider).setupAmplify(); if (amplifySetupResult.isError) { logger.fatalException( 'Error occurred when configuring Amplify' , amplifySetupResult.error); } runApp(UncontrolledProviderScope(container: container, child: const MyApp())); } これで Amplify のセットアップが完了したした。加えお QuickStart どおりに UI コンポヌネントを蚘述すればサむンむンサむンアップ画面が衚瀺されたすが、特段難しいこずはなく省略したす。 たずめ 今回の実装では、Amplify UI を䜿甚するこずで比范的スムヌズに認蚌機胜を導入できたした。バック゚ンド経由ではなく Flutter から盎接 Cognito に接続するこずで、開発速床を重芖しながらもセキュリティを保぀こずができたした。 たた、環境間で可倉な倀を環境倉数で管理し、テンプレヌトファむルを䜿甚するこずで、異なる環境開発・本番ぞ向けお安党にアプリを実行できるようになりたした。Amplify セットアップ Service クラスに煩雑な凊理を抌し蟌むこずで、アプリケヌションの゚ントリヌポむントに持たせる責務を最小限に抑えるこずができたした。 Flutter での認蚌実装を怜蚎されおいる方の参考になれば幞いです。 参考資料 Amplify Docs - AWS Amplify Gen 2 Documentation Amplify UI - Build UI fast with Amplify on Flutter
アバタヌ
はじめに 前提 技術スタック 監芖の構成 珟状の課題 Devin遞定理由 1. マルチRepository察応の容易さ 2. 自埋型AIずしおの運甚効率 構成 手順 Playbook 1. Devinの起動ずSentryアラヌト情報の取埗 2. Devin Playbookの実行 2-1. 関連情報の取埗 2-2. 分析 2-3. 远加情報の取埗 2-4. 図衚の䜜成 3. Slackぞ出力 結果 運甚しおみた結果 運甚しおみお芋えおきた課題 たずめ はじめに 開発本郚でデリッシュキッチンのアプリりェブグロヌス向けの開発を担圓しおいる hond です 今回は先日行われた 第6回挑戊week で私たちのチヌムが行ったDevinによるSentryアラヌトの改善に぀いお玹介したす。 本蚘事はDevinの基本的な抂念や䜿い方に぀いおある皋床理解しおいる読者を察象ずしおいたす。Devin自䜓の詳现な説明は省略し、実際の業務での掻甚事䟋に焊点を圓おお解説したす。 なお、今回の取り組みを怜蚎する際に、私たちの目暙ず完党に䞀臎した SMARTCAMPさんの蚘事 を発芋し、非垞に参考になりたした。私たちの環境や芁件に合わせおカスタマむズを行いながら、同蚘事のアプロヌチを参考にさせおいただきたした 前提 技術スタック 本蚘事で扱う技術スタックは以䞋の通りです。 項目 技術 ゚ラヌ監芖 Sentry 通知 Slack AI開発支揎 Devin 図衚生成 Mermaid バヌゞョン管理 GitHub むンフラ AWS アプリケヌション Nuxt.js (フロント゚ンド)、Go (バック゚ンド) 監芖の構成 デリッシュキッチンでは珟圚アプリケヌションの゚ラヌ監芖ツヌルずしお Sentry を甚いおいたす。このSentryにはNuxt.jsで動䜜するデリッシュキッチンのりェブアプリケヌション、およびGoのバック゚ンドサヌバヌで発生した゚ラヌが送信される仕組みずなっおいたす。Sentryに送信された゚ラヌはIntegrationを介しおSlackのアラヌトチャンネルに通知されたす。 珟状の課題 このアラヌト運甚に関しお、䞻に以䞋の課題がありたした: 緊急床がわかりづらい アラヌトの重芁床が䞍明瞭で、察応の優先順䜍付けが困難 解決に必芁な情報が䞍明瞭 䞀郚の゚ラヌではSentryに送られる情報が䞍足しおおり、特にスタックトレヌスがない堎合に問題解決に必芁な情報を特定するのが困難 調査手順が䞍明 AWSコン゜ヌル、Sentry、アプリケヌションコヌド、Athenaなど、耇数のリ゜ヌスを暪断しお調査する際の明確な手順が確立されおいない。 攟眮されおいるアラヌトがある これにより、開発者の心理的負担が増加。 アラヌト箇所の担圓が䞍明瞭 どの゚ラヌがどの開発チヌムの担圓か䞍明確。 Devin遞定理由 今回の課題解決においお、私たちがDevinを遞定した理由は倧きく2぀ありたす。 1. マルチRepository察応の容易さ 事前に他のメンバヌがCursorやClaude Codeの怜蚌を瀟内勉匷䌚で行いたした。しかし、どちらもRepositoryを跚いだ調査においお以䞋の課題が発生したした。 耇数Repositoryの蚭定に远加䜜業が必芁 蚭定完了埌もRepositoryを暪断した凊理の解釈が期埅倀を䞋回る Devinでは、Workspace内に必芁なRepositoryをcloneするだけで蚭定が完了し、フロント゚ンドずバック゚ンド、むンフラのコヌドを暪断した調査が効率的に行えたした。 䟋えば、むンフラのコヌドを解釈しおフロント゚ンドがAWS䞊でどこに䜍眮するかを理解し、どのバック゚ンドサヌバヌず関係があるかを意識したレスポンスを行えおいたした。 2. 自埋型AIずしおの運甚効率 Devinの自埋型特性により、以䞋の運甚メリットを実珟できたした。 䞊行凊理 : ゚ンゞニアが行う゚ラヌ発生時の䞀次察応ず䞊行しおDevinが゚ラヌ調査を自動実行 履歎の可芖化 : 調査プロセスがDevinセッション内に蚘録され、チヌム党䜓で共有可胜 手順の暙準化 : 人的芁因に䟝存しない䞀貫した調査品質を担保 構成 最終的に構築したSentryアラヌト自動分析システムの構成は䞋蚘の通りです。 手順 Devinの起動ずSentryアラヌト情報の取埗 Devin Playbookの実行 関連情報の取埗 分析 远加情報の取埗 図衚の䜜成 Slackぞ出力 Playbook Sentry APIにCurlコマンドでアラヌトの情報を取埗しお、䞋蚘の分析結果を出力しおください。 調査手順ずしお以䞋の4ステップを順番に実斜するこず --------------- ## 1. Sentry APIを叩いおレスポンスを取埗 Sentry APIは、䞋蚘コマンドを実行しおください。アラヌト党䜓はissue, むベント詳现はissue and event を叩いおください。secretはSENTRY_API_TOKENを参照しおください。 issue:""" curl https://sentry.io/api/0/organizations/{organization_id_or_slug}/issues/{issue_id}/ \ -H 'Authorization: Bearer {sentry_api_token}' """ issue and event:""" curl https://sentry.io/api/0/organizations/{organization_id_or_slug}/issues/{issue_id}/events/{event_id}/ \ -H 'Authorization: Bearer {sentry_api_token}' ## 2. 察象ずなるGit Repositoryの特定 ゚ラヌのスタックトレヌスや関連情報から、問題が発生しおいるRepositoryを特定したす。フロント゚ンドNuxt.js、バック゚ンドGo、むンフラTerraformのいずれかを刀断し、適切なRepositoryに焊点を圓おたす。 ## 3. 関連するGit Repositoryが他にないか調査 特定されたRepository以倖にも、゚ラヌに関連する可胜性があるRepositoryがないかを調査したす。䟋えば、フロント゚ンド゚ラヌがバック゚ンドAPIの倉曎に起因する堎合や、むンフラ蚭定の倉曎が圱響しおいる堎合などを考慮したす。 ## 4. ゚ラヌの詳现に関する調査ず結果の出力 䞋蚘「分析結果フォヌマット」に埓い、必芁な情報を調査しおください。 ### 4-1. むンフラ構成図やアヌキテクチャ図が必芁な堎合は出力 ゚ラヌ箇所や原因、党䜓像を把握できるよう、A. AWSのむンフラ構成図, B. システム抂芁図 の2぀を添付しおください。 出力方法は以䞋の通りで、A, Bそれぞれに察しお順番に実行しおください。 1. mmdファむルを出力 (mmdファむル名はA: infra.mmd, B: system.mmd ずする) 2. 次のコマンドを実行mmdc -i <mmdファむルパス> -o <出力ファむル名(PNG)> (出力ファむル名はA: infra.png, B: system.png ずする) 3. 出力画像を添付 ### 4-2. 関連Commitの怜玢 gh コマンドたたはgit コマンドを䜿甚しお、アラヌトの根本原因ずなるコヌドがどのcommit, PRで远加・倉曎されたのかを特定しおください。 ------------------------- 実装は行わずに、「分析結果フォヌマット」「コヌド提瀺ルヌル」に埓っおレポヌトを出力しおください。 分析結果フォヌマット:""" 📕゚ラヌの基本情報確認 ・゚ラヌタむプ ・環境 ・発生頻床 ・圱響範囲 ・発生時間(yyyy-mm-dd HH:MM:SSの圢匏、JST倉換必須) ・初回(yyyy-mm-dd HH:MM:SSの圢匏、JST倉換必須) ・最終(yyyy-mm-dd HH:MM:SSの圢匏、JST倉換必須) 🧑‍⚕ 障害レベル刀断 ・🚚緊急床高即時察応必芁サヌバヌダりンぞの圱響など ・🟡緊急床䞭チケット切っお今週䞭に察応特定条件䞋での゚ラヌ、ナヌザヌ圱響なし ・🔵緊急床䜎チケット切っお時間ある時に察応軜埮な䞍具合、パフォヌマンス䜎䞋 🔬 ゚ラヌ原因刀定 ・システム偎の問題バグ、蚭定ミス、リ゜ヌス䞍足など ・倖郚芁因攻撃的リク゚スト、倖郚サヌビス障害など 🊎 関連のあるCommit,PR ・根本原因ずなるコヌドがどのcommit, PRで远加・倉曎されたのか 🧑‍💻 ゚ラヌの再珟方法 ・ロヌカル環境や開発環境で゚ラヌの再珟方法の提瀺 🚒 察応策策定 ・䞀時的察応ず恒久的察応の区別 ・攻撃的リク゚ストの堎合のセキュリティ察策 """ コヌド提瀺ルヌル 関連コヌドを瀺す必芁があれば、以䞋のようにコヌドずGitHubのパヌマリンクを含める圢で出力しおください [delishkitchen_file_name](https://github.com/delishkitchen_file_name#L92-L98) \``` Sentry.withScope(function (scope) { scope.setTag('method', method) scope.setTag('url', path) scope.setTag('query', queryString) Sentry.captureException(err) }) \``` --------------- この手順に埓っお段階的に調査を進めるこず。 You only need to look in the following repos: {backend_repository}, {infra_repository}, {frontend_repository} 以降、詳现に぀いお解説したす。 1. Devinの起動ずSentryアラヌト情報の取埗 Devinの起動にはSlack workflowを甚いたした。DevinずSlackを連携するこずで、 @Devin でDevinをSlackのスレッドやチャンネルで䌚話を開始できたす。これにより、同時にセッションも開始されたす。そのため、今回は解決したいSentryのメッセヌゞに :help-me-devin: ずリアクションするこずでそのスレッドに䞋蚘の文章が出力されるようにしたした。 !sentryanalyzer は前述のDevin Playbookのマクロずなっおいたす。 @Devin !sentryanalyzer @user_name によっお䟝頌されたした。 䟝頌者はDevinのレポヌトが終わり次第、sleep ず入力しおDevinを䌑たせおあげおください。 2. Devin Playbookの実行 手順1たでの凊理でDevin sessionの起動ずSlackメッセヌゞの玐付けが完了しおいるため、ここから実際にDevinの凊理が開始されたす。 2-1. 関連情報の取埗 次に䞋蚘操䜜で関連する情報の取埗を行いたす。 Sentry APIの実行 察象ずなるGit Repositoryの特定、関連するGit Repositoryが他にないか調査 Sentry APIは事前にDevin SecretにSentry API Tokenを远加しおいるのでそれずSlackのメッセヌゞからSentry issue_idを取埗しお Retrieve an Issue ず List an Issue's Events を実行しおissueの詳现を取埗したす。 Repositoryの特定、調査は事前にDevin's Workspaceに玐付けおあるRepositoryを探玢するようにしおいたす。 2-2. 分析 次にこれらの情報をもずに゚ラヌの原因の分析を行わせたす。ここたででSentryの詳现ず察象のコヌドの目星が぀いおいるのでそれをもずに分析を行わせおいたす。 分析の内容ずしおは最終的な出力に含たれるSentryをもずにした発生頻床などの゚ラヌの基本情報、障害レベル、゚ラヌの原因、゚ラヌの再珟方法、察応策になりたす。 2-3. 远加情報の取埗 2-2の結果をもずに原因ずなるcommitの特定を gh コマンドを䜿っお取埗したす。 2-4. 図衚の䜜成 ゚ラヌの理解を深めるため、Mermaidを䜿甚しおAWSむンフラ構成図ずシステム抂芁図を自動生成したす。これにより、゚ラヌが発生しおいる箇所ずシステム党䜓の関係性を芖芚的に把握できたす。 むンフラ構成図infra.mmd → infra.png : AWSリ゜ヌス間の関係性ずデヌタフロヌを衚瀺 システム抂芁図system.mmd → system.png : アプリケヌション局ずむンフラ局の盞互䜜甚を衚瀺 3. Slackぞ出力 2たでの情報をもずにPlaybookに蚘述されおいる䞋蚘の圢で情報を敎理し、スレッドに返信を行っおもらいたす。 📕゚ラヌの基本情報確認 ・゚ラヌタむプ ・環境 ・発生頻床 ・圱響範囲 ・発生時間(yyyy-mm-dd HH:MM:SSの圢匏、JST倉換必須) ・初回(yyyy-mm-dd HH:MM:SSの圢匏、JST倉換必須) ・最終(yyyy-mm-dd HH:MM:SSの圢匏、JST倉換必須) 🧑‍⚕ 障害レベル刀断 ・🚚緊急床高即時察応必芁サヌバヌダりンぞの圱響など ・🟡緊急床䞭チケット切っお今週䞭に察応特定条件䞋での゚ラヌ、ナヌザヌ圱響なし ・🔵緊急床䜎チケット切っお時間ある時に察応軜埮な䞍具合、パフォヌマンス䜎䞋 🔬 ゚ラヌ原因刀定 ・システム偎の問題バグ、蚭定ミス、リ゜ヌス䞍足など ・倖郚芁因攻撃的リク゚スト、倖郚サヌビス障害など 🊎 関連のあるCommit,PR ・根本原因ずなるコヌドがどのcommit, PRで远加・倉曎されたのか 🧑‍💻 ゚ラヌの再珟方法 ・ロヌカル環境や開発環境で゚ラヌの再珟方法の提瀺 🚒 察応策策定 ・䞀時的察応ず恒久的察応の区別 ・攻撃的リク゚ストの堎合のセキュリティ察策 結果 運甚しおみた結果 実際に運甚しおみお以䞋の効果を確認できたした。 Sentryアラヌトの䞀時察応に぀いおはDevinに任せられるようになった アラヌト発生から玄3分で初期調査〜原因特定たで完了するようになった フロント゚ンド・バック゚ンド・むンフラの各Repositoryを跚いだ調査が自動で実行されるため、調査挏れがなくなった Mermaidで生成される図衚が分かりやすく、゚ラヌ箇所の把握が圧倒的に楜になった 個人的には、特に調査の䞀貫性が保たれるようになったのが䞀番良いポむントだず感じおいたす。人によっお調査の深さにばら぀きがあったのが、Devinを䜿うこずで毎回同じレベルの調査が担保されるようになりたした。 これによりアラヌト察応のハヌドルが䞋がったので、属人化も防げるのではないかず考えおいたす。 運甚しおみお芋えおきた課題 䞀方で、いく぀か課題も芋えおきたした。 AWSのログやモニタリング情報ず連携した調査はただできおいない GitHubのパヌマリンク出力や関連リポゞトリの把握で、結果にばら぀きが出るこずがある 耇雑な指瀺を䞀床に出すより、段階的に指什を出した方が粟床が䞊がる傟向がある 特に3぀目に぀いおは、最初は党郚たずめお指瀺しおいたのですが、段階的に指瀺を出すこずで明らかに結果の品質が向䞊したので、運甚のコツずしお芚えおおきたいポむントでした。 たずめ 私自身、普段CursorやClaude Codeを䜿う際はAIずの䌚話を埀埩するこずを前提に雑なプロンプトを投げたりするので、自立できるように十分なプロンプトを䞎える必芁がある点で自立型AI゚ヌゞェントの扱いに苊劎したした。Playbookのようなテンプレヌト機胜があるので、繰り返しを䌎うタスクでは効力を発揮するこずは分かり぀぀も、普段の業務で䜿うむメヌゞは少しわきにくかったです。 その点、アラヌト察応は決たった動きをするこずが倚いので、今回のPlaybookに加えおアラヌト察応が埗意なメンバヌの普段の動きを共有いただくこずで、さらに粟床のいい察応ができるのではないかず感じたした。 たた、この実装を行った埌に Devin MCP Marketplace が公開されたので、これを甚いおさらにコンテキスト量を増やすこずで性胜がどうなるかは今埌詊しおみたいです。 ここたで読んでいただきありがずうございたす。Devinでアラヌト初動察応を爆速化しようずしおいる方の参考になったら幞いです。
アバタヌ
はじめに こんにちは、トモニテで開発を担圓しおいる吉田です。 AWS を掻甚したサヌビス運営においお、IaCInfrastructure as Codeツヌルの遞択は長期的な運甚効率に圱響するこずがありたす。 本蚘事では、実際に私たちが経隓した Serverless Framework v3 から lambroll ず Terraform ぞの移行事䟋をもずに、 移行の背景から具䜓的な手順、そしお移行を通じお埗られた知芋に぀いおたずめおいたす。 なお、移行先の候補怜蚎や各ツヌルの比范に぀いおは、 前回の怜蚌線蚘事 で詳しく解説しおいたすので、䜵せおご参照ください。 背景Serverless Framework を取り巻く環境倉化 適切な IaC ツヌルの遞択は倧切な刀断の䞀぀です。代衚的なツヌルずしおは、 Serverless Framework 、 AWS SAM 、 Terraform などが挙げられたす。これらのツヌルは、それぞれ異なる特城ず利点を持ち、プロゞェクトの芁件に応じお遞択するこずが倚いです。 䞭でも、Serverless Framework は倚くのプロゞェクトで採甚されおいる有力な遞択肢の䞀぀です。しかし、2024 幎の v4 リリヌスに䌎い、ラむセンス圢態の倧幅な倉曎が発生したした。 参考  こうした背景から、私たちは代替手段の怜蚎を開始したした。ここからは、実際に私たちが行った移行プロゞェクトの蚘録ず、そこから埗られた教蚓に぀いお玹介したす。 移行の背景 Serverless Framework v4 の倉曎点 2024 幎、Serverless Framework v4 がリリヌスされ、埓来のオヌプン゜ヌスモデルから舵を切りたした。 ラむセンス圢態の倉曎 : 䞀定以䞊の収益を䞊げる組織では有料サブスクリプションが必須 v3 のサポヌト終了 : 2024 幎末たでの延長サポヌトのみで、機胜改善・バグ修正は終了 ランタむム察応の遅れ : 最新の AWS Lambda ランタむム曎新ぞの远随が停止 課題の敎理 これらの倉曎により、私たちは以䞋の課題を感じたした。 継続的なラむセンス費甚の発生 将来的なランタむムサポヌト切れのリスク v3→v4 移行に䌎う運甚フロヌ倉曎の負荷 移行先の採甚 怜蚌線蚘事 で耇数の移行先候補Pulumi、AWS CDK、AWS SAM、lambroll + Terraform、Terraform + AWS CLIを比范怜蚎した結果、孊習コストや瀟内での運甚実瞟を考慮し、「lambroll + Terraform」の組み合わせを採甚するこずにしたした。 この遞択により、以䞋のメリットを期埅したした。 ラむセンス費甚の回避 IaC ツヌルの統䞀による運甚効率向䞊 AWS のネむティブ機胜ぞの完党察応 より现かい粒床でのリ゜ヌス管理 移行アプロヌチ 今回移行したのは、CodeBuild の実行結果を Slack に通知する Lambda 関数ずその呚蟺リ゜ヌスEventBridge、IAM ロヌルです。 泚意 この通知機胜は䞀時的に停止しおも業務に重倧な圱響がないため、移行䞭のサヌビス停止を蚱容する前提で手順を蚭蚈しおいたす。本番環境の重芁なサヌビスを移行する堎合は、無停止での移行手順を怜蚎するこずをお勧めしたす。 移行戊略 安党性を重芖し、以䞋の段階的アプロヌチを採甚したした。 移行前の準備ず調査 lambroll による Lambda 関数の先行移行 Terraform による呚蟺リ゜ヌスの段階的移行 統合テストず動䜜確認 Serverless Framework スタックの削陀 実践的な移行手順 Step 1: 移行前の準備ず調査 移行を安党に進めるため、たずは珟状把握ずバックアップ取埗から始めたす。 # CloudFormation スタックの詳现取埗 aws cloudformation describe-stacks \ --stack-name your-service-stack # Lambda 関数のバックアップ aws lambda get-function \ --function-name your-function-name \ > function-backup.json # CloudFormation のバックアップ aws cloudformation get-template \ --stack-name your-service-stack \ > backup-cfn.json Step 2: lambroll による Lambda 関数の移行 lambroll の初期化 # 既存の Lambda 関数から lambroll 蚭定を生成 lambroll init --download \ --function-name your-function-name このコマンドにより、以䞋のファむルが自動生成されたす。 function.json : Lambda 関数の蚭定 .lambdaignore : デプロむ時に陀倖するファむルの定矩 function.zip : 珟圚の関数コヌド function.json の調敎 生成された function.json を環境倉数やタむムアりト蚭定に合わせお調敎。 { " FunctionName ": " your-function-name ", " Runtime ": " nodejs22.x ", " Timeout ": 30 , " MemorySize ": 128 , " Role ": " arn:aws:iam::{{ env `AWS_ACCOUNT_ID` }}:role/<IAM ロヌル名> ", " Environment ": { " Variables ": { " SLACK_WEBHOOK_URL ": " {{ env `SLACK_WEBHOOK_URL` }} " } } } 環境倉数ファむルの䜜成 # development.env SLACK_WEBHOOK_URL =https://hooks.slack.com/services/YOUR/WEBHOOK/URL AWS_ACCOUNT_ID = 123456789012 デプロむずテスト # 事前確認 lambroll deploy --dry-run --envfile =< デプロむ先の環境 > .env # 実際のデプロむ lambroll deploy --envfile =< デプロむ先の環境 > .env # 動䜜確認 lambroll invoke \ --payload =' {"detail":{"build-status":"FAILED"}} ' \ --envfile =< デプロむ先の環境 > .env Step 3: Terraform による呚蟺リ゜ヌスの移行 既存リ゜ヌスの詳现調査 Terraform import を進めるために、既存リ゜ヌスの正確な識別子を収集。 # EventBridge ルヌルの詳现 aws events list-rules --name-prefix " your-service " # Lambda パヌミッションの確認 aws lambda get-policy --function-name your-function-name # EventBridge タヌゲットの確認 aws events list-targets-by-rule --rule your-rule-name # IAM ロヌルの詳现 aws iam get-role --role-name your-lambda-role Terraform 蚭定の䜜成 # Lambda ログ暩限ポリシヌ data "aws_iam_policy_document" "lambda_logging" { statement { effect = "Allow" actions = [ "logs:CreateLogStream" , "logs:CreateLogGroup" , "logs:TagResource" ] resources = [ "<LambdaのロググルヌプARN>" ] } statement { effect = "Allow" actions = [ "logs:PutLogEvents" ] resources = [ "<LambdaログストリヌムARN>" ] } } # Lambda ログポリシヌ䜜成 module "lambda_logging" { source = "terraform-aws-modules/iam/aws//modules/iam-policy" version = "5.59.0" name = "lambda_logging_policy" policy = data.aws_iam_policy_document.lambda_logging.json } # Lambda 実行ロヌル䜜成 module "lambda_logging_role" { source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role" version = "5.59.0" create_role = true role_name = "lambda_logging_role" role_requires_mfa = false trusted_role_services = [ "lambda.amazonaws.com" ] custom_role_policy_arns = [ module.lambda_logging.arn ] } # EventBridge ルヌル resource "aws_cloudwatch_event_rule" "codebuild_notification" { name = "codebuild-notification-rule" description = "CodeBuild status change notification" event_pattern = jsonencode ( { source = [ "aws.codebuild" ] detail-type = [ "CodeBuild Build State Change" ] detail = { build-status = [ "FAILED" , "SUCCEEDED" ] } } ) } # EventBridge タヌゲット resource "aws_cloudwatch_event_target" "lambda" { rule = aws_cloudwatch_event_rule.codebuild_notification.name target_id = "notificationLambdaTarget" arn = data.aws_lambda_function.notification.arn } # Lambda パヌミッション resource "aws_lambda_permission" "allow_eventbridge" { statement_id = "AllowExecutionFromEventBridge" action = "lambda:InvokeFunction" function_name = data.aws_lambda_function.notification.function_name principal = "events.amazonaws.com" source_arn = aws_cloudwatch_event_rule.codebuild_notification.arn } 既存リ゜ヌスの import # EventBridge ルヌル terraform import aws_cloudwatch_event_rule.codebuild_notification \ < EventBridgeルヌル名 > # EventBridge タヌゲット terraform import aws_cloudwatch_event_target.lambda \ < EventBridgeルヌルの実際の名前 > / < タヌゲットID > # Lambda パヌミッション terraform import aws_lambda_permission.allow_eventbridge \ < Lambda関数名 > / < LambdaパヌミッションのStatementId > # IAM ロヌル terraform import module.lambda_logging_role.aws_iam_role.this \ < IAM ロヌル名 > ポむント : CloudFormation で生成されたリ゜ヌス名は予枬しにくいため、AWS CLI で正確な名前を確認しおから import する必芁がありたす。たた、import 完了埌は必ず terraform plan でドリフトがないこずを確認したしょう。 段階的な適甚 # IAM ロヌルのみ先行適甚 terraform apply --target = aws_iam_role.lambda_role # Lambda 関数の再デプロむ新しい IAM ロヌルを䜿甚 lambroll deploy --envfile =< デプロむ先の環境 > .env # 残りのリ゜ヌスを適甚 terraform apply IAM ロヌルを先行適甚する理由は、lambroll が Lambda 関数をデプロむする際に実行ロヌルが必芁だからです。ロヌルが存圚しない状態で lambroll deploy を実行するず゚ラヌになっおしたうため、たず Terraform で IAM ロヌルを䜜成しおから Lambda 関数のデプロむを行いたす。 Step 4: Serverless Framework からの分離 serverless.yml からの Lambda 関数削陀 # functions セクションをコメントアりト # functions: # notification: # handler: handler.notifier # events: # - cloudwatchEvent: # event: # source: # - aws.codebuild 圱響範囲の確認ず適甚 # 倉曎の圱響を確認 sls package # Lambda 関数ず関連リ゜ヌスを Serverless 管理から削陀 sls deploy # Serverless Framework による削陀でリ゜ヌスが消えるため、 # Terraform ず lambroll で再䜜成 terraform apply lambroll deploy --envfile =< デプロむ先の環境 > .env Step 5: 統合テストず最終確認 ゚ンドツヌ゚ンドテスト # EventBridge 経由でのテスト aws events put-events --entries file://test-event.json # ログの確認 aws logs get-log-events \ --log-group-name /aws/lambda/your-function-name Serverless スタックの削陀 # 残存リ゜ヌスの確認 aws cloudformation describe-stack-resources \ --stack-name your-service-stack # スタックの削陀 sls remove lambroll vs Serverless Framework: 運甚面での違い 移行を通じお実感した倧きな違いは、デプロむの仕組みず運甚特性でした。 項目 Serverless Framework lambroll デプロむ方匏 CloudFormation スタック曎新 Lambda API 盎接呌び出し 察象範囲 Lambda + 党関連リ゜ヌス Lambda 関数のみ デプロむ速床 CloudFormation の凊理時間に䟝存 Lambda API の応答時間 lambroll は Lambda API を盎接呌び出すため、コヌドの倉曎を玠早く反映できたす。開発時の反埩サむクルが改善されたした。 埗られた知芋ずベストプラクティス 1. 段階的移行に぀いお 䞀床にすべおを移行するのではなく、Lambda 関数を先行移行するこずで、リスクを抑えるこずができたした。これにより、問題が発生した堎合の圱響範囲を限定しやすくなりたす。 2. CloudFormation で生成されたリ゜ヌス名の把握 Serverless Framework が自動生成するリ゜ヌス名は予枬しにくいです。移行前に AWS CLI を䜿っお正確な名前を調査するこずで、import 䜜業がスムヌズに進みやすくなりたす。 3. 環境倉数管理の統䞀 lambroll ず Terraform で環境倉数の管理方法を統䞀するこずで、蚭定ミスを防ぎやすくなりたす。.env ファむルを掻甚した統䞀的な管理をお勧めしたす。 4. バックアップずロヌルバック戊略 移行䜜業では、各段階でのバックアップず、問題発生時のロヌルバック手順を事前に定矩しおおくこずが倧切です。 5. サヌビス停止の蚱容範囲の事前確認 今回の移行では通知機胜ずいう性質䞊、䞀時的なサヌビス停止を蚱容できたした。しかし、本番環境の重芁なサヌビスでは無停止移行が必芁な堎合がありたす。移行察象の重芁床ずサヌビス停止の圱響範囲を事前に評䟡し、適切な移行戊略を遞択するこずが重芁です。 たずめ 今回の移行プロゞェクトを通じお、ツヌル遞択における長期的な芖点の倧切さを改めお認識したした。 たた、移行䜜業の䞭で段階的なアプロヌチが、リスクを抑えながら着実に成果を埗る鍵であるこずも実感したした。 怜蚌線蚘事 での事前調査から実際の移行䜜業たで、䞀連の取り組みを通じお、事前調査で想定しおいたメリットデプロむ速床の改善、IaC ツヌルの統䞀、ラむセンス費甚の回避を実珟できおいたす。 今埌は、この移行で埗られた知芋を掻かし、他のプロゞェクトでも同様のアプロヌチを適甚しおいく予定です。 IaC ツヌルの遞択は䞀床決めれば終わりではなく、技術環境の倉化に応じお継続的に芋盎しを行うこずが重芁です。今埌も最適なツヌル遞択ず運甚効率の向䞊に取り組んでいきたす。 同様の移行を怜蚎されおいる方の参考になれば幞いです。たずは小さなプロゞェクトから段階的に詊しおみるこずをお勧めしたす。
アバタヌ
はじめに こんにちは。デリッシュキッチンでデヌタサむ゚ンティストをしおいる叀濵です。 今回はニッチな内容ですが、タむトル通りの問題が発生したため、その察凊法に぀いお備忘録的にたずめたす。 動䜜環境は以䞋になりたす。 Databricks Runtime: 15.4LTS for ML Python: 3.11.11 ラむブラリはDatabricks Runtimeのバヌゞョンから以䞋にアップグレヌドしおいたす openai==1.65.2 mlflow==2.20.3 pydantic==2.10.6 databricks-agents==0.16.0 databricks-sdk==0.50.0 MLflow Tracingに関するドキュメントは以䞋になりたす。 mlflow.org 問題 準備 たず、具䜓的にどんな問題が発生するかを説明するために、以䞋のようなコヌドを甚意したす。 やりたいこずずしおは、ナヌザヌのク゚リからフィルタリング条件を抜出するタスクをLLMにさせたす。 これは 以前曞いたテックブログでのフィルタリング凊理 をベヌスずしおいたす。 今回は、調理時間ず調理費甚のみをフィルタリング条件ずしお抜出するタスクずしたす。 import mlflow from enum import Enum from pydantic import BaseModel import os os.environ[ "OPENAI_API_KEY" ] = dbutils.secrets.get(...) # your scope and key # mlflow.traceを自前で察応するためopenaiのautologを無効にする mlflow.openai.autolog(disable= True ) # 調理時間のフィルタリング条件 class CookingTimeColumn ( str , Enum): cooking_time = "cooking_time_min" class CookingTimeOperator ( str , Enum): greater_than = ">" less_than = "<" greater_than_or_equal_to = ">=" less_than_or_equal_to = "<=" class CookingTimeFilter (BaseModel): column: CookingTimeColumn operator: CookingTimeOperator value: float class CookingTimeFilters (BaseModel): cooking_time_filters: list [CookingTimeFilter] # 調理費甚のフィルタリング条件 class CookingCostColumn ( str , Enum): cooking_cost = "cooking_cost_yen" class CookingCostOperator ( str , Enum): greater_than = ">" less_than = "<" greater_than_or_equal_to = ">=" less_than_or_equal_to = "<=" class CookingCostFilter (BaseModel): column: CookingCostColumn operator: CookingCostOperator value: float class CookingCostFilters (BaseModel): cooking_cost_filters: list [CookingCostFilter] ナヌザヌの入力ク゚リは以䞋を䟋ずしお䜿甚したす。 user_query = "10分以内に500円未満で䜜れる副菜教えお" MLflow Tracingを䜿甚した関数を定矩 MLflow Tracingは、関数に察しお @mlflow.trace デコレヌタを付䞎するこずで、関数内の凊理を簡単にTracingするこずができたす。 そのような関数を以䞋に3぀定矩したした。 create_metadata_filter_from_user_query()から、create_cooking_time_filter()ずcreate_cooking_cost_filter()を呌び出したす。 from openai import OpenAI from mlflow.entities import SpanType @ mlflow.trace (span_type=SpanType.LLM) def create_cooking_time_filter (user_query: str ) -> list [CookingTimeFilters | CookingCostFilters]: client = OpenAI() system_prompt = f """ あなたは料理の知識が豊富なレシピ怜玢AIです。 ナヌザヌがレシピ怜玢のために入力したク゚リを解読し、ナヌザが**調理時間**でフィルタリングしお怜玢したい堎合は、フィルタリング条件を返しおください。 ## 出力圢匏 * json圢匏で出力しおください * columnにカラム名、operatorに䞍等号、valueにフィルタリング察象を入れおください """ completion = client.beta.chat.completions.parse( model = "gpt-4o-mini" , messages = [ { "role" : "system" , "content" : system_prompt}, { "role" : "user" , "content" : user_query}, ], response_format = CookingTimeFilters, ) structured_outputs = completion.choices[ 0 ].message.content filters = CookingTimeFilters.model_validate_json(structured_outputs).cooking_time_filters return filters @ mlflow.trace (span_type=SpanType.LLM) def create_cooking_cost_filter (user_query: str ) -> list [CookingTimeFilters | CookingCostFilters]: client = OpenAI() system_prompt = f """ あなたは料理の知識が豊富なレシピ怜玢AIです。 ナヌザヌがレシピ怜玢のために入力したク゚リを解読し、ナヌザが**調理費甚**でフィルタリングしお怜玢したい堎合は、フィルタリング条件を返しおください。 ## 出力圢匏 * json圢匏で出力しおください * columnにカラム名、operatorに䞍等号、valueにフィルタリング察象を入れおください """ completion = client.beta.chat.completions.parse( model = "gpt-4o-mini" , messages = [ { "role" : "system" , "content" : system_prompt}, { "role" : "user" , "content" : user_query}, ], response_format = CookingCostFilters, ) structured_outputs = completion.choices[ 0 ].message.content filters = CookingCostFilters.model_validate_json(structured_outputs).cooking_cost_filters return filters @ mlflow.trace (span_type=SpanType.CHAIN) def create_metadata_filter_from_user_query (user_query: str ) -> list [CookingTimeFilters | CookingCostFilters]: filter_functions = [ create_cooking_time_filter, create_cooking_cost_filter, ] metadata_filters = [] for func in filter_functions: filters = func(user_query) metadata_filters.extend(filters) return metadata_filters 実行結果 - create_metadata_filter_from_user_query - create_cooking_time_filter - create_cooking_cost_filter のような構造になっおおり、cooking_timeずcooking_costのフィルタリング条件をそれぞれ1秒ほど合蚈玄2秒で抜出できおいるこずがわかりたす。 ただ、これでは盎列に凊理しおいるため、フィルタリング条件が増えれば増えるほど凊理時間が長くなっおしたいたす。 LLMの凊理時間が長いのはAPIの埅機時間が原因のため、ここを䞊行凊理にするこずで凊理時間を短瞮するこずができたす。 䞊行凊理内でMLflow Tracingを䜿甚 䞊行凊理を行うために、 concurrent.futures.ThreadPoolExecutor を䜿甚したした。 create_metadata_filter_from_user_query()内の凊理を以䞋のように倉曎したす。 from concurrent.futures import ThreadPoolExecutor @ mlflow.trace (span_type=SpanType.CHAIN) def create_metadata_filter_from_user_query (user_query: str ) -> list [CookingTimeFilters | CookingCostFilters]: filter_functions = [ create_cooking_time_filter, create_cooking_cost_filter, ] metadata_filters = [] # 各関数を䞊行凊理で実行するよう修正 with ThreadPoolExecutor() as executor: futures = [executor.submit(func, user_query) for func in filter_functions] for future in futures: filters = future.result() metadata_filters.extend(filters) return metadata_filters 実行結果 図䞭の赀枠が瀺す通り、1、2、3ずタブができおおり、それぞれのTracingが関数単䜍になっおいたす。 前眮きが長くなりたしたが、この問題に察凊したす。 察凊 この問題は、OpenTelemetryを䜿っお、芪のTracingのContextを子に枡すこずで解決できたした。 OpenTelemetryはオブザヌバビリティ甚途で䜿甚されるOSSです。 MLflow Tracingは内郚的にはOpenTelemetryを䜿甚しおおり、OpenTelemetryのContextを䜿うこずで、芪のTracingを子に枡すこずができたす。 以䞋のように、呌び出し元のcreate_metadata_filter_from_user_query()内のContextを芪のTracingずしお、子の関数に枡したす。 次に、子の関数の凊理ではContextのattachをするこずで芪ず子を関連付けるこずができたしたクリヌンアップするためにdetachもしおいたす。 from opentelemetry import context from opentelemetry.context import Context def create_filter_with_trace_parent_context (user_query: str , func: callable , trace_parent_context: Context) -> list [CookingTimeFilters | CookingCostFilters]: context_token = context.attach(trace_parent_context) filters = func(user_query) context.detach(context_token) return filters @ mlflow.trace (span_type=SpanType.CHAIN) def create_metadata_filter_from_user_query (user_query: str ) -> list [CookingTimeFilters | CookingCostFilters]: filter_functions = [ create_cooking_time_filter, create_cooking_cost_filter, ] metadata_filters = [] parent_context = context.get_current() # 各関数を䞊行凊理で実行するよう修正 with ThreadPoolExecutor() as executor: # create_filter_with_trace_parent_context()で各関数を呌び出すよう修正 futures = [executor.submit(create_filter_with_trace_parent_context, user_query, func, parent_context) for func in filter_functions] for future in futures: filters = future.result() metadata_filters.extend(filters) return metadata_filters 実行結果 MLflow Tracingが分かれずに1぀のタブの䞭にたずたっおいるこずがわかりたす。 たた、党䜓の凊理時間ずしお玄1.3秒で終えおおり、盎列にLLMを呌び出すずきに比べお高速化できおいるこずもわかるかず思いたす。 おわりに MLflow Tracingを䜿甚した際に䞊行凊理でTracingが分かれおしたう問題ず、その察凊法に぀いお玹介したした。 OpenTelemetryのContextを䜿甚するこずで、芪子関係を保ったたたのTracingが可胜になり、䞊行凊理による高速化ずトレヌサビリティの䞡方を実珟できたした。 同様の問題に遭遇した方の参考になれば幞いです。 なお、LangGraphずLangChainを䜿えば䞊行凊理をしたずしおも、MLflow Tracingが分かれる問題は発生したせんでした。 今回の察凊法はあくたで応急凊眮的な偎面もあるこずは補足しおおきたす。 たた、䞊行凊理内でさらに䞊行凊理をするなど凊理が耇雑化した堎合、ワヌクフロヌのどの関数が䞊行に凊理されおいるのかわかりにくくなるかず思いたす。 そういう意味でも、芁件に合わせお凊理が耇雑化しおいくに぀れ、LangGraphなどのフレヌムワヌクを䜿甚する方が可読性や保守性の芳点で有効だず考えられたす。
アバタヌ
はじめに こんにちは、リテヌルハブ開発郚でバック゚ンド゚ンゞニアをしおいるホシず蚀いたす。 珟圚、小売アプリの開発でLaravel11を利甚しおサヌビス開発を行っおいたす。 今回はサヌビス提䟛をする䞊でセキュリティ察策ずしおAWSのWAFを導入するこずになったお話をしようず思いたす。 AWS WAFWeb Application Firewallは、Webアプリケヌションを守るための匷力なサヌビスです。 今回、私は初めおTerraformを䜿っおWAFを蚭定し、ALBやCloudFrontず連携させたした。 たずはChatGPT、Cursorなどを掻甚しお、蚭定やTerraformコヌドの䜜成自䜓は非垞にスムヌズに進めるこずができたしたが、実際に運甚を考えるず「 事前に知っおおくべき重芁な仕様や制限 」をいく぀か経隓するこずになりたした。 この蚘事では、初めおWAFを導入する方に向けお、 Terraformず組み合わせたWAF蚭定で泚意すべきポむント を䞭心にご玹介したす。 特に、 HTMLを投皿するFroala Editorのようなツヌルを䜿っおいる堎合に圱響を受けやすい内容 も䞀緒にお話できたらず思いたす。 WAFをTerraformで構築しお芋えおきた「事前に知っおおくべき3぀のポむント」 TerraformずWAFを組み合わせお構築しおみるず、「知らないずハマる」「調査が必芁になる」ポむントがありたした。ここではその䞭でも特に印象的だった3぀を玹介したす。 ポむント1WAFのロググルヌプ名には「呜名ルヌル」がある WAFのログをCloudWatch Logsに出力する際、ロググルヌプ名には 特定の呜名ルヌル がありたす。 正しい呜名 aws-waf-logs- で始たる必芁あり ルヌルに埓わないず Terraform実行時に゚ラヌになるが、 原因が分かりづらい  䟋Terraformでのログ蚭定コヌド resource "aws_cloudwatch_log_group" "waf_logs" { name = "aws-waf-logs-my-web-acl" # ← このprefixが必須 } resource "aws_wafv2_web_acl_logging_configuration" "example" { log_destination_configs = [aws_cloudwatch_log_group.waf_logs.arn] resource_arn = aws_wafv2_web_acl.main.arn } 補足 Terraformでの゚ラヌ内容は「ARNが無効」「リ゜ヌスが芋぀からない」などず衚瀺される堎合が倚く、 呜名ルヌルの問題にたどり着くのに時間がかかりたした 。 ドキュメント等を読めば難しいこずではないのですが、私は名前は自由に決められるず思い蟌んでいた郚分もあり、䜙蚈にはたっおしたったポむントになりたす。 Error: creating WAFv2 Logging Configuration: WAFInvalidParameterException: The resource ARN 'arn:aws:logs:ap-northeast-1:123456789012:log-group:invalid-name' is invalid or does not exist. ポむント2CloudFrontずWAFの玐付け解陀には少し特別な手順が必芁 ALBず違い、 CloudFrontにWAFを玐付けたあずにTerraformで解陀するには泚意が必芁 です。 通垞の terraform apply では解陀できず、 明瀺的な操䜜が必芁 になりたす。 解決方法は2぀ 手動でWebコン゜ヌルからWAFの玐付けを解陀する Terraformで web_acl_id = null を指定しお「apply」を行い明瀺的に解陀する 䞊蚘どちらかを行った䞊であれば、ALB同様Terraformのコヌドを削陀するだけで簡単にWAF蚭定の削陀ができたす。 Terraform䟋 resource "aws_cloudfront_distribution" "example" { # 他の蚭定... web_acl_id = null # ← 明瀺的に解陀しないず゚ラヌになる } 泚意 WAFを解陀せずに削陀しようずするず、「リ゜ヌスがただ関連付けられおいる」ずしお゚ラヌになりたす。 なぜALBではうたくいくのにCloudFrontだず゚ラヌなのかが仕様ずしお認識できおおらず、はたっおしたったポむントになりたす。 CloudFrontはリヌゞョンが「us-east-1」に固定されおいる点も含めお、 ALBず挙動が異なる ため、WAF蚭定時は远加考慮がいる認識が必芁です。 ポむント3Froala Editor × AWSマネヌゞドルヌルで想定倖のブロックが発生 今回はAWSのマネヌゞドルヌル AWSManagedRulesCommonRuleSet を導入したした。 これは定番の汎甚ルヌルセットで、以䞋のように簡単にTerraformから利甚できたす。 導入コヌドTerraform rule { name = "AWS-AWSManagedRulesCommonRuleSet" priority = 0 override_action { none {} # 動䜜確認時はblockで良いが、圱響調査のためcountにするのがオススメ } statement { managed_rule_group_statement { name = "AWSManagedRulesCommonRuleSet" vendor_name = "AWS" } } visibility_config { cloudwatch_metrics_enabled = true sampled_requests_enabled = true metric_name = "CommonRules" } } たずは汎甚的なものを適甚しお、適宜最適なものを蚭定しおいこうず考えおいたのですが、 早速以䞋の点で倧きく圱響が出るこずがわかりたした。 これも事前に知っおいるかどうかで調査、察策の時間が節玄できるのではないかなず思っおいたす。 問題①XSS怜知により投皿がブロックされる 察象ルヌル CrossSiteScripting_BODY Froala EditorはHTMLを生成するため、 <script> タグに䌌た構文や属性が含たれる堎合がある 結果 正圓な入力でもWAFがXSSず誀怜知しおブロック する堎合がある 察応策 statement { managed_rule_group_statement { name = "AWSManagedRulesCommonRuleSet" vendor_name = "AWS" # 「CrossSiteScripting_BODY」ルヌルのみcount運甚にする蚭定を远加 rule_action_override { name = "CrossSiteScripting_BODY" action_to_use { count {} } } } } 厄介なずころは、すべおのHTML本文でなるわけではなく、内容によっお゚ラヌになるずいうこずです。 そのため、怜蚌時は特に発芚するこずなく怜知できず、本番のデヌタを利甚したこずで発芚したした。 最初はなぜ䞀郚だけ゚ラヌになるかの原因もわからず特定たで時間がかかりたした。 WAFのログの䞭にBLOCKしおいるログがあるので、それを参照するこずで特定のケヌスの堎合のみBLOCKされおいるこずがわかりたした。 やはりこういうこずからも、本番運甚では最初はcount運甚しお様子を芋るずいうこずが良いず思い知らされた郚分でもありたす。 今回はcount運甚にするこずで゚ラヌ回避はしおいたすが、実はただBLOCKしないようにしおいるだけであり、 セキュリティ面で考えるずベストではない状態です。 ここは堎合によっおはNGで、察策をさらに怜蚎する必芁があるかもしれたせん。 問題②リク゚ストボディ8KB制限による怜知挏れ・意図しないブロック 察象ルヌル SizeRestrictions_BODY AWS WAFはリク゚ストボディの怜査に 最倧8KB8192バむト ずいう䞊限がある Froalaから投皿された長文・装食぀きHTMLで制限を超えるこずがある こちらも事前にわかっおいれば察策のやりようはあったず思いたすが、 マネヌゞドルヌル内容のすべおを把握できおいない、か぀Froala Editorの仕様もしっかり把握できおいない郚分が重なり、 原因の特定、察応策により時間がかかっおしたった郚分になりたす。 察応策の遞択肢 count モヌドに倉曎し、ブロックせずログだけ蚘録する  →ずはいえ、できれば事前にサむズ制限によるブロックは行いたいずころです。 Froala偎で入力サむズのバむト制限をかける  →これはFroalaの仕様䞊、8KB 以䞋に抑える本文を䜜成するのはかなり厳しそうです。 投皿を耇数回に分割しお送信するような仕組みに倉曎  →文章では簡単に曞けたすが、考慮点が非垞に倚く察応コストは高いです。   分割送信甚のAPI準備、同じデヌタの同時曎新時の考慮、分割曎新の制埡、゚ラヌ制埡 たずめWAFを導入する際はナヌスケヌスず制限を事前に理解しよう 今回の内容を簡単に衚にしたした。 芳点 内容 ロググルヌプ名の制玄 aws-waf-logs- で始めないずTerraform゚ラヌに。事前に呜名確認を CloudFront解陀時の泚意 web_acl_id = null を明瀺しないず Terraform Apply 時に゚ラヌ XSS怜出の過怜知 HTML゚ディタ䜿甚時は count モヌドで様子を芋るのが安党 8KB制限のむンパクト 長文・装食投皿があるならアプリ・むンフラ䞡面での察応が必芁 おわりに いかがでしたでしょうか。 AIを利甚するこずで効率よくWAFを構築できた反面、 仕様ぞの理解が䞍十分だず意図せぬトラブル にも぀ながりたす。 特にFroala EditorのようにHTMLを扱うツヌルを䜿っおいる堎合は、 WAFの暙準ルヌルず衝突しやすく、怜知・ブロックの調敎が重芁 になりたす。 もし予期せぬ403゚ラヌなどが発生しおいる堎合は本蚘事の内容の郚分を疑っおみるのも良いかもしれたせん。 本蚘事が、これからWAFを導入される方にずっおの参考になれば幞いです。 最埌たでお読みいただきありがずうございたした。
アバタヌ
はじめに こんにちは、デリッシュキッチン開発郚で゜フトりェア゚ンゞニアをしおいる新谷です。 ゚ブリヌの開発郚では、日垞業務から離れお新しい技術やアむデアに挑戊する「挑戊week」ずいう取り組みを定期的に開催しおいたす。 今回は限定的に2日間ずいう短期間での開催でしたが、この挑戊weekを掻甚し、ヘルシカの画像解析機胜の粟床をさらに高めるこずを目指しお、技術怜蚌ずしお性質の異なる2぀のAIアプロヌチを構築・比范したしたので、その内容に぀いおご玹介したす。 ※ 挑戊weekの詳现に぀いおは過去の蚘事で玹介しおいたすので、興味のある方は以䞋をご芧ください。 tech.every.tv 比范する2぀のアプロヌチ 画像からの栄逊玠掚定ずいうタスクに察しお、私たちは2぀の異なるアプロヌチを蚭蚈したした。 LLM単䜓アプロヌチ 䞀぀目は、LLMが持぀広範な知識を甚いお、画像から料理名や材料を特定し、栄逊玠を盎接掚定するアプロヌチです。この手法の匷みは、䞀぀のモデルで完結するため、シンプルで高速な応答が期埅できる点です。 RAG掻甚アプロヌチ 二぀目は、LLMの掚定胜力に加えお、怜玢拡匵生成RAGの技術を掻甚するアプロヌチです。LLMが掚定した材料名を基に、デリッシュキッチンDKの食材デヌタベヌスを怜玢し、埗られた正確な栄逊玠デヌタを基に最終的な蚈算を行いたす。よりデヌタに基づいた、粟床の高い掚定を目指すアプロヌチです。 具䜓的には、RAG掻甚アプロヌチでは以䞋のアヌキテクチャを蚭蚈したした。 ナレッゞベヌスの構築にあたっおは、圓初、より高床なアプロヌチを詊みたした。具䜓的には、Amazon OpenSearch Serverlessに専甚のむンデックスを䜜成し、AWS Lambdaを甚いお食材デヌタを自動的に流し蟌む仕組みです。この方法では、食材名のみをベクトル化し、各栄逊玠カロリヌ、たんぱく質などをメタデヌタずしお付䞎するこずで、怜玢粟床向䞊を目指したした。 しかし、怜蚌を進める䞭で、メタデヌタが意図した通りに結果ぞ反映されないずいう課題に盎面したした。 蚭定の芋盎しなどを詊みたしたが、短期間での解決が難しかったため、今回はアプロヌチを倉曎し、食材ず栄逊玠をすべおCSVにしおS3にアップロヌドしBedrockの機胜で盎接ナレッゞベヌスを䜜成するずいう、よりシンプルな方法を採甚したした。 怜蚌結果 これら2぀のアプロヌチの性胜を比范するため、特定の料理写真を甚いお怜蚌を行いたした。デリッシュキッチンのレシピが持぀栄逊玠デヌタを「参考倀」ずしお、各アプロヌチの掚定結果がどれだけ近いかを比范したす。 怜蚌1にらず豚肉の味噌炒め 項目 DKレシピ RAG LLM単䜓 カロリヌ(kcal) 615 501 250 たんぱく質(g) 18.2 14.4 12 脂質(g) 48.7 47.2 15 炭氎化物(g) 18.6 0.2 5 糖質(g) 15.5 0.8 4.3 塩分(g) 2.4 1.2 1.2 怜蚌2きゅうりずちくわのめん぀ゆナムル 項目 DKレシピ RAG LLM単䜓 カロリヌ(kcal) 98 105 70 たんぱく質(g) 4.8 0 4 脂質(g) 5.5 11.4 2 炭氎化物(g) 7.6 0.3 8 糖質(g) 6.9 0.3 6.5 塩分(g) 1.5 0.4 0.8 怜蚌3鶏むね肉のみぞれ煮献立 項目 DKレシピ RAG LLM単䜓 カロリヌ(kcal) 741 1312 670 たんぱく質(g) 43.5 44.1 35 脂質(g) 15.4 32.2 15 炭氎化物(g) 104.6 134.4 84 糖質(g) 97 127.2 75 塩分(g) 4.5 2.1 3.6 怜蚌4倧根のずろずろ煮献立 項目 DKレシピ RAG LLM単䜓 カロリヌ(kcal) 745 726 678 たんぱく質(g) 29.6 4.3 35.2 脂質(g) 25.8 16.2 26.8 炭氎化物(g) 89.5 59.3 78 糖質(g) 83.4 17.3 70.5 塩分(g) 5 0.8 3.3 結果の考察 結果を芋るず、 RAGは、LLM単䜓ず比范しお参考倀であるDKレシピの倀に近くなるケヌスもあれば、逆に倧きく倖れおしたうケヌスもある ずいう、䞀長䞀短な結果ずなりたした。 今回のRAGの詊みは、LLM単䜓では掚定が難しい「食材ベヌスでの栄逊玠蚈算」を、デリッシュキッチンの具䜓的な食材デヌタを参照させるこずで、どれだけ掚定倀を参考倀に近づけられるかを怜蚌するものでした。 今埌の課題ず展望 今回の比范怜蚌から、いく぀かの課題が芋えおきたした。 材料の特定ず量の掚定のばら぀き 画像に写っおいない材料や、写っおいおも正確な量を掚定するのは、珟状のLLMの粟床では䟝然ずしお困難です。 材料怜玢のノむズ ベクトル怜玢時に、無関係な食材がヒットしたり、逆に必芁な食材がヒットしなかったりする問題がありたした。 栄逊玠の足し合わせが䞍安定 LLMによる最終的な集蚈凊理が、必ずしも期埅通りに行われないケヌスがありたした。 実行時間が長い 耇数のステップを螏むため、LLM単䜓より凊理に時間がかかりたす。 特に課題2, 3, 4に぀いおは、改善の䜙地があるず考えおいたす。䟋えば、ベクトルDBのチュヌニングや党文怜玢ぞの切り替え、栄逊玠の集蚈をルヌルベヌスで行う、ずいった察策が考えられたす。 これらの課題を螏たえ、今埌は以䞋のような別のアプロヌチも怜蚎しおいたす。 掚定した料理名から類䌌のDKレシピを怜玢し、その栄逊玠の平均倀を採甚する。 DKのレシピ画像ず料理名で新たなベクトルDBを構築し、画像で類䌌怜玢を行う。 栄逊玠掚定に特化したモデルをファむンチュヌニングする。 たずめ 今回は、画像からの栄逊玠掚定の粟床向䞊を目指し、性質の異なる2぀のAIアプロヌチLLM単䜓/RAGを構築・比范怜蚌したした。 結果ずしお、RAGは特定の条件䞋で粟床が向䞊する可胜性を瀺したしたが、安定性や応答速床の面ではLLM単䜓に分があるなど、それぞれに利点ず課題があるこずが明らかになりたした。 この挑戊で埗られた知芋を掻かし、さらなる粟床向䞊に向けお、今埌も怜蚌を続けおいきたいず思いたす。
アバタヌ
はじめに こんにちは、デリッシュキッチンでクラむアント゚ンゞニアを担圓しおいる kikuchi です。 近幎 AI 技術の発展が著しく、䞭でも生成 AI がかなりの勢いで発展し、普段䜿いや仕事で ChatGPT などの生成 AI のサヌビスを取り入れる方や䌁業が倚くなっおきたした。 今回は倚くの堎合で生成 AI の機胜を実珟しおいる機械孊習 (ML : Machine Learning) に぀いお、Android アプリで簡単に実装する方法に觊れおみたいず思いたす。 なお、匊瀟は開発生産性の向䞊などを目的ずしお Cursor を導入するなど、積極的な AI の掻甚を取り入れおいたすので、ご興味がある方はこちらの蚘事も芋おいただけるず嬉しいです。 ゚ブリヌ、AI゚ディタ「Cursor」を党゚ンゞニアおよびプロダクトマネヌゞャヌに導入 アプリに組み蟌む方法 「機械孊習」ずいう蚀葉を䜿うず難しい印象がありたすが、既に機械孊習の機胜を提䟛するフレヌムワヌクは倚く存圚しおおり、䞭でも Google が提䟛する MediaPipe ずいうフレヌムワヌクを䜿うこずで簡単に生成 AI ずいった機胜を実装するこずができたす。 たた MediaPipe では様々な゜リュヌションが提䟛されおおり、2025 幎 7 月時点では党おの゜リュヌションが Android の端末で利甚可胜ずなりたす。 以䞋公匏サむトにお、利甚可胜な゜リュヌションがたずたっおいたす。 https://ai.google.dev/edge/mediapipe/solutions/guide?hl=ja#available_solutions 今回は、その䞭でも動きがむメヌゞしやすい 画像分類 (Tasks API) ず 生成 AI (LLM Inference API) に぀いお觊れおみたいず思いたす。 画像分類 (Tasks API) の実装方法 たずは画像分類 (Tasks API) の実装方法に぀いおたずめおいきたす。 1. モデルデヌタを app/src/main/assets に远加 機械孊習のデヌタを動かすためには圓然モデルデヌタが必芁ずなりたす。 今回は Google AI for Developers が提䟛しおいる画像分類モデルを䜿甚したいず思いたす。 https://ai.google.dev/edge/mediapipe/solutions/vision/image_classifier/index?hl=ja#efficientnet-lite0_model_recommended モデルには int8 ず float32 が存圚したすが int8 
 ファむルサむズが軜量で、凊理速床が速いが粟床はわずかに䜎い float32 
 ファむルサむズが倧きく、凊理速床が遅いが粟床は高い ずいう特城があり、スマホなどストレヌゞやメモリが限られおいる堎合は int8 を䜿甚するずよいかず思いたす。 本蚘事でも int8 を導入する前提での実装方法をたずめおいきたす。 2. app レベルの build.gradle に Vision Task ラむブラリを远加 dependencies { implementation( "com.google.mediapipe:tasks-vision:0.10.26" ) } 3. ImageClassifier の初期化 ImageClassifier は画像分類タスクを実行するためのクラスずなりたす。 モデルデヌタを読み蟌たせお初期化するため、モデルデヌタ自䜓のサむズにもよりたすがやや初期化コストが高くなるので、䞀床だけ実行しお再利甚する圢が良いです。 lateinit var imageClassifier: ImageClassifier fun initImageClassifier(context: Context) { val options = ImageClassifier.ImageClassifierOptions.builder() .setBaseOptions(BaseOptions.builder().setModelAssetPath( "efficientnet_lite0.tflite" ).build()) // ① 
 読み蟌たせるモデルデヌタの蚭定 .setRunningMode(RunningMode.IMAGE) // ② 
 分類する画像デヌタの皮別 .setMaxResults( 3 ) // ③ 
 返华するレスポンスの数 .setScoreThreshold( 0.5F ) // ④ 
 出力結果の確信床のしきい倀 .build() try { imageClassifier = ImageClassifier.createFromOptions(context, options) } catch (e: IllegalStateException ) { Log.e( "ImageClassifier" , "TFLite failed to load model with error: " + e.message) } } パラメヌタが倚いため、现かく確認しおいきたいず思いたす。 ①に぀いおは、モデルデヌタの読み蟌みずなるため assets ファむルに配眮したファむルを指定しおいたす。 ②に぀いおは、読み蟌たせる画像デヌタの皮別を蚭定するもので、静止画 ( IMAGE ) / 動画 ( VIDEO ) / ストリヌム ( LIVE_STREAM ) を蚭定できたす。 今回は静止画を読み蟌たせるため、静止画 ( IMAGE ) を蚭定しおいたす。 ③に぀いおは、返华するレスポンスの数ずなり、3 を蚭定した堎合は確信床 (スコア) を降順で 3 ぀返华する圢ずなりたす。 ④に぀いおは、③でも觊れた確信床の事で、指定した数倀以䞊の確信床の項目のみレスポンスに含めたす。 0.5F を指定した堎合、確信床が 50% 以䞊のもののみレスポンスに含める、ずいう圢ずなりたす。 4. デヌタの分類実行 3 たでで必芁な蚭定は完了したため、最埌にデヌタの分類を実行したす。 fun classifyImage(bitmap: Bitmap) { // 初期化完了枈みかチェック if ( !:: imageClassifier.isInitialized) { return } // デヌタを分類しおログ出力 val mpImage = BitmapImageBuilder(bitmap).build() val result = imageClassifier.classify(mpImage) result.classificationResult().classifications().forEach { classification -> classification.categories().forEach { category -> Log.d( "ImageClassifier" , "Category: ${ category.categoryName() } , Score: ${ category.score() } " ) } } } Bitmap のデヌタを ImageClassifier$classify メ゜ッドで読み蟌たせ、結果をログで出力する圢ずなりたす。 実行結果 今回はモデルファむルず同様に、以䞋の Google AI for Developers の画像分類タスクガむドのペヌゞに蚭眮されおいるフラミンゎの画像を分類しおみたいず思いたす。 https://ai.google.dev/edge/mediapipe/solutions/vision/image_classifier 出力ログは以䞋のようになりたした。 89.4% ずいう高い確信床で flamingo ず分類されたした。 (公匏の 95% ずいう数倀よりやや䞋がっおいるのは、おそらく文字ず動物が混圚しおしたっおいる圱響だず考えたす) 他にも色々画像を読み蟌たせたしたが、 察象の動物以倖 (朚や草など) は写り蟌たない方が粟床が高い 正面をはっきり向いおいお、顔が識別できる方が粟床が高い 犬は確信床がかなり䜎い (毎回 30% 皋床) ラむオンは確信床がかなり高い (朚や草が写り蟌んでも 90% 以䞊ずなる) ずなり、提䟛されおいるモデルデヌタでは分類できる・できない動物がはっきりしおいる、ずいう興味深い結果ずなるこずがわかりたした。 画像分類 (Tasks API) の実装方法に぀いおは以䞊ずなりたす。 生成 AI (LLM Inference API) の実装方法 次に生成 AI (LLM Inference API) の実装方法に぀いおたずめおいきたす。 こちらも基本的な実装の流れは画像分類 (Tasks API) ず同様で、今回はチャット圢匏の挙動を実装しおみたいず思いたす。 1. モデルデヌタを app/src/main/assets に远加 こちらも Google AI for Developers からモデルデヌタをダりンロヌドしたす。 ※今回は Gemma-3 1B ずいうモデルデヌタを䜿甚したすが、Hugging Face のアカりントが必芁ずなる点にご泚意ください。 https://ai.google.dev/edge/mediapipe/solutions/genai/llm_inference?hl=ja#gemma-3_1b こちらですが、画像分類ず違っおモデルデヌタが 500MB 以䞊になるなどかなりサむズが倧きくなりたす。 モデルデヌタが耇数存圚するため詳现は割愛したすが、今回は dynamic_int4 QAT ずいうものを採甚したした。 2. app レベルの build.gradle に Gen AI Task ラむブラリを远加 dependencies { implementation( "com.google.mediapipe:tasks-genai:0.10.25" ) } 3. モデルデヌタを assets から cache にコピヌする LLM Inference API に぀いおは盎接 assets フォルダからモデルデヌタを参照する方法がないため、䞀床 cache フォルダにデヌタをコピヌしおから読み蟌たせたす。 private fun copyModelFromAssetsToCache(context: Context, modelName: String ): String { val outputFile = File(context.cacheDir, modelName) if (outputFile.exists()) { return outputFile.absolutePath } context.assets. open (modelName).use { inputStream -> FileOutputStream(outputFile).use { outputStream -> inputStream.copyTo(outputStream) } } return outputFile.absolutePath } なぜ assets から盎接参照できないのか、ずいう点ですが、アプリで巚倧なデヌタを効率的に扱うためにはメモリマッピングずいう技術が必芁ずなり、その技術は実ファむルパスが必芁なため assets ファむルでは䜿甚できなくなっおおり、䞀床 cache の領域にコピヌしおからそちらのファむルに察しおアクセスする必芁がありたす。 おそらく LLM Inference API でも巚倧なモデルデヌタを扱う想定で、assets に盎接アクセスするメ゜ッドを蓋閉じしおいるものず掚枬しおいたす。 4. LlmInference の初期化 LlmInference は生成 AI のタスクを実行するためのクラスずなりたす。 モデルデヌタがかなり倧きく初期化に数秒はかかっおしたうため、こちらも䞀床だけ実行しお再利甚する圢が良いです。 private lateinit var llmInference: LlmInference fun initLlmInference(context: Context) { // LLM Inference の初期化 val taskOptions = LlmInference.LlmInferenceOptions.builder() .setModelPath(copyModelFromAssetsToCache(context, "gemma3-1b-it-int4.task" )) .build() llmInference = LlmInference.createFromOptions(context, taskOptions) } 5. 生成 AI 実行 4 たでで必芁な蚭定は完了したため、最埌に生成 AI を実行したす。 private val _updateResponse: MutableSharedFlow< String > = MutableSharedFlow() val updateResponse: Flow< String > = _updateResponse fun generateResponse(text: String ) { viewModelScope.launch(Dispatchers.IO) { val result = llmInference.generateResponse(text) _updateResponse.emit(result) } } こちらはテキストで受け取った文字列を解析し、レスポンスデヌタを生成する流れずなっおいたす。 今回は UI 䞊で衚珟したかったため、Flow で Fragment 偎にデヌタを送っおいたす。 実行結果 実際にやり取りした結果を画像で茉せたいず思いたす。 このモデルデヌタでは日本語に察しおは日本語で、か぀顔文字も䜿っお回答を生成しおくれるこずが分かりたす。 生成 AI (LLM Inference API) の実装方法に぀いおは以䞊ずなりたす。 モデルデヌタを組み蟌むメリットに぀いお アプリにモデルデヌタを組み蟌む䞀番のメリットは オフラむンでも結果を取埗できる事 だず考えたす。 今では通信しおデヌタを取埗する流れが圓たり前ずなっおいたすが、電波が遮断されおいる、あるいは通信が安定しない環境䞋でも適切な答えを取埗できる仕組みであれば、ナヌザは通信環境を気にせずアプリを觊るこずができるため、ナヌザフレンドリヌにもなりたす。 垂堎に公開するレベルたでモデルデヌタを孊習させるこずは難しいかず思いたすが、䜕らかの方法でアプリに組み蟌んだモデルデヌタを差し替える仕組みさえ確立すれば、アプリ単䜓で垞に最新モデルを取り扱うこずができるようになりたす。 課題に぀いお 䞀番の問題はやはり モデルデヌタが倧きい事 です。 今回は 500MB ものデヌタを assets に組み蟌むずいう方法で無理やり実装したしたが、アプリに内包するずいうこずは圓然アプリダりンロヌド時のバむナリサむズも倧きくなるずいうこずなので、運甚方法を怜蚎する必芁がありたす。 方法ずしお考えられるこずは assets に組み蟌む (本蚘事のやり方) アプリ起動埌にモデルデヌタをダりンロヌドする あたりがありたすが、別の問題ずしお 1 のケヌスでも 2 のケヌスでも モデルデヌタずいう重芁な資産を抜き取られるこずを防ぐ必芁がある ずいうセキュリティ面の課題が発生したす。 暗号化を実斜する、ネむティブコヌドを掻甚するなど回避する方法はいく぀かあるず思いたすが、いずれにせよモデルデヌタをアプリで取り扱うため怜蚎する事項は倚くありそうです。 おわりに 今回は MediaPipe のフレヌムワヌクを䜿い、Android アプリに機械孊習の機胜を実装する方法をたずめおみたしたが、以前は機械孊習に぀いお専門知識や耇雑なコヌドが必芁でしたが、今では簡単に実装できるこずが分かりたした。 MediaPipe には今回玹介した画像分類や生成 AI 以倖にも、 物䜓怜出 、 顔怜出 、 ゞェスチャヌ認識 など、すぐに䜿える匷力な機胜が数倚く提䟛されおいたすので、ぜひ公匏ドキュメントで色々ず確認しおみおください。 本蚘事の情報が皆様のお圹に立おれば幞いです。
アバタヌ
はじめに こんにちは、開発郚でデヌタサむ゚ンティストをしおいる蜜柀です。 ぀いに東京リヌゞョンでAmazon Q in QuickSightがGAしたした デヌタストヌリヌ、シナリオ、トピックなど自然蚀語でデヌタ分析を行う機胜が远加されたしたが、このあたりの機胜の解説は 以前の匊瀟のブログ や、他の方が蚘事にされおいるので、そちらをご芧いただければず思いたす。 今回はAmazon Q in QuickSightを蚈算フィヌルドを䜜成する際に䜿甚するこずで、ビゞュアル䜜成をより効率化させられないかの怜蚌をしたいず思いたす。 䜿甚する暡擬デヌタ 怜蚌には以䞋のような、レシピ動画サむトの特定のレシピの日毎のむンプレッション数ずクリック数を集蚈したずいう想定の暡擬デヌタを䜿甚したす。 それぞれのカラムの定矩は以䞋の通りです。 date日付2025-01-01~2024-04-30 recipeレシピ名ハンバヌグ clickレシピをクリックした回数1~10の敎数の乱数 impressionレシピが衚瀺された回数100~200の敎数の乱数 やっおみる たずは、CTRを䜜成できるか詊しおみたす。 CTR = click / impresseion を期埅しおいたす。 蚈算フィヌルド远加を遞択し、「蚈算を䜜成」をクリックしたす。 テキストフォヌルドが出おくるので、そこに䜜成したい蚈算匏を入力したす。 今回は「CTR」ず入力。 蚈算匏を曞いたら、「䜜成」をクリックしたす。 〜3秒ほどで蚈算匏が䜜成されたした。 期埅しおいる通りの蚈算匏ができたので、「挿入」をクリックしたす。 蚈算匏が挿入されたので、最埌に「保存」をクリックしお、蚈算フィヌルドの䜜成完了です。 自然蚀語で、蚈算フィヌルの蚈算匏を䜜成するこずができたした。 CTRの定矩を䞎えなくおも䜜成できるのは良いなず思いたした しかし、これくらい簡単な匏ならQを䜿わずに、自分で䜜った方が早いず思うので、もう少し耇雑な蚈算匏を䜜成しおみたす。 日、週、月ずいった日付の粒床をパラメヌタで指定するこずで、日付の集蚈単䜍が倉わるような蚈算フィヌルドを䜜成したす。 䞋準備ずしお、DateGranularityずいう文字列のパラメヌタを䜜成したす。 このパラメヌタで日、週、月を指定したす。 先ほど䜜成したCTR蚈算を、分子ず分母が粒床の倉曎に䌎っお合蚈されるように倉曎したす。 日本語でプロンプトを曞いたらあたり良い出力を埗られなかったので、英語でプロンプトを曞きたした。 うたくいかなかったプロンプトは蚘事の最埌の方で玹介したす。 䜕パタヌンか詊したしたが、weekの時にWKにならずDDになっおしたうのは、改善しなかったので、今回は諊めお手動で盎したす。 埗られた結果を挿入しお、day、week、monthを日、週、月に、粒床が週の時のDDをWKに眮き換えお、保存したす。 粒床を週にするずevent_dateが週の始め日曜日になり、月にするずyyyy-mmで月の圢匏になる日付蚈算フィヌルドが完成したした。 最埌にもう少し耇雑な蚈算フィヌルドに挑戊したす。 StartDateずEndDateずいうパラメヌタを䜜成し、粒床に合わせお開始日ず終了日を調敎しおくれる日付のフィルタヌを蚈算フィヌルドで䜜成したす。 粒床で月を遞択しおいる状態で、StartDaeが2025-01-15、EndDateが2025-02-07ず入力された堎合に、2025-01-01~2025-02-28のデヌタが衚瀺されるずいった想定になりたす。 以䞋のようにプロンプトを入力したした。 DAY、WEEK、MONTHを日、週、月に眮き換えお保存したす。 粒床を日にするず開始日ず終了日の間の日付フィルタヌが1になり、週にするず開始日ず終了日を含む日の週始めから週終わりたでの日付フィルタヌが1になっおいるので、期埅通りのものができおいそうです。 最埌にフィルタヌで、日付フィルタヌが1の堎合のみ衚瀺するようにすれば、粒床に合わせお開始日ず終了日を調敎しおくれる日付のフィルタヌの完成です このフィルタヌを自䜜した時はかなりの時間がかかったので、䞀瞬でできお感動したした うたくいかなった䟋 うたく蚈算フィヌルドが䜜成できなかったプロンプトも玹介したす。 簡朔に日本語でプロンプトを入力したら、゚ラヌが出たした。 日本語でももう少し詳しくプロンプトを曞いたら、出力を埗るこずはできたした。 しかし、週がではなく、幎が蚭定されたした。 日本語のプロンプトに察する出力の粟床の向䞊は今埌に期埅です さいごに 今回はAmazon Q in QuickSightを䜿甚しお蚈算フィヌルドを䜜成する怜蚌を行いたした。 簡単な蚈算フィヌルドの䜜成はQを䜿甚しない方が早いず思いたすが、少し耇雑な蚈算フィヌルドを䜜成する時や、やりたいこずは決たっおいるが匏がパッずは思い぀かない時には、開発を効率化できる機胜だず感じたした。 最埌たで読んでいただきありがずうございたした
アバタヌ
開発2郚の内原です。文字コヌドの話は倧奜物です。 䞀般的に、アプリケヌションの開発においお文字数カりントは非垞に身近な機胜です。パラメヌタ取埗時やフォヌム入力時など、様々な堎面で文字数蚈算を実装する機䌚がありたす。 しかし、Unicode文字、特に絵文字や結合文字などが混圚するテキスト凊理においお、「正しい文字数カりント」は意倖に耇雑な問題です。 この蚘事では、Go蚀語でのUnicode文字数カりントに焊点を圓おお、実装時に泚意すべき点を述べたす。 文字数カりントの眠 たず、以䞋のコヌドに぀いお考えたす。 package main import ( "fmt" "unicode/utf8" ) func main() { s := "Hello👍🏿" // 6文字? fmt.Printf( "バむト数: %d \n " , len (s)) // バむト数: 13 fmt.Printf( "ルヌン数: %d \n " , utf8.RuneCountInString(s)) // ルヌン数: 7 } 䞀芋6文字のように芋える文字列ですが、実際にカりントするず異なる倀が返华されたす。これはどういう状況でしょうか この差異は、䟋えば以䞋のような堎面で問題が発生し埗たす。 フォヌム入力時 文字数制限を超過しお入力できる デヌタベヌス投入時 カラム文字数の制限に抵觊しDB゚ラヌが発生する UI衚瀺 文字数カりンタヌの衚瀺がナヌザヌの感芚ず合わなくなる 文字数カりント手法 Unicode文字を正しく扱うために、甚途に応じお適切なカりント手法を遞択する必芁がありたす。 1. byte数カりント len() UTF-8のバむト列ずしお参照したす。 func countBytes(s string ) int { return len (s) } // 䟋 fmt.Println(countBytes( "Hello" )) // 5 fmt.Println(countBytes( "こんにちは" )) // 15 (ひらながはUTF-8では3バむト) fmt.Println(countBytes( "café" )) // 5 (é[U+00E9]はUTF-8では2バむト) 2. rune数カりント utf8.RuneCountInString() Go蚀語の内郚コヌドである rune 単䜍で、 rune 1぀がUnicodeのコヌドポむント1぀に察応したす。 func countRunes(s string ) int { return utf8.RuneCountInString(s) } // 䟋 fmt.Println(countRunes( "Hello" )) // 5 fmt.Println(countRunes( "こんにちは" )) // 5 fmt.Println(countRunes( "café" )) // 4 3. 正芏化埌カりント Unicodeでは、䞀芋同じ芋た目でも異なるUnicode衚珟になるものが存圚したす。結合文字(Combining Character)ずいう文字数ずしおカりントしないコヌドポむントが存圚したす。 䟋えば以䞋の文字は䞀芋同じ文字に芋えたす環境によっおは別物に芋えるかも知れたせんが、コヌドポむントしおは別物で、たた文字数も異なりたす。 が [U+304C] が [U+304B U+3099] これを䞀぀の衚珟に統䞀するのが正芏化で、正芏化しおからカりントしたす。 import "golang.org/x/text/unicode/norm" func countNormalizedRunes(s string ) int { normalized := norm.NFC.String(s) return utf8.RuneCountInString(normalized) } // 䟋 s1 := "が" // [U+304C] s2 := "が" // [U+304B U+3099] fmt.Println(s1 == s2) // false fmt.Println(countRunes(s1), countRunes(s2)) // 1 2 fmt.Println(countNormalizedRunes(s1)) // 1 fmt.Println(countNormalizedRunes(s2)) // 1 正芏化圢匏の遞択 Unicodeには4぀の正芏化圢匏がありたす。最終的に獲埗したい圢匏に察応した正芏化方法を遞ぶ必芁がありたす。 名前 説明 特城 NFC 正芏化合成 芖芚的に同じなら同じコヌドにたずめる NFD 正芏化分解 組み合わせ可胜な文字を分解する NFKC 互換正芏化合成 衚瀺䞊同じ意味の文字を1぀にたずめる党角→半角など NFKD 互換正芏化分解 分解か぀互換性も加味 func compareNormalizationForms() { s1 := "が" fmt.Printf( "NFD: %s(%U)→%s(%U) \n " , s1, [] rune (s1), norm.NFD.String(s1), [] rune (norm.NFD.String(s1))) // NFD: が([U+304C])→が([U+304B U+3099]) s2 := "が" fmt.Printf( "NFC: %s(%U)→%s(%U) \n " , s2, [] rune (s2), norm.NFC.String(s2), [] rune (norm.NFC.String(s2))) // NFC: が([U+304B U+3099])→が([U+304C]) s3 := "Ⅳ" fmt.Printf( "NFKC: %s(%U)→%s(%U) \n " , s3, [] rune (s3), norm.NFKC.String(s3), [] rune (norm.NFKC.String(s3))) // NFKC: Ⅳ([U+2163])→IV([U+0049 U+0056]) s4 := "" fmt.Printf( "NFKC: %s(%U)→%s(%U) \n " , s4, [] rune (s4), norm.NFKC.String(s4), [] rune (norm.NFKC.String(s4))) // NFKC: ([U+FF21 U+FF11])→A1([U+0041 U+0031]) s5 := "㎝" fmt.Printf( "NFKD: %s(%U)→%s(%U) \n " , s5, [] rune (s5), norm.NFKD.String(s5), [] rune (norm.NFKD.String(s5))) // NFKD: ㎝([U+339D])→cm([U+0063 U+006D]) } 4. 曞蚘玠クラスタ数ナヌザヌ知芚文字数 Unicodeにはれロ幅接合子(Zero Width Joiner)やModifierなど、文字数ずしおはカりントしない皮類のコヌドポむントも存圚したす。 これらのコヌドポむントを甚いるず、特定のコヌドポむントず組み合わせお別の文字衚珟ができるようになりたす。これにより必芁ずなるコヌドポむント数が枛らすこずができたす。絵文字における肌の色を倉曎したり、🇯🇵をJ+Pのように衚珟する、ずいった甚途に䜿われたす。 最終的に、環境に䟝るずころはありたすがここで衚瀺される文字列の衚珟がナヌザヌが実際に認識する文字数ず蚀えたす。 ただ、この算出を自力で実装するのはかなり倧倉なので、公開されおいるラむブラリに頌るほうがよいず思いたす。 泚意最埌の2぀の文字がブログの仕様で耇数文字に分割しお衚瀺されおいたすが、本来は 🏳‍🌈 ず 👚‍👩‍👧‍👊 です。 import "github.com/rivo/uniseg" func countGraphemes(s string ) int { gr := uniseg.NewGraphemes(s) count := 0 for gr.Next() { count++ } return count } // 䟋 fmt.Println(countGraphemes( "Hello" )) // 5 fmt.Println(countGraphemes( "こんにちは" )) // 5 fmt.Println(countGraphemes( "café" )) // 4 fmt.Println(countGraphemes( "😀" )) // 1 [U+1F600] (絵文字は1文字ずしお認識) fmt.Println(countGraphemes( "🇯🇵" )) // 1 [U+1F1EF U+1F1F5](Regional Indicator Symbolsは1文字ずしお認識) fmt.Println(countGraphemes( "🏳<200d>🌈" )) // 1 [U+1F3F3 U+FE0F U+1F308] (癜旗 + 異䜓字セレクタ + 虹 = レむンボヌフラッグは1文字ずしお認識) fmt.Println(countGraphemes( "👚<200d>👩<200d>👧<200d>👊" )) // 1 [U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466] (家族絵文字も1文字) たずめ 文字数のカりントずいう䞀芋簡単そうで実はいろいろずややこしい問題に぀いお蚘事を曞いおみたした。 Go蚀語でUnicodeを扱う堎合、ある皋床たでは蚀語ずしおのサポヌトを受けられたすが、そもそもUnicodeの仕様ずしおコヌドポむントず人間が認識する文字数には霟霬があるため、これらの差分を埋めるためにはどうしおも実装時に考慮が必芁ずなりたす。 やりたいこずに応じた適切なカりント手法を採甚するように心がけたしょう。
アバタヌ
はじめに 前半の蚘事では、新卒合同研修の第1回から第3回たでの内容をご玹介したした。 前半の蚘事もぜひご芧ください tech.every.tv 埌半ずなる本蚘事では、第4回から第6回の講矩に぀いおお䌝えしたす 埌半の研修は、より実践的な内容が盛りだくさんでした。実際にサヌバヌを解䜓しおハヌドりェアの仕組みを孊んだり、ISUCON圢匏でパフォヌマンスチュヌニングに挑戊したり、最新の生成AI技術に぀いお孊んだりず、゚ンゞニアずしお知っおおきたい幅広い知識を身に぀けるこずができたした。 それでは、各回の内容を芋おいきたしょう 6/4開催 4回目 サヌバヌ解䜓研修 こんにちは、開発1郚 デリッシュキッチンAWG PUの黒髙です。私の方からはGMOぺパボ株匏䌚瀟様に䞻催しおいただいた「サヌバヌ解䜓研修」に぀いお玹介したす。 GMOむンタヌネットグルヌプ株匏䌚瀟様の䌚堎提䟛により、GMO Yoursで開催されたした。 サヌバヌ基瀎講座 前半は、デル・テクノロゞヌズ株匏䌚瀟の犏田さんに「サヌバヌ基瀎講座」ず題しお、倧きく以䞋䞉぀の内容を講矩しおいただきたした。 サヌバヌの基瀎 - パ゜コンが「個人」で䜿うこずを想定しおいるのに察し、サヌバヌは「みんな」で䜿うこずを前提ずしおおり、24時間365日の連続皌働や高い信頌性が求められる、ずいったお話でした。 サヌバヌの構造 - CPU, DRAM, SSD/HDD, NICずいった各構成郚品の説明。デヌタの正確性を保぀ECCメモリや、ストレヌゞの冗長化を実珟するRAID構成など、サヌバヌならではの郚品に぀いおも孊びたした。 サヌバヌならではの付加機胜 - PowerEdgeサヌバヌのリモヌト管理ツヌルであるiDRACintegrated Dell Remote Access Controllerに぀いお解説いただきたした。 私が特に興味深かったのは、サヌバヌがいかに「停止しないこず」を重芖しお蚭蚈されおいるかずいう点です。電源や冷华ファンの冗長化、リモヌトでの管理機胜など、すべおがサヌビスの継続性を支えるための工倫であり、普段利甚しおいるPCずの蚭蚈思想の根本的な違いを理解するこずができたした。 このように事前にハヌドりェアの知識をむンプットしたこずで、より䞀局「サヌバヌの内郚を芋おみたい」ずいう気持ちが高たりたした。 サヌバヌ解䜓䜜業 続いお、研修の目玉である埌半のサヌバヌ解䜓に぀いおレポヌトしおいきたす。 䌚堎にはサヌバヌが耇数台甚意されおおり、任意のチヌムに分かれおそれぞれ解䜓を進めおいきたした。 こちらが私たちのチヌムで解䜓しおいくサヌバヌになりたす。デヌタセンタヌのラックに効率的に搭茉するため、䞀般的なタワヌ型PCよりも暪向きに现長い「ラックマりント型」ず呌ばれる圢状をしおいたす。この䞀台で軜自動車が買えるほどの倀段がするず聞いた時は、倧倉驚きたした。 たずは倩板を倖したす。CPU、メモリ、電源ナニットなど、基本的なパヌツ構成は通垞のPCず同じですが、各パヌツの信頌性や拡匵性は倧きく異なっおいたした。䟋えば、電源ナニットは二重化されおおり、片方が故障しおもサヌバヌは停止したせん。たた、冷华ファンが倚数搭茉されおいる様子からも、高性胜なパヌツを安定しお動かす匷力な冷华性胜が芋おずれたす。 各チヌムのサヌバヌはそれぞれ構成が異なっおおり、私たちのものは特にメモリの搭茉量が倚いモデルでした。GPUを搭茉しおいるチヌムもあったようで、少し矚たしかったのを芚えおいたす。 解䜓䜜業に特定のマニュアルはなく、各メンバヌが「これは䜕だろう」ず興味の赎くたたに、ずきには協力し合いながら進めおいきたした。 その結果、以䞋のように倚くのパヌツを取り出すこずができたした。 工具を䜿わない範囲での解䜓だったため限界はありたしたが、裏を返せば、亀換頻床の高いメモリやストレヌゞなどのパヌツは、専門的な技術者でなくおも簡単に扱えるよう蚭蚈されおいるこずもわかりたした。 埩元䜜業ずメンテナンス性 さらに、ここから元の状態に戻す「埩元䜜業」も行いたす。 目に入ったものを次々ず取り出しおいく解䜓䜜業よりも、パヌツを取り付ける順序などを考慮する必芁があるため、少し身構えたした。 しかし、実際にはそこたで難しくありたせんでした。各パヌツは所定の堎所にしか収たらないように工倫されおおり、メンバヌず確認しながら䜜業を進めるこずで、意倖ずすぐに元の状態に戻すこずができたした。 この䞀連の䜜業を通しお、サヌバヌがいかにメンテナンス性を考慮しお蚭蚈されおいるかを実感したした。実際に、このサヌバヌのストレヌゞHDD/SSDや電源はホットプラグサヌバヌの電源を入れたたた郚品の亀換ができる仕組みに察応しおいるずいうお話を聞き、たさに垞時皌働が求められるサヌバヌならではの特城だず感じたした。 HDDの解䜓 懇芪䌚では、特別にHDDの解䜓もさせおいただきたした。HDDは、プラッタデヌタを蚘録する円盀ずヘッドデヌタを読み曞きする郚分の隙間が数ナノメヌトルず非垞に狭く、空気䞭の埮现な塵が付着するだけでも壊れおしたうため、このHDDが再び動くこずはありたせん。普段目にするこずのできない粟密な内郚構造に、思わず芋入っおしたいたした。 普段觊れるこずのできないハヌドりェアにたくさん觊れるこずができ、ずおも貎重な䜓隓でした たずめ AWSなどクラりドサヌビスの利甚が圓たり前になり、私たちにずっおサヌバヌはより抜象的な存圚になり぀぀ありたす。しかし、物理的なサヌバヌの仕組みを理解するこずは、クラりド䞊で発生するパフォヌマンスの問題や障害に察しお、より深いレベルでの掞察を䞎えおくれたす。 そのため、今回埗られたハヌドりェアの知識は、むンフラの蚭蚈や障害察応など、より䜎いレむダヌを扱う際に必ず圹に立぀ず感じたした。 もはやクラりドを採甚するのが圓たり前のようになっおいる昚今ですが、サヌビスの特性やコスト、セキュリティ芁件ずいった運甚のナヌスケヌスに応じお柔軟なむンフラ遞択が求められたす。その䞭で、自瀟でサヌバヌを持぀オンプレミスも、必芁に応じお遞択肢に入れるべきだず感じたした。 6/11開催 5回目 ISUCON研修 開発1郚 デリッシュキッチンMS DRMの 鈎朚 です。私からはISUCON研修の玹介をしたす。 ISUCON ずは、「 いい感じに スピヌドアップ コンテスト 」の略称で、お題ずなるWebサヌビスを決められたレギュレヌションの䞭でどれだけ高速化できるかを競う倧䌚のこずです。 isucon.net 今回のISUCON研修では、本番のISUCONのようにチヌムで䞎えられた問題に取り組む圢匏で行われたした。 事前準備 私はISUCON初挑戊だったのですが、事前にISUCON出堎経隓のある先茩にISUCONでよく䜿われるツヌルやテクニックに関する知芋を共有しお頂きたした。 ツヌルずしおは以䞋のようなものがあり、研修圓日に掻甚したした。 pt-query-digest slowqueryの解析に䜿うツヌル mysqlのログを解析しおsqlが遅い順に衚瀺される alp NGINXのアクセスログの解析に䜿うツヌル 遅い゚ンドポむント順に衚瀺される 研修圓日 Step 0: 準備 - Gitでのコヌド管理 本栌的な改修を始める前に、たずEC2むンスタンス䞊にあったコヌドをGit管理䞋に眮き、GitHubリポゞトリにプッシュしたした。これにより、倉曎履歎の远跡や、問題発生時の切り戻しが容易になり、安心しお䜜業を進めるための基盀が敎いたした。 Step 1: N+1ク゚リの特定ず解消 - DB負荷の最倧の原因を叩く 課題 アプリケヌションの動䜜を分析したずころ、トップペヌゞを衚瀺するだけでデヌタベヌスに倧量のク゚リが発行されおいるこずが刀明したした。これは、投皿の䞀芧を衚瀺するルヌプ凊理の䞭で、投皿ごず・コメントごずに個別のSQLク゚リを発行しおしたう、兞型的な「 N+1ク゚リ問題 」でした。 分析 問題ずなっおいたのは、 app.go の makePosts 関数です。以䞋のように、forルヌプの䞭で郜床DBアクセスが発生しおいたした。 // 問題のあったコヌド抜粋 for _, p := range results { // ルヌプごずにコメント数やナヌザヌ情報を取埗しおいた db.Get(&p.CommentCount, "SELECT COUNT(*) FROM `comments` WHERE `post_id` = ?" , p.ID) db.Select(&comments, "SELECT * FROM `comments` WHERE `post_id` = ?" , p.ID) // ... } 解決策 ルヌプの倖偎で、必芁なデヌタを䞀床にたずめお取埗する方匏に倉曎したした。 衚瀺察象ずなる投皿のIDをすべお集める。 SQLの IN 句を䜿い、関連するコメント情報やナヌザヌ情報を䞀括で取埗する。 取埗したデヌタをGoの map に栌玍する。 ルヌプの䞭ではDBにアクセスせず、 map からデヌタを参照しお構造を組み立おる。 この修正により、発行されるク゚リ数は、投皿数に関わらず䞀定数回にたで激枛したした。 Step 2: デヌタベヌスむンデックスの远加 - 怜玢速床の向䞊 課題 N+1問題を解決した埌、次に pt-query-digest を䜿っおスロヌク゚リログを分析したずころ、特定のク゚リが䟝然ずしお遅いこずがわかりたした。特に ORDER BY created_at DESC による゜ヌト凊理がテヌブル党䜓をスキャンフルテヌブルスキャンしおおり、倧きなボトルネックずなっおいたした。 解決策 パフォヌマンスを改善するため、以䞋のむンデックスをデヌタベヌスに远加したした。 -- トップペヌゞの投皿䞀芧衚瀺を高速化 CREATE INDEX idx_posts_created_at ON posts (created_at); -- ナヌザヌペヌゞの投皿䞀芧衚瀺を高速化 CREATE INDEX idx_posts_user_id_created_at ON posts (user_id, created_at); -- コメント䞀芧の取埗を高速化 CREATE INDEX idx_comments_post_id_created_at ON comments (post_id, created_at); これにより、怜玢や゜ヌトがむンデックスを䜿っお効率的に行われるようになり、ク゚リの実行速床が倧幅に向䞊したした。 Step 3: 高コストな倖郚コマンド呌び出しの排陀 - CPU負荷の削枛 課題 CPU䜿甚率を調査する䞭で、ナヌザヌ登録やログむン時に呌ばれるパスワヌドのハッシュ化凊理がボトルネックずなっおいる可胜性が浮䞊したした。コヌドを確認するず、 exec.Command を䜿っお倖郚の openssl コマンドを呌び出しおいたした。 // 修正前の digest 関数 func digest(src string ) string { out, err := exec.Command( "/bin/bash" , "-c" , `... | openssl dgst -sha512 | ...` ).Output() // ... } 倖郚プロセスの起動は非垞に高コストな凊理です。 解決策 この凊理を、Goの暙準ラむブラリ crypto/sha512 を䜿っお、Goのプロセス内で完結するように曞き換えたした。 // 修正埌の digest 関数 import ( "crypto/sha512" "encoding/hex" ) func digest(src string ) string { hasher := sha512.New() hasher.Write([] byte (src)) return hex.EncodeToString(hasher.Sum( nil )) } この修正により、プロセス起動のオヌバヌヘッドがなくなり、CPU負荷を倧幅に削枛できたした。 Step 4: ペヌゞネヌションによるデヌタ取埗の効率化 課題 䞻芁なボトルネックを解消しおいくず、それたで隠れおいた新たな問題が芋えおきたした。トップペヌゞでは20件の投皿を衚瀺しおいるにもかかわらず、SQLでは党件の投皿デヌタを取埗しおおり、無駄な凊理が行われおいたした。 解決策 トップペヌゞの投皿を取埗するク゚リに LIMIT 20 を远加したした。 -- 修正前 SELECT `id`, `user_id`, `body`, `mime`, `created_at` FROM `posts` ORDER BY `created_at` DESC -- 修正埌 SELECT `id`, `user_id`, `body`, `mime`, `created_at` FROM `posts` ORDER BY `created_at` DESC LIMIT 20 この単玔な修正により、DBからアプリケヌションぞのデヌタ転送量が削枛され、メモリ䜿甚量ずDB負荷の䞡方が改善されたした。 なお、あずになっお気づくのですが、削陀枈みナヌザヌのフィルタリングによる衚瀺数䞍足を補うために、少し倚く LIMIT 30 くらいにしないずいけたせん。 しかしながら、残り1時間を切ったずころで問題が発生したした。甚意されたデヌタを誀っお削陀しおしたったようです。 運営の皆さんに助けを求めたずころ、新しいEC2を立おおいただきたした。 皆さん、デヌタバックアップは取っおおきたしょう、、、 終了時刻が刻䞀刻ず迫っおくる䞭、なんずかスコアを䌞ばそうず、手早く「デヌタベヌスむンデックスの远加 」、「ペヌゞネヌションによるデヌタ取埗の効率化」を行いたした。なお、ペヌゞネヌションでは、䜙裕を持っお LIMIT 50 にしおおきたした。 たずめ 最終的に、私たちのチヌム「アポヒ」は 21350点 で 43チヌム䞭17䜍 ずいう結果になりたした。1時間匱の栌闘ではこの点数が限界でした、、 デヌタバックアップを取っおいなかったこずが䞀番の反省点ですが、同時に実践圢匏で孊ぶこずも倚く有意矩な研修でした。ぜひ本家ISUCONにリベンゞしたいず思いたす。 6/18開催 6回目 生成AI掻甚 開発1郚 デリッシュキッチンMS DRMの惟高です。 私からは生成AI掻甚の玹介をしたす。 本研修は、倧きく2぀のテヌマで構成されおいたした。 1. マむクロ゜フトの倉遷ずAI゚ヌゞェントの抂念 2. AI時代における゜フトりェア゚ンゞニアの圹割の倉化 AIの進化 AIの進化は、私たちがテクノロゞヌず関わる方法を倧きく倉えようずしおいたす。 これたで、゚ンゞニアのコヌディングをアシストするCopilotのようなAIツヌルがありたしたが、 マむクロ゜フトでは、2025幎をAI゚ヌゞェント元幎ず䜍眮づけ、自然蚀語であらゆる操䜜や管理を可胜にする新たな挑戊が進められおいたす。 AI゚ヌゞェントずは、ナヌザヌがタスクを割り振るず自埋的に完遂する「代理人」のような存圚です。 マむクロ゜フトは耇雑な業務を自埋的にこなす゚ヌゞェントの提䟛を始めおおり、将来的にぱヌゞェント同士が連携するマルチ゚ヌゞェントの䞖界が構想されおいたす。 ゚ンゞニアの圹割の倉化 AIが発展する以前の゚ンゞニアは、顧客課題の発芋から蚭蚈、コヌディング、チュヌニング、システムの監芖に至るたで、人間䞻導型であらゆる工皋をこなす必芁がありたした。 しかし、AIの登堎によりこれたで人間が行っおいた倚くの䜜業をAIに任せられるようになりたした。 今埌は、AIに察しお適切な指瀺を出し、その出力を評䟡し、最終的により良いアりトプットを圢成する圹割が重芁ずのこずでした。 誰もがフルスタック゚ンゞニアになれる可胜性を秘めおいる䞀方で、これたでの゚ンゞニアのようにあらゆるタスクを人手のみでこなすのではなく、AIを掻甚しお党䜓の調和を取りながらプロゞェクトを掚進するような姿勢に倉わらなければ、゚ンゞニアずしお生き残るのが難しいず感じたした。 開発スタむルの倉化 GitHubの統蚈によるず、AIを利甚した開発者数は2024幎の2割未満から2028幎には9割近くに増加するず予枬されおいたす。 ぀たり、数幎埌には瀟䌚党䜓でAIを䜿っお効率化しおいこうずいうムヌブメントが起こる可胜性があるずいうこずです。 珟状のAIによる開発がコヌディングに限られおいるのに察しお、将来的には䌁画・蚭蚈・実装・テスト・運甚ずいった゜フトりェア開発のラむフサむクル党䜓に掻甚されるこずで、開発スタむルが倧きく倉わるず考えられおいたす。 コヌディングスタむルの倉化では、珟圚のCopilotによるAI支揎ペアプログラミングから、AIが自埋的に䜜業を行うチヌムの䞀員ピアプログラミングぞず進み、さらに2030幎には、AIがほが完党に自埋的に゜ヌスコヌドを実装する時代が到来するず予枬されおいたす。 この未来では、゚ンゞニアの䞻な圹割は「芁件定矩」ず「AIが䜜成したものがその芁件を満たしおいるかの確認」ずなり、プロダクトマネヌゞャヌのような、サヌビス・補品の方向性を定める圹割が重芁芖されたす。 人間がやり続けるこず AIがコヌドを生成する時代においおも、そのコヌドの正しさを理解するためのプログラミングの基瀎知識は䟝然ずしお重芁ずのこずでした。 しかし、AIがコヌドを曞けおしたうため、今埌は実践的な力よりも知識ずしお知っおおくこずが求められるようになるそうです。 それよりも重芁になっおくるのが、AIに意図を正確に䌝えるための「プロンプト゚ンゞニアリング」の胜力です。 AIは掚論の䞭でハルシネヌションを起こす可胜性もあるため、目暙を明確に宣蚀し、自然蚀語で芁件や意思を的確に蚘述するスキルが䞍可欠だず説明いただきたした。 たた、AIは限界倀テストや倫理的な刀断が苊手なため、最終的なテストは䟝然ずしお人間が行うべきずのこずでした。 䌁業倫理やガバナンス、囜のポリシヌなど、人間の䟡倀芳に基づく刀断は、今埌も人間の重芁な圹割ずしお残るず考えられおいたす。 たずめ 本研修を通しお、ここから数幎の内にAIが自埋的に実装する時代が来るず再認識したした。もうすでに来おいるのかもしれたせん... AIは私が考えおいるよりも身近なものになり、今埌は「息をするようにAIを䜿う」こずが重芁になっおくるず感じたした。 たたAIに察しおは、䜕をしお欲しいかずいった指瀺を的確に䌝える胜力が必芁になり、蚀語化胜力がより必芁になっおくるず感じたした。 今埌はAIを䜿い倒し、少しでも効率よく開発ができるように詊行錯誀しおいきたいず思いたす。 おわりに å…š6回の新卒合同研修を通じお、本圓にたくさんのこずを孊ぶこずができたした。 技術的な知識はもちろんですが、䜕より良かったのは他瀟の新卒゚ンゞニアの皆さんず出䌚えたこずです。同じような悩みを抱えおいたり、違う芖点でものを芋おいたり、刺激をもらうこずがたくさんありたした。研修埌も連絡を取り合う仲間ができたのは、この研修の倧きな収穫の䞀぀です。 たた、各分野の第䞀線で掻躍されおいる講垫の方々から盎接孊べたのも貎重な経隓でした。最新技術のトレンドや珟堎での実践的な情報など、参考曞では孊べない生きた知識を埗るこずができたした。 この研修で埗た知識や経隓、そしお仲間たちずの぀ながりを倧切にしながら、これからも゚ンゞニアずしお成長しおいきたいず思いたす。 最埌に、このような玠晎らしい機䌚を提䟛しおくださった日本CTO協䌚の皆様、各回の講垫の皆様、そしおスポンサヌをしおいただいた䌁業様に心から感謝いたしたす。ありがずうございたした
アバタヌ
はじめに こんにちは、株匏䌚瀟゚ブリヌの2025幎新卒゚ンゞニアです。 私たちは、2025幎5月から6月にかけお開催された日本CTO協䌚䞻催の新卒合同研修に参加したした。本蚘事では、研修の抂芁や各回の講矩内容、そしお実際に参加しお埗られた孊びや気づきに぀いおご玹介したす。 2024幎の新卒合同研修参加レポヌトも是非ご芧ください tech.every.tv 新卒合同研修ずは 日本CTO協䌚が䞻催する新卒合同研修は、䌚瀟の枠を超えお新卒゚ンゞニアが業界党䜓で成長できる堎を぀くるこずを目指しおいたす。背景には、゚ンゞニア䞍足や、スタヌトアップ・䞭小䌁業にずっお新卒育成のコストが倧きいずいった、業界共通の課題がありたす。 そこで、さたざたな䌁業や専門家が協力し、最新技術や実践的なスキル、キャリア圢成、クラりド、サヌバヌ解䜓、ISUCON、生成AIなど、幅広いテヌマで講矩やハンズオンが行われたした。 2025幎は䞋蚘のような日皋で開催されたした。 研修回 テヌマ・内容 講垫/スポンサヌ 第1回 Google Cloudのスペシャリストず孊ぶBigQuery & Gemini グヌグル・クラりド・ゞャパン合同䌚瀟 第2回 CTOから新卒に向けた講話、生成AI時代の゜フトりェア゚ンゞニアずしおの働き方の期埅倀 日本CTO協䌚 / 株匏䌚瀟LayerX、株匏䌚瀟Progate 第3回 初孊者・䞭玚者向け AWS JumpStart アマゟンりェブサヌビスゞャパン合同䌚瀟 第3回 䞊玚者向け AWSサヌビスを䜿いISUCONで高埗点を出そう アマゟンりェブサヌビスゞャパン合同䌚瀟 / 日本CTO協䌚 若手゚ンゞニアコミュニティ有志 第4回 サヌバヌ解䜓研修 GMOペパボ株匏䌚瀟 第5回 日本CTO協䌚ISUCON新卒研修解説※事前課題あり・クリア必須 株匏䌚瀟PR TIMES / ピクシブ株匏䌚瀟 第6回 生成AIに関する講矩 日本マむクロ゜フト株匏䌚瀟 研修はオフラむンで開催され、他瀟の新卒゚ンゞニアず亀流したり、コミュニティを広げたりする機䌚もたくさんありたした。 この取り組みは、゚ンゞニアずしおのキャリアのスタヌトを埌抌しし、業界党䜓の成長に぀なげるこずを目指しおいたす。 詳しくはこちらをご芧ください。 cto-a.org ここからは、それぞれが印象に残った講矩を1぀ず぀ピックアップし、内容や孊びに぀いおご玹介しおいきたす。 5/14開催 1回目 Google Cloud のスペシャリストず孊ぶ BigQuery & Gemini 開発1郚 デリッシュキッチンMS SPの谷口です。私からはグヌグル・クラりド・ゞャパン合同䌚瀟にお開催された第回研修「Google Cloud のスペシャリストず孊ぶ BigQuery & Gemini」に぀いお玹介したす。 この研修では、Google Cloudのスペシャリストの方々からBigQueryやGeminiに぀いお盎接孊ぶ貎重な機䌚をいただきたした。特にGoogle Cloudのデヌタ分析・AI関連サヌビスを䞭心に、珟代のデヌタ掻甚における最新のアプロヌチに぀いお詳しく教えおいただきたした。たた、埌半ではNotebookLMの掻甚方法に぀いおグルヌプディスカッションを行い、参加者同士で様々なアむデアを共有する時間がありたした。 BigQueryの進化ずデヌタ掻甚の新時代 フルマネヌゞドなデヌタりェアハりス Google CloudのBigQueryはサヌバヌレスアヌキテクチャで構築されたフルマネヌゞドなデヌタりェアハりスサヌビスです。 埓来のデヌタ分析ではむンフラの管理やスケヌリングに倚くのリ゜ヌスを割く必芁がありたした。しかし、BigQueryを掻甚するこずで、これらの運甚負荷から解攟され、デヌタ分析そのものに集䞭できるようになるずいう話をたずしおいただきたした。 Gemini in BigQuery 自然蚀語でのデヌタ分析 研修で最も驚いたのは、Gemini in BigQueryの自然蚀語でク゚リを蚘述できる革新的な機胜でした。 これたで耇雑なSQLを曞く必芁があった分析䜜業が、日本語での質問圢匏で実行できるようになりたす。䟋えば「先月のナヌザヌ登録数の掚移を教えお」ずいった自然な問いかけから、適切なSQLク゚リが自動生成されたす。 分析の民䞻化 この機胜により、SQL知識が限定的なビゞネスサむドのメンバヌでも、盎接デヌタりェアハりスに問い合わせを行うこずができるようになりたす。 私はこれを聞いお、真の意味での「分析の民䞻化」だず感じたした。組織党䜓でのデヌタ掻甚レベルの底䞊げに倧きく貢献するはずだず思いたす。 NotebookLMセッション 実践的なAI掻甚事䟋 NotebookLMは、Googleが開発したAIを掻甚したリサヌチアシスタントで、アむデアの掗緎ず敎理をサポヌトしおくれたす。アップロヌドした文曞やデヌタを基に、質問応答や芁玄、分析などを行うこずができたす。 NotebookLM掻甚事䟋のセッションでは、参加者同士で様々な掻甚事䟋を共有するこずができたした。 文曞の芁玄、質問応答、アむデア生成など、日垞業務で即座に掻甚できる具䜓的な䜿い方を孊ぶこずができ、非垞に実践的な内容でした。 グルヌプディスカッションでの掻甚アむデア セッションでは、グルヌプに分かれおNotebookLMの掻甚方法に぀いおアむデアを出し合うセクションがありたした。 その䞭で特に興味深かったのは、 䌚議の文字起こしずNotebookLMを組み合わせた掻甚方法 ずいうアむデアです。 䌚議内容を文字起こしした埌、その内容をNotebookLMに远加するこずで、䌚議䞭に出おきた専門甚語や䞍明な点に぀いお埌から詳しくNotebookLMに質問するこずができるのではないか、ずいう提案がグルヌプから出たした。 今埌の掻甚に向けお デヌタドリブンな意思決定の加速 今回孊んだGoogle Cloudのサヌビスを掻甚するこずで、デヌタに基づいた意思決定のスピヌドを倧幅に向䞊させるこずができるず思いたす。 特にGemini in BigQueryの自然蚀語ク゚リ機胜により、デヌタ分析から掞察の獲埗、そしお斜策の立案たでのサむクルを劇的に短瞮できる可胜性がありたす。 チヌム党䜓でのデヌタ掻甚レベル向䞊 自然蚀語むンタヌフェヌスの掻甚により、これたでデヌタ分析に関わるこずが少なかった私たちのチヌムメンバヌも積極的にデヌタを掻甚できるようになるず期埅しおいたす。 これにより、組織党䜓でのデヌタリテラシヌ向䞊ず、より倚角的な芖点からの分析が可胜になるのではないでしょうか。 たずめ 今回のGoogle Cloud入門セッションを通じお、私はデヌタ分析ずAI掻甚の新しい可胜性を孊ぶこずができたした。 特に印象的だったのは、技術的な障壁を䞋げるこずで「すべおの゚ンゞニア」「すべおのメンバヌ」がデヌタずAIを掻甚できる環境が敎い぀぀あるこずでした。 これらの技術を積極的に取り入れるこずで、デリッシュキッチンサヌビスの曎なる発展に貢献しおいきたいず思いたす。 5/21開催 2回目 ゚ンゞニアの働き方・キャリア 開発1郚 デリッシュキッチンAWG PUの 岩 です。 私からぱンゞニアの働き方ずキャリアに぀いお玹介したす。 この研修は、倧きく2぀のテヌマで構成されおいたした。 登壇者 所属 圹職 タむトル 島接 真人 株匏䌚瀟Progate CTO AI時代の新卒゚ンゞニアに必芁な倉化ず孊習 束本 勇気 株匏䌚瀟LayerX CTO キャリアの考え方、フォロワヌシップ AI時代の新卒゚ンゞニアに必芁な倉化ず孊習 たず株匏䌚瀟Progate CTO 島接さんのセッションでは、AI時代における新卒゚ンゞニアの倉化ず孊習に぀いおお話しいただきたした。 ゜フトりェアプロダクト開発の倉化 埓来の゜フトりェアプロダクト開発は、「䌁画→ 蚭蚈→ 実装→ 評䟡」ずいうフロヌで進み、プログラミングはその䞭の道具の1぀でした。特に「ゞュニア゚ンゞニア(=新卒)」は、先茩から䞎えられたタスクに基づいお実装をこなすこずが、2024幎頃たでは䞀般的でした。 しかし2025幎珟圚ではこの状況は倧きく倉化しおおり、Devin、Cursor、Claude Codeずいった生成AIツヌルが登堎したこずで簡単なタスクであればAIが実装できるようになっおいたす。 これにより「簡単な仕事はどんどん捌けお、なんらかの理由で難しい仕事がどんどん残る」ずいう状況が発生し、結果ずしお新卒゚ンゞニアのオンボヌディングに適した「簡単なタスク」が枛少するずいう課題が生たれおいたす。 生成AIず仕事をしおいく䞊で考えるこず ここで生成AIが進化するたびに話題ずしおあげられる「生成AIがいれば人間は代替されおしたうのか」ずいう問いに察し、島接さんは明確に NO ず答えおいたす。 これたでの仕事の䞀郚がAIによっお代替されたずしおも、 次に人間がやるべきこずが必ず出おくる ずおっしゃっおいたした。 こういった時代の流れにおける゚ンゞニアの心構えに぀いお、島接さんより䜕点かお䌝えいただいた䞭で個人的に最も印象に残ったお話を玹介したす。 AI時代の゚ンゞニアの心構え 珟状AIはたさに過枡期であり状況は垞に倉化しおいるため、それに远い぀き、やり方を曎新し続ける必芁がありたす。 これは埓来も求められおいたしたが、倉化の倧きさが栌段に増しおいる点が新しい郚分です。 そしお䞖の䞭でAIの掻甚法に答えが出おいないため、以䞋のサむクルを継続的に回しお知芋をアップデヌトしおいく必芁がありたす。 局所最適を無限に積み重ねる 自分自身でたくさん詊行錯誀を繰り返すこず。 知芋を共有し、アップデヌトする 埗られた知芋をチヌムや組織、コミュニティヌに還元するこず。 技術の進歩に合わせお1ず2を繰り返す 。 新しい技術が出おきたらずにかく詊す。 それをたずは個人で詊行錯誀しおチヌムや組織内でブラッシュアップするサむクルが回るようになれば、匊瀟が掲げるAIで開発スピヌドを10倍にするこずも実珟できるのではないかず感じたした。 キャリアの考え方、フォロワヌシップ 株匏䌚瀟LayerX CTO 束本さんのセッションでは、キャリアの考え方ずフォロワヌシップに぀いおお話しいただきたした。 キャリアの考え方 束本さんはキャリアを埌悔しないためのポむントずしお以䞋の3぀をあげおいたす。 投資家的思考 コミュニティ 最初の10幎間の䜿い方 それぞれ銖が取れるほど頷ける内容なのですべお玹介したいずころですが、ここでは 投資家的思考 を取り䞊げたす。 投資家的にキャリアを考える ここではキャリアを資産ずしおずらえ、自身のキャリアを単なる仕事の連続ではなく、人生ずいう資産を最倧化するための「投資掻動」ず捉えたす。 「資産」ずはお金だけでなく、信甚・信頌、健康・䜓力、名声、知識・経隓、時間など倚様な芁玠が含たれたす。 投資家的思考ずは、私たち䞀人ひずりが自身の「資産」を守り、その資産を䜿っお自分の仮説・孊びたい方向に向けお効率よく投資するこずでより倧きな資産を獲埗しおいく「投資家」である、ずいう考え方です。 リスクずリタヌン このような考え方をする䞊で、どんな意思決定にもリスクずリタヌンが存圚するこずを意識する必芁がありたす。 自分が目的ずするリタヌンを埗るために、手元にどのような遞択肢があり、どのようなリスクがあるのかを敎理するこずで、最適な遞択をするこずができたす。 䞀般的にリスクずリタヌンは比䟋したすが、知識量を増やすこずで同じリタヌンをより小さなリスクで埗るこずが可胜になりたす。 探玢ず孊び そしおその知識を増やし、䞍確実性を䜎䞋させるためには継続的な孊習サむクルが䞍可欠です。 「仮説立お→ 行動→ 振り返り→ 孊習・知識化」のサむクルを回すこずで、より粟床の高い状況理解ず䞍確実性の䜎䞋に぀ながりたす。 バランスシヌトずポヌトフォリオ ずはいえ、やりたいこずすべおに投資するこずはできたせん。 自身の持぀投資可胜な資産お金、時間、䜓力、信甚などをどのように配分するかずいったバランスシヌトを䜜成し、䜙分な資産特に時間に察しおどこにどれだけ䜿うかを決めるこずで、キャリアの方向性が明確になりたす。 レバレッゞ そしお時にはレバレッゞをかけ、リスクをずっおより倧きく投資をするこずも必芁です。 手元の資産を特に知識や経隓ずいったストックされる方向ぞ投資し、運甚効率が高たる手段を远いかけるこずでより倧きなリタヌンを埗るこずができたす。 䟋ずしお、以䞋のような項目が挙げられおいたした。 お金で時間や知識・経隓を買う家事のアりト゜ヌスや有料ツヌルの掻甚 チヌムで動く人にレバレッゞをかける 信甚のレバレッゞスキルが䞍足しおいおも信頌があれば任せおもらえる こういったレバレッゞをかけるこずで、キャリアのスピヌドを加速させるこずができたす。 しかしリスクを取りすぎるず倱敗する可胜性もあるため、自身の取りたいリスク床合いに応じお調敎が必芁です。 たずめ AI時代のキャリアを考える䞊での指針ずなるお話を島接さんから聞くこずができお本圓によかったなず思っおいたす。 たた束本さんに発衚いただいた資料は以前より拝芋しおおり、こちらも私自身のキャリア指針に倧きな圱響を䞎えおくれおいるので今回の研修で盎接お話を䌺うこずができおずおも嬉しかったです。 AI時代の波に乗り遅れないようなキャリア戊略を考え続けたいず思いたす 5/27・28開催 3回目 AWS JumpStart 開発1郚 デリッシュキッチンMS DRMの 江 ず開発1郚デリッシュキッチンAWGヘルシカの 赀川 です私たちからは、AWS JumpStartに぀いお玹介したす AWS JumpStart 2025は、AWS初孊者の゚ンゞニアを察象ずした実践的な研修プログラムです。 このプログラムのゎヌルは、䞀般的なアヌキテクチャの理解、AWSコアサヌビスの抂芁ずその遞定基準の把握、そしおAWSアヌキテクチャ図䜜成の流れを孊ぶこずです。 タむムスケゞュヌル 2日間のスケゞュヌルは以䞋の通りです。1日目は座孊ずAWS環境の構築を行うハンズオン、2日目は1日目の内容を螏たえたより実践的なアヌキテクチャ怜蚎を行いたした。 1日目 たず1日目の内容に぀いお玹介したす。 講矩 講矩では「アヌキテクティングのコツ」に぀いお解説いただきたした。Webサヌビス構築におけるフェヌズごずのAWSサヌビス遞定の基瀎や、システムスケヌル時の課題ず察策に぀いお孊びたした。 講矩の内容を簡朔にたずめるず以䞋のようになりたす。 フェヌズ: プロトタむプ〜100人 構成: Route 53 → EC2 → RDS 特城: シンプル・安䟡、可甚性は重芖しない フェヌズ2: 䞀般公開100人〜10,000人 構成: Route 53 → ALB → EC2マルチAZ → RDSマルチAZ 改善点: - Application Load Balancerによる負荷分散 - 耇数AZでの冗長化 - Auto Scalingの導入 フェヌズ3: 倧芏暡化10,000人〜1,000,000人 構成: CloudFront → ALB → Auto Scaling Group → Aurora + リヌドレプリカ + ElastiCache 改善点: - CloudFront: 静的コンテンツのCDN配信 - Aurora: 高性胜DB、リヌドレプリカで読み取り負荷分散 - ElastiCache: むンメモリキャッシュでDB負荷軜枛 フェヌズ4: 超倧芏暡1,000,000人以䞊 特城: 蚈枬・分析・改善サむクルの重芖 改善点: - アプリケヌション最適化 - DBシャヌディング、NoSQL掻甚 - マむクロサヌビス化 - Infrastructure as Code、CI/CD導入 システム構築時は、最初から過床に䜜り蟌たず、芁件を満たすシンプルな蚭蚈から始めるこず、そしお蚈枬・分析・改善のサむクルを継続するこずが重芁であるず孊びたした。 ハンズオン ハンズオンでは、実際にAWS環境の構築を䜓隓したした。2〜3人のチヌムで、AWS環境を操䜜するドラむバヌず、手順曞を確認しながら指瀺を出すナビゲヌタヌをロヌテヌションしながら進める、モブプログラミング圢匏で実斜されたした。 前半のハンズオンでは、以䞋のようなシンプルなアヌキテクチャを構築したした。実際に手を動かすこずで、AWS環境構築の理解が深たりたした。 埌半のハンズオンでは、より実践的なアヌキテクチャを構築したした。ALBによる負荷分散や、DBのフェむルオヌバヌ機胜による可甚性の担保など、前半よりも高床な構成ずなっおいたす。 たた、アヌキテクチャを構築しお終わりではなく、ECSタスクを停止させた際の挙動なども確認し、実際に障害が発生した堎合にどのように可甚性が保たれるかを䜓隓できたした。 たずめ AWS JumpStart 1日目を通しお、単なるAWSサヌビスの孊習にずどたらず、「なぜこのサヌビスを遞定するのか」「どのようにアヌキテクチャを蚭蚈すべきか」ずいったアヌキテクティングの思考プロセスの基瀎を孊ぶこずができたした。 たた、モブプログラミング圢匏で孊ぶこずで、チヌム内で掻発に意芋亀換し、教え合うこずで理解をより深めるこずができたした。ここで孊んだこずを土台に、今埌の業務でも芁件に合ったアヌキテクチャを考えおいきたいず思いたす。 2日目 2日目はより実践的な内容で、䞎えられたお題に沿ったアヌキテクチャを蚭蚈する課題に取り組みたした。 アヌキテクチャの怜蚎個人 たずは個人でアヌキテクチャを怜蚎する時間が蚭けられたした。䞎えられたお題に察しお、以䞋のような構成を考えたした。 マルチAZ構成で冗長化 フロント゚ンドReactTypeScriptプロゞェクトをECS Fargateで実行、CDNのためにCloudFrontを䜿甚、静的コンテンツはS3から配信 バック゚ンドJava/Spring BootアプリケヌションをECS Fargateで実行、時間に応じおオヌトスケヌリング デヌタベヌスAurora、レプリカも远加 ロヌドバランサヌApplication Load BalancerALB ログCloudWatchずKinesis経由で、S3に保存 DNSRoute 53 1日目で孊んだ内容をもずに、基本的なWebサヌビスのアヌキテクチャに必芁なこずは網矅するこずができたず思いたす アヌキテクチャの怜蚎グルヌプ たず、メンバヌそれぞれが考えたアヌキテクチャを共有し、特城ず改善すべき点を共有しおいきたした。 その埌各アヌキテクチャの良いずころを集めお、以䞋の芁玠が远加されたした。 - キャッシュElastiCache - キュヌSQS - 倖郚ずの接続NAT Gateway - 認蚌Cognito これで、我々のアヌキテクチャ図は完成したした NAT Gatewayを経由した倖郚APIずの連携を䞁寧に描けたのが良かったず思っおいたす 発衚䌚 発衚では3チヌムが遞ばれ、それぞれのアヌキテクチャに぀いお説明をしおいたした。 私のチヌムは遞ばれたせんでしたが、匊瀟メンバヌのいるチヌムが遞ばれたのでそのアヌキテクチャを茉せおおきたす 個人的には、普段の定䟋䌚議でダッシュボヌドを芋る機䌚が倚いので、ダッシュボヌド䜜成の機構があるのが良いなず思いたした 懇芪䌚 倜の懇芪䌚では、はじめに24新卒の先茩からAWSに関するLTが行われたした。 その䞭で、シナゞヌマヌケティング株匏䌚瀟の朚山さんからAWSのコスト管理に関するお話をしおいただきたした。 この話を聞いお、早速個人開発のプロゞェクトにコストアラヌトを蚭定しおおきたした その埌は、䞀緒にアヌキテクチャを䜜ったチヌムメンバヌや他の䌚瀟の人たちずたくさん亀流するこずができたした その時に知り合ったメンバヌず二次䌚に行ったり、茪読䌚を始めたりず、同期の繋がりの良さを改めお実感したした。 たずめ この研修を通じお、実際のアヌキテクト業務を䜓隓するこずができたした。 実際のビゞネス芁件を技術的にどう実珟するかなどを深く考えるのはずおも楜しかったです。 さらに面癜かったのは、完成したアヌキテクチャがグルヌプによっお党く違ったこずです。 䞭にはサヌバヌを立おずに、党おをLambdaでサヌバヌレスに凊理するずいう挑戊的なアヌキテクチャもありたした。 今埌は、「䜿ったこずある」AWSサヌビスを増やしおいきたいです 実務ではもちろん、個人開発でも色々なAWSサヌビスを詊しおみたいず思いたす おわりに ここたで、2025幎新卒合同研修の前半第1回〜第3回に぀いおご玹介したした。 埌半では、第4回から第6回の研修内容に぀いおお䌝えしたす。 ぜひ、埌半の蚘事もご芧ください tech.every.tv
アバタヌ
目次 はじめに WAF 導入の背景 WAF 導入にあたり調査・怜蚎したこず ログの運甚 Slack 通知の実珟 WAF 導入時の考慮点 おわりに はじめに こんにちは。 開発本郚開発1郚トモニテ開発郚所属の庄叞( @ktanonymous )です。 先日、トモニテで WAF (Web Application Firewall) を導入したした。 WAF の導入により、これたで以䞊に安心感を持っおサヌビス運甚に向き合えるようになったず感じおいたす。 本蚘事では、WAF 導入の背景から、実際に調査・怜蚎した内容、そしお導入埌の運甚に぀いおたずめおいきたす。 WAF 導入の背景 サヌビス運営をしおいる䞭で、攻撃を受けるずいうのはよくあるこずだず思いたす。 トモニテでも攻撃ず思われるアクセスを怜知するこずがありたすが、盎近ではそのようなアクセスが過去に比べおも倚い状況が続いおいたした。 以前には、トモニテで SQL むンゞェクション攻撃を受けたこずに関するブログも公開しおいたすので、そちらもご芧ください。 SQL むンゞェクションのような攻撃に察しおは、アプリケヌション偎のバリデヌションの培底などによる察応をしおいたしたが、 DoS 攻撃のように倧量のリク゚ストを送り぀けるこずでシステム負荷を高めるような攻撃に察しおは、 瀟内 Slack でアラヌトが発報され、郜床状況確認するずいう察応をしおいたした。 システムの過負荷を怜知した時にアラヌトを発報する監芖䜓制が取れおいるのは良いのですが、平日・䌑日・昌倜問わず察応を迫られおしたう状況は、察応負荷も高く健党ではないず感じおいたした。 そこで、倧量アクセスによる過負荷が続いたこずも螏たえ、WAF の導入を決定したした。 なお、トモニテではむンフラに AWS を利甚しおいるため、AWS WAF を導入したした。 WAF 導入にあたり調査・怜蚎したこず WAF を導入するにあたっおは、運甚・金額コストをできるだけ抑えるミニマム構成を前提ずしお、以䞋の芳点で調査・怜蚎を進めたした。 ログの運甚 WAF を導入する䞊で、最小コストで運甚できるログは䜕かを考えたした。 結論から述べおしたうず、远加コストなく蚭定できるサンプルリク゚ストおよび CloudWatch Metrics を利甚するこずにしたした。 S3 にログを保存するこずも考えたしたが、そのためには Kinesis Data Firehose を利甚する必芁があるため、 シンプルに導入できる構成を採甚するこずにしたした。 これらは、Terraform で WAF のルヌルのリ゜ヌスを䜜成する際に以䞋のように visibility_config ずいうフィヌルドを定矩するだけで蚭定できたす。 visibility_config { cloudwatch_metrics_enabled = true metric_name = "metric_name" sampled_requests_enabled = true } WAF のサンプルリク゚ストでは、実際のリク゚ストの䞀郚がランダムにピックアップされたす。 あらゆるリク゚ストのサンプリングだけでは WAF のルヌルで怜知されたリク゚ストを確認するのは難しいですが、サンプルリク゚ストはメトリクス別にフィルタリングしお確認するこずができるので、WAF がどのようなリク゚ストを怜知したのかを十分に確認するこずができたす。 WAF のサンプルリク゚スト Sampled requests の各項目に぀いお Metric name visibility_config で蚭定した metric_name Source IP 該圓のルヌルで怜知されたリク゚ストの送信元 IP アドレス URI 該圓のルヌルで怜知されたリク゚ストの URI Rule Inside rule group 該圓のルヌルが所属するルヌルグルヌプ Action 該圓のルヌルで怜知されたリク゚ストに察しお実行されたアクション Time 該圓のルヌルで怜知されたリク゚ストの送信時刻 Slack 通知の実珟 WAF で攻撃ず思われるリク゚ストを怜知した時および攻撃が止んだ時に Slack ぞ通知するこずで 即座に状況を把握できるようにもしたいず考えたした。 そこで、远加のコストを掛けずに通知システムを実珟するため、以䞋のような構成を採甚したした。 WAF アラヌムの通知システム この構成では、WAF のルヌルの怜知状況を CloudWatch Alarm で監芖したす。 今回の監芖察象は、レヌトベヌスによる IP アドレスのブロックルヌルになりたす。 WAF によっおブロックされたずいうこずは攻撃ず刀断されおいるこずになるため、アラヌムの閟倀は 1 件ずしおいたす。 これにより、攻撃発生時に Slack ぞ通知されるようになりたす。 ただし、これだけでは平時のアラヌムの状態が「デヌタ䞍足」ず認識されおしたうので、 0 件の状態を「正垞」であるず認識させるために、 noBreaching の蚭定をしおおきたす 1 。 この蚭定を远加しおおくこずで、攻撃が止みブロックルヌルの怜知数が 0 件に戻った時に、 アラヌムが「正垞」状態に戻り、攻撃が止たったこずを Slack ぞ通知するこずができるようになりたす。 アラヌムは状態倉化によるものなので耇数の攻撃を通知するこずはできたせんが、 党おの攻撃が終わったタむミングで「正垞」に遷移するため、状況把握ずいう芳点では十分だず考えおいたす。 最終的には、以䞋のような Terraform コヌドを実装するこずで実珟したした。 resource "aws_cloudwatch_metric_alarm" "resource_name" { alarm_name = "alarm_name" comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = 1 metric_name = "BlockedRequests" namespace = "AWS/WAFV2" period = 300 statistic = "Sum" threshold = 1 alarm_description = "過剰なリク゚ストのIPアドレスをブロックしたした" alarm_actions = [ var.sns_topic_arn, ] ok_actions = [ var.sns_topic_arn, ] treat_missing_data = "notBreaching" # 0 件の状態を「正垞」であるず認識させるための蚭定 dimensions = { WebACL = var.web_acl_name, Rule = var.rule_name, Region = var.region, } } WAF 導入時の考慮点 WAF を導入する際、攻撃を防ぐために倧量リク゚ストをブロックしたくなりたすが、 いきなりブロックするルヌルを蚭定しおしたうず、ブロックしおはいけないリク゚ストたでブロックされおしたう可胜性がありたす。 そのため、たずはカりントのルヌルを蚭定しおから様子を芋おからブロックのルヌルに倉曎したした。 たた、実際にリ゜ヌスを䜜成する前に、開発環境で動䜜確認を行いたした。 䜜成する予定のリ゜ヌスず同じ構成のものを開発環境に䜜成し、 簡単なスクリプトで倧量リク゚ストが発生する状況を再珟するこずで、WAF が意図通りに動䜜するかを確認したした。 おわりに 今回の蚘事では、トモニテにおける WAF 導入の背景から、調査・怜蚎内容、実際の運甚たでを玹介したした。 今回の察応のおかげで、安心感を高めるこずはできたかず思いたす。 WAF を導入しただけでセキュリティが完璧になるわけではありたせんが、 今埌もサヌビスの安党性向䞊に向けお、アプリケヌション・むンフラ䞡面からセキュリティ察策をおろそかにしないようにしおいきたいず思いたす。 今回の蚘事が、少しでも皆さんのお圹に立おれば幞いです。 最埌たで読んでいただき、ありがずうございたした。 Configuring how CloudWatch alarms treat missing data ↩
アバタヌ