📑

技術コミュニティで学んだ知識を上手く実務に活かせた話

に公開

はじめに

Cloud Pratica Advent Calendar 2025の18日目です。今年の5月あたりからこちらのコミュニティでインフラ系技術の勉強をさせていただいており、そこで得た知見を本業のプロジェクトにそのまま持ち込んだら、めちゃくちゃ上手くいったという成果報告的な記事です。

自己紹介

都内のアドテク企業に勤める新卒2年目のソフトウェアエンジニアです。業務では主にGoでのバックエンド開発、AWS, Terraformでの基盤構築に携わってます。

状況:インフラ未経験の先輩と挑む、S3 + CloudFront移行

本業にて、Laravelで配信していた静的ページをパフォーマンス向上のために S3 + CloudFront 構成へ移行するプロジェクトが立ち上がりました。

このプロジェクトの主担当は、対象ページの実装を行っている先輩のフロントエンドエンジニアでした。チームの方針として「フロントエンドエンジニアもインフラまで一気通貫で理解できた方が良い」となり、先輩がインフラ構築も主導することになりました。

しかし、その先輩はフロントエンドに関しては強強ですが、インフラ(AWS)構築の経験はゼロという状態でした。そこで、Cloud Praticaでインフラ修行中の自分が僭越ながらサポートに入ることになりました(自分もまだまだ未熟ですが学んだことを人に伝えるという形でアウトプットすることでさらに理解が深まりました)

学びの実践①:最初はマネコンで作る

インフラ初心者の先輩に対し、最初はどう進めるか悩みましたが、ここでCloud Praticaで学んだマネコンで作成ー>コード化の流れを実践しました。

初心者がいきなりTerraformで実装しようとすると下記のデメリットがあります。

  • 直感の欠如: AWSエンジニアが心血を注いで作った「直感的に分かりやすいコンソールUI」の恩恵を捨ててしまう。

  • 全体像の喪失: リソース同士の依存関係や、デフォルト設定値の確認がおろそかになり、行き当たりばったりになりやすい。

マネコンにはマネコンの良さがあることを伝え、以下のフローを実践しました。

  1. コンソールで作成: 画面共有しながらAWSコンソールを操作。GUIの恩恵を受けながら、「ここをこう設定するとキャッシュが効く」などの手触り感を得る。

  2. 動作確認: ブラウザで実際にページが表示されることを確認。

  3. コード自動生成: -generate-config-outオプションでコードを逆引きで生成

この流れで先にマネコンで作った「正解の状態」をそのままコードとして出力させました。 マネコンのUIで全体像を掴み、その結果をコードに落とし込むというステップを踏むことで先輩はインフラの構成をスムーズに理解されていました。

学びの実践②:CloudFront からS3への繋ぎこみで403エラーが返ってきたらNot Foundを疑え

構築中、S3に配置したファイルへアクセスするとステータスコード403が返ってくる事象が発生しました。

この時自分の頭にはCloud Praticaで教わった教訓が浮かびました。

「CloudFront からS3への繋ぎこみで403エラーが返ってきたらNot Foundを疑え」

以前の自分なら、権限周りの設定ばかりを疑って、時間を溶かしていたと思います。 実際、先輩も真っ先に権限周りの調査をされていました。

S3はセキュリティの観点から、ファイルが存在しない場合でも「無い」とは言わずに「権限がない(403)」と返してくることがあります。これを知識として知っていたおかげで、無駄な調査を回避できました。

パスミスの可能性を伝えて調査したところ、案の定パス書き換えのロジックと実際のS3オブジェクトのキーが微妙にズレていました。 知識があるだけで、トラブルシュートの時間が数時間から数分に短縮されるということを肌で感じ流ことが出来た瞬間でした。

学びの実践③:CloudFront Functions vs Lambda@Edge の最適解

今回の要件では拡張子をユーザーに意識させないようにするためCloudFront側で拡張子を補完する必要がありました。

CloudFrontでコードを実行する場合、CloudFront Functions と Lambda@Edge の2つの選択肢があります。

ここも以前の自分であればどちらを使えばいいか悩んでいたと思います。しかし、Cloud Praticaでこの部分もしっかり学習済みであったため自信を持って選定することが出来ました。

Lambda@Edge と CloudFront Functions の違いと使い分け
CloudFrontのエッジでロジックを実行する際、Lambda@Edge と CloudFront Functions という2つの選択肢があります。この2つは役割が似ているため迷いやすいですが、以下の通り明確な違いと使い分けがあります。

  1. 概要と直感的な理解
    まず、ざっくりとした認識として「Lambda@Edgeの方ができることが多い分、高機能でコストが高い」「CloudFront Functionsは機能が制限される分、超軽量で爆速・低コスト」と覚えておくと分かりやすいです。

Lambda@Edge: CloudFrontと連携して動作するAWS Lambdaの拡張版。Node.jsやPythonが動き、複雑な処理が可能。

CloudFront Functions: エッジロケーションで実行される非常に軽量なJavascript環境。シンプルな処理に特化している。

  1. 決定的な4つの違い
    技術的な観点から、選定に直結する主な違いは以下の4点です。

① 実行環境とランタイム

Lambda@Edge: Node.js や Python が動作します。外部ライブラリの使用も可能で、メモリも最大10GBまで積めます。

CloudFront Functions: JavaScriptのみが動作します。外部ライブラリは一切使えず、コードサイズも最大10KBという制約があります。

② イベントトリガー(発火タイミング)

Lambda@Edge: 4つのタイミングすべて(ビューワーリクエスト/レスポンス、オリジンリクエスト/レスポンス)で発火可能です。

CloudFront Functions: 「ビューワーリクエスト」と「ビューワーレスポンス」の2箇所(ユーザーに近い側)でのみ発火可能です。

③ ネットワークとファイルシステム

Lambda@Edge: 外部ネットワークへのアクセスが可能です(AWS SDKを使ってDynamoDBを叩く、外部APIをコールするなど)。

CloudFront Functions: ネットワークアクセスは不可です。完全に閉じられた環境で、リクエスト/レスポンスの内容だけを操作します。

④ パフォーマンスとコスト

Lambda@Edge: 実行時間はミリ秒単位。コールドスタート(起動遅延)が発生する可能性があります。

CloudFront Functions: 実行時間はマイクロ秒単位で爆速。スケーラビリティも非常に高く、コストはLambda@Edgeの約1/6程度です。

  1. ユースケースの使い分け
    それぞれの特性を踏まえた、適切な利用シーンは以下の通りです。

CloudFront Functions を選ぶべきシーン 基本的に「リクエスト/レスポンスの書き換え」だけで完結する軽量な処理に向いています。

HTTPヘッダーの操作(CORSやセキュリティヘッダーの追加など)

URLの書き換え・正規化(リダイレクト、拡張子の補完など)

キャッシュキーの正規化

JWTなどのシンプルなトークン検証(外部通信を行わないもの)

Lambda@Edge を選ぶべきシーン 外部との連携や、重たい処理が必要な場合に向いています。

外部APIやDBへのアクセスが必要な処理

画像のリサイズや変換、動的コンテンツの生成

複雑な認証・認可フロー(OIDC連携など)

オリジンへリクエストを投げる前の複雑な前処理

迷った時の選定チェックリスト
「どっちを使えばいいかわからない」となった時は、以下の質問を自分に投げかけます。これらに1つでも「はい」があるなら Lambda@Edge、「いいえ」なら CloudFront Functionsです。

  1. 処理に1ms以上の時間がかかる可能性があるか?

  2. 外部APIやAWSサービス(DynamoDB等)にアクセスする必要があるか?

  3. オリジンリクエスト/レスポンスフェーズでの処理が必要か?

  4. HTTPボディを操作する必要があるか?

  5. 10KB以上のコードサイズや、外部ライブラリが必要か?

  6. Node.jsやPythonなど、JavaScriptより高度な言語機能が必要か?

今回の決断
今回の要件は「URLの末尾に拡張子がない場合、.html を補完する」という非常にシンプルな文字列操作だけです。

外部APIへのアクセス? → 不要

処理時間? → 一瞬で終わる

ボディ操作? → 不要

外部ライブラリや高度な言語機能? → 不要

全てのチェックリストが「いいえ」になったため、今回は迷わず CloudFront Functionsが最適だと自信を持って提案することが出来ました。

なんとなく「高機能だからLambda@Edge」とするのではなく、学んだ比較軸に基づいて「なぜCloudFront Functionsなのか」をロジカルに説明できたことで、チームとしての技術選定の納得感も高まりました。

【自戒】考慮漏れによる失敗:Blue/Greenデプロイの動作確認

ここまで上手くいった話ばかり書いてきましたが、1つだけ自分の考慮不足で発生した失敗談(冷や汗エピソード)も共有します。

既存のリリースフローとの衝突
自分たちのチームでは、アプリケーションのデプロイに Blue/Greenデプロイ を採用していました。 具体的なフローは以下の通りです。

  1. デプロイパイプラインを実行することで新環境が立ち上げる。

  2. 8080ポートを使って、新環境にアクセスし動作確認を行う。

  3. 問題なければトラフィックを切り替える。

しかし、今回の移行でリクエストの入り口が CloudFront に変わりました。 ここで問題が発生しました。

「CloudFront経由だと、8080ポートでアクセスできない…!」

CloudFrontは、80番 (HTTP) と 443番 (HTTPS) ポートしかサポートしていません。 そのため、これまでのように https://example.com:8080 といった形でポート指定で裏側の新環境を確認しようとしても、CloudFrontがそのリクエストを受け付けてくれませんでした。

暫定対応と反省
リリース直前の動作確認でこの仕様制約に気づき、チーム内が一瞬ザワつきました。 「動作確認どうする?」「CloudFrontの設定でなんとかなる?」と焦りましたが、CloudFrontの仕様である以上、ポートを増やすことはできないようでした。

結局、その場での暫定対応として以下の策を取りました。

対応策: 動作確認用のドメインを新しく設定し、CloudFrontをバイパスして直接オリジンに向くようにした。

運用: 8080ポートでの動作確認時は、正規ドメインではなく、このバイパス用ドメイン経由でアクセスする。

結果としてリリースは無事にできましたが、構成図だけでなく、デプロイや確認のフローまで引いて考えるべきだったと深く反省しました。 現状はこの暫定対応で運用していますが、セキュリティや手間の観点からも、もっとスマートな方法があれば改善していきたいと考えています。

おわりに

今回のプロジェクトを通して得られた成果は以下の通りです。

  • スムーズなスキル移転: generate-config-out による答え合わせのおかげで、先輩がインフラへの苦手意識を持つことなくTerraformを理解できた。

  • 根拠のある技術選定: 学んだ比較軸に基づき、オーバースペックなLambda@Edgeを避け、最適なCloudFront Functionsを選定できた。

  • 運用の視点: 構成変更がデプロイフローに与える影響など、失敗を通じてより広い視野を持てるようになった。

改めて振り返ると、Cloud Praticaで学んでいたことは、単なる「AWSの操作方法」ではありませんでした。

第一線で活躍する強強エンジニアが、長い時間をかけ、膨大な試行錯誤の末に辿り着いた「実務における最適解」であり、「プロの思考プロセス」そのものだったんだなあと実感しました。

本来であれば現場で何年も揉まれてようやく身につくはずの「泥臭い知見」や「判断の物差し」を、ショートカットして吸収できていたからこそ新卒2年目の経験の浅い自分でもチームをリードできたのだと思います。

学んだことを自分の中に留めず、チームに還元できたことが何より嬉しかったです。 今後もインプットしたことをどんどん本業でアウトプットしていきます!

Discussion