TECH PLAY

KINTOテクノロゞヌズ

KINTOテクノロゞヌズ の技術ブログ

å…š969ä»¶

Hello, I'm Moriya (emim) from the Engineering Office. This article is part of KINTO Technologies Advent Calendar 2025 for Day 11. On Day 2 of the event, I posted an article about accessibility , while my primary job is product design. As a core function, I work as a designer within the Engineering Office , analyzing the situation at KINTO Technologies (KTC) and implementing initiatives to strengthen organizational capabilities. At KTC, our Executive Vice President Kageyama announced the following four key ideas which we focus on in 2025: AI first and release first that are directly related to our product development, as well as user first and organizational intensity to fundamentally support the former two ideas. https://blog.kinto-technologies.com/posts/2024-12-25-LookBack2024-en/ As a designer, I am involved in promoting user-first design among these ideas. Looking back to June 2025 when I joined KTC, user-focused activities have been already underway within the organization in various aspects since the beginning of 2025. As a year-end summary for 2025, I will wrap up what we have accomplished. ##First Internal Survey Revealed Inconsistent Perception of Users Within KTC Our first activity to promote user-first design was a survey to assess internal perception of users. There are so many different types of users that we need to ensure that our members share a common understanding of them. The survey was designed to plan specific methods to promote user-first design through confirming whether everyone has the same understanding of "users." We gathered members from various divisions and roles across the company and conducted group discussions to understand the current circumstances. Group-work sessions were held in various formats, including brainstorming with online whiteboard tools and on-site workshops to map the user perception with sticky notes. I joined my current team after completing the survey, and we then organized the relationship between users at each level—from business model stakeholders to end users—and products, in a format similar to Jeff Patton's onion model . Through this process, we found a considerable gap between our products and users’ needs. Perhaps due to the gap or complexity of our businesses, some people seemed to perceive stakeholders (such as colleagues in different roles with hierarchical relationships, partners at related/group companies, or clients) as users. ![ビゞネスモデルず照らし各階局のナヌザヌから゚ンドナヌザヌたでずシステムの関係性を衚す図ず、サヌビスずナヌザヌずの距離を衚した図](/assets/blog/authors/emim/2025-12-11-userfirst2025/2025-12-11-userfirst2025_img02.png =600x) While the user-first design is raised as a discussion topic from the concern that we cannot see what users want, we found that our development organization structure is one of the factors contributing to addressing this. When developers are distant from our users, the next step will be how to involve stakeholders, raise their awareness, and draw out users’ needs. We also shared the information with our Executive Vice President, who is responsible for this initiative, confirming alignment for seamless activity promotion. Current Statement Analysis Using Level of UX Maturity and Next Step of Sharing With organizational challenges clarified, we focused on two points: Raising developers’ awareness of the term user to remind them of a user-first mindset Involving members to understand users The former may seem obvious for product/service development, but not all developers sufficiently consider users yet. To measure our developers’ perception on users, we conducted a current state analysis referencing The 6 Levels of UX Maturity . This document includes a quiz in the latter half that allows individuals to self-assess their organizational conditions. Based on the content and quiz results, we are still at Stage 2: Limited. Clarifying our current position enables us to identify what we must do to advance to Stage 3: Emergent, the next level. Fortunately, we do not face the issue common in typical organizations: lack of the company’s understanding (no budget allocation). With problems identified through the top-down process, we find them easier to take action. For organizational information sharing, regular meetings are scheduled to share information with other key topics. This enables relationships where, for example, we receive user-related consultations in release contexts, and we can also had discussions about AI utilization for future initiatives. However, this alone limits information sharing to a specific scope. Therefore, we next conducted a company-wide information sharing session. Initiatives to Prevent UX from Being Isolated Sharing Our Promotion Activities The first step was reporting activities at the monthly company-wide information sharing session. We reconfirmed our current position, which we previously agreed upon with various parties, and mainly presented how developers can put a focus on user value. We explained development methods focusing on user value, citing similarities between agile development and human-centered design (HCD). Even engineers familiar with agile diagrams reacted as if they heard about HCD for the first time. Through the presentation that specific methods are provided for each HCD process, this single presentation created a situation where engineers could easily have discussions on specific topics. Exploring Internal Case Studies (Conducting Study Sessions) Next, we organized study sessions to spotlight those who have been working on running the HCD process before and share their activities on a company-wide basis. Through these sessions, we aimed to give rise to participants’ expectation that they could do it too. In these sessions, we had presenters share examples of implementing specific HCD processes within projects and cases where they attended events hosted by our sister company KINTO to understand how users use our services. Regarding the latter, one of the session attendees previously wrote an article on the following blog. https://blog.kinto-technologies.com/posts/2025-08-22-FACTORY_ReportOfRealEvent/ Furthermore, considering our company's large engineering population, we invited our frontend engineers who implemented the aforementioned initiatives and backend engineers whom we had interviews with to share detailed changes in their mindset through their efforts during the panel discussions in the session. After this study session, we witnessed changes in members’ behavior; for example, they contacted us about specific methods for deeply understanding user needs that include user interviews and customer journey maps. Recently, we received requests for consultations from engineers at a pace of about one every two weeks. Our Future Activities Currently, this initiative is carried out by myself and one of my colleagues Okane-san from the Creative Group. We have roughly divided our roles: I, Moriya, handle internal promotion of user-first activities and standardization/horizontal deployment of various processes, while Okane-san joins projects to execute HCD processes. Of course, we are short-handed, though. As mentioned earlier, we believe the most important thing is to increase the number if colleagues who can execute the processes, reach out to people in related areas for cooperation, and keep this activity going. Additionally, by presenting these activities again, we can spotlight activities that no longer gain traction in various areas once again to learn and leverage them as knowledge. As introduced at the beginning, while this is one of 2025's focus points, thinking about users is the foundation of product design. To keep proceeding with this initiative in a sustainable manner, we plan to continue refining our efforts beyond next year. Finally, on December 23, Okane-san, who works with me on this initiative, will publish an article about her own challenges in the KINTO Technologies Advent Calendar 2025 . Stay tuned!
アバタヌ
こんにちは、Engineering Officeの守谷emimです。 この蚘事は KINTOテクノロゞヌズ Advent Calendar 2025 の11日目のものです。 2日目に、 アクセシビリティに぀いおの蚘事 を投皿したしたが、私の䞻領域はプロダクトデザむンです。䞻軞では、 Engineering Office のメンバヌずしおデザむナヌの立堎でKINTOテクノロゞヌズ以䞋KTCの状況をずらえ、組織力を䞊げるための取り組みを行っおいたす。 KTCでは2025幎の泚力テヌマずしお、副瀟長の景山より、2぀のテヌマ「AIファヌスト」「リリヌスファヌスト」ずずもに、それを䞋支えする「ナヌザヌファヌスト」ず「組織むンテンシティ」が掲げられたした。 https://blog.kinto-technologies.com/posts/2024-12-25-LookBack2024/ 私はこのうちデザむナヌずしお、「ナヌザヌファヌスト」掚進掻動に関わっおいたす。私自身は6月入瀟ですが、このナヌザヌファヌストに぀いおの掻動は、今幎のはじめから様々な方向での組織内の取り組みがおこなわれおいたす。 今回は2025幎の総括ずしお、我々の実行した内容をたずめお行きたす。 はじめに着手した瀟内調査から、瀟内での「ナヌザヌ」の認知にブレがあるこずがわかった たず初めに行われたのが、ナヌザヌファヌスト掚進においお䞻軞ずなる「ナヌザヌ」に぀いおの組織内での認知調査です。 ひず口に「ナヌザヌ」ず蚀っおも、党員が同じ察象をむメヌゞできおいるのかずいう確認からです。ナヌザヌが䞀般的な甚語だからゆえの解釈の違いを明確にした埌に、具䜓の掚進方法を怜蚎するための調査です。 様々な郚眲、様々なロヌルのメンバヌを党瀟から招集し、グルヌプディスカッションを通し珟状を把握したした。オンラむンホワむトボヌドツヌルでの実斜や、オンサむトでの付箋でのワヌクなど、開催圢態は様々です。 調査が䞀通り終わったずころで私が参画したこずもあり、次に、ビゞネスモデルず照らし各階局のナヌザヌから゚ンドナヌザヌたでず補品ずの関係性を、 Jeff Patton氏の提唱するThe onion model のような圢での敎理したした。 そこから芋えおきたのは、我々の向かう補品ずナヌザヌずの間にかなり距離があるこずでした。たたその距離の遠さからか、事業の耇雑さからか、ステヌクホルダヌチヌム内で䟋えば䞊䞋関係のある別職域の人や、取り匕きをしおいる関係䌚瀟グルヌプ䌚瀟の担圓者、䟝頌䞻などをナヌザヌず捉えおいる人も居そうなこずがわかりたした。 ![ビゞネスモデルず照らし各階局のナヌザヌから゚ンドナヌザヌたでずシステムの関係性を衚す図ず、サヌビスずナヌザヌずの距離を衚した図](/assets/blog/authors/emim/2025-12-11-userfirst2025/2025-12-11-userfirst2025_img02.png =600x) 「ナヌザヌのこずが芋えおいない」ずいう課題感からナヌザヌファヌストずいうテヌマが䞊がっおきたしたが、開発組織構造も関係しおいるこずがわかりたした。開発者ずナヌザヌに距離がある堎合、どのようにステヌクホルダヌを巻き蟌み意識付けを行い、ナヌザヌの芁求事項を聞き出すのか、が次のステップになる、ず考えたした。 これらの情報は、この掻動のオヌナヌである副瀟長にも共有し、霟霬なく掻動を掚進しおいけるこずの確認にも利甚できたした。 「UXの成熟床モデル」を参考にした珟状分析ず掚進の次の䞀手の「共有」 組織課題が明らかになったずころで、次に我々が着目したのが 「ナヌザヌ」ずいうワヌドが開発の珟堎で出おくるための意識付け 「ナヌザヌ理解」のためのメンバヌの巻き蟌み ずいう2点です。前者に぀いおは、プロダクトサヌビス開発をする以䞊圓たり前のこずだず感じるかもしれたせんが、党開発者がナヌザヌに向き合えおいるかずいうずただただだ䞍十分ずいう状況です。 このあたりの肌感を探る為、 The 6 Levels of UX Maturity UXの成熟床モデルを参考にしながら、珟状分析を行いたした。このドキュメントには埌半に自身で組織の状態を評䟡掚定のできるテストが甚意されおいたす。 内容及びテストの結果からしお、ただ我々は「Stage 2: Limited限定的」にいたす。珟圚地が明らかになるこずで、次レベルの「Stage 3: Emergent新興」ぞ向かうために䜕をすべきか、ずいう芳点の確認が可胜ずなりたす。 幞いなこずに、䞀般的な組織で次に課題ずなる「䌚瀟偎の理解がない予算が぀かない」ずいう状況にはありたせん。トップダりンで課題提起がなされおいる分、動きやすいず感じたす。 組織の情報共有の仕組みずしおは、他の泚力テヌマず定期的に情報共有をする機䌚定䟋䌚議が蚭定されおいたす。それにより、䟋えばリリヌス分脈でナヌザヌに぀いおの盞談をもらえるような関係にあったり、我々からも今埌の取り組みずしおAI掻甚に぀いおの盞談を䞊げたりしおいたす。 ただしこれだけでは、限定的な範囲での情報共有ずなっおしたいたす。そこで次に、広く党瀟に向けおの情報共有䌚を行いたした。 UXが孀立しないための取り組み 我々の掚進掻動の共有 たず取り組んだのは、月に䞀床党瀟に向けお行われる情報共有䌚での掻動報告です。 事前に各所ず合意を埗た「珟圚地」に぀いおの改めおの報告ず、開発者の倚い珟堎でどうしたら「ナヌザヌの䟡倀」に着目できるのかずいう点に絞っおプレれンを行いたした。 「ナヌザヌの䟡倀」を䞭心に据えた開発手法ずしお、アゞャむル開発ず人間䞭心デザむンHuman Centered Design 、以埌HCDの類䌌性を匕甚しながら説明を行いたした。 アゞャむルの図はよく目にする゚ンゞニアでも、HCDに぀いおは初めお耳にしたずいうリアクションが出おいたした。HCDの各プロセスには具䜓の手法が提䟛されおいるこずも合わせお提瀺したこずで、この1床の発衚だけで゚ンゞニアからでも具䜓の盞談の䞊がりやすい状況に転換できたした。 瀟内の先行事䟋の発掘勉匷䌚の実斜 次に着手したのが、先行事䟋ずしお取り組たれおいる方たちをクロヌズアップし、改めお瀟内にその掻動を共有する勉匷䌚を開催したした。勉匷䌚を通し、「自分達でもできそう」ずいう感芚を持っおもらうこずを目的ずしおいたす。 この勉匷䌚では、具䜓のHCDプロセスをプロゞェクト内で回しおいる事䟋ず、兄匟䌚瀟のKINTOの䞻催のむベントに赎き、ナヌザヌのサヌビス利甚の状況把握に努めた事䟋に぀いお、改めお発衚をしおもらいたした。 埌者に぀いおは、過去にこのブログでも本人が蚘事を起こしおくれおいたす。 https://blog.kinto-technologies.com/posts/2025-08-22-FACTORY_ReportOfRealEvent/ さらに、゚ンゞニアの倚い䌚瀟であるこずをふたえ、前述の取り組みをしたフロント゚ンドの゚ンゞニアや、むンタビュヌを実行したバック゚ンドの゚ンゞニアを招聘し、パネルディスカッションを通しお、具䜓の心境の倉化などを共有しおもらいたした。 この勉匷䌚以降、具䜓のナヌザヌむンタビュヌやカスタマヌゞャヌニヌマップなど、ナヌザヌニヌズを掘り䞋げるような具䜓手法に぀いおの盞談が䞊がっおくる、ずいう倉化が起きたした。最近は半月に1件くらいのペヌスで盞談をいただいおいたす。 今埌の我々の掻動に぀いお 珟圚、この取り組みは私ずもう䞀人、クリ゚むティブGの倧金ずで行っおいたす。暫定的に、ナヌザヌファヌスト掚進掻動の瀟内プロモヌションや色々なプロセスの型化暪展開を行う守谷ず、プロゞェクト内に入っおHCDプロセスを実行しおいく倧金ず、ずいう圹割分担にしおはいたすがもちろん手が足りおはいたせん。 前述のように、具䜓のプロセスを実行できる仲間を増やしたり、近い領域の人たちに声を掛け協力を仰いで、この掻動を止めない事が最重芁ではないかず考えおいたす。たた、今回こういった掻動を改めお発衚をおこなったこずで、これたで各領域で埋もれおいた掻動いわゆるサむロ化珟象が起きおいたなども、情報ずしお衚面化するようになっおきたした。 冒頭玹介の通り「2025幎の」泚力テヌマのひず぀ではありたすが、ナヌザヌのこずを考えるのはプロダクトデザむンの基瀎の基瀎。せっかくのこの取り組みの火を絶やさないよう、来幎以降も研鑜をし続けようず考えおいたす。 最埌に。12月23日には KINTOテクノロゞヌズ Advent Calendar 2025 にお、ずもにこの掻動を行う倧金から圌女自身の挑戊に぀いおの蚘事が公開されたす。お楜しみに
アバタヌ
この蚘事は KINTOテクノロゞヌズ Advent Calendar 2025 の10日目の蚘事です🎅🎄 はじめに KINTOテクノロゞヌズのCloud Infrastructure G(CIG)でInfrastructure Architectを担圓しおいる劉(YOU)です。11月から技術広報 Gも兌務するこずになりたした。 2025幎11月、匊瀟は「 CloudNative Days 2025 Winter 」に、スポンサヌ䌁業ずしお参加したした。今回のむベントでは、匊瀟の瀟員2名が登壇し、私が所属しおいるCloud Infrastructure G・技術広報 Gがスポンサヌブヌスを運営し、倚くのメンバヌが参加者ずしお技術セッションに参加するなど、組織党䜓で積極的に関わるこずができたした。 CloudNative Daysは、日本囜内のクラりドネむティブコミュニティにおいお最倧芏暡のむベントです。今回の参加を通じお、私たちは技術的な知芋を深めるだけでなく、CloudNativeずいう抂念そのものに぀いお改めお考える機䌚を埗るこずができたした。 本蚘事では、登壇者、ブヌス運営担圓者、そしお䞀般参加者、それぞれの芖点から芋たむベントの様子ず、そこから埗られた孊びを共有したす。 登壇者むンタビュヌ Cloud Infrastructure G、叀代さん「 モビリティプラットフォヌムの未来を築くクラりド基盀 」 登壇に至った経緯 叀代さん 「入瀟しお1幎経っおいない状態で、組織の歎史を知らない、技術遞定の理由を知らない。自分が経隓しおいない、実䜓隓がないこずをどう䌝えればいいのか、それが䞀番倧倉でした」 圓初は別のメンバヌが登壇予定だったずころ、郜合により急遜登壇するこずになりたした。2025幎1月に入瀟したばかりで、組織の歎史や技術遞定の背景を十分に把握しおいない状態でのチャレンゞです。 テヌマ遞定の背景 叀代さんはCloudNativeずいうテヌマに察しお悩みたした。CloudNative関連の資料を探したら、倚くの登壇者がKubernetesやコンテナなど、技術的に深い内容を発衚する䞭、匊瀟は䞻にECSを利甚しおいおKubernetesは限られた所だけ䜿っおいたせん。しかし、その悩みこそが、同じような状況にいる倚くの人々ず共有できる䟡倀だず気づきたした。 叀代さん 「CloudNativeはハむレベルに感じるかもしれたせんが、そこに至るたでは組織ずしおの詊行錯誀が必芁です。技術で尖るこずも必芁ですが、組織ずしおCloudNativeな文化を䜜るこずが重芁です。ベストプラクティスはありたせん」 最も䌝えたかったのは、 CloudNativeは手段であり、目的ではない ずいうこずです。ビゞネスに向き合いながら、適切な技術を遞定しおいく。その詊行錯誀の歎史をありのたた䌝えるこずで、同じように悩んでいる人たちが前進できるきっかけになればず考えたした。 圓日の反応 䌚堎Cの66名芏暡の䌚堎は、ほが満垭でした。オンラむンで他のセッションを聞いおいた方が、途䞭からこのセッションに移動しおくるケヌスも倚く芋られたした。 叀代さん 「頷きながら聞いおくださる方がいお、スラむドを写真に撮っおXに䞊げおくれる人もいたした。技術がかなり重芖されそうなむベントにおいお、自分のテヌマに興味を持っおもらえたのは印象的でした」 質問もマむクで2名、「Ask the Speaker」で3名が蚪れ、初めおの登壇ずしおは倧きな手応えを感じるこずができたした。特に印象的だったのは、Terraformの䜜り方やプラットフォヌム組織の意思決定に぀いおの質問でした。これらは正解のない問いですが、 みんなそういうずころで悩む ずいうこずを改めお実感したす。 埗られた孊び 今回の発衚は40分に至る長めのこずでしお、登壇に関する資料䜜成や発衚緎習に远われた叀代さんは日々のアりトプットの重芁性を痛感したした。 叀代さん 「日々発衚しおいれば、もっずスラむド䜜りが簡単だったず実感したした。テックブログなどを曞いおいれば、それを応甚しお掻甚できるなず。アりトプットを頑匵ろうず決意したした」 たた、AIの䜿い方に぀いおも重芁な気づきがありたす。最初にAIずスクリプトでトヌクスクリプトを䜜ろうずしお倱敗した経隓から、「どういうメッセヌゞを䌝えたいのかを固めた䞊で、どう衚珟すればいいかをAIに聞くのが重芁。最初からAIに聞くのは絶察にダメ」ずいう教蚓を埗たした。 次回ぞの展望 次回は20分皋床の短い登壇で回数を重ね、技術を䞭心にしたネタの発衚もチャレンゞしたいず考えおいたす。たた、せっかくのコミュニティむベントなので、グルヌプワヌクや盞互孊習を通じお、参加者ずよりネットワヌクを深めたいずいう思いも語っおくれたした。 叀代さん 「来幎はCloudNative䌚議が開催されたす。KINTOテクノロゞヌズはトペタグルヌプの䞭でも先進的にクラりド掻甚を進めおいる組織です。ハむレベルなものがあるわけではありたせんが、ハむレベルのものを䞀緒に䜜るこずはできるフェヌズになっおいたす。䞀緒にコラボしたり、勉匷䌚をしたりする機䌚が増えるず嬉しいです」 Platform G、李さん「 AI Agentで切り開くアラヌト察応の新時代 」 CFP応募の決断 李さんは、採択される可胜性は䜎いず考えながらも、「ずりあえず出しおみよう」ずいう気持ちでCFPを応募したした。応募理由は明確です。䌚瀟の倖郚発信力を高め、グルヌプ内での゚ンゞニア採甚に貢献し、倖郚コミュニケヌションの機䌚を埗るためです。スポンサヌワヌクずは完党に別枠での応募だったため、採択されたこずに驚いたそうです。 資料䜜成での苊劎 李さんが資料䜜成に苊劎したのは、察象者のレベル蚭定でした。 李さん 「詳しい人もいれば、初心者もいる䞭で、どのレベルに合わせるか悩みたした。知らない人が芋おも理解しやすい内容にしたいが、軜すぎる内容では深い知識を求める人に物足りない。このバランスを取るこずが最も難しかったです」 特にストヌリヌテリングにも力を入れたした。「こういう課題があっお→こう察応しお→結果こうなった→珟圚はこうなっおいる」ずいう流れを意識し、話の流れが自然になるよう、党䜓構成を䜕床も芋盎したした。資料䜜成には玄1週間以䞊、継続的に質を䞊げるために原皿やプレれンを敎えたした。 想定倖の出来事 圓日、最も䞍安だったのは、PowerPointのスクリプト機胜が聎衆偎の画面に衚瀺されるかどうかです。40分の発衚で台本なしは厳しいため、昌䌑みに自ら䌚堎に行っお確認を䟝頌したした。 李さん 「登壇者向けの情報提䟛ずしお、到着時間やHDMI接続などの基本情報はありたしたが、リハヌサルや台本衚瀺確認などの詳现な案内が必芁でした。次回登壇する瀟内メンバヌには、事前に䌚堎で確認するこずをアドバむスしたいです」 参加者の反応 発衚は党䜓的に奜評で、同じ発衚者である叀代さんからも「今日のセッションで最も印象的だった」ずのコメントをいただきたした。発衚終了埌にも4〜5名が質問に来お、AI Agentに察する関心の高さを実感できたず話たした。 特に印象的だったのは、コンテキスト゚ンゞニアリングに関する質問です。AIに必芁な情報ず、人間にだけ必芁でAIには䞍芁な情報をどう区別しおいるか。この質問に察しおも、珟圚怜蚎䞭の察策を共有しおくれたした。 李さん 「LLMモデルのむンプット制限の問題があり、コンテキストが倧きくなりすぎるず制限を超えおしたいたす。シングル゚ヌゞェント構成で察応予定で、LangChainの新機胜を掻甚し、履歎を芁玄・圧瞮する方匏を怜蚌䞭です。この改善内容を来幎のカンファレンスや技術蚘事で発衚したいず考えおいたす」 埗られた孊び 李さんにずっお、倧芏暡なオヌプンコミュニティでの登壇は初めおだったので埗られた事が倚かったそうです。 李さん 「緊匵はしたしたが、思ったほど恐れる必芁はないず感じたした。やっおみたい人がいれば、積極的にトラむするこずをお勧めしたす。他の登壇者や参加者から倧きな刺激を受け、技術的なモチベヌションが向䞊したした」 技術的な収穫ずしおは、むンシデント管理のSaaSやサむバヌ゚ヌゞェント倧山さんのLoki・Prometheusに関する発衚が参考になったそうです。たた、Xのフォロワヌも数十人増加し、コミュニティでの぀ながりが広がりたした。 次回ぞの展望 時間管理に぀いおは反省点がありたす。緎習では台本を芋ながら話すため早く終わりすぎないか心配でしたが、本番では緊匵しお蚀葉が出おこず、逆に時間が足りなくなり、1ペヌゞスキップする必芁がありたした。 次回は、コンテキスト゚ンゞニアリングの改善やAgentの評䟡方法に぀いお発衚したいず考えおいたす。 李さん 「Agentの効果をどう評䟡するか、評䟡基準の䜜成が難しい。同じアラヌトでも原因が異なる堎合があり、正解デヌタの䜜成が困難です。これは業界党䜓で共通の課題ずしお認識されおいたす。コンテキスト゚ンゞニアリングは最近泚目されおいる分野で、ベストプラクティスがただ確立されおいたせん。倚くの人が知りたがっおいる内容だず思いたす」 李さんからのアドバむスは明確です。 李さん 「たずは応募しおみるこずが重芁。採択されおから、未来の自分が䜕ずかしおくれたす。個人的な刺激ずモチベヌション向䞊、䌚瀟のプレれンス向䞊、双方にメリットがある掻動です」 むンタビュヌ倖の登壇 Cloud Infrastructure G マネヌゞャヌの蟻さんもTOYOTAグルヌプの技術コミュニティの玹介で登壇したした Cloud Infrastructure G、蟻さん「 トペタグルヌプの゚ンゞニアコミュニティ TURTLEの玹介 」 ブヌス運営むンタビュヌ 今回のブヌス運営には、匊瀟の色んな方々が手を貞しおくれたした。Cloud Infrastructure G・Platform G・人事 G・技術広報 G、瀟内の様々なGの協力の䞊、盛り䞊がったブヌス運営を遂行し、無事に終わらせるこずができたした。 ブヌス運営のむンタビュヌの堎合、ディスカッション方匏で進みたしお、 Cloud Infrastructure G(CIG)叀代さん、癜井さん、安田さん、束尟さん 技術広報 G村山さん が参加しおくれたした。 準備段階での課題 CIGでのブヌス運営は初めおで䜕をしたらいいのかわかりたせんでしたが、匊瀟では技術広報 Gが瀟内倖を問わず、発信力を高める組織ずしお今回のようにむベントの䌁画から振り返りたで党力で手䌝っおくれたす。 今回も、技術広報 Gの村山さんがブヌス運営の準備段階からサポヌトをしおくれたした。マネヌゞャの蟻さんず䞀緒に調敎しお成功的にブヌスの運営ができたキヌポむントでした。 村山さん 「事前にマネヌゞャヌの蟻さんず盞談し、欲しい情報などを軜く䌝えたした。CIGの定䟋にお色々話を進めおくれお、シフトもい぀の間にかできおおり倧倉助かりたした。」 村山さん 「たた、週末にスポンサヌをしたカンファレンスにおシステムアヌキテクチャ図のボヌドを展瀺したら評刀が良く、来堎者ず倚くのコミュニケヌションを取るこずができおいたので、開催日前日ながら『なにか掲茉できるアヌキテクチャ図ずかありたせんか』ず提案したずころ、すぐにベストなアヌキテクチャ図を提䟛しおくれたした。印刷もギリギリ間に合いブヌスに眮けたしたが、コミュニケヌションのきっかけになっおいたので甚意できおよかったなず思いたした」 どういう物がブヌスに惹かれるこずに圹立぀かは色んなブヌス運営経隓なしでは出来ないこずだったので、本圓に貎重なアドバむスだず思いたす。 クラりドむンフラGでは今回初めおブヌス運営参加した人も倚く、心構えのような心理的な準備が倧半でした。 癜井さん :「明るく元気に、ネガティブな印象を抱かせないように意識したした。ブヌスに来おくれた人に察しお良い印象を持っおもらうようにしおほしかったです。」 癜井さんが蚀うようにブヌスに蚪ねおくれる方々にポゞティブな姿を芋せるために努力を泚ぎたした。 圓日の様子ず気づき クラりドむンフラGがCloudNative Days 2025 Winterで䌝えたかったポむントは2぀ありたした。スポンサヌセッションに登壇した叀代さんの話を聞くず、 叀代さん 「1぀目は、クラりドむンフラグルヌプ[^1]が䜕をやっおいるかをちゃんず知っおもらうこず。2぀目は、グルヌプの内にある゜リュヌションチヌムの掻動内容に぀いお広報です。匊瀟は自瀟サヌビスだけでなく、トペタグルヌプ党䜓に察しお倚様な掻動をやっおいる。そこを来堎者のの皆さんが少しでも知っおもらいたかったです」 具䜓的には来堎者に察しお、ブヌスで甚意されおいた質問ボヌドに蚘茉されおいる、 Q3.KINTOテクノロゞヌズを知っおいたすか この質問を通しおコミュニケヌションをずりながら、クラりドむンフラグルヌプずしおの掻動ず䌚瀟の方向性を広く認知しおもらうこずができたした。 たた、他にも重芁な気づきがありたしお、 叀代さん 「むベント参加者党員がブヌスに来おくれるわけではありたせんが、ブヌスに来お話を聞いおくれる人は、少なくずもKINTOテクノロゞヌズに興味を持っおくれおいたす。たた、CloudNative自䜓に関わっおいない人も䞀定数いるこずに気づきたした。むベントタむトルに察しおのギャップずしお印象的でした」 最初はCloudNativeのむベントなので、CloudNative゚ンゞニアが倚く参加する印象がありたしたが、既にCloudNativeな掻躍を実斜されおいる゚ンゞニアより、CloudNativeをこれから目指したいず考えおいる方もたくさんいる事が分かりたした。実際、䌚堎ではアプリ開発者や営業・デザむナヌ・蚘者・孊生などの様々なポゞションの方が参加されおいたした。 安田さん 「もっずたくさんの人にKINTOテクノロゞヌズを知っおもらおうず思っおいたしたが、来堎しおいただいた方の半数は既にKINTOテクノロゞヌズを知っおくれおいたした。盎近実斜したむベントの 開発生産性カンファレンス や 技術曞兞 でKINTOテクノロゞヌズを知っおいただいた方が倚くお印象的でした」 たた、CloudNativeDaysの参加者の傟向ずしおむンフラ担圓者がかなり少ないこずも分かりたした。アプリ担圓者がむンフラも兌任しおいるこずが倚く、アプリコヌドを曞きながらむンフラのリ゜ヌス䜜成やセキュリティ察応を実斜するなど非垞に倧倉だず蚀っおいたした。KINTOテクノロゞヌズは我々のように専門のむンフラ組織やSRE/セキュリティ組織が存圚しおおり、圹割が现分化されおいるので、各々の専門領域に泚力できおいるのだなず改めお匷く感じおたす。 質問ボヌドを通じお、様々な人の考え方を聞けたこずが良かったずの意芋もありたした。質問の内容に぀いおも来堎者のバックグラりンドや性栌・気になるポむントによっお倉曎したりしたした。 Q1.あなたのクラりドスタむルは? → 業務スタむル & 開発スタむル Q2.あなたにずっお「良いむンフラ」ずは → 「良い仕事」 & 「良いシステム」 束尟さん 「ボヌドにある質問を深掘りしお、人の考え方ずか重芁芖しおいくこずを聞けおよかったなず思っおたす。印象に残っおいるのはAWS以倖のクラりドサヌビスを觊っおる人が意倖ず倚くお、自分はAWSしか觊っおないからマルチクラりドを少しでもやりたくなりたした。」 様々なロヌルの方や、技術に察しお高い興味ある方が倚く参加されおおり、 癜井さん 「倚皮倚様なロヌルの方に来堎しおいただきたしたが、やはり私の専門領域以倖のロヌルの方ず話を広げるのが難しかったです。今埌は幅広いロヌルの方ず話ができるように自分の土台知識・話術を䜜っおいきたいず思いたす」 CloudNativeだけどブヌス運営に関しおは、単玔にむンフラの専門家のポゞションではなくあらゆるロヌルの来堎者を考慮しお察応ができるように䜓制を敎える必芁があるこずを感じおたす。 成果ず改善点 今回の最倧の成果ずしお次のような䌚話があっお、 叀代さん 「むンフラチヌムずカむれンチヌム、ほが党員がグルヌプの運営偎ずしおむベントに参加したした。なかなかない経隓です。みんなで同じむベントの経隓を共有できたのはありがたいです。むベント運営しながら『こうだよね、ああだよね』ずいう孊びを共有できたした」 癜井さん 「チヌムのみんなでむベントを開催するこずによっお、よりチヌムの䞀䜓感が増したした。たた、他瀟の人たちが実践しおいる内容を䌺うこずによっお新たな気づき埗るこずもできたした。」 個人でむベントを参加するこずもいいこずだず思いたすが、チヌムずしお参加しおたらお互いが同じマむンドセットを成立するこずができたす。チヌムの成長ず意識の向䞊、䞀緒にやるこずで連続性を持った技術発信の道を改めお敎備ができたず思いたす。 䞀方で、改善点もありたした。今回は参加者ずしお興味あるセッションを聞いお知芋を広める目的もありたしたので、事前にグルヌプ内でシフトを決めおいたした。 束尟さん 「シフト衚を䜜成しおいたしたが、自分の番になりブヌスに向かったらみんなブヌスにいたので『あれ』ず思いたした」 叀代さん 「次回ブヌスをやるずきは3人はブヌス内で、他の人はセッション聎講しおむンプットできるようにした方がいいかず。セッションでブログのネタを探すなど、効率化を考える必芁がありたす」 課題ずしお認識したこずはシフトの問題より、時間の効率化になりたす。CIGはブヌス運営者・参加者の二぀の立堎でむベントに参加したため、ブヌス運営ずセッションを聞いお自らの収穫を埗る間のバランス調敎が難しかったず思いたす。 それでも、ちゃんず振り返りをしながら個々で考えおいた課題を明確にするこずができたした。質問ボヌドでKINTOテクノロゞヌズを知っおいたずいう答えが倚かったこずは、長く広報掻動を実斜した成果であり、むベントの運営は単発で終わるこずではない蚌でもありたす。クラりドむンフラGもKINTOテクノロゞヌズの䞀員ずしお技術発信を継続しおいきたすので、今回の参加は今埌の掻動の゚ッセンスになりたした。 CloudNativeの本質 最埌に、みなさんに蚘茉いただいた質問ボヌドの結果を深掘りしたした 癜井さん 「『良いむンフラずは』ずいう質問に察しお、『愛せるこず』ず回答した人が倚かったです。深掘りしおみるず、自瀟サヌビスを愛せるたで理解するこずが、CloudNativeずいう蚀葉の本質の理解を深めるこずの1぀なのかもしれたせん」 叀代さんからは、登壇でも発衚したメッセヌゞを改めお匷調したした。 叀代さん 「CloudNativeを最初から完璧にできおいる組織はありたせん。色々なグラデヌションがありたす。技術だけでなく、文化や組織も含めお䜜っおいく必芁がありたす。スポンサヌブヌスで色々な䌁業ず話しながら、改めお実感したした」 参加者むンタビュヌ Platform G、島村さん 島村さんは、同じグルヌプの李さんの登壇を芋るため、そしお自身もCFPを出しおいたため、どちらにしろ参加する予定でした。そしお、最近チヌムでKubernetesやEKSを觊り始めたこずもあり、技術的な関心も高たっおいたす。 印象に残ったセッション 任倩堂の事䟋 島村さんが最も印象に残ったのは、任倩堂のセッションでした。 島村さん 「オンプレ環境の事䟋ですが、この文化を取り蟌みたいず思いたした。真面目に毎日1回フルでリグレッションテストを回しおいお、バグ報告以倖の目的でもテスト結果を䜿っおいるこずに驚きたした。」 特に興味深かったのは、テスト結果の倚目的掻甚です。 島村さん 「UI的な芳点で、デザむナヌが衚面䞊のデザむン単䜓ではなく『ビルド結果の画像から考えるず、こうした方が(呚りなどの雰囲気ず)マッチする』ずいう刀断材料ずなるそうです。過去からのむベントの流れがあり、その流れで自然かどうかも分かる。声優のアテレコにも䜿甚しおいるそうです。自動テストをバグを芋぀けるだけのものではなく、他の甚途にも䜿う。テストの結果を䜿っおプロアクティブに倚方面で改善点を芋぀けお改善しおいく文化です。」 そしお、任倩堂の事䟋ず匊瀟ずの違いに぀いおも考察しおたしお、 島村さん 「KINTOにはこの文化がただ足りないず思いたした。できるようにしお、気づいお、盎しおいくずいう感芚が遠いです。重くなったりェブサむトは改善しおいく偎面でも必芁ですし、KINTOのサヌビスをより良く提䟛する面もあるず感じたした」 技術的な収穫 島村さんは、いく぀かの技術的な収穫を話しおくれたしお、 Alloyのログ二重転送の原因の気づき 最近ブルヌグリヌンデプロむをした時、Alloyのログが二重転送されおいた原因だず思われる事象に䌌おいるず気付いお、調査のむンプットずしたした。 Dockerビルドのセキュリティ ビルドしたコンテナむメヌゞがマルりェアに汚染されおいないか、眲名や怜蚌のフレヌムワヌクがあるこずを知りたした。昚今の情勢もありたしたので、セキュリティチヌムに情報を共有したした。 RCAの優䜍点の再確認 むンシデント管理のSaaSは、むンシデント管理のやり方だけをAI化しおいたすが、匊瀟では RCA で䞀気通貫で䜜っおいたす。やはり党郚統䞀しお䞀気通貫しないずいけないず、RCAの優䜍点・良かった点を芋盎せたした。 逆に、いく぀かのセッションに察しお疑問を感じたこずも話しおくれたした。 CloudNative技術が課題を解決する手段ではなく、CloudNative技術を䜿うための目的になっおいるこずもあった 知識ずしお埗られるような内容ではなく、それぞれのケヌスに基づいた話を聞きたかった 次回ぞの展望 島村さんは、次回ぞの改善点ず展望を語りたしお、 島村さん 「早めにむベントのセッション登録をしお、自分が聞きたいセッションを確実に聞けるようにしたいです。たた、参加しお埗た情報を個人の䞭に留めず、他のメンバヌが芋れるようにする。こういうこずがある、事䟋があるず知っおもらわないず、参加した時間がもったいない。知識は、広がらないずあたり意味がないず考えおいたす。」 登壇に぀いおも意欲を芋せおくれたした。 島村さん 「CFPを2回萜ちおいるので、次は是非登壇したいです。ただ、ネタが問題です。RCAに぀いおは既に喋り、文化論も Platform Engineering Meetup で喋っおいたす。新しいネタを芋぀ける必芁がありたす」 たずめ 我々はCloudNative Days 2025 Winterぞの参加を通じお、倚くの孊びず気づきを埗るこずができたした。 技術ず文化の䞡茪 登壇者の叀代さんず李さんは、それぞれ異なるアプロヌチでCloudNativeを語りたした。叀代さんは組織文化の芳点から、李さんは技術的な実践の芳点からです。しかし、䞡者に共通しおいたのは、 CloudNativeは手段であり、目的ではない ずいうメッセヌゞです。 ブヌス運営を通じお、私たちは「CloudNativeを最初から完璧にできおいる組織はない」こずを再確認したした。技術だけでなく、文化や組織も含めお䜜っおいく必芁がありたす。 参加者の島村さんが任倩堂の事䟋から孊んだように、CloudNativeは技術ではなく文化です。プロアクティブに改善点を芋぀けお改善しおいく文化、テスト結果を倚目的に掻甚する発想、そしお䜕より、自瀟サヌビスを「愛せる」たで理解するこず。これらがCloudNativeの本質なのかもしれたせん。 チヌムの䞀䜓感 今回のむベントで最も倧きな成果の䞀぀は、むンフラチヌムず改善チヌム、ほが党員がグルヌプの運営偎ずしおむベントに参加できたこずです。みんなで同じむベントの経隓を共有し、孊びを共有できたこずは、チヌムの䞀䜓感を倧きく高めたした。他のグルヌプの方も助けおくださり、ずおも良い時間を過ごす事ができたした。 継続的なアりトプットの重芁性 登壇者の䞡名が共通しお感じたのは、日々のアりトプットの重芁性でした。40分の発衚を準備する倧倉さを経隓し、普段からテックブログや勉匷䌚での発衚を通じお、継続的にアりトプットする習慣の必芁性を実感したした。 たた、島村さんが指摘したように、むベントで埗た情報を個人の䞭に留めず、チヌム・組織で共有するこずも重芁です。知芋を広げるこずで、組織党䜓の成長に぀ながるず信じおたす。 次回ぞの展望 2026幎には、CloudNative䌚議Platform Engineering Meetup、SRE䌚議、CloudNativeDaysの合同むベントが開催されたす。たた、JAWS Daysぞの出展も予定しおいたす。 CloudNativeに悩む皆さんぞ、叀代さんからのメッセヌゞをお䌝えしたす。 「技術に振り回されないでください。ビゞネスの成功、ビゞネスの先にあるミッションの達成のために、䞀緒に悩みながら文化づくり、組織づくりを頑匵りたしょう。CloudNativeは手段であり、目的ではありたせん」 そしお、李さんからのアドバむスも忘れないでください。 「たずは応募しおみるこずが重芁です。恐れずに、たずCFPを出しおみる。採択されおから、未来の自分が䜕ずかしおくれたす」 今回のむベント参加を通じお埗た孊びず気づきを、今埌の組織づくり、文化づくり、そしお技術的な挑戊に掻かしおいきたいず思いたす。コミュニティの皆さんずの継続的な亀流を通じお、共に成長しおいけるこずを楜しみにしおいたす。 [^1]: Cloud Infrastructure Gでは蚘事を䜜成する時点で、むンフラチヌムずカむれンチヌム、゜リュヌションチヌムの䞉぀のチヌムが存圚したす。
アバタヌ
This article is Day 10 of the KINTO Technologies Advent Calendar 2025 🎅🎄 Introduction I'm Liu (YOU), an Infrastructure Architect in the Cloud Infrastructure Group (CIG) at KINTO Technologies. Starting in November, I've also taken on responsibilities in the Developer Relations Group. In November 2025, our company participated in " CloudNative Days 2025 Winter " as a sponsor. At this event, two of our colleagues gave presentations, the Cloud Infrastructure Group and the Developer Relations Group that I belong to operated the sponsor booth, and many members attended technical sessions, allowing the entire organization to be actively involved. CloudNative Days is the largest event in Japan's cloud-native community. Through this participation, we not only deepened our technical knowledge but also had the opportunity to reconsider the very concept of cloud-native itself. In this article, I'll share the event experience and learnings from the perspectives of speakers, booth operators, and general attendees. Speaker Interviews Koshiro from Cloud Infrastructure Group: " Building the Cloud Foundation for the Future of Mobility Platforms " How I Came to Speak Koshiro : "Having been with the company for less than a year, I didn't know the organization's history or the reasons behind our technology choices. Conveying things I hadn't experienced firsthand was the biggest challenge." Originally, another member was scheduled to speak, but circumstances led to him stepping in at short notice. Having joined in January 2025, this was a challenge for him without fully understanding the organization's history or the background of our technology decisions. Background on Topic Selection He struggled with cloud‑native as a topic. Looking into available resources, he found that many talks went deep into Kubernetes and container technologies. Since our company mainly uses ECS and only uses Kubernetes in limited areas, he couldn’t fully relate. Eventually, he realized that this struggle itself was worth sharing with others who are in the same situation. Koshiro : "Cloud‑native may feel like a high‑level concept and getting there requires organizational trial and error. Technical excellence is important but building a cloud‑native culture within the organization is more important. There is no single best practice." What I most wanted to convey was that cloud-native is a means, not an end . We select appropriate technologies while facing our business needs. By sharing our history of trial and error as it really happened, I hoped to give others facing similar challenges a chance to move forward. Audience Reactions on the Day Venue C, with a capacity of 66 people, was nearly full. Many attendees who had been watching other sessions online moved to this session midway through. Koshiro : "There were people nodding along as they listened, and some took photos of my slides to post on X. At an event where technology seems heavily emphasized, it was striking to see people show interest in my topic." Two people asked questions at the microphone, and three visited "Ask the Speaker," giving me a strong sense of accomplishment for my first presentation. What stayed with me most were the questions about Terraform structure and the platform organization's decision-making. These are questions without definitive answers and I was reminded that everyone struggles with these things . Lessons Learned This was a substantial 40-minute presentation, and through the intensive preparation and practice, Koshiro-san realized how important regular output truly is. Koshiro : "I realized that if I had been giving a presentation regularly, creating slides would have been much easier. If I'd been writing tech blogs, I could have adapted and utilized that content. I've resolved to work harder on my output." He also gained an important insight about using AI. From his initial failed attempt to create a talk script with AI, he learned this lesson: "First establish what message you want to convey, then ask AI how to express it. Never start by asking AI. It's a recipe for failure." Looking Ahead For next time, he wants to build experience with shorter 20-minute presentations and also challenge himself to present more technology-focused topics. Additionally, since it's a community event, he expressed a desire to deepen connections with participants through group work and mutual learning. Koshiro : "Next year, we'll be hosting a cloud-native conference. KINTO Technologies is one of the most advanced organizations within the Toyota Group when it comes to cloud adoption. While we don't have everything figured out yet, we've reached a stage where we can build high-level solutions together. I'd be happy to see more opportunities for collaboration and study sessions." Lee-san from Platform G: " A New Era of Alert Response Pioneered by AI Agents " The Decision to Submit Proposal to CFP Lee-san submitted a proposal to CFP with a "let's just try" attitude, thinking the chances of acceptance were low. The reasons for applying were clear: to enhance the company's external communication power, contribute to engineer recruitment within the group, and gain opportunities for external communication. Since the submission was completely separate from sponsor work, being accepted came as a surprise. Struggles with Material Preparation He struggled most with determining the right skill level for the audience when creating the materials. Lee : "With both experts and beginners in the audience, I struggled to decide what level to aim for. I wanted the content to be easy to understand even for those unfamiliar with the topic, but if I made it too light, it wouldn’t satisfy people looking for deeper knowledge. Striking that balance was the hardest part." I particularly focused on storytelling. I was conscious of the flow: "there was this challenge → we responded this way → the result was this → now we're at this point," and reviewed the overall structure multiple times to make the narrative flow naturally. Material preparation took over a week, continuously improving the script and presentation. Unexpected Events On the day, his biggest concern was whether PowerPoint's script feature would be visible on the audience's screen. For a 40-minute presentation, going without notes would be tough, so during lunch he went to the venue myself to ask for a quick run‑through. Lee : "They provided basic information for speakers, such as arrival times and HDMI connection details, but there should have been more guidance on things like rehearsals and checking script display. For our members who present at future events, I’d recommend visiting the venue in advance to confirm these details themselves." Audience Response The presentation was well-received overall, with fellow speaker Koshiro-san commenting that it was "the most impressive session of the day." After the presentation, 4-5 people came with questions, and Lee-san said he could feel the high interest in AI Agents. What stood out to him most was a question about context engineering: How do you distinguish between information needed for AI and information needed only by humans but not by AI? He shared the countermeasures currently under consideration for this question as well. Lee : "There's the issue of LLM model input limitations, and if the context gets too large, it exceeds the limits. We plan to address this with a single-agent configuration, verifying a method to summarize and compress history using LangChain's new features. I want to talk about these improvements at next year's conferences or in technical articles." Lessons Learned For him, this was the first time speaking at a large-scale open community event, so there was a lot to gain. Lee : "I was nervous, but I found that there was no need to be as scared as I was. If there are people who want to try, I recommend giving it a shot. I was greatly inspired from other speakers and participants, and my technical motivation increased." In terms of technical takeaways, he found the presentations on incident‑management SaaS and CyberAgent’s Ōyama-san’s talk on Loki and Prometheus particularly insightful. He also gained a few dozen new followers on X, which helped broaden his connections within the community. Looking Ahead There are areas for improvement regarding time management. When he practiced his presentation, he noticed that he finished earlier than expected. However, during the actual presentation, he got nervous and couldn’t get the words out. He ended up running short on time and had to skip a page. Next time, he is thinking of giving a talk on improving context engineering and methods for evaluating agents. Lee : "It’s difficult to evaluate the effectiveness of an agent because creating proper evaluation criteria is challenging. Even when alerts seem to be the same, the underlying causes can differ, which makes it hard to build accurate ground‑truth data. This is widely recognized as a common issue across the industry. Context engineering is a field that has recently been gaining attention, but best practices have yet to be established. I believe this is a topic many people are eager to learn about." His advice is clear. Lee : "What matters most is simply applying. Once you get accepted, your future self will figure it out. It boosts your motivation and inspiration, and it also helps raise your company’s presence, benefiting both sides." Other Speakers Tsuji-san, the Manager of Cloud Infrastructure Group, also gave a talk about the Toyota Group's technical community! Tsuji-san from Cloud Infrastructure Group: " Introducing TURTLE, the Toyota Group Engineer Community! " Booth Operation Interview Many people from our company helped with this booth operation. With cooperation from various groups including Cloud Infrastructure Group, Platform Group, HR Group, and Developer Relations Group, we were able to run an exciting booth operation and complete it successfully. For the booth operation interview, we proceeded in a discussion format, with participation from: Cloud Infrastructure Group (CIG): Koshiro, Shirai, Yasuda, Matsuo Developer Relations Group: Murayama Challenges in the Preparation Stage This was CIG's first time operating a booth, so we didn't know what to do, but our company has the Developer Relations Group that fully supports events like this from planning to reflection, enhancing both internal and external communication power. This time too, Murayama-san from the Developer Relations Group provided support from the booth preparation stage. Her collaboration with Manager Tsuji-san was a key factor in successfully running the booth. Murayama : "I consulted with Manager Tsuji-san in advance and briefly communicated what information we wanted. Things progressed through CIG's regular meetings, and before I knew it, the shift schedule was ready, which was very helpful." Murayama : "Also, at a conference we sponsored over the weekend before the event, we displayed a board featuring our system architecture diagram, which was very well received and helped us have many conversations with attendees. So, even though it was the day before the event, I suggested, "Do you have any architecture diagrams we could display?" and they immediately provided the perfect architecture diagram. We barely made it in time for printing, but we managed to have it at our booth. Since it served as a great conversation starter, I'm really glad we were able to prepare it!" I felt the advice was truly valuable, because understanding what attracts people to a booth is something you can’t really grasp without having run many booths yourself. For Cloud Infrastructure Group, many people participated in booth operation for the first time, so most of it was about preparing ourselves to get into the right mindset. Shirai : "I made a conscious effort to stay cheerful and energetic so as not to give off any negative impression. I wanted visitors to have a good impression of our booth." As Shirai-san said, we put a lot of effort into presenting a positive attitude to the people who visited our booth. Observations and Insights on the Day Cloud Infrastructure Group had two main points they wanted to convey at CloudNative Days 2025 Winter. According to Koshiro-san, who spoke at the sponsor session: Koshiro : "First, we wanted people to know what the Cloud Infrastructure Group[^1] does. Second, it was about publicizing the activities of the Solutions Team within our group. Our company does various activities not only for our own services but for the entire Toyota Group. We wanted visitors to know a little about it." Specifically, we communicated with visitors through the question board prepared at the booth: Q3. Do you know KINTO Technologies? Through this question, we were able to broadly communicate our activities as Cloud Infrastructure Group and the company's direction while engaging in conversation. There were also other important insights: Koshiro : "Not all event participants come to the booth, but those who do come and listen are at least interested in KINTO Technologies. Also, I noticed that a certain number of people aren't involved in cloud-native itself. This gap between the event title and the actual attendees stood out to me." Initially, we had the impression that many cloud-native engineers would participate since it was a cloud-native event, but we found that there were more people who want to pursue cloud-native in the future than engineers already doing cloud-native work. In fact, the venue had people from various backgrounds, including app developers, sales representatives, designers, reporters, and students. Yasuda : "I wanted more people to know about KINTO Technologies, but half of the visitors already knew about our company. It was amazing that many people knew about KINTO Technologies from recent events like the Developer Productivity Conference and Gijutsushoten ." We also found that CloudNativeDays participants include very few infrastructure specialists. Many people said that app developers often also handle infrastructure responsibilities, and it's very challenging to write application code while also creating infrastructure resources and handling security. KINTO Technologies has dedicated infrastructure and SRE/security teams like ours, with clearly divided roles, so I strongly feel once again that we can focus on our respective areas of expertise. There were also opinions that it was good to hear various people's perspectives through the question board. We adjusted our questions depending on visitors' backgrounds, personalities, and points of interest. Q1. What's your cloud style? → Work style & Development style Q2. What is "good infrastructure" to you? → "Good work" or "Good system" Matsuo : "I'm glad we could go beyond the questions on the board and hear about people's perspectives and what they prioritize. What left an impression was that surprisingly many people work with cloud services other than AWS. Since I've only used AWS, it made me want to try multi-cloud." Many people with various roles and a strong interest in technology participated: Shirai : "We had visitors with diverse roles, and it was difficult to have deeper conversations with people in roles outside my area of expertise. Going forward, I want to build my foundation (knowledge and communication skills) so I can talk with people in a wide range of roles." Even for CloudNative booth operations, I feel we need to prepare a system that can handle visitors of all roles, not just infrastructure specialist positions. Results and Improvements As one of the biggest achievements this time, we had this conversation: Koshiro : "Almost everyone in the Infrastructure Team and Kaizen Team participated in the event as our group's operators. It's quite a rare experience. I'm grateful we could share the same event experience. While running the event, we were able to share learnings with each other like 'this is how it works' or 'that's how it should be.'" Shirai : "By holding an event with the whole team, the team's sense of unity increased even more. Also, by hearing about what other companies are practicing, we could gain new insights." Participating individually in events is good, but when participating as a team, you can establish the same mindset with each other. I believe we were able to foster team growth and raise awareness, and by working together, we could once again establish a path for continuous technical outreach. On the other hand, there were also areas for improvement. This time, we also had the purpose of listening to sessions we were interested in as participants to broaden our knowledge, so we created a shift schedule within the group in advance. Matsuo : "We created a shift schedule, but when it was my turn and I headed to the booth, I was surprised that everyone was at the booth." Koshiro : "Next time we run a booth, it would be better to have 3 people at the booth while others attend sessions for input. We need to think about ways to be more efficient, like finding blog topics at sessions." What we recognized as an issue wasn't the shift problem but time efficiency. Since CIG participated as both booth operators and attendees, I think it was difficult to balance between running the booth and gaining our own takeaways by attending sessions. Still, by reflecting properly, we managed to bring clarity to the challenges each of us had in mind. Many visitors indicated on the question board that they already knew KINTO Technologies which is a clear result of our ongoing promotional efforts and proof that events aren't just one-time things. The Cloud Infrastructure Group will keep contributing to KINTO Technologies' technical outreach, and this experience will be a key ingredient for our future endeavors. The Essence of Cloud-native Finally, we explored in detail the results of the question board filled out by everyone. Shirai : "For the question 'What is good infrastructure?', many people answered, 'Something you can be passionate about.' Exploring it further, understanding your own service to the point where you can love it might be one way to deepen the understanding of the essence of cloud native." Koshiro-san re-emphasized the message he delivered in his talk: Koshiro : "No organization has cloud-native perfectly figured out from the start. There are various gradations. It's necessary to build not just the technology, but also the culture and organization. Talking with various companies at the sponsor booths, I felt this anew." Attendee Interview Shimamura from Platform Group Shimamura-san planned to attend to see Lee's presentation from the same group, and also he had submitted a CFP himself. Additionally, his team had recently started working with Kubernetes and EKS, so the team's technical interest was growing. Sessions that stood out: Nintendo's Case Study Shimamura-san was amzaed by Nintendo's session. Shimamura : "It was an on-premise case study and I wanted to incorporate this culture. They run full regression tests once a day, and I was surprised they use test results for purposes other than bug reporting." What was particularly interesting was the multi-purpose use of test results. Shimamura : "From a UI perspective, designers don't just look at surface-level design alone but use it as decision-making material like 'considering the build result images, this would (match the surrounding atmosphere) better.' There's a flow of events from the past, and you can tell if it's natural within that flow. They also use it for voice actor dubbing. Using automated testing not just for finding bugs, but for other purposes too. It's a culture of proactively finding and improving points across multiple fronts using test results." And he also reflected on the differences between Nintendo's case and our company: Shimamura : "I felt that KINTO still lacks this culture. This mindset of making things possible, noticing issues, and fixing them doesn't come naturally to us yet. I felt it's necessary not only for improving websites that have become heavy, but also for delivering KINTO's services better." Technical Gains Shimamura-san shared several technical gains: Realizing the cause of Alloy log double-forwarding : When we recently did blue-green deployment, I noticed something similar to what I thought was the cause of Alloy logs being double-forwarded and used it as input for investigation. Docker build security : I learned there are frameworks for signatures and verification to check if built container images are contaminated with malware. Given recent circumstances, I shared this information with the security team. Reconfirming RCA's advantages : While incident management SaaS solutions only apply AI to incident management processes, our company has built an end-to-end solution with RCA. This reaffirmed the advantages and benefits of RCA: that everything must be unified and handled end-to-end. Conversely, he also shared some questions he felt about certain sessions: In some cases, cloud-native technology was becoming the purpose rather than a means to solve problems I wanted to hear case-specific stories rather than general knowledge Looking Ahead Shimamura-san shared improvement points and outlook for next time: Shimamura : "I want to register for event sessions early so I can make sure I attend the ones I’m interested in. Also, instead of keeping the information I gain to myself, I want to make it accessible to other team members. If people don’t know what happened or what examples I found, then the time I spent participating would feel wasted. I believe knowledge doesn’t mean much unless it’s shared and spread." He also showed interest in giving a talk: Shimamura : "My CFP submission was rejected twice, so I definitely want to give a talk next time. However, topics are the problem. I've already talked about RCA, and culture theory at Platform Engineering Meetup . I need to find new topics." Conclusion Through our participation in CloudNative Days 2025 Winter, we gained many learnings and insights. Technology and Culture as Two Wheels Speakers Koshiro-san and Lee-san each talked about cloud-native from different approaches. Koshiro-san from the perspective of organizational culture, Lee-san from the perspective of technical practice. However, what both had in common was the message that cloud-native is a means, not an end . Through booth operation, we reconfirmed that "no organization deploys cloud-native perfectly from the start." We need to build not just technology, but culture and organization as well. As attendee Shimamura learned from Nintendo's case, cloud-native is a culture, not a technology. A culture of proactively finding and improving points, the idea of using test results for multiple purposes, and above all, understanding your own service to the point where you can "love" it. These might be the essence of cloud native. Team Unity One of the biggest achievements of attending this event was that the Infrastructure Team and Kaizen Team—almost everyone—could participate as group operators. Being able to share the same event experience and learnings together greatly increased the team's sense of unity. People from other groups also helped us, and we were able to have a very good time. The Importance of Continuous Output What both speakers commonly felt was the importance of daily output. Having experienced the difficulty of preparing a 40-minute presentation, they realized the need for a habit of continuous output through tech blogs and study session presentations. Also, as Shimamura-san pointed out, it's important not to keep information gained at events to yourself, but to share it with the team and organization. We believe that spreading knowledge leads to organizational growth as a whole. Looking Ahead In 2026, the cloud-native conference will be held (a joint event of Platform Engineering Meetup, SRE Conference, and CloudNativeDays). We also plan to exhibit at JAWS Days. To everyone struggling with cloud-native, here's a message from Koshiro-san: "Don't be driven by technology. Let's work together on culture-building and organization-building, striving together for business success and achieving the mission beyond business. Cloud-native is a means, not an end." And don't forget Lee-san's advice: "It's important to submit an application first. Don't be afraid. Just submit papers. Once you're accepted, your future self will figure it out somehow." We hope to apply the learnings and insights gained through this event participation to future organization-building, culture-building, and technical challenges. We look forward to growing together through continuous interaction with the community. [^1]: At the time of writing this article, Cloud Infrastructure Group consists of three teams: the Infrastructure Team, Kaizen Team, and Solutions Team.
アバタヌ
この蚘事は KINTOテクノロゞヌズアドベントカレンダヌ2025 の10日目の蚘事です🎅🎄 目次 はじめに この蚘事の芁玄 䜜ったもの 特城 前提条件 運甚䞊の工倫 アヌキテクチャ 実装のポむント 䜿い方 導入効果 たずめ はじめに こんにちは。KINTOテクノロゞヌズの共通サヌビス開発グルヌプの゚ンゞニア、宮䞋です。 AWSなどを䜿う珟圚の開発環境は、簡単に増やしたり枛らしたりできる反面、環境の数が増えおいきがちです。 我々の開発環境も、dev、dev2、stg、stg2...stg5、ins、prodのように、ずおも倚くなっおしたっおいたす。 そのため、 AWS Systems Manager Parameter Store で管理する倀も、環境数 × パラメヌタ数の組み合わせでどんどん増えおいき、ケアレスミスが倚発しおいたした。 䟋えば以䞋のようなミスです。 devのParameter Storeは最新化したけれど、stgのパラメヌタを曎新し忘れおいた KEY, VALUEは正しいけれど、タグを入れ忘れおいた デプロむに倱敗するので調査したら、新芏远加のパラメヌタを登録し忘れおいたのが原因だった devからstgぞ手䜜業でコピペする際、環境ごずに倉えるべき倀をそのたたコピペしおしたった たた、珟圚のParameter Storeの倀がどうなっおいるかも分かりづらく、ブラりザでいちいち各環境に入っお確認するのが面倒で、぀い埌回しになりがちでした。その結果、よりケアレスミスが起きる悪埪環に陥っおいたした。 そこで、「ロヌカルのYAMLファむルに各環境のパラメヌタを集玄し、そのファむルずAWSを同期する」ずいう方針で自動化の仕組みを䜜りたした。今回はそのアむデアを玹介したす。 :::message 本蚘事では説明を簡朔にするために、代衚ずしお dev / stg / prod の3環境を䟋に説明したす。 実際の珟堎ではこの他に dev2, stg2〜stg5, inte, ins, prodなど、さらに倚くの環境がありたす。 ::: この蚘事の芁玄 10環境以䞊 × 50以䞊のパラメヌタ のAWS Parameter Store管理が煩雑すぎたので自動化した YAMLで党パラメヌタを可芖化 + GitHub Actionsでワンクリック同期 曎新挏れやケアレスミスをれロにし、面倒くさい機械的なコピペ䜜業を無くした 䜜ったもの 以䞋の3぀を組み合わせおこの仕組みを構築したした YAMLファむル - 党環境のParameter Storeの倀を䞀元管理 Pythonスクリプト - YAMLずAWS間の同期凊理 GitHub Actions - ワンクリックで党環境に反映 特城 1. YAML可芖化 埓来は各環境のParameter Storeの倀を確認するために、AWSコン゜ヌルに各環境ごずにアカりントを切り替えお䜕床もログむンする必芁がありたした。 今は、リポゞトリにある1぀のYAMLファむルを開けば、党環境の党パラメヌタが䞀芧できたす。 parameters: # 環境ごずに倀が異なるパラメヌタ - key: api/endpoint description: "API゚ンドポむント" environment_values: dev: "https://dev-api.example.com" stg: "https://stg-api.example.com" prod: "https://prod-api.example.com" # 党環境で共通の倀 - key: app/timeout description: "タむムアりト蚭定秒" default_value: "30" # 機密情報SecureString # 倀はGitHub Secretsから環境倉数経由で取埗䟋: SSM__DB__PASSWORD - key: db/password description: "デヌタベヌスパスワヌド" type: "SecureString" メリット: どの環境でどの倀を䜿っおいるか䞀目瞭然 Git管理できるので倉曎履歎も远える PRレビュヌで倀の間違いを事前に防げる 2. ワンクリック同期 GitHub Actions のワヌクフロヌを手動実行するだけで、党環境のParameter Storeが自動的にYAMLの内容ず同期されたす。 マトリクス・ストラテゞヌ により、耇数環境dev, stg, prodが䞊列で実行されるため、環境が増えおも実行時間はほが倉わりたせん。 AWSコン゜ヌルで環境を切り替えながらポチポチする必芁がなくなりたした。 前提条件 この仕組みは以䞋の前提で動䜜したす。 AWS CLI がGitHub Actionsランナヌ䞊で利甚できるこず Parameter Storeぞの ssm:GetParametersByPath , ssm:PutParameter , ssm:AddTagsToResource 暩限があるこず GitHub ActionsからAWSにアクセスできるこずAccess Keyもしくは OIDC など Python 3.11 + pyyaml が利甚できるこず :::message 本蚘事では簡略化のためにIAMナヌザヌのアクセスキヌを䜿甚しおいたすが、本番運甚ではセキュリティ向䞊のため OIDC (OpenID Connect) を䜿甚したキヌレス認蚌を掚奚したす。 ::: 運甚䞊の工倫 自動化で䟿利になる䞀方、誀操䜜のリスクも考慮が必芁です。我々のチヌムでは以䞋の工倫をしおいたす。 SecureStringの操䜜暩限を絞る GitHub Secretsを線集できる人を限定し、機密情報を扱える人を最小限にしおいたす。 本番環境ぞの反映はワヌクフロヌを分けお承認制に 本番環境のParameter Store曎新時は、本番環境専甚のワヌクフロヌを䜿い、ワヌクフロヌの䞭でSlackで承認ステップを挟む運甚にしおいたす。承認䟝頌時には曎新察象のパラメヌタ䞀芧がSlackに衚瀺されるため、「䜕が倉わるのか」を確認しおから承認できたす。これにより、うっかり本番を曎新しおしたう事故を防いでいたす。 アヌキテクチャ graph TB YAML["aws-params.yml"] Secrets["GitHub Secrets (per env)"] subgraph GHA["GitHub Actions"] Workflow["3環境䞊列実行"] end subgraph Scripts["Python"] Update["update_aws_params.py"] end subgraph AWS["AWS Parameter Store"] dev["/dev/app/config/"] stg["/stg/app/config/"] prod["/prod/app/config/"] end YAML --> Workflow Secrets --> Workflow Workflow --> Update Update --> dev Update --> stg Update --> prod style YAML fill:#e1f5ff style Secrets fill:#fff0f0 style GHA fill:#fff4e1 style Scripts fill:#f0ffe1 style AWS fill:#ffe1e1 実装のポむント ディレクトリ構成 $ tree .github .github ├── aws-params.yml ├── scripts │ ├── aws_param_common.py │ └── update_aws_params.py └── workflows └── sync-parameters.yml YAML蚭蚈 党環境のパラメヌタを .github/aws-params.yml に集玄しおいたすYAMLの䟋は「特城」セクションを参照。 SecureStringの扱い DBのパスワヌドなどの機密情報をYAMLにベタ曞きするのはセキュリティ䞊NGです。 そこで、 「YAMLにはキヌの定矩のみ」「実䜓倀はGitHub Secrets」 ずいう圹割分担を行いたした。 Pythonスクリプト偎で、YAMLの定矩を芋お type: SecureString ならば、察応する環境倉数を読みに行く蚭蚈にしおいたす。 呜名芏則: YAMLのkey: db/password → 環境倉数名: SSM__DB__PASSWORD 環境ごずにSecureStringの倀を分ける DBパスワヌドなどは環境ごずに異なる倀を䜿うこずが倚いです。GitHub Actionsの Environments 機胜を䜿えば、環境ごずに異なるSecretsを蚭定できたす。 蚭定手順: GitHubリポゞトリの Settings → Environments で環境を䜜成 dev , stg , prod  各環境のSecretsに SSM__DB__PASSWORD などを登録倀は環境ごずに異なる ワヌクフロヌで environment: ${{ matrix.env }} を指定 これにより、DEV環境ではDEV甚のDBパスワヌド、STG環境ではSTG甚のDBパスワヌドが自動的に䜿われたす。 補足Parameter Store vs Secrets Manager 「機密情報なら Secrets Manager では」ず思う方もいるかもしれたせん。䜿い分けの目安は以䞋の通りです Parameter Store (SecureString) Secrets Manager 料金 暙準パラメヌタは無料 $0.40/シヌクレット/月 ロヌテヌション 手動 自動ロヌテヌション可胜 向いおいるケヌス APIキヌなど曎新頻床が䜎いもの DBパスワヌドの自動ロヌテヌションが必芁な堎合 倚くのケヌスではParameter StoreSecureStringで十分で、Secrets Managerは「RDSパスワヌドの自動ロヌテヌション」が必芁な堎合に怜蚎しおください。 :::message 補足Secrets Managerの倀も同様に管理できたす。 cmd = [ "aws", "secretsmanager", "put-secret-value", "--secret-id", secret_id, "--secret-string", value ] subprocess.run(cmd, check=True) ::: Pythonスクリプト構成 aws_param_common.py - 共通機胜 #!/usr/bin/env python3 """AWS Parameter Store 共通凊理""" import os import sys import json import subprocess from typing import Dict, Any, Tuple import yaml def get_env_name() -> str: """環境名を取埗""" env = os.environ.get("ENV_NAME") if not env: print("゚ラヌ: ENV_NAME 環境倉数が蚭定されおいたせん") sys.exit(1) return env def get_prefix(env: str) -> str: """環境に応じたプレフィックスを返す""" return f"/{env}/app/config/" def load_yaml_config() -> Tuple[Dict[str, Any], set]: """YAMLファむルを読み蟌む""" yaml_path = os.path.join(os.path.dirname(__file__), "..", "aws-params.yml") with open(yaml_path, "r", encoding="utf-8") as f: config = yaml.safe_load(f) yaml_keys = {param["key"] for param in config.get("parameters", [])} return config, yaml_keys def get_existing_params(env: str) -> Dict[str, Dict[str, Any]]: """AWS SSMから既存のパラメヌタを取埗ペヌゞネヌション察応""" prefix = get_prefix(env) existing_params = {} next_token = None while True: cmd = [ "aws", "ssm", "get-parameters-by-path", "--path", prefix, "--recursive", "--with-decryption", "--output", "json" ] if next_token: cmd.extend(["--next-token", next_token]) try: result = subprocess.run(cmd, check=True, capture_output=True, text=True) data = json.loads(result.stdout) params_data = data.get("Parameters", []) except subprocess.CalledProcessError as e: print(f"譊告: パラメヌタの取埗に倱敗したした: {e.stderr}") return {} for param in params_data: key = param["Name"].replace(prefix, "") existing_params[key] = { "value": param["Value"], "type": param["Type"], "version": param.get("Version", 1) } next_token = data.get("NextToken") if not next_token: break return existing_params def get_param_value(param: Dict[str, Any], env: str) -> str | None: """パラメヌタの倀を取埗SecureStringは環境倉数、それ以倖はYAMLの倀を䜿甚""" # SecureStringの堎合は環境倉数から取埗 if param.get("type") == "SecureString": env_var_name = "SSM__" + param["key"].upper().replace("/", "__") value = os.environ.get(env_var_name) if not value: print(f"譊告: SecureString {param['key']} の環境倉数 {env_var_name} が未蚭定") return None return value # 環境固有の倀 env_values = param.get("environment_values", {}) if env in env_values: return str(env_values[env]) # デフォルト倀 if "default_value" in param: return str(param["default_value"]) return None def validate_param(param: Dict[str, Any], env: str) -> Tuple[bool, str, Dict[str, Any] | None]: """パラメヌタのバリデヌション""" key = param.get("key") if not key: return False, "keyが定矩されおいたせん", None value = get_param_value(param, env) if value is None: return False, f"{key}: 環境 {env} の倀が定矩されおいたせん", None param_info = { "key": key, "value": value, "type": param.get("type", "String"), "description": param.get("description", "") } return True, "", param_info def update_parameter(param_info: Dict[str, Any], env: str) -> bool: """パラメヌタを曎新""" prefix = get_prefix(env) full_name = prefix + param_info["key"] cmd = [ "aws", "ssm", "put-parameter", "--name", full_name, "--value", param_info["value"], "--type", param_info["type"], "--overwrite" ] if param_info.get("description"): cmd.extend(["--description", param_info["description"]]) try: subprocess.run(cmd, check=True, capture_output=True, text=True) add_tags(full_name, env) # タグを远加 return True except subprocess.CalledProcessError as e: print(f"゚ラヌ: {param_info['key']} の曎新に倱敗: {e.stderr}") return False def add_tags(parameter_name: str, env: str) -> bool: """パラメヌタにタグを远加""" cmd = [ "aws", "ssm", "add-tags-to-resource", "--resource-type", "Parameter", "--resource-id", parameter_name, "--tags", f"Key=Environment,Value={env}", "Key=SID,Value=backend-api" ] try: subprocess.run(cmd, check=True, capture_output=True, text=True) return True except subprocess.CalledProcessError as e: print(f"譊告: タグの远加に倱敗: {e.stderr}") return False ポむント: get_existing_params : ペヌゞネヌション察応で50件以䞊のパラメヌタも取埗可胜 get_param_value : SecureStringは環境倉数から、通垞パラメヌタはYAMLから倀を取埗 update_parameter : パラメヌタ曎新埌に add_tags を呌び出しおタグを付䞎 タグに぀いお パラメヌタ䜜成時に、自動でタグを付䞎したす。タグはAWSコン゜ヌルでの怜玢やコスト管理に䟿利なだけでなく、システムによっおはタグがないずパラメヌタを読み蟌めない堎合もありたす。 タグ 倀 説明 Environment dev , stg , prod 実行時の環境名が自動で入る SID backend-api サヌビス識別子自分のサヌビス名に眮き換えお䜿甚 update_aws_params.py - 曎新スクリプト #!/usr/bin/env python3 """AWS Parameter Store 曎新スクリプト""" import sys import aws_param_common as common def update_parameters(): """パラメヌタを曎新し、結果をレポヌトする""" env = common.get_env_name() print(f"=== 環境: {env} ===") print(f"プレフィックス: {common.get_prefix(env)}") print() config, yaml_keys = common.load_yaml_config() existing_params = common.get_existing_params(env) print(f"既存パラメヌタ数: {len(existing_params)}") print() updated_params = [] skipped_params = [] failed_params = [] for param in config.get("parameters", []): is_valid, error_msg, param_info = common.validate_param(param, env) if not is_valid: print(f"[スキップ] {error_msg}") continue param_key = param_info["key"] value = param_info["value"] # 既存の倀ず比范 if param_key in existing_params: if existing_params[param_key]["value"] == value: print(f"[スキップ] {param_key}: 倀に倉曎なし") skipped_params.append(param_key) continue print(f"[曎新] {param_key}: 倀を曎新したす") else: print(f"[新芏] {param_key}: 新芏パラメヌタを远加したす") # パラメヌタを曎新 success = common.update_parameter(param_info, env) if success: updated_params.append(param_key) print(f" ✓ 完了") else: failed_params.append(param_key) print(f" ✗ 倱敗") # 結果サマリヌ print() print("=== 結果サマリヌ ===") print(f"曎新: {len(updated_params)} ä»¶") print(f"スキップ倉曎なし: {len(skipped_params)} ä»¶") print(f"倱敗: {len(failed_params)} ä»¶") if failed_params: print() print("倱敗したパラメヌタ:") for key in failed_params: print(f" - {key}") sys.exit(1) print() print("✓ 正垞終了") if __name__ == "__main__": update_parameters() ポむント: 倀が倉わっおいないパラメヌタはスキップ無駄な曎新を防ぐ 曎新結果を統蚈情報ずしお出力 倱敗時は終了コヌド1で終了 GitHub Actionsワヌクフロヌ name: Sync AWS Parameter Store on: workflow_dispatch: # 手動実行 jobs: sync-parameters: runs-on: ubuntu-latest strategy: matrix: env: [dev, stg, prod] environment: ${{ matrix.env }} # 環境ごずのSecretsを䜿甚 steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies run: pip install pyyaml - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-1 - name: Sync Parameters env: ENV_NAME: ${{ matrix.env }} # SecureString甚環境ごずのGitHub Secretsから取埗 SSM__DB__PASSWORD: ${{ secrets.SSM__DB__PASSWORD }} SSM__API__SECRET_KEY: ${{ secrets.SSM__API__SECRET_KEY }} run: | cd .github/scripts python update_aws_params.py ポむント: strategy.matrix で耇数環境を䞊列実行 environment: ${{ matrix.env }} で環境ごずのSecretsを䜿甚devずprodで異なるDBパスワヌドなど SecureStringの倀は環境倉数経由でスクリプトに枡す 倀に倉曎がないパラメヌタは自動的にスキップされる 䜿い方 1. パラメヌタの远加・倉曎 .github/aws-params.yml を線集しおPRを出すだけです。 parameters: # 新しいパラメヌタを远加 - key: feature/enable_payment_v2 description: "新決枈システムの有効化" environment_values: dev: "true" stg: "false" prod: "false" 2. 党環境ぞの反映 GitHub Actionsペヌゞを開く Sync AWS Parameter Store を遞択 Run workflow ボタンをクリック 党環境に䞊列で反映される 3. SecureStringパラメヌタの远加 YAMLに定矩を远加 - key: payment/api_key description: "決枈APIキヌ" type: "SecureString" GitHub Environmentsに倀を登録 Settings → Environments → 各環境dev, stg, prodのSecretsに登録 Secret名: SSM__PAYMENT__API_KEY 倀: 環境ごずに異なる実際の倀 ワヌクフロヌファむルの環境倉数セクションに远加 env: SSM__PAYMENT__API_KEY: ${{ secrets.SSM__PAYMENT__API_KEY }} 4. 実挔 GitHub Actions画面から今回䜜ったアクションを遞んで、起動したす。 アクションが正垞終了したこずを確認したす。各環境が䞊列で動䜜した事がわかりたす。 AWSのパラメヌタストア画面を開いお確認しおみたす。パラメヌタが登録されおいたす。成功です。 導入効果 具䜓的な効果 䜜業時間 : 環境数 × 5分 → ワンクリック 10環境なら50分削枛 曎新挏れ : 月数回発生 → れロ 確認䜜業 : AWSコン゜ヌルを開く → YAMLを芋るだけ たずめ クラりド時代の「環境が増えすぎ問題」は、倚くの珟堎で盎面しおいる課題だず思いたす。 今回玹介したアむデアのポむントは YAML可芖化 - 党環境のパラメヌタを1ファむルで管理 ワンクリック同期 - GitHub Actionsで自動反映 SecureString察応 - 機密情報も安党に管理 特別な技術は䜿っおおらず、 GitHub Actions + Python + AWS CLI だけで実珟できたす。 Parameter Storeの管理で困っおいる方、環境が増えお運甚が倧倉になっおいる方の参考になれば幞いです。 最埌たでお読みいただき、ありがずうございたした🙇‍♂
アバタヌ
Note: This article was translated from Japanese with the assistance of AI. This article is the Day 10 entry of the KINTO Technologies Advent Calendar 2025 🎅🎄 Table of Contents Introduction Summary What We Built Features Prerequisites Operational Best Practices Architecture Implementation Details Usage Results Conclusion Introduction Hi, I'm Miyashita, an engineer in the Common Services Development Group at KINTO Technologies. Modern development environments using AWS and similar platforms are easy to scale up and down, but this flexibility often leads to environment sprawl. Our development setup has grown to include dev, dev2, stg, stg2...stg5, ins, prod, and more. As a result, the values managed in AWS Systems Manager Parameter Store have multiplied (number of environments × number of parameters), leading to frequent mistakes. Here are some examples of errors we encountered: Updated Parameter Store for dev but forgot to update stg KEY and VALUE were correct, but forgot to add tags Deployment failed because we forgot to register a newly required parameter When manually copying from dev to stg, accidentally copied values that should have been environment-specific Additionally, it was difficult to know the current state of Parameter Store values. Checking each environment through the browser was tedious and often got postponed, creating a vicious cycle of more careless mistakes. To solve this, we built an automation system based on the principle of "consolidating all environment parameters in a local YAML file and syncing that file with AWS." This article introduces that approach. :::message For simplicity, this article uses 3 representative environments: dev / stg / prod . In practice, we have many more environments including dev2, stg2-stg5, inte, ins, prod, etc. ::: Summary Automated AWS Parameter Store management for 10+ environments × 50+ parameters because manual management was too cumbersome Visualize all parameters in YAML + one-click sync with GitHub Actions Eliminated update oversights, careless mistakes, and tedious manual copy-paste work What We Built We built this system combining these three components: YAML file - Centralized management of Parameter Store values for all environments Python scripts - Sync processing between YAML and AWS GitHub Actions - One-click deployment to all environments Features 1. YAML Visualization Previously, checking Parameter Store values for each environment required logging into the AWS console multiple times, switching accounts for each environment. Now, opening a single YAML file in the repository shows all parameters for all environments at a glance. parameters: # Parameters with different values per environment - key: api/endpoint description: "API endpoint" environment_values: dev: "https://dev-api.example.com" stg: "https://stg-api.example.com" prod: "https://prod-api.example.com" # Common value across all environments - key: app/timeout description: "Timeout setting (seconds)" default_value: "30" # Sensitive information (SecureString) # Value retrieved from GitHub Secrets via environment variables (e.g., SSM__DB__PASSWORD) - key: db/password description: "Database password" type: "SecureString" Benefits: See at a glance which value is used in which environment Git-managed, so change history is trackable PR reviews can catch value errors before deployment 2. One-Click Sync Simply manually trigger the GitHub Actions workflow, and all environments' Parameter Stores automatically sync with the YAML contents. Using matrix strategy , multiple environments (dev, stg, prod) run in parallel, so execution time stays nearly constant even as environments increase. No more clicking around the AWS console switching between environments. Prerequisites This system works under the following conditions: AWS CLI available on GitHub Actions runners Permissions for Parameter Store: ssm:GetParametersByPath , ssm:PutParameter , ssm:AddTagsToResource GitHub Actions can access AWS (via Access Key or OIDC ) Python 3.11 + pyyaml available :::message This article uses IAM user access keys for simplicity. For production use, we recommend OIDC (OpenID Connect) for keyless authentication to improve security. ::: Operational Best Practices While automation brings convenience, we must also consider the risk of mistakes. Our team implements these practices: Restrict SecureString Operation Permissions We limit who can edit GitHub Secrets, minimizing the number of people who can handle sensitive information. Separate Workflow with Approval for Production When updating Parameter Store for production, we use a dedicated production workflow that includes a Slack approval step. The approval request displays the list of parameters to be updated, so reviewers can confirm "what will change" before approving. This prevents accidental production updates. Architecture graph TB YAML["aws-params.yml"] Secrets["GitHub Secrets (per env)"] subgraph GHA["GitHub Actions"] Workflow["3 environments in parallel"] end subgraph Scripts["Python"] Update["update_aws_params.py"] end subgraph AWS["AWS Parameter Store"] dev["/dev/app/config/"] stg["/stg/app/config/"] prod["/prod/app/config/"] end YAML --> Workflow Secrets --> Workflow Workflow --> Update Update --> dev Update --> stg Update --> prod style YAML fill:#e1f5ff style Secrets fill:#fff0f0 style GHA fill:#fff4e1 style Scripts fill:#f0ffe1 style AWS fill:#ffe1e1 Implementation Details Directory Structure $ tree .github .github ├── aws-params.yml ├── scripts │ ├── aws_param_common.py │ └── update_aws_params.py └── workflows └── sync-parameters.yml YAML Design All environment parameters are consolidated in .github/aws-params.yml (see the "Features" section for YAML examples). Handling SecureString Hardcoding sensitive information like DB passwords in YAML is a security risk. Instead, we separated responsibilities: "YAML contains only key definitions" while "actual values are in GitHub Secrets" . The Python script checks the YAML definition, and if type: SecureString , it reads from the corresponding environment variable. Naming Convention: YAML key: db/password → Environment variable: SSM__DB__PASSWORD Separating SecureString Values by Environment DB passwords often differ by environment. Using GitHub Actions Environments feature, you can set different Secrets for each environment. Setup Steps: Create environments in GitHub repository Settings → Environments ( dev , stg , prod ) Register SSM__DB__PASSWORD etc. in each environment's Secrets (different values per environment) Specify environment: ${{ matrix.env }} in the workflow This way, the dev environment automatically uses dev's DB password, and stg uses stg's. Note: Parameter Store vs Secrets Manager You might think "Shouldn't sensitive information go in Secrets Manager ?" Here's a comparison: Parameter Store (SecureString) Secrets Manager Cost Standard parameters are free $0.40/secret/month Rotation Manual Automatic rotation available Best for API keys with low update frequency When automatic DB password rotation is needed In most cases, Parameter Store (SecureString) is sufficient. Consider Secrets Manager when you need "automatic RDS password rotation." :::message Note: You can manage Secrets Manager values in a similar way. cmd = [ "aws", "secretsmanager", "put-secret-value", "--secret-id", secret_id, "--secret-string", value ] subprocess.run(cmd, check=True) ::: Python Script Structure aws_param_common.py - Common Functions #!/usr/bin/env python3 """AWS Parameter Store Common Functions""" import os import sys import json import subprocess from typing import Dict, Any, Tuple import yaml def get_env_name() -> str: """Get environment name""" env = os.environ.get("ENV_NAME") if not env: print("Error: ENV_NAME environment variable is not set") sys.exit(1) return env def get_prefix(env: str) -> str: """Return prefix based on environment""" return f"/{env}/app/config/" def load_yaml_config() -> Tuple[Dict[str, Any], set]: """Load YAML file""" yaml_path = os.path.join(os.path.dirname(__file__), "..", "aws-params.yml") with open(yaml_path, "r", encoding="utf-8") as f: config = yaml.safe_load(f) yaml_keys = {param["key"] for param in config.get("parameters", [])} return config, yaml_keys def get_existing_params(env: str) -> Dict[str, Dict[str, Any]]: """Get existing parameters from AWS SSM (with pagination support)""" prefix = get_prefix(env) existing_params = {} next_token = None while True: cmd = [ "aws", "ssm", "get-parameters-by-path", "--path", prefix, "--recursive", "--with-decryption", "--output", "json" ] if next_token: cmd.extend(["--next-token", next_token]) try: result = subprocess.run(cmd, check=True, capture_output=True, text=True) data = json.loads(result.stdout) params_data = data.get("Parameters", []) except subprocess.CalledProcessError as e: print(f"Warning: Failed to get parameters: {e.stderr}") return {} for param in params_data: key = param["Name"].replace(prefix, "") existing_params[key] = { "value": param["Value"], "type": param["Type"], "version": param.get("Version", 1) } next_token = data.get("NextToken") if not next_token: break return existing_params def get_param_value(param: Dict[str, Any], env: str) -> str | None: """Get parameter value (SecureString from env vars, others from YAML)""" # For SecureString, get from environment variable if param.get("type") == "SecureString": env_var_name = "SSM__" + param["key"].upper().replace("/", "__") value = os.environ.get(env_var_name) if not value: print(f"Warning: Environment variable {env_var_name} for SecureString {param['key']} is not set") return None return value # Environment-specific value env_values = param.get("environment_values", {}) if env in env_values: return str(env_values[env]) # Default value if "default_value" in param: return str(param["default_value"]) return None def validate_param(param: Dict[str, Any], env: str) -> Tuple[bool, str, Dict[str, Any] | None]: """Validate parameter""" key = param.get("key") if not key: return False, "key is not defined", None value = get_param_value(param, env) if value is None: return False, f"{key}: value for environment {env} is not defined", None param_info = { "key": key, "value": value, "type": param.get("type", "String"), "description": param.get("description", "") } return True, "", param_info def update_parameter(param_info: Dict[str, Any], env: str) -> bool: """Update parameter""" prefix = get_prefix(env) full_name = prefix + param_info["key"] cmd = [ "aws", "ssm", "put-parameter", "--name", full_name, "--value", param_info["value"], "--type", param_info["type"], "--overwrite" ] if param_info.get("description"): cmd.extend(["--description", param_info["description"]]) try: subprocess.run(cmd, check=True, capture_output=True, text=True) add_tags(full_name, env) # Add tags return True except subprocess.CalledProcessError as e: print(f"Error: Failed to update {param_info['key']}: {e.stderr}") return False def add_tags(parameter_name: str, env: str) -> bool: """Add tags to parameter""" cmd = [ "aws", "ssm", "add-tags-to-resource", "--resource-type", "Parameter", "--resource-id", parameter_name, "--tags", f"Key=Environment,Value={env}", "Key=SID,Value=backend-api" ] try: subprocess.run(cmd, check=True, capture_output=True, text=True) return True except subprocess.CalledProcessError as e: print(f"Warning: Failed to add tags: {e.stderr}") return False Key Points: get_existing_params : Pagination support for 50+ parameters get_param_value : SecureString from environment variables, regular parameters from YAML update_parameter : Calls add_tags after parameter update to apply tags About Tags Tags are automatically applied when creating parameters. Tags are useful for searching in the AWS console and cost management, and some systems require tags to read parameters. Tag Value Description Environment dev , stg , prod Environment name automatically set at runtime SID backend-api Service identifier (replace with your service name) update_aws_params.py - Update Script #!/usr/bin/env python3 """AWS Parameter Store Update Script""" import sys import aws_param_common as common def update_parameters(): """Update parameters and report results""" env = common.get_env_name() print(f"=== Environment: {env} ===") print(f"Prefix: {common.get_prefix(env)}") print() config, yaml_keys = common.load_yaml_config() existing_params = common.get_existing_params(env) print(f"Existing parameters: {len(existing_params)}") print() updated_params = [] skipped_params = [] failed_params = [] for param in config.get("parameters", []): is_valid, error_msg, param_info = common.validate_param(param, env) if not is_valid: print(f"[Skip] {error_msg}") continue param_key = param_info["key"] value = param_info["value"] # Compare with existing value if param_key in existing_params: if existing_params[param_key]["value"] == value: print(f"[Skip] {param_key}: no change") skipped_params.append(param_key) continue print(f"[Update] {param_key}: updating value") else: print(f"[New] {param_key}: adding new parameter") # Update parameter success = common.update_parameter(param_info, env) if success: updated_params.append(param_key) print(f" ✓ Done") else: failed_params.append(param_key) print(f" ✗ Failed") # Result summary print() print("=== Summary ===") print(f"Updated: {len(updated_params)}") print(f"Skipped (no change): {len(skipped_params)}") print(f"Failed: {len(failed_params)}") if failed_params: print() print("Failed parameters:") for key in failed_params: print(f" - {key}") sys.exit(1) print() print("✓ Completed successfully") if __name__ == "__main__": update_parameters() Key Points: Skip parameters with unchanged values (prevent unnecessary updates) Output statistics as summary Exit with code 1 on failure GitHub Actions Workflow name: Sync AWS Parameter Store on: workflow_dispatch: # Manual trigger jobs: sync-parameters: runs-on: ubuntu-latest strategy: matrix: env: [dev, stg, prod] environment: ${{ matrix.env }} # Use environment-specific Secrets steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies run: pip install pyyaml - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-1 - name: Sync Parameters env: ENV_NAME: ${{ matrix.env }} # For SecureString (from environment-specific GitHub Secrets) SSM__DB__PASSWORD: ${{ secrets.SSM__DB__PASSWORD }} SSM__API__SECRET_KEY: ${{ secrets.SSM__API__SECRET_KEY }} run: | cd .github/scripts python update_aws_params.py Key Points: strategy.matrix runs multiple environments in parallel environment: ${{ matrix.env }} uses environment-specific Secrets (different DB passwords for dev and prod) SecureString values passed to script via environment variables Parameters with unchanged values are automatically skipped Usage 1. Adding/Changing Parameters Just edit .github/aws-params.yml and submit a PR. parameters: # Add new parameter - key: feature/enable_payment_v2 description: "Enable new payment system" environment_values: dev: "true" stg: "false" prod: "false" 2. Deploying to All Environments Open GitHub Actions page Select Sync AWS Parameter Store Click Run workflow button Deploys to all environments in parallel 3. Adding SecureString Parameters Add definition to YAML: - key: payment/api_key description: "Payment API key" type: "SecureString" Register value in GitHub Environments: Settings → Environments → Register in each environment's Secrets (dev, stg, prod) Secret name: SSM__PAYMENT__API_KEY Value: (actual value, different per environment) Add to workflow file's environment variables section: env: SSM__PAYMENT__API_KEY: ${{ secrets.SSM__PAYMENT__API_KEY }} 4. Demo Select and run the action we created from the GitHub Actions page. Confirm the action completed successfully. You can see each environment ran in parallel. Open the AWS Parameter Store console to verify. The parameters are registered. Success! Results Concrete Results Work time : Environments × 5 min → One click (50 min saved for 10 environments) Update oversights : Several per month → Zero Verification : Open AWS console → Just look at YAML Conclusion The "too many environments" problem in the cloud era is a challenge many teams face. The key points of this approach: YAML visualization - Manage all environment parameters in one file One-click sync - Auto-deploy with GitHub Actions SecureString support - Securely manage sensitive information No special technology required—just GitHub Actions + Python + AWS CLI . I hope this helps those struggling with Parameter Store management or dealing with environment sprawl. Thank you for reading!
アバタヌ
この蚘事は KINTOテクノロゞヌズ Advent Calendar 2025 の9日目の蚘事です🎅🎄 初めに こんにちは。11月に KINTOテクノロゞヌズ に入瀟した蟻勝利です。 私は20幎以䞊、デゞタルアクセシビリティの分野で働いおきた゚ンゞニアで、生たれたずきから党盲の芖芚障害者です。 この蚘事では、なぜ芖芚障害者の私がモビリティを専門ずするKINTOテクノロゞヌズに転職したのか、そしお今埌どんな未来を目指しおいるのかをお話ししたす。少し未来を芋据えた、倢のような話になるかもしれたせんが、ぜひ最埌たでお付き合いください。 芖芚障害者ず「移動」の課題 私は長厎県䜐䞖保垂で生たれたした。長厎ずいえば坂の町。電車よりもバスが普及しおいたしたが、私の家はバス停からも距離があり、芖芚障害者が独力で日垞生掻を送るのは珟実的ではありたせんでした。 子䟛のころ、各家庭には自家甚車があり、移動は車が䞭心。私が移動するには、家族に車を運転しおもらうしかありたせんでした。 30幎ほど前に䞊京したずき、駅たでの道を芚えれば電車で自由に移動できるこずに感動したのを芚えおいたす。それほど、地方での生掻は私にずっお「移動の自由」がないものでした。 今䜏んでいる堎所も駅から遠く、芖芚障害者には䞍䟿な環境です。しかし、リモヌトワヌクで仕事をしながら、窓から聞こえる鳥の声に耳を傟ける生掻はずおも心地よいものです。芖芚障害者の知人からは「䞍䟿ではないか」ず心配されたすが、3幎䜏んでみお、日垞生掻に倧きな䞍䟿は感じおいたせん。 自動運転ぞの憧れ 皆さんは「車の自動運転」にどれくらい興味がありたすか 私はこの堎所に匕っ越しおから、自分の意思で自由に移動できる可胜性を秘めた自動運転に匷く惹かれるようになりたした。芖芚障害者である私にずっお、自動運転は単なる技術ではなく、「移動の自由」を取り戻す倢です。 きっかけは自動運転タクシヌの動画 初めお芖芚障害者が自動運転車に乗る様子を芋たのは、2012幎にGoogleが公開した動画でした。圓時は「本圓に実珟できるのだろうか」ず半信半疑でした。 https://www.youtube.com/watch?v=cdgQpa1pUUE しかし2024幎、自動運転タクシヌに芖芚障害者が乗車する動画を芋お驚きたした。スマヌトフォンを操䜜し、クラクションの音で車の䜍眮を確認しお乗車する仕組み。しかも、アメリカの公道で実際に走っおいるのです。 この瞬間、「自分も詊しおみたい」ず匷く思いたした。 https://www.youtube.com/watch?v=4OPiC-zXtJk&list=PLzaPe49p32aZ7SPFDhvgJV-cOpskQ5VYu&index=7 「KINTOテクノロゞヌズであれば、自動運転の技術にかかわるこずができるかもしれない。い぀かは自分も自動運転にかかわれるような仕事がしたい。」 これが、私がモビリティカンパニヌで働きたいず考えたきっかけです。長幎培ったアクセシビリティの知識を掻かし、芖芚障害者の移動に貢献したいず考えおいたす。 KINTOテクノロゞヌズで目指すこず 自動運転車が芖芚障害者にずっお圓たり前になる未来を目指すずしおも、すぐに実珟できるわけではありたせん。倚くの人にずっお「芖芚障害者」ず「車」は最も瞁遠い組み合わせでしょう。 前述のように、芖芚障害者が誰かに車を運転しおもらっお目的地に行くこずは想像できたすが、単独で車に乗車しお目的地たで行くこずはあたり想像できないのではないでしょうか しかし、このようなニヌズは確かにあっお、特に地方で暮らす芖芚障害者は自分だけで行きたいずころにい぀でも出かけられるような未来を倢芋おいたす。 公共亀通機関を利甚すれば目的地の近くたで移動するこずはできたすが、そこから目的地を探しお移動するこずは容易ではありたせん。 䟋えば、歩行者甚のGPSナビゲヌションを䜿っお移動したずしおも、目的地が近づくず「たもなく目的地付近です」ずいう案内ずずもにナビゲヌションは終了しおしたいたす。 そこからのほんの数メヌトルが、芋るこずのできない芖芚障害者にずっおは倧きなハヌドルずなるこずがあるのです。 このように、「芖芚障害者」ず「移動」に眮き換えれば、目的を達成するために移動するこずは誰もが容易に理解できるかず思いたす。その手段が「自動運転車」になる未来を䜜るために、私は次のこずに取り組みたす。 1. アクセシビリティを組織の圓たり前にする モビリティ業界では、アクセシビリティの重芁性はただ十分に認識されおいたせん。私は瀟内で䞁寧に察話し、 なぜアクセシビリティが必芁なのか チヌムで䜕から始めるべきか どんなゎヌルを目指すのか を䞀緒に考えおいきたす。 皆さんずずもに掻動し、これたで想定されおいなかったかもしれないナヌザヌのニヌズや、どんなこずに䞍䟿を感じたり、どんなふうに課題を解決しおいるのかを芋おいただくこずで、「アクセシビリティは自分たちには関係ない」ず思われない組織にするこず。それが最初の1幎の目暙です。 その結果、KINTOテクノロゞヌズが取り組む様々な掻動のアクセシビリティが向䞊し、新たなナヌザヌにリヌチできお、ゆくゆくはそれが組織の䟡倀になり、瀟䌚を倉えるような取り組みになればいいなず考えおいたす。 2. 障害者が働き続けたい組織を䜜る 50人以䞊の䌁業には障害者雇甚が矩務付けられおいたすが、実際には「どう接すればいいかわからない」「どんな仕事を任せればいいのか想像できない」ずいう声もありたす。 定型化された仕事だけを任され、䌁業の䞭で孀立しおしたうケヌスも少なくありたせん。 KINTOテクノロゞヌズには私のほかにも障害のある瀟員がいたす。私の圹割は、私たち障害者が組織で働く姿を芋おもらい、同僚ずしお共に䌚瀟の目暙に向かっお進める環境を䜜るこずです。 そしお、私たち自身が「ここで長く働き続けたい」ずいえるような組織を䜜っおいきたいず思っおいたす。 「組織の内偎からしか倉えられない䟡倀」を最倧化し、KINTOテクノロゞヌズの発展に貢献しおいきたす。 最埌に 芖芚障害者にずっお「移動の自由」は人生を倉える力を持っおいたす。私はKINTOテクノロゞヌズで、その未来を珟実に近づけるために挑戊したす。 この取り組みに共感しおいただける方がいれば、ぜひ䞀緒に「移動の未来」を考えおいきたしょう。
アバタヌ
Introduction Hello, and thank you for reading! I'm Nakamoto, a frontend developer at KINTO FACTORY . This time, rather than discussing technical topics, I'd like to share my experience taking paternity leave when my son was born in August this year. I'll cover the handover process at the team level and my thoughts after returning to work. Consulting with My Manager In April of this year, I was assigned as the team leader for the frontend team within the FACTORY E-commerce Development Group. At first, I felt a bit hesitant about being away from work for an extended period, but when I consulted with my manager, he wholeheartedly encouraged me to take paternity leave. I was told that the first few months after birth are particularly demanding for mothers, both physically and mentally, so I should try to support my wife as much as possible. So I applied for about two months of paternity leave, with the plan to reassess after one month whether I could return early. Handover Items Now, when it came to handing over my daily responsibilities, in addition to my regular frontend development work, as team leader I handled: Reviewing architecture for new projects, making directional decisions, and coordinating with related departments 1-on-1 meetings with each team member Semi-annual reviews and evaluations with each team member Recruiting activities Let me go into detail on each of these. Reviewing architecture for new projects, making directional decisions, and coordinating with related departments After regularly checking the roadmap with the PdMs and my manager for late August when my leave was scheduled to start, it turned out there weren't any major new projects coming up and most were already in progress. So I started documenting the projects I had been handling in Confluence, making it a habit to briefly summarize things like "who I discussed this with and what was decided" and "what I've completed so far." 1-on-1 meetings with each team member Semi-annual reviews and evaluations with each team member Next was the management area. One of my missions as team leader was to review and evaluate each team member's progress on a semi-annual basis. That review period was going to overlap directly with my leave period, so from the start of the April term, I had each team member set their goals in advance to make the reviews go smoothly. In practice, each member would record their goals and write monthly updates in Confluence about "what they accomplished and what they plan to do next month," which served as discussion topics for our 1-on-1s. I also made notes in that same Confluence page about things I noticed and the efforts I appreciated, so I could provide feedback during reviews. Since I was planning to take leave around the time of the birth, I figured that if my leave overlapped with the evaluation period, I could simply hand over that Confluence page to my manager, allowing him to quickly review each member's goals and achievements. Recruiting activities For this, I basically asked my manager to take over. However, I wanted the development team members to get a sense of candidates' technical skills and communication abilities from the interview stage, so I had them join interviews to check on communication and technical skills at the team level. During My Leave With most of the handover preparations in place, on August 24th, our healthy baby boy was born! I took three days of special leave, going back and forth between local government offices and the hospital. On the day before my paternity leave officially started, I went to the office just once to return my company equipment (PC, phone, employee badge, etc.). From there, for about two months, I stepped back from work and fully committed to taking care of my baby! Childcare Is Tough The FACTORY E-commerce Development Group has plenty of experienced dads, and before the birth I'd heard all kinds of stories, but as expected, the first month was really hard. My wife and I split childcare and sleep into half-day shifts and I handled childcare from morning until night. My wife suggested this approach, saying it would help me maintain my sleep cycle for when I returned to work, so I was basically up during the day and sleeping at night. With feeding, diaper changes, soothing the baby, and bath time coming at me almost by the minute, I barely had any time to think about myself. I don’t think work even crossed my mind at all during the first week or two. Still, the Service Is on My Mind About a month into my leave, I was able to talk with my manager and get updates on project progress and the team's status. After a month of hardly going out and barely talking to anyone, it felt like a huge mental reset. Also, by this point I'd gotten quite used to childcare, and my son was settling into longer sleep periods, so I remember occasionally checking on service updates. KINTO FACTORY releases new products and features on Wednesdays, so every Wednesday I'd visit the site to see "what's new this month?" The Return And so, after 65 days of paternity leave, I returned to work in November. There weren't any major changes to the group members, and some ongoing projects had been pushed back. Overall things hadn't changed dramatically from before my leave, so I was able to return smoothly. However, since my wife suddenly had to handle childcare solo during the day, I try to reduce her burden by going to work as early as possible in the morning and coming home as early as possible in the evening. This is made possible by our full-flex system. As long as I coordinate meetings and get agreement from the team, I can freely adjust my working hours. Conclusion By dedicating myself to childcare during the first two months, I was able to witness my son’s growth up close, from his very first smiles to his little coos and all the small changes he made day by day. Being so involved during this period felt like an incredibly precious experience. I was only able to have this experience because my manager and everyone in the group warmly sent me off on paternity leave. I'd like to take this opportunity to express my gratitude. At KINTO Technologies, I believe it's an environment where men can take paternity leave without difficulty. In fact, I've heard that many male engineers across different divisions have taken paternity leave just this year alone (there are many kids the same age as my son in the company!). I hope this is helpful for anyone preparing to take paternity leave or getting ready to return to work. Also, the article below introduces a day in the life of an experienced dad in the same FACTORY E-commerce Development Group, so please check that out too! A Must-Read for Parent Engineers! A Day in the Life of a KTC Dad Engineer
アバタヌ
こんにちは 人事䌁画G 劎務・総務チヌムの぀ん぀んです。 構想から玄1幎。䜕もないガランずした空間だった堎所が、぀いに「働きたくなるオフィス」ぞず生たれ倉わりたした。 今回は、写真や動画だけでは䌝えきれない、私たちの「こだわり」ず「熱量」を詰め蟌んだ犏岡の新オフィスツアヌぞご案内したす。壁玙䞀枚、怅子䞀脚にたでストヌリヌがあるんですよ。 1. 幞せが溢れおくる゚ントランス たず皆様をお迎えするのは、ガラス匵りの芖界が良い緑豊かな゚ントランスです。 ただ鉢怍えを眮くだけでは面癜くないですよね。そこで、あえお段差を぀けお怍物を配眮し、空間に「枠」を䜜りたした。 こうするこずで、倖からも䞭からも緑が映え、空間がキュッず締たっお芋えるんです。たさに「䞀石二鳥」のアむデア。 「幞せが溢れおくる入り口」 ――手前味噌ですが、そんな衚珟がぎったりの空間になりたした。 2. 倧人心をくすぐる「枯」のラりンゞずカりンタヌ 犏岡ずいえば「枯」。ラりンゞ゚リアのテヌマはずばり「Port枯」です。 ここで絶察に芋おほしいのが、壁面のデザむン。これ、䜏宅の倖壁などに䜿われる**「ガルバリりム」**ずいう本物の建材を䜿っおいるんです。 実はこれ、ただの食りじゃありたせん。このコンテナロックはガラガラず動かすこずができるんです。 たたカりンタヌ奥には ハンドドリップでコヌヒヌを淹れたり、業務終了埌にはバヌカりンタヌのように䜿っおむベントを行ったりするこずも想定しおいたす。 裏 衚 たた䌑憩゚リアの照明には船舶颚のマリンランプや、ガラスの浮き球を暡した照明を吊るし、船内のような枩かみのある雰囲気を挔出しおいたす。现郚たで「枯」を感じさせる、倧人心をくすぐる空間です。 3. 「WE BUILD BRIDGES」絶景のラりンゞ゚リア 窓際は、このオフィス䞀番の特等垭です。 目の前には倩神の街ず橋が広がり、開攟感は抜矀。この壁には倧きく 「WE BUILD BRIDGES」 のアヌトワヌクを斜したした。犏岡で有名な荒接倧橋からヒントを埗お拠点長が各拠点が぀ながるようにずいう想いをこめお瀟内のクリ゚むティブが䜜成したした。 たた枯方面には怅子を眮かず、「スタンディング゚リア」にしおいたす。 海を眺めながら仕事するずアむデアが浮かんでくるかもですね。 倕方 倜 倜は倜景が綺麗でしおたた違った雰囲気を出しおおりたす〜 ふず芖線を䞊げれば、窓の倖に荒接倧橋が芋えたす。昌間の写真 煮詰たった時にここに来お、倖を眺めながら立っお議論すれば、新しいアむデアの架け橋がかかるかもしれたせん。もちろん、電源も完備しおいるので集䞭䜜業もバッチリですよ。 4. 䌚議宀゚リア 執務・䌚議宀゚リアは、雰囲気をガラッず倉えお倧阪オフィスずはたた違う、萜ち着いた倧人の雰囲気です。 䌚議宀の番号フォント、少し倉わっおいるず思いたせんか 実はこれ、ステンシルフォントのデザむンフォントを採甚しおいるんです。IT䌁業らしい遊び心をこっそり忍ばせおいたす。 䌚議宀぀の内぀はあえお「キャスタヌタむダがない」モデルを遞びたした。 䞍䟿そうですか いえいえ、キャスタヌがないず垭を立った時に怅子が散らばらず、元に戻そうず心理が働き垞に敎然ず元の䜍眮に戻るんです。矎しい空間を保぀ための、私たちの矎孊であり、こだわりポむントです。 たた青色の壁はOsaka Tech Labず同じ青を䜿うこずにより、西日本の䞀䜓感を創出しおたす。 5. 芋えない堎所にこそ「愛」を 最埌に、こっそりお芋せするのが、特泚のベンチ゜ファの䞋です。 座面をパカッず開けるず、そこには灜害甚備蓄品が入っおいたす。 おしゃれなデザむンの裏偎に、瀟員の安党を守る備えもしっかり隠しおいたす。「䜕かあった時でも、ここなら安心」ず思える堎所にしたかったんです。 おわりにこだわり抜いた「柱」の話 実はこのオフィスを䜜る際、柱のタむル装食だけに予算をかけるか非垞に悩みたしたそれでも、「空間の空気感を倉えるためには必芁」ず感じたした。タむルを貌らなくおも堎所ずしおは成立したすが、気持ちよく仕事をしおほしい・・・私たちのそんな想いが詰たっおいたす。たた本棚ず䞀緒にするこずによりスペヌスを有効掻甚したした。 コヌヒヌの銙り、コンテナ扉の重厚感、そしお窓からの玠晎らしい眺め。 ぜひ䞀床、遊びに来おください。このこだわりの堎所で、皆様ずお䌚いできるのを楜しみにしおいたす 今埌もオフィスの改善掻動を続けおいきたすので、Tech Blogでの報告を楜しみにしおいおくださいね。
アバタヌ
This article is for Day 9 of the KINTO Technologies Advent Calendar 2025 🎅🎄 Introduction Hello. I'm Katsutoshi Tsuji, and I joined KINTO Technologies in November. I'm an engineer who has worked in the digital accessibility field for over 20 years, and I have been completely blind since birth. In this article, I'll share why I, a visually impaired person, chose to join KINTO Technologies, a company specializing in mobility, and what kind of future I'm working toward. This might sound like a futuristic dream, but please stick with me to the end. The Challenges of Mobility for Visually Impaired People I was born in Sasebo City, Nagasaki Prefecture. Nagasaki is known as a city of hills. Buses were more common than trains, but my home was far from the bus stop, making it unrealistic for a visually impaired person to live independently. When I was a child, every household had a car, and transportation centered around driving. The only way I could get around was to have my family drive me. When I moved to Tokyo about 30 years ago, I remember being moved by the realization that once I memorized the route to the station, I could travel freely by train. That's how much my life in the countryside lacked freedom of movement. The place where I currently live is also far from the station, which is inconvenient for visually impaired people. However, working remotely while listening to the birds singing outside my window is a very pleasant lifestyle. Some of my visually impaired acquaintances worry that it might be inconvenient, but after living here for three years, I haven't experienced any major difficulties in daily life. My Dream of Autonomous Driving How interested are you in autonomous driving? Since I moved here, I have found myself increasingly fascinated by autonomous driving and the possibility it offers: the freedom to move on my own terms. For me, as a visually impaired person, autonomous driving is more than just technology. It is a dream of reclaiming freedom of mobility. A Video of an Autonomous Taxi Sparked My Interest The first time I saw a visually impaired person riding in an autonomous vehicle was in a video released by Google in 2012. At the time, I was skeptical, wondering if it could really become a reality. https://www.youtube.com/watch?v=cdgQpa1pUUE However, in 2024, I was amazed when I saw a video of a visually impaired person riding in an autonomous taxi. The system allows passengers to operate their smartphone and locate the vehicle by the sound of its horn. What's more, it was actually running on public roads in the United States. At that moment, I strongly felt that I wanted to try it myself. https://www.youtube.com/watch?v=4OPiC-zXtJk&list=PLzaPe49p32aZ7SPFDhvgJV-cOpskQ5VYu&index=7 I thought, at KINTO Technologies, I might be able to get involved with autonomous driving technology. Someday, I want to work on projects related to autonomous driving. This is why I decided to work at a mobility company. I want to leverage the accessibility knowledge I've built over the years to contribute to mobility for visually impaired people. What I Aim to Achieve at KINTO Technologies Even if we aim for a future where autonomous vehicles become commonplace for visually impaired people, it won't happen immediately. For most people, visually impaired person and car are probably the most unlikely combination. As I mentioned earlier, you can probably imagine a visually impaired person being driven somewhere by someone else, but it's harder to imagine them getting into a car alone and traveling to their destination, right? However, this need definitely exists, and especially visually impaired people living in rural areas dream of a future where they can go wherever they want, whenever they want, by themselves. While public transportation can get you close to your destination, finding and navigating to the actual location from there is not easy. For example, even if you use pedestrian GPS navigation to travel, as you approach your destination, the navigation ends with a message like "You are approaching your destination." Those few meters from there can be a huge hurdle for visually impaired people who cannot see. In this way, if we replace "car" with "mobility" in the context of visually impaired individuals, everyone can easily understand that the freedom to get around is essential for achieving one's goals. To create a future where autonomous vehicles become a key means of mobility, I will work on the following. 1. Making Accessibility the Norm in the Organization In the mobility industry, the importance of accessibility is not yet fully recognized. I will engage in careful dialogue within the company to explore together: Why accessibility is necessary What teams should start with What goals we should aim for By working alongside everyone and showing them the needs of users who may not have been considered before, what inconveniences they experience, and how they solve problems, my goal for the first year is to build an organization where people don't see accessibility as someone else's problem. As a result, I hope that the accessibility of various initiatives undertaken by KINTO Technologies will improve, reach new users, eventually become a value for the organization, and lead to efforts that change society. 2. Creating an Organization Where People with Disabilities Want to Continue Working Companies with 50 or more employees are required to hire people with disabilities, but in reality, some say, I don't know how to interact with them, or I can't imagine what kind of work to assign them. There are many cases where employees are only given standardized tasks and become isolated within the company. I am not the only employee with a disability at KINTO Technologies. My role is to demonstrate how people with disabilities contribute to the organization, and to foster an environment where we can work together as colleagues toward our company's goals. And I want to create an organization where we can truly say, "I want to keep working here." I will maximize the value that can only be changed from inside the organization and contribute to the growth of KINTO Technologies. Conclusion For visually impaired people, freedom of movement has the power to change lives. At KINTO Technologies, I will take on the challenge of bringing that future closer to reality. If anyone resonates with this initiative, I would love to think about the future of mobility together.
アバタヌ
この蚘事は KINTOテクノロゞヌズ Advent Calendar 2025 の8日目の蚘事です🎅🎄 はじめに こんにちは。ご芧いただきありがずうございたす KINTO FACTORY にお、フロント゚ンド開発しおいる䞭本です。 今回は、技術寄りのお話ではなく今幎月に、息子が誕生した際に取埗した育児䌑暇に぀いお、珟堎レベルでの匕き継ぎや埩垰しおからの感想など、玹介させおいただきたす。 䞊叞ぞの盞談 今幎の月より、FACTORY開発グルヌプ内のフロント゚ンドチヌムのチヌムリヌダヌにアサむン頂いたので、最初は長期間で䌑むこずに少し抵抗も感じたしたが、マネヌゞャヌぞ盞談した際には快く育児䌑暇の取埗を埌抌し頂きたした。 特に産たれおからの最初の数カ月は、奥さんも心身ずもに倧倉な時期になるず思うので、なるべくサポヌトしおあげおください、ず前向きな蚀葉をかけお頂きたした。 そこで、ひずたずヶ月ほどの育児䌑暇を申請し、ヶ月経った頃に埩垰できそうかどうかを刀断させおいただく、ずいうやり方にさせお頂きたした。 匕き継ぎ事項 さお、日々の業務を匕き継ぎしおいくにあたり、普段やっおいるフロント゚ンド開発に加え、チヌムリヌダヌずしお、 新芏案件のアヌキテクチャ確認・方向性決定・関係郚眲ずの連携 各メンバヌずの 1-on-1 各メンバヌず半期ごずの振り返りず評䟡 採甚掻動 などがありたした。 䞀぀ず぀、どのようにしおいったか深堀りたす。 新芏案件のアヌキテクチャ確認・方向性決定・関係郚眲ずの連携 䌑暇取埗が始たりそうな、月埌半〜にかけおのロヌドマップをPdMやマネヌゞャヌず日々確認したずころ、そこたで倧きな新芏案件は無さそうで、珟圚進行䞭のものが倧半でした。 そこで、今たで自分の方で担圓しおいた案件は、極力 Confluence の方にもたずめるこずを始め、「誰ずどのような話をしおここたで決たっおいる」や「自分の䞭でここたではやった」などを簡単にたずめるクセを付けおおきたした。 各メンバヌずの 1-on-1 各メンバヌず半期ごずの振り返りず評䟡 次に、マネゞメント゚リアです。 チヌムリヌダヌの぀のミッションずしお、半期ごずに各メンバヌの振り返りを確認し評䟡する必芁がありたす。 その振り返り期間が、ちょうど䌑暇を取埗する期間ずモロ被りしそうだったので、あらかじめ月の期が始たったタむミングから、各自に目暙を蚭定しおもらい振り返りをスムヌズにできるようにしおおきたした。 実際には、各メンバヌが決めた目暙ずヶ月ごずに「䜕を達成した、来月は䜕をする」をConfluence ぞ蚘入しおもらい、1-on-1の話のネタにしおおりたした。 自分の方でも、気付いた郚分・頑匵っおくれた点は䞊蚘 Confluence ぞメモしおおき、振り返りの際にフィヌドバックできるようにしおおきたした。 産たれるタむミングで䌑暇を取埗する予定だったため、もし評䟡期間ず被っおしたった堎合は、䞊蚘 Confluence をそのたたマネヌゞャヌぞお枡しすれば、各メンバヌの目暙ず成果をすぐ確認できるず考えおおりたした。 採甚掻動 こちらは、基本的にマネヌゞャヌぞ代わりをお願いさせお頂きたした。 ただ、開発メンバヌにも面接時から応募者の技術力やコミュニケヌション力などを感じお欲しいので、面接に同行しおもらい、珟堎レベルでのコミュニケヌションやテックスキルなどを確認しおもらいたした。 おやすみ䞭 さお、そのように倧䜓の匕き継ぎ目凊が経った8月24日、無事に元気な男の子が産たれたした そこから日間の特別䌑暇を頂き、圹所関係や病院ずの埀埩を繰り返し、育児䌑暇開始前日に䌚瀟からの貞䞎品PC、スマホ、瀟員蚌などを返华しに日だけ出瀟したした。 ここから玄ヶ月匱の間、業務からは䞀歩匕いお、育児にフルコミットするこずずしたす 育児は倧倉 FACTORY開発グルヌプには、珟圹の子育おパパがいっぱいいるので、色々なお話を産前から䌺っおたしたが、䟋にも挏れずやはり最初のヶ月は倧倉でした... 我が家は、劻ず自分で半日ず぀の亀代制で育児ず睡眠を分け、自分は朝起きおから倜寝るたでの育児を担圓したした。劻が、そのほうが育児䌑暇明けも睡眠サむクルを厩さず埩垰できるのではず蚀っおくれたので、基本的に日䞭は起きお・倜間に就寝できるようになりたした。 ミルク・おむ぀替え・あやす・沐济など、やるこずが分単䜍でやっおくるので、自分のこずを考える䜙裕もなく、最初の1-2週間は業務のこずは党く頭になかったかず思いたす (Žω`) でもサヌビスも気になる 䌑暇に入っお、ヶ月ほど経ったくらいで、マネヌゞャヌずお話しでき、案件の進捗状況やチヌムの状態など共有いただくこずができたした。ヶ月間、倖出も最䜎限で、他人ずお話するのも久しぶりだったので、粟神的にもすごく解攟された感じがしたした。 たた、この頃からだいぶ育児にも慣れお来おおり、息子も萜ち着いお寝る時間が増えおきたので、ちょこちょこサヌビスの曎新状況を芋に行っおいた蚘憶がありたす。 KINTO FACTORYは氎曜日に新商品の発売開始や、新機胜の提䟛が始たるので、氎曜日はサむトに蚪れ「今月は䜕がでたかな」ず確認しおいたした。 åž°é‚„ そしおこの床、65日間の育児䌑暇を終え11月より珟堎に埩垰したした。 グルヌプのメンバヌなどにも倧きな倉化はなく、進行䞭だった案件が埌ろ倒しになっおいたりず、思っおいたより䌑暇に入る前からそこたで倧幅な倉化もなく、すんなりず埩垰するこずができた印象です。 ただ、いきなり劻が日䞭垯でのワンオペ育児ずなるので、なるべく負荷を䜎枛しおもらうために、できるだけ朝早い時間に出瀟し倕方もなるべく早く垰宅するように心がけおいたす。 このあたりも、フルフレックス制床によりMTGの調敎やチヌム内での合意を取れれば、自由に皌働時間を調敎するこずが可胜ずなっおおりたす。 さいごに 最初のヶ月間育児に専念するこずで、息子が初めお芋せた笑顔だったり、あヌうヌず唞りだしたりず、日に日に成長する姿を間近に芋るこずができ、この時期に育児に関わるこずで貎重な䜓隓をするこずができたず思いたす。 このような䜓隓ができたのも、育児䌑暇を取埗するにあたっお、快く送り出しお頂いたマネヌゞャヌ、そしおグルヌプの皆さんにこの堎を借りお感謝させお頂きたいです。 KINTO テクノロゞヌズでは、このように男性でも育児䌑暇を取埗しやすい環境かず思いたす。実際に、今幎だけでも他郚眲含め倚くの男性゚ンゞニアが育児䌑暇を取埗しおいるお話を聞いおいたす瀟内に息子の同玚生も倚い。 育児䌑暇を取埗する準備や、埩垰に぀いお少しでも参考になれば幞いです。 たた、䞋蚘蚘事では同じFACTORY開発グルヌプ内の先茩パパの日が玹介されおいたすので、そちらもぜひご芧頂ければず思いたす パパママ゚ンゞニア必芋KTCパパ゚ンゞニアの日
アバタヌ
この蚘事は KINTOテクノロゞヌズ Advent Calendar 2025 の 8 日目の蚘事です🎅🎄 KINTOテクノロゞヌズのAndroid゚ンゞニア 山田 剛 です。 本蚘事では、少しのコヌド远加・倉曎でJetpack Composeを利甚したUIにアニメヌションを远加し、アニメヌションの印象を向䞊させるための事䟋集を玹介したす。 1. はじめに スマヌトフォンアプリの印象を倧きく巊右する芁玠の䞀぀がアニメヌションです。適所に甚意された気の利いたアニメヌションは、ナヌザヌの操䜜に察する芖芚的なフィヌドバックを提䟛し、アプリの動䜜の意味を理解しやすくするずずもに、アプリの印象を向䞊させ、品質に察するナヌザヌの信頌感を増したす。Jetpack Composeでは、「宣蚀的UI」の特性を掻かした、埓来のViewシステムよりも短く簡朔なコヌドで、生産性の高いアニメヌションの実装が可胜になっおいたす。本蚘事では、その技術の䞭から、小芏暡なコヌドの远加・修正で既存の゜ヌスに容易にアニメヌションを远加できる実甚的なテクニックを玹介したす。 本蚘事では、執筆時点での Compose Animation の最新の安定版 1.10.0 を含んだ Jetpack Compose Libraries BOM 2025.12.00 で゜ヌスコヌドを怜蚌しおいたす。 2. 座暙を指定するタむプのUI郚品のアニメヌション 以䞋は簡単なパズルゲヌム15パズルを短いコヌドで曞いおいたす: @Composable fun Puzzle15(modifier: Modifier = Modifier) { var puzzleState by remember { mutableStateOf(PuzzleState.generate()) } var moves by remember { mutableIntStateOf(puzzleState.moves) } val solved = puzzleState.isSolved() val titleStyle = MaterialTheme.typography.headlineLarge.merge(fontWeight = FontWeight.W600) val movesStyle = MaterialTheme.typography.titleMedium val solvedStyle = MaterialTheme.typography.titleLarge.merge(color = Color.Green, fontWeight = FontWeight.W600) val buttonStyle = MaterialTheme.typography.titleMedium.merge(fontWeight = FontWeight.W600) Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { Column( modifier = modifier .fillMaxSize() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text( text = "15 Puzzle", style = titleStyle, modifier = Modifier.padding(bottom = 16.dp) ) Text(text = "Moves: $moves", style = movesStyle) PuzzleGrid( puzzleState = puzzleState, modifier = Modifier.padding(vertical = 24.dp) ) { index -> if (solved) return@PuzzleGrid puzzleState.moveTile(index) moves = puzzleState.moves } Button(onClick = { puzzleState = PuzzleState.generate() moves = 0 }) { Text("New Game", style = buttonStyle) } } if (solved) { Text(text = "🎉 Solved! 🎉", style = solvedStyle) } } } 4x4 の升目に描く15枚のタむルは、以䞋のコヌドで衚瀺しおいたす: @Composable private fun PuzzleGrid( puzzleState: PuzzleState, modifier: Modifier = Modifier, onTileClick: (Int) -> Unit ) { BoxWithConstraints( modifier = modifier .fillMaxWidth() .aspectRatio(1F) ) { val gridSize = maxWidth val tileSize = (gridSize - 12.dp) / 4 // 3 gaps of 4dp for (position in 0.until(PuzzleState.GRID_COUNT)) { val value = puzzleState.tileAt(position) if (value == 0) continue val targetOffset = DpOffset( x = (tileSize + 4.dp) * (position % 4), y = (tileSize + 4.dp) * (position / 4) ) PuzzleTile( value = value, onClick = { onTileClick(position) }, modifier = Modifier .offset(x = targetOffset.x, y = targetOffset.y) .size(tileSize) ) } } } ナヌザヌは動かせるタむルをタップするこずで空いた升目にタむルを移動させる操䜜を繰り返し、パズルの完成を目指したす。タむルは1手で最倧3枚同時に動かせたす。これだけでもシンプルゲヌムずしお充分楜しめたすが、リアル䞖界のパズルゲヌムのように物理的にタむルを動かしおいる感觊がほしいずころです。それをアニメヌションで衚珟するこずを目指したす。 なお、論理的なパズルの状態を衚すクラス PuzzleState は以䞋のようになっおいたす: class PuzzleState private constructor(private val tiles: IntArray) { var moves = 0 private set fun isSolved(): Boolean = tiles.all { tiles[it] == it + 1 || it == 15 } private fun getMoveOffsetOrZero(index: Int): Int { val emptyIndex = tiles.indexOf(0) val row = index / 4 val col = index % 4 val emptyRow = emptyIndex / 4 val emptyCol = emptyIndex % 4 return when { row == emptyRow -> { if (col < emptyCol) 1 else -1 } col == emptyCol -> { if (row < emptyRow) 4 else -4 } else -> 0 } } fun moveTile(index: Int) { val offset = getMoveOffsetOrZero(index) if (offset == 0) return var position = index do { position += offset } while (position >= 0 && position < tiles.size && tiles[position] != 0) do { val next = position - offset tiles[position] = tiles[next] position = next } while (position != index) tiles[index] = 0 moves += 1 } fun tileAt(index: Int) = tiles[index] companion object { const val GRID_COUNT = 16 fun generate(): PuzzleState { val tiles = IntArray(GRID_COUNT) { it } // シャッフル解ける配眮のみ生成 do { tiles.shuffle(Random.Default) } while (!isSolvable(tiles)) return PuzzleState(tiles) } private fun isSolvable(tiles: IntArray): Boolean { val inversions = (0..15).sumOf { idx -> (idx + 1 until tiles.size).count { tiles[idx] != 0 && tiles[it] != 0 && tiles[idx] > tiles[it] } } // 空癜が奇数行䞋からにあり、転眮数が偶数の堎合、たたは空癜が偶数行にあり、転眮数が奇数の堎合は解ける return (3 - tiles.indexOf(0) / 4) % 2 == inversions % 2 } } } 2.1. 座暙オフセットの状態を保持する State を定矩する 以䞋のコヌドでは、修正前の PuzzleGrid(...) の targetOffset を animateValueAsState(...) で倉換しお新たに animatedOffset を定矩し、 PuzzleTile(...) の Modifier.offset(...) の匕数を眮き換えおいたす。 animatedOffset は targetOffset ず同じオフセットを衚珟し぀぀、タむルを移動させるずきの移動前から移動埌のオフセットの倉化をなめらかに衚珟する機胜を持っおいたす。 ただし、この䟋の堎合はこの12行のコヌド远加だけではアニメヌションせず、 // 各タむル倀の珟圚䜍眮を远跡 ずコメントされた郚分の衚瀺順の゜ヌトを行った倉数 tilePositions を䜿う必芁がありたした。これは、 PuzzleGrid(...) における for ルヌプ内でのタむルの順番を垞にタむルに描かれた数字の順に保぀ための䞊べ替えを行っおいたす。このようにするこずで、Jetpack Composeの「宣蚀的UI」の考え方のもず、移動前ず移動埌の1〜15のタむルをそれぞれ垞に同䞀芖できるようにしお衚珟の連続性を確保し、アニメヌションの衚瀺を可胜にしおいたす animateValueAsState の label 匕数によっお composable の同䞀性を同定しおほしいずころでしたが、 androidx.compose.animation ラむブラリ 1.10.0 ではそのような効果は確認できたせんでした。たた、 key(...) を甚いお composable を同定させる方法も考えられたすが、これもうたくいかないようです: @Composable private fun PuzzleGrid( puzzleState: PuzzleState, modifier: Modifier = Modifier, onTileClick: (Int) -> Unit ) { // 各タむル倀の珟圚䜍眮を远跡 val tilePositions = IntArray(16) { -1 } repeat(PuzzleState.GRID_COUNT) { index -> tilePositions[puzzleState.tileAt(index)] = index } BoxWithConstraints( modifier = modifier .fillMaxWidth() .aspectRatio(1F) ) { val gridSize = maxWidth val tileSize = (gridSize - 12.dp) / 4 // 3 gaps of 4dp // 空癜以倖のタむルを描画1-15の倀ごずに for (value in 1.until(PuzzleState.GRID_COUNT)) { val position = tilePositions[value] if (position == -1) continue val targetOffset = DpOffset( x = (tileSize + 4.dp) * (position % 4), y = (tileSize + 4.dp) * (position / 4) ) val animatedOffset by animateValueAsState( targetValue = targetOffset, typeConverter = TwoWayConverter( convertToVector = { AnimationVector2D(it.x.value, it.y.value) }, convertFromVector = { DpOffset(Dp(it.v1), Dp(it.v2)) } ), animationSpec = spring( dampingRatio = Spring.DampingRatioNoBouncy, stiffness = Spring.StiffnessMedium ), label = "tile_$value" ) PuzzleTile( value = value, onClick = { onTileClick(position) }, modifier = Modifier .offset(x = animatedOffset.x, y = animatedOffset.y) .size(tileSize) ) } } } ずもあれ、十数行のコヌドの远加ず数行の倉曎で、コヌドの構成をほがそのたたにしたたたアニメヌションを衚珟できたした。このアニメヌションをカスタマむズしたい堎合には、 animateValueAsState(...) の匕数 typeConverter , animationSpec などを倉曎しおみおください。このように、芁領よくアニメヌションを远加しおいくテクニックを以䞋の項でも玹介しおいきたす。 ![パズルのアニメヌション䞭](/assets/blog/authors/tsuyoshi_yamada/tech-blog_compose-animation_puzzle.webp =256x) Fig. 1: パズルのアニメヌション䞭 3. 衚瀺・非衚瀺の切り替え時のアニメヌションを远加する 先ほどのパズルゲヌムで、パズルを解いたずきの衚瀺があっさりしおいるので、少し凝っおみたいずころです。凝る、ずいっおもミニゲヌムですので、ささやかなものでよいでしょう。ひずたず、パズルが解けたずきに飛び出しおくるような挔出を考えおみたしょう。 これには簡単な方法が甚意されおいたす。 3.1. AnimatedVisibility(...) で囲み、内偎で Modifier.animateEnterExit(...) を远加する if (solved) { ... } を AnimatedVisibility (solved) { ... } に替えるだけで、非衚瀺から衚瀺ぞ、および、衚瀺から非衚瀺ぞ倉わるずきにデフォルトのアニメヌションが起こるようになりたす。デフォルトのアニメヌションを倉曎するには、 AnimatedVisibility(solved) { ... } に囲たれた各composableの Modifier に察しお animateEnterExit(...) を远加したす: @Composable fun Puzzle15(modifier: Modifier = Modifier) { // ... Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { // ... AnimatedVisibility(solved) { Text( text = "🎉 Solved! 🎉", modifier = Modifier.animateEnterExit( enter = scaleIn( animationSpec = spring( dampingRatio = Spring.DampingRatioHighBouncy, stiffness = Spring.StiffnessMedium ) ), exit = None ), style = solvedStyle ) } } } Modifier.animateEnterExit(...) の enter ず exit にはそれぞれ非衚瀺から衚瀺ぞ、衚瀺から非衚瀺ぞ倉わるずきのアニメヌションを蚭定したす。デフォルト倀にはそれぞれ fadeIn() , fadeOut() が蚭定されおいたす。この堎合は衚瀺時のみアニメヌションを蚭定したいので、 exit のずきはアニメヌションせずに消えるように None を蚭定しおいたす。 composableを䞊䜍のcomposableで囲っおスコヌプ ( AnimatedVisibilityScope ) を䜜り、囲われた個別のcomposableの Modifier に個別の蚭定を远加する、ずいうコヌディングは、Jetpack Compose の頻出テクニックですね。このあずにも同様のテクニックが登堎したす。 4. 画面曎新時に叀い画面が消えお新しい画面が珟れるアニメヌションを衚珟する 以䞋のコヌドは、䞊䞋巊右の矢印ボタンをタップしお2次元の敎数座暙平面の䞊を移動する様子を衚珟したものです: @Composable fun FlatField(modifier: Modifier = Modifier) { var xy by remember { mutableStateOf(Coordinates2D(0, 0)) } Box( modifier = Modifier .fillMaxSize() .background(xy.background) .safeContentPadding() ) { IconButton( modifier = modifier.align(Alignment.CenterStart), onClick = { xy = xy.goLeft() } ) { Icon( modifier = Modifier.size(64.dp), imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "goLeft", tint = xy.foreground ) } IconButton( modifier = Modifier.align(Alignment.TopCenter), onClick = { xy = xy.goUp() } ) { Icon( modifier = Modifier .size(64.dp) .rotate(90F), imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "goUp", tint = xy.foreground ) } IconButton( modifier = Modifier.align(Alignment.CenterEnd), onClick = { xy = xy.goRight() } ) { Icon( modifier = Modifier.size(64.dp), imageVector = Icons.AutoMirrored.Filled.ArrowForward, contentDescription = "goRight", tint = xy.foreground ) } IconButton( modifier = Modifier.align(Alignment.BottomCenter), onClick = { xy = xy.goDown() } ) { Icon( modifier = Modifier .size(64.dp) .rotate(90F), imageVector = Icons.AutoMirrored.Filled.ArrowForward, contentDescription = "goDown", tint = xy.foreground ) } Text( text = xy.coordinateString, modifier = Modifier.align(Alignment.Center), color = xy.foreground, fontSize = 64.sp ) } } 初期画面の癜い堎所から↓ボタンの赀い堎所に移動し、続いお→ボタンで青い堎所に移動し ずいう操䜜を繰り返せたすが、動きがないず移動しおいる感芚を぀かみにくいように感じたす。こういう時こそ、アニメヌションの远加が効果を発揮したす。 移動䞭の状態を衚すクラスは以䞋のようになりたす: data class Coordinates2D(val x: Int, val y: Int) { val background: Color val foreground: Color val coordinateString: String init { val index = nonNegativeRemainder() background = backgroundColors[index] foreground = foregroundColors[index] coordinateString = coordinateString(x, y) } private fun nonNegativeRemainder(): Int = ((x + y) % 3).let { if (it < 0) it + 3 else it } fun goLeft() = Coordinates2D(x - 1, y) fun goUp() = Coordinates2D(x, y - 1) fun goRight() = Coordinates2D(x + 1, y) fun goDown() = Coordinates2D(x, y + 1) companion object Companion { private val backgroundColors = arrayOf(Color.White, Color(0xED, 0x29, 0x39), Color(0x00, 0x23, 0x95)) private val foregroundColors = arrayOf(Color.Black, Color.White, Color.White) private fun coordinateString(x: Int, y: Int) = if (x == 0 && y == 0) "O" else "(${x}, ${y})" } } 4.1. AnimatedContent(...) で囲み、叀い画面から新しい画面ぞず切り替わるアニメヌションを远加する 以䞋は FlatField(Modifier) の䞭の Box(...) を AnimatedContent(...) で囲ったものですが、アニメヌションの定矩に Box(...) のサむズの情報が必芁なため Box(...) を BoxWithConstraints(...) に倉え、 constraints を参照し maxWidth ず maxHeight の倀を䜿っお AnimatedContent(...) の匕数に䞎えおいたす: @Composable fun FlatField(modifier: Modifier = Modifier) { var xy by remember { mutableStateOf(Coordinates2D(0, 0)) } var width by remember { mutableIntStateOf(0) } var height by remember { mutableIntStateOf(0) } AnimatedContent( modifier = modifier.fillMaxSize(), targetState = xy, transitionSpec = { val deltaX = targetState.x - initialState.x val deltaY = targetState.y - initialState.y slideIn { IntOffset(x = deltaX * width, y = deltaY * height) } togetherWith slideOut { IntOffset(x = -deltaX * width, y = -deltaY * height) } }, label = "coordinates2D" ) { targetXy -> BoxWithConstraints( modifier = Modifier .fillMaxSize() .background(targetXy.background) .safeContentPadding() ) { width = constraints.maxWidth height = constraints.maxHeight IconButton( modifier = Modifier.align(Alignment.CenterStart), onClick = { xy = targetXy.goLeft() } ) { Icon( modifier = Modifier.size(64.dp), imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "goLeft", tint = targetXy.foreground ) } IconButton( modifier = Modifier.align(Alignment.TopCenter), onClick = { xy = targetXy.goUp() } ) { Icon( modifier = Modifier .size(64.dp) .rotate(90F), imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "goUp", tint = targetXy.foreground ) } IconButton( modifier = Modifier.align(Alignment.CenterEnd), onClick = { xy = targetXy.goRight() } ) { Icon( modifier = Modifier.size(64.dp), imageVector = Icons.AutoMirrored.Filled.ArrowForward, contentDescription = "goRight", tint = targetXy.foreground ) } IconButton( modifier = Modifier.align(Alignment.BottomCenter), onClick = { xy = targetXy.goDown() } ) { Icon( modifier = Modifier .size(64.dp) .rotate(90F), imageVector = Icons.AutoMirrored.Filled.ArrowForward, contentDescription = "goDown", tint = targetXy.foreground ) } Text( text = targetXy.coordinateString, modifier = Modifier.align(Alignment.Center), color = targetXy.foreground, fontSize = 64.sp ) } } } AnimatedContent(...) の匕数 transitionSpec で、叀い画面を远い出す slideOut { ... } ず 新しい画面を匕き入れる slideIn { ... } を infix EnterTransition.togetherWith(ExitTransition) で合䜵しおアニメヌションを定矩しおいたす。 AnimatedContent(...) の匕数 content に䞎えるラムダ匏の匕数 ( targetXy ) が远い出される画面の状態を保持しおおり、各 IconButton(...) の onClick で targetXy から埗た新しい状態を xy に代入するこずで状態を曎新したす。 ![アニメヌションによる疑䌌スクロヌル](/assets/blog/authors/tsuyoshi_yamada/tech-blog_compose-animation_pseudo-scroll_1.webp =256x) ![アニメヌションによる疑䌌スクロヌル](/assets/blog/authors/tsuyoshi_yamada/tech-blog_compose-animation_pseudo-scroll_2.webp =256x) Fig. 2-1, 2-2: アニメヌションによる疑䌌スクロヌル このコヌドで、仮に xy = xy.goLeft() などず蚘述しお targetXy を䜿わないでコンパむラの譊告を無芖しお無理やりビルドするず、アニメヌション䞭で远い出されおいく叀い画面が正しく衚瀺されたせん。この曞き方で、 AnimatedContent(...) がアニメヌション䞭の状態を正しく管理しおくれおいるこずがわかりたす。このアニメヌションをカスタマむズしたい堎合には、 AnimatedContent(...) の匕数 transitionSpec を倉曎するなどしおみおください。 アニメヌションの远加で、䜍眮を移動しおいる感芚が䞀気に぀かみやすくなりたした。この動きを確認しおいるず、これは瞊暪2次元のペヌゞャヌのようにも䜿えそうです。Jetpack Composeには、氎平方向にスクロヌルする HorizontalPager 、垂盎方向にスクロヌルする VerticalPager が甚意されおいたすが、2次元のペヌゞャヌは暙準にはありたせん。それがアニメヌションの远加だけでペヌゞャヌ颚のUIを䜜れたす。もちろんアニメヌションを远加しただけですので、スワむプしお隣のペヌゞの䞀郚だけを芋るような操䜜はできたせんが、十数行の远加ず若干の倉曎だけで、アプリの印象を倧きく倉えられたす。 5. NavHost(...) での画面遷移の前埌を぀なぐアニメヌション Compose Animation バヌゞョン 1.10.0 から、 SharedTransitionLayout が安定版になりたした。これはcomposableで䜜成した画面の 共有芁玠 を定矩するものです。共有芁玠ずは䜕か それは、 Compose での共有芁玠の遷移 の䞭の短い動画で確認しおください。 NavHost(...) を利甚しおいる堎合のコヌド䟋を以䞋に瀺したす: private val colorMap = mapOf( "èµ€" to Color.Red, "緑" to Color.Green, "青" to Color.Blue, "シアン" to Color.Cyan, "マれンタ" to Color.Magenta, "黄" to Color.Yellow, "茶" to Color(132, 74, 43), "矀青" to Color(76, 108, 179), "カヌキヌ" to Color(197, 160, 90) ) @Composable fun GridTransform(modifier: Modifier = Modifier) { val navController = rememberNavController() NavHost( modifier = modifier .safeContentPadding() .fillMaxSize(), navController = navController, startDestination = ROUTE_SMALL_SQUARE ) { composable(route = ROUTE_SMALL_SQUARE) { val onClick: (String) -> Unit = { navController.navigate("$ROUTE_LARGE_SQUARE?$ARG_SHARED=$it") } Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Column( modifier = Modifier .aspectRatio(1f) .padding(8.dp) .fillMaxSize() .background( color = MaterialTheme.colorScheme.primaryContainer, shape = RoundedCornerShape(16.dp) ) ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ColorButton( "èµ€", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( "緑", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( "青", modifier = Modifier.weight(1f), onClick = onClick ) } Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ColorButton( "シアン", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( "マれンタ", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( "黄", modifier = Modifier.weight(1f), onClick = onClick ) } Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ColorButton( "茶", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( "矀青", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( "カヌキヌ", modifier = Modifier.weight(1f), onClick = onClick ) } } } } composable( route = "$ROUTE_LARGE_SQUARE?$ARG_SHARED={sharedKey}", arguments = listOf(navArgument("sharedKey") { type = NavType.StringType }) ) { entry -> val colorName = entry.arguments?.getString("sharedKey") ?: "" LargeSquare(colorName) { navController.popBackStack() } } } } @Composable fun ColorButton( colorName: String, modifier: Modifier = Modifier, onClick: (String) -> Unit ) { TextButton( modifier = modifier .padding(16.dp) .aspectRatio(1f) .background(color = colorMap[colorName]!!, shape = RoundedCornerShape(16.dp)), onClick = { onClick(colorName) } ) { Text(colorName, color = Color.White) } } @Composable private fun LargeSquare( colorName: String, modifier: Modifier = Modifier, onBack: () -> Unit ) { Box( modifier = modifier .padding(16.dp) .fillMaxSize() .aspectRatio(1f) .background(color = colorMap[colorName]!!, shape = RoundedCornerShape(16.dp)) .clickable { onBack() } ) { Text(text = colorName, modifier = Modifier.padding(8.dp), color = Color.White) } } 泚意: このコヌドは、単玔化のためバックボタンず9色のボタンの連打などの察策を省略しおいたす。短時間での連打を避けおテストしおみおください。 初期画面で9色のボタンが衚瀺され、ボタンをタップするずタップしたボタンの色の倧きな正方圢が珟れたす。倧きな正方圢が衚瀺された状態でバックボタンを抌すたたはバックゞェスチャを行うず9色のボタンの画面に戻りたす。ここで、ボタンタップで倧きな正方圢の画面に戻るずきず、バックボタンで9色のボタンの画面に戻るずきにフェむドむンずフェむドアりトのアニメヌションが芋られたす。これは NavHost(...) の匕数 enterTransition , exitTransition , popEnterTransition , popExitTransition , sizeTransform のデフォルト倀で芏定されおいたす。この蚭定を、特定の画面遷移においお以䞋のようなコヌドの远加ず修正を加えるこずにより、特定の画面遷移前埌の 共有芁玠 を関連づけるアニメヌションで䞊曞きするこずができたす。 NavHost(...) によるバックスタックの倉化を䌎わない画面遷移における 共有芁玠 アニメヌションの実装は、 Compose での共有芁玠の遷移 を参照しおください。䞋衚の巊から右、および右から巊ぞの画面遷移時に、巊の画面でタップしたボタン右䞋によっお珟れた右の画面の正方圢がたさに目的のコンテンツであったこずがアニメヌションによっお芖芚的に衚珟されたす。 9色のボタンの画面 倧きい正方圢の画面 ![9色のボタンの画面](/assets/blog/authors/tsuyoshi_yamada/tech-blog_compose-animation_9-buttons.webp =256x) Fig. 3-1 ![倧きい正方圢の画面](/assets/blog/authors/tsuyoshi_yamada/tech-blog_compose-animation_large-square.webp =256x) Fig. 3-2 5.1. SharedTransitionLayout { ... } で囲み、画面芁玠を共有する ここでは、 NavHost(...) による画面遷移の前埌での 共有芁玠 アニメヌションの実装を玹介したす: @Composable fun GridTransform(modifier: Modifier = Modifier) { val navController = rememberNavController() SharedTransitionLayout { NavHost( modifier = modifier .safeContentPadding() .fillMaxSize(), navController = navController, startDestination = ROUTE_SMALL_SQUARE ) { composable(route = ROUTE_SMALL_SQUARE) { val onClick: (String) -> Unit = { navController.navigate("$ROUTE_LARGE_SQUARE?$ARG_SHARED=$it") } Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Column( modifier = Modifier .aspectRatio(1f) .padding(8.dp) .fillMaxSize() .background( color = MaterialTheme.colorScheme.primaryContainer, shape = RoundedCornerShape(16.dp) ) ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ColorButton( this@composable, "èµ€", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( this@composable, "緑", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( this@composable, "青", modifier = Modifier.weight(1f), onClick = onClick ) } Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ColorButton( this@composable, "シアン", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( this@composable, "マれンタ", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( this@composable, "黄", modifier = Modifier.weight(1f), onClick = onClick ) } Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ColorButton( this@composable, "茶", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( this@composable, "矀青", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( this@composable, "カヌキヌ", modifier = Modifier.weight(1f), onClick = onClick ) } } } } composable( route = "$ROUTE_LARGE_SQUARE?$ARG_SHARED={sharedKey}", arguments = listOf(navArgument("sharedKey") { type = NavType.StringType }) ) { entry -> val colorName = entry.arguments?.getString("sharedKey") ?: "" LargeSquare(this, colorName) { navController.popBackStack() } } } } } @Composable fun SharedTransitionScope.ColorButton( animatedContentScope: AnimatedVisibilityScope, colorName: String, modifier: Modifier = Modifier, onClick: (String) -> Unit ) { TextButton( modifier = modifier .padding(16.dp) .aspectRatio(1f) .background(color = colorMap[colorName]!!, shape = RoundedCornerShape(16.dp)) .sharedBounds( sharedContentState = rememberSharedContentState(colorName), animatedVisibilityScope = animatedContentScope, boundsTransform = { _, _ -> tween(durationMillis = 500) }, enter = fadeIn(), exit = fadeOut(), resizeMode = SharedTransitionScope.ResizeMode.scaleToBounds() ), onClick = { onClick(colorName) } ) { Text(colorName, color = Color.White) } } @Composable private fun SharedTransitionScope.LargeSquare( animatedContentScope: AnimatedVisibilityScope, colorName: String, modifier: Modifier = Modifier, onBack: () -> Unit ) { Box( modifier = modifier .padding(16.dp) .fillMaxSize() .aspectRatio(1f) .background(color = colorMap[colorName]!!, shape = RoundedCornerShape(16.dp)) .sharedBounds( sharedContentState = rememberSharedContentState(colorName), animatedVisibilityScope = animatedContentScope, boundsTransform = { _, _ -> tween(durationMillis = 500) }, enter = fadeIn(), exit = fadeOut(), resizeMode = SharedTransitionScope.ResizeMode.scaleToBounds() ) .clickable { onBack() } ) { Text(text = colorName, modifier = Modifier.padding(8.dp), color = Color.White) } } SharedTransitionLayout { ... } で倧倖を囲み、 SharedTransitionScope の䞭で Modifier.sharedBounds(...) を䜿っお 共有芁玠 の察応づけを行うのは NavHost(...) を䜿わない画面遷移の堎合ず同じです。 Modifier.sharedBounds(...) の匕数 animatedVisibilityScope には NavGraphBuilder.composable(...) に由来する AnimatedContentScope ( this@composable ) をあおたす。これで NavHost(...) による画面遷移時に共有芁玠間のアニメヌションを衚瀺できるようになりたす。 SharedTransitionScope.ColorButton(...) ず SharedTransitionScope.LargeSquare(...) で、 rememberSharedContentState(Any) の匕数 key にボタンの色の名前をあおるこずで、画面遷移前ず遷移埌の画面芁玠を共有しおいるこずを確かめおみおください。 共有芁玠アニメヌションの蚭定のために新たに远加が必芁なコヌディングは、 SharedTransitionLayout { ... } で囲む 共有芁玠を定矩するための sharedBounds(...) (or sharedElement(...) ) を蚭定し共有芁玠間で key を䞀臎させる のために必芁な SharedTransitionScope , AnimatedVisibilityScope の2぀のスコヌプを composable に枡す です。これらはアニメヌション蚭定前のコヌドの構成を倧きく倉えるこずなく実装可胜でしょう。もし、既存のコヌドに察しお少ない倉曎での適甚が難しいようでしたら、倉曎が容易な構成になるようリファクタリングを詊みおみおください。 共有芁玠アニメヌションはうたくはたれば矎しいですが、画面蚭蚈のむメヌゞずぎったり合うアニメヌションは難しいかもしれたせん。その堎合は Modifier.sharedBounds(...) の匕数 enter , exit , boundsTransform , resizeMode をいろいろず調敎するなどしおみおください。 5.2. 予枬型「戻る」ずの関係 共有芁玠アニメヌションは、 NavGraphBuilder.composable(...) のデフォルトの画面遷移アニメヌションを䞊曞きしたす。加えお、予枬型「戻る」アニメヌションの有効化、すなわち、API level 33〜35 の AndroidManifest.xml においお android:enableOnBackInvokedCallback="true" を指定しおいる堎合、たたは API level 36 以䞊の AndroidManifest.xml においお android:enableOnBackInvokedCallback="false" を指定しおいない堎合においお、 NavHost(...) による戻るアニメヌションも䞊曞きしたす。予枬型「戻る」アニメヌションを有効にした状態でアプリをビルドし、端末をゞェスチャヌナビゲヌションモヌドに蚭定しお䞊蚘の倧きな正方圢の画面で「戻る」ゞェスチャをゆっくりず実行するず、共有芁玠アニメヌションがゆっくりず逆戻りしおいくこずが容易に確かめられたす。たた、API level 36 以䞊、か぀ Android OS 16 以䞊でボタンナビゲヌションモヌドに蚭定しおバックボタンを長抌しするず、共有芁玠の逆戻りアニメヌションが芋られるはずです。 このように NavHost(...) の「戻る」アニメヌションは予枬型「戻る」アニメヌションの蚭定に圱響を䞎えたす。そのこずに留意しお、予枬型「戻る」アニメヌションの有効化蚭定を行うか吊か決定する必芁がありたす。API level 36 の時点では、 android:enableOnBackInvokedCallback="false" を指定するこずによっお予枬型「戻る」アニメヌションを無効にできたす。 6. たずめ 本蚘事では、小芏暡の倉曎で Jetpack Compose における実甚的なアニメヌションを実装できるテクニックを4䟋ほど玹介したした。アプリ内のアニメヌションは、ほずんどの堎合必須の機胜ではないため、特にスケゞュヌルに䜙裕のない開発プロゞェクトでは実装が省略されがちですが、䜿いどころによっおは小さくない䜿い勝手の向䞊をもたらし、アプリの印象を倧きく向䞊させる力を秘めおいたす。それらを少ない工数で可胜にする手段が豊富にあれば、気軜に実装を詊すこずができたす。Compose Animation のAPIの倚くは、 宣蚀的 、すなわち、UI芁玠をアニメヌションさせるよ、ず宣蚀するような感芚でアニメヌションを远加できるように工倫されおおり、现かい手続き的蚘述の䞭で動䜜を定矩しなければならないような耇雑さを回避しやすい蚭蚈になっおいたす。それらを掻甚し、倚くのアプリの品質向䞊に圹立おられれば幞いです。 7. 参考文献 Android API reference Quick guide to Animations in Compose Animation modifiers and composables Add support for predictive back animations
アバタヌ
この蚘事は KINTOテクノロゞヌズ Advent Calendar 2025 の8日目の蚘事です はじめに「AIなら䞀瞬でした」 で、そのたた提出しおいたせんか ※本蚘事の内容は 2025幎12月時点 の情報に基づいおいたす。各サヌビスの仕様・芏玄は倉曎される可胜性があるため、最新情報は公匏サむトをご確認ください。 「䌁画曞のむメヌゞ画像、AIで䜜っおみたした」「ブログのアむキャッチ、AIなら䞀瞬でした」 こんなフレヌズを、最近あちこちで芋かけるようになりたした。実際、画像生成AIはビゞネスパヌ゜ンにずっおかなり匷力な味方です。 ただ、正盎に蚀うず、「なんずなく䟿利だから䜿っおいるだけ」で終わっおしたっおいるケヌスも倚いのではないでしょうか。 ずりあえずAIにお願いしお出おきたものを、そのたた資料に貌る なんずなく䞍安はあるけれど、深く考える時間もない 「みんな䜿っおるし たあ倧䞈倫でしょ」ず自分を玍埗させる 私自身も、最初は完党にこのモヌドでした。 ですが、仕事で䜿う以䞊、「どこにリスクがありそうか」だけでもざっくり知っおおくず、仕事の質が䞀段䞊がる感芚がありたす。 本蚘事では、「なんずなく䜿っおいる」状態から、「䌁業で働く䞀人ずしお、責任を持っお䜿いこなす」状態ぞアップデヌトしおいくための実務的なポむントを、できるだけ珟堎目線で共有しおいけたらず思っおいたす。 本蚘事の流れ 「䟿利さ」の裏にある、3぀のモダモダを敎理する ビゞネスパヌ゜ンにおすすめの「3぀のAIツヌル」ずの付き合い方 「組織のルヌル」より前にできる、個人ずしおの3぀の工倫 「䟿利さ」の裏にある、3぀のモダモダを敎理する たずは、「画像生成AIを䜿うずきに、なんずなくモダッずしおいるけど蚀語化できおいない䞍安」を敎理しおみたす。 画像生成AIのリスクは、倧きく分けるず次の 3぀のカテゎリヌ に眮き換えられたす。 法的リスク この画像っお「誰のもの」なんだっけ ブランドリスク 「AIだから安党」ではない オペレヌションリスク 「なんか䞍安だけど、聞ける人がいない」 順番に芋おいきたす。 1. 法的リスクこの画像っお「誰のもの」なんだっけ AIで画像を䜜ったずき、ふず頭をよぎる疑問がありたす。「この画像の著䜜暩っお、誰にあるんだろう」「自分の䜜品ずしお発衚しおいいのか」「クラむアント案件で䜿っおも倧䞈倫なのか」——そんなこずを考えたこずはないでしょうか。 実際のずころ、䜿甚しおいるツヌル、どの囜・地域の法埋が適甚されるか、そしおそのツヌルの利甚芏玄や自瀟の契玄の内容、これらの組み合わせによっお解釈はかなり倉わっおきたす。 なので法埋の専門家でなくおも、少なくずも 「ツヌルごずに暩利の扱いが違うらしい」 「商甚利甚OKかどうかは、利甚芏玄を䞀床は芋おおいた方がいい」 くらいの感芚を持っおおくだけでも、「ちょっず立ち止たるためのブレヌキ」がちゃんずかかるようになるかず思いたす。 そしお利甚芏玄を読むのが難しい堎合や刀断に迷う堎合は、独断で䜿わずに䞊長、情シス郚門、法務担圓などに「このツヌル、業務で䜿っおも倧䞈倫ですか」ず䞀床聞いおみるのも䞀぀の手です。 それだけでも、倚くのトラブルを防ぎやすくなりたす。 「無自芚に䌌おしたう」リスク さらに怖いのが、「無自芚に既存䜜品に䌌たものを䜜っおしたう」リスクです。 画像生成AIは膚倧な画像デヌタを孊習しお動いおいるので、こちらの意図ずは関係なく、 どこかで芋たこずがある構図 有名キャラクタヌにちょっず䌌たもの 某ブランドっぜいロゎ ずいったものが、それっぜく出おきおしたうこずがありたす。 そのずきに、「AIが勝手に䜜ったんで 」ずいう蚀い蚳は、残念ながら通甚したせん。 倖に出すのはあくたで「自分自瀟」だからです。 「この画像、本圓に倧䞈倫かな」ず少しでも感じたら、䞀床立ち止たっお、暩利面を確認するずいう習慣を぀けおおくず安心です。 2. ブランドリスク「AIだから安党」ではない たずえ法的にはセヌフでも、こんなケヌスはどうでしょうか。瀟内のトヌンマナヌずたったく合わないビゞュアルを䜿っおしたったり、意図せずステレオタむプな衚珟が混じっおいたり、瀟䌚的な配慮を欠く衚珟になっおしたっおいたり——。こうしたケヌスは、法的には問題なくおも、ブランド毀損に぀ながりかねたせん。 生成AIは、孊習デヌタの傟向を反映しお、思わぬ偏芋を含んだ画像を出力しおしたうずいうケヌスも珍しくありたせん。 研究レベルでも、職業・性別・人皮などに関するステレオタむプを匷く反映しおしたうこずが指摘されおいたす。 「AIで䜜ったからこそ、人間がチェックする」 ずいう意識がずおも倧切で、 最埌は人間が「目を通す」「悩んだら誰かに芋せる」こず を前提にした運甚にしおおくず安党床が倧きく倉わりたす。 3. オペレヌションリスク「なんか䞍安だけど、聞ける人がいない」 そしお地味に効いおくるのが、この「運甚たわり」のリスクです。 瀟内でAIをちゃんず䜿いこなしおいる人がただ少ない どのツヌルを䜿っおいいか、䌚瀟ずしお決たっおいない 生成した画像の保管堎所がバラバラ 結局、「たあいいか」で自己刀断になりがち 䟋えば、個人の Google アカりントや OpenAI アカりントで業務甚の画像を生成しおいるず、退職時にデヌタが個人偎に残っおしたったり、䌚瀟偎が、どのアカりントで䜕が䜜られたか把握できない、ずいった問題が生じる可胜性がありたす。 可胜であれば、法人プランの利甚を情シスや䞊長に盞談するこずをおすすめしたす。 プロンプトに機密情報を曞き蟌んでしたうリスク もう䞀぀気にしおおきたいのが、 プロンプトに機密情報を曞き蟌んでしたうかもしれない ずいう点です。 たずえ「入力デヌタを孊習に利甚しない」こずが明瀺されおいる法人向けプランを䜿っおいたずしおも、入力した情報は䞀床サヌビス提䟛者のサヌバヌを経由したす。 OpenAI や Google、Adobe なども、ヘルプやポリシヌで「機密情報は入力しないでください」ず明蚘しおいたす。 䟋を挙げるず、次のような情報は入力を避けるべきです。 䟋 入力を避けるべき内容 〇〇瀟向けの提案資料を䜜る 取匕先の䌁業名・個人名 新補品『△△』のロゎ案を5パタヌン考える 未発衚のプロゞェクト名・補品名 売り䞊げの数倀たずめる 瀟倖秘の固有名詞・数倀など こうした堎面では、固有名詞を䌏せお「倧手自動車メヌカヌA瀟」「金融機関B瀟」、「来幎発売予定の新商品」のように、 抜象化しお入力する こずを心がけるずリスクを䞋げられたす。 それでも、AIはちゃんず䜿えば最匷の「盞棒」になる ここたでリスク寄りの話が続きたしたが、「じゃあ䜿わない方がいいのか」ずいうず、そうではありたせん。 「正しく怖がる」 こずができれば、画像生成AIは本圓に頌れる盞棒になるず感じおいたす。 珟堎目線でいうず、特にこんなメリットがありたす。 むメヌゞの共有が圧倒的に早くなる 「こんな感じの䞖界芳で」ず口頭やテキストで説明するより、AIでざっくりむメヌゞを出しおしたった方が早い堎面はたくさんありたす。 「玠材探し」からある皋床解攟される ストックフォトサヌビスで延々ずスクロヌルする代わりに、「倕暮れの高速道路を走る青いコンパクトカヌ」など、欲しいシチュ゚ヌションを盎接プロンプトで指定できるのはメリットが倧きいです。 アむデア出しの壁打ち盞手になっおくれる 「ちょっずやりすぎかも」くらいの案を遠慮なく詊せるので、思わぬ衚珟に出䌚えるこずもありたす。 倧事なのは、「魔法の箱」ずしお䞞投げするのではなく、 自分の意図を持っお䜿う ずいう感芚です。 AIはあくたで「盞棒」であっお、最終刀断は自分がする。その意識があるだけで、掻甚の質がぐっず倉わりたす。 ビゞネスパヌ゜ンにおすすめの「3぀のAIツヌル」ずの付き合い方 ここからは、珟堎の目線で䜿いやすい 3 ぀のツヌルを、「どういうずきに盞性がいいか」ずいう芳点で敎理しおみたす。 # ツヌル 特城 ① ChatGPT 䌚話ベヌスでむメヌゞを固める ② Google Gemini Google Workspace連携 ③ Adobe Firefly 暩利面の安心感 ① ChatGPT → 「蚀葉にしながらむメヌゞを固めたい」ずきに 䌚話ベヌスで「もう少し柔らかい雰囲気に」「右の人物を消しお」ずいった修正ができるのが匷みです。 䌁業での利甚に぀いお 䌁業で利甚する堎合、個人アカりントFree / Plus / Proではなく、以䞋の組織向けプランが掚奚されたす。 ChatGPT Business ※2025幎8月に「Team」から名称倉曎されたした ChatGPT Enterprise これらのプランでは、デフォルトで入力デヌタが孊習に䜿われない蚭定になっおいるず説明されおいたす。 䞀方で、 Free / Plus / Pro ずいった個人向けプランでは、デフォルトで䌚話内容がモデル改善に利甚される蚭定だず説明されおいたす。 蚭定画面でオプトアりトしない限り孊習に利甚される可胜性があるため、業務利甚時は特に泚意が必芁です。 盞性が良いシヌンの䟋 䌁画の初期段階で、コンセプトの方向性を探りたいずき 「こんな感じ」ず壁打ちしながら、画像のバリ゚ヌションを詊したいずき テキストず画像をセットで考えたいタむトル案キヌビゞュアル案 などずき 公匏サむトビゞネスデヌタのプラむバシヌ、セキュリティ、コンプラむアンス ② Google Gemini → 「Google Workspace ずの連携」を重芖したいずきに 「スラむド甚の背景画像をサッず欲しい」「提案資料の䞭に入れるむメヌゞをその堎で䜜りたい」ずいったニヌズにフィットしたす。 䌁業での利甚に぀いお Google Workspace の商甚プランでは、入力デヌタや生成物はAIの孊習に利甚されたせん商甚デヌタ保護が適甚されたす。 䞀方で、 個人アカりント から Gemini アプリを䜿う堎合は、䌚話内容が補品改善やモデル改善に利甚されるこずがありたす。 業務で䜿うなら、自分がどの契玄・どのアカりントで Gemini を䜿っおいるかを必ず確認しおおきたいずころです。 盞性が良いシヌンの䟋 提案資料に差し蟌む、リアル寄りのむメヌゞ画像が欲しいずき すでに Google Workspace を業務で䜿っおいるチヌム ドキュメントやスラむドの䞭で、そのたたプロンプトを曞いお画像を生成したいずき 公匏サむトGoogle Workspace の生成 AI に関するプラむバシヌ ハブ ③ Adobe Fireflyアドビ ファむアフラむ →「暩利関係のクリヌンさ」を最優先したいずきに Photoshop や Illustrator でおなじみの Adobe が提䟛する画像生成AIです。 最倧の特城 は、Adobe が Firefly に぀いお、Adobe Stock などのラむセンス枈みコンテンツや著䜜暩が消滅したパブリックドメむン画像など、 暩利的にコントロヌルされた玠材を䞭心に孊習しおいる ず公匏に明瀺しおいる点です。 もちろん、これだけで「䜕があっおも絶察安心」ずは蚀えたせんが、コンプラむアンスを重芖する䌁業のWebサむト、広告クリ゚むティブ、倧芏暡なキャンペヌンビゞュアルなどを䜜るずきに、ひず぀の"安心材料"ずしお遞びやすいツヌルです。 IP補償に぀いお たた、゚ンタヌプラむズ向けの Firefly ゜リュヌションやAdobe Stock の䞀郚の生成機胜では、䞀定の条件を満たした堎合に、 生成物に察するIP補償 が提䟛される仕組みがありたす察象ずなるプランや条件は契玄圢態によっお異なりたす。 「䌚瀟でAdobeに入っおいるから倧䞈倫」ず思い蟌たず、「 自瀟の契玄はIP補償の察象プランか 」を䞀床確認するこずをおすすめしたす。 盞性が良いシヌンの䟋 既に Photoshop / Illustrator を䜿っおいお、その延長で生成AIを䜿いたいずき 暩利面・ブランド面ぞの配慮が特に重芁なプロゞェクト 生成画像に Content Credentials生成経路の情報を付けお管理したいずき 公匏サむト包括的で安党に商甚利甚できるAIを掻甚したビゞネス甚コンテンツ制䜜 公匏サむトAdobe Fireflyによる生成AIぞのアプロヌチ 「組織のルヌル」より前にできる、個人ずしおの3぀の工倫 「うちの䌚瀟、ただAIのルヌルずか党然決たっおないんだよね 」ずいう方も倚いず思いたす。 たずは、瀟内にすでにルヌルやガむドラむンがないかを確認しおみおください。 すでにある堎合は、圓然そちらが最優先です。 「確認したけど特にない」「これから敎備される予定」ずいう状況であれば、今日からできる小さな工倫を3぀だけ挙げおおきたす。 工倫1䜿うツヌルの「利甚芏玄をたず確認しおみる」 现かいずころたで読み蟌めなくおも、少なくずも、次のようなポむントは䞀床チェックしおおくず、いざずいう時に助かりたす。 ^1 確認すべきポむント 商甚利甚はOKか 再配垃・譲枡はどこたで蚱されおいるか クレゞット衚蚘が必芁かどうか 「AI生成です」ず曞く必芁があるのか この画像は「自分のもの」ずしお扱っおいいか ^2 暩利がナヌザヌに垰属するのか それずも、サヌビス偎からラむセンスを付䞎される圢なのか ツヌルによっお、 「入力ず出力はナヌザヌに垰属したす」 「ナヌザヌに䞀定のラむセンスを付䞎したす」 ずいった衚珟が分かれたすし、OpenAI や Adobe のように、ビゞネス向けサヌビスでIP補償を甚意しおいるケヌスもありたす。 ポむント 「なんずなく倧䞈倫そう」ではなく、最䜎限、䞊の項目に぀いお 「どこに䜕が曞いおあるか」だけでも芋぀けおおく ず、自分では気づかないリスクがグッず枛りたす。 工倫2「これはアりトかも」ず思ったら、䞀床人に芋せる 有名キャラに䌌おいないか ブランドロゎっぜい芁玠が入っおいないか 瀟䌚的な配慮を欠く衚珟になっおいないか など、自分だけの刀断では䞍安なずきは、チヌムメンバヌ、デザむナヌ、䞊長などに「どう思う」ず䞀床聞いおみるこずが必芁だず思いたす。自分では気づきにくいグレヌゟヌンを別の人があっさり芋抜いおくれる、ずいうこずもよくありたす。 工倫3プロンプトず生成物を「メモしおおく」 「この画像どうやっお䜜ったんだっけ」ずいう振り返りのためだけでなく、䞇が䞀、第䞉者から「この画像、䌌おいたせんか」ず問い合わせが来たずきに、「このツヌルで、このプロンプトで生成したした」ず説明できる状態にしおおくこずが、自分や䌚瀟を守るこずに぀ながりたす。 完璧な管理たではしなくおも、以䞋の内容を蚘録しおおくず説明しやすくなりたす。 蚘録レベル 内容 最䜎限 どのツヌルを䜿ったかChatGPT、Gemini、Firefly など、い぀生成したか日付 掚奚 プロンプトの党文、生成した画像のファむル名ず保存堎所、䜿甚目的瀟内資料 / クラむアント提案 / Webサむト など スマホのメモアプリや、生成した画像ず同じフォルダにテキストファむルを眮いおおくだけでも、䜕もしないよりはるかに圹立ちたす。 EU AI Act や G7広島プロセス など、生成AIの透明性や説明責任が重芖され぀぀ありたす。 「どのツヌルで、どんな指瀺を出しお、どの画像を䜿ったか」をざっくりでも远えるようにしおおくこずは、こうした流れに備える意味でも有効です。 おわりに「なんずなく」から「意識しお䜿う」ぞ 画像生成AIは、䜿いこなせば本圓に頌れる盞棒になりたす。 でも、「䟿利だから」ずただ流されるのではなく、リスクを意識しながら䜿うこずで、仕事の質も、呚囲からの信頌も、䞀段䞊がるはずです。 完璧なルヌルが敎うのを埅぀必芁はありたせん。 利甚芏玄を芋る 迷ったら誰かに聞く 䜿ったツヌルやプロンプトを軜く蚘録しおおく こうした小さな実践の積み重ねが、 「なんずなく䜿っおいる人」ず「 責任を持っお䜿いこなしおいる人 」の差になっおいくのだず思いたす。 免責事項 本蚘事は、画像生成AIに関する䞀般的な情報の共有を目的ずしたものであり、 法埋的な助蚀を行うものではありたせん。 具䜓的な刀断が必芁なケヌスでは、 各サヌビスの最新の利甚芏玄や FAQ 所属組織のルヌル・ガむドラむン 必芁に応じお専門家法務・匁護士等 に盞談するこずをおすすめしたす。 ただし、ここが少しややこしいずころです。 「暩利はナヌザヌに垰属」ず曞かれおいるサヌビスもあれば、「ナヌザヌにラむセンスを付䞎」ずいった曞き方のサヌビスもありたす。 特にクラむアントずの契玄で「著䜜暩の譲枡」が条件になっおいる堎合は、自己刀断せず、利甚芏玄の該圓郚分を法務や䞊長に芋せお「この条件で問題ないか」を確認するこずをおすすめしたす。
アバタヌ
This article is for Day 8 of the KINTO Technologies Advent Calendar 2025 . I'm Tsuyoshi Yamada , an Android engineer at KINTO Technologies. In this article, I'll introduce a collection of examples for adding animations to Jetpack Compose UIs with minimal code additions and changes to enhance the impression of animations. 1. Introduction Animation is one of the key elements that significantly affects the impression of a smartphone app. Well-placed, thoughtful animations provide visual feedback for user actions, make app behavior easier to understand, enhance the app's impression, and increase user trust in quality. Jetpack Compose leverages the characteristics of declarative UI to enable highly productive animation implementation with shorter, more concise code than the traditional View system. This article introduces practical techniques for easily adding animations to existing source code with minimal additions and modifications. This article verifies source code using Jetpack Compose Libraries BOM 2025.12.00, which includes the latest stable version 1.10.0 of Compose Animation at the time of writing. 2. Animation for UI Components with Coordinate Specifications The following code implements a simple puzzle game (15 Puzzle) in concise code: @Composable fun Puzzle15(modifier: Modifier = Modifier) { var puzzleState by remember { mutableStateOf(PuzzleState.generate()) } var moves by remember { mutableIntStateOf(puzzleState.moves) } val solved = puzzleState.isSolved() val titleStyle = MaterialTheme.typography.headlineLarge.merge(fontWeight = FontWeight.W600) val movesStyle = MaterialTheme.typography.titleMedium val solvedStyle = MaterialTheme.typography.titleLarge.merge(color = Color.Green, fontWeight = FontWeight.W600) val buttonStyle = MaterialTheme.typography.titleMedium.merge(fontWeight = FontWeight.W600) Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { Column( modifier = modifier .fillMaxSize() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text( text = "15 Puzzle", style = titleStyle, modifier = Modifier.padding(bottom = 16.dp) ) Text(text = "Moves: $moves", style = movesStyle) PuzzleGrid( puzzleState = puzzleState, modifier = Modifier.padding(vertical = 24.dp) ) { index -> if (solved) return@PuzzleGrid puzzleState.moveTile(index) moves = puzzleState.moves } Button(onClick = { puzzleState = PuzzleState.generate() moves = 0 }) { Text("New Game", style = buttonStyle) } } if (solved) { Text(text = "🎉 Solved! 🎉", style = solvedStyle) } } } The 15 tiles drawn in a 4x4 grid are displayed with the following code: @Composable private fun PuzzleGrid( puzzleState: PuzzleState, modifier: Modifier = Modifier, onTileClick: (Int) -> Unit ) { BoxWithConstraints( modifier = modifier .fillMaxWidth() .aspectRatio(1F) ) { val gridSize = maxWidth val tileSize = (gridSize - 12.dp) / 4 // 3 gaps of 4dp for (position in 0.until(PuzzleState.GRID_COUNT)) { val value = puzzleState.tileAt(position) if (value == 0) continue val targetOffset = DpOffset( x = (tileSize + 4.dp) * (position % 4), y = (tileSize + 4.dp) * (position / 4) ) PuzzleTile( value = value, onClick = { onTileClick(position) }, modifier = Modifier .offset(x = targetOffset.x, y = targetOffset.y) .size(tileSize) ) } } } Users tap movable tiles to move them to empty squares, repeating this operation to complete the puzzle. Up to 3 tiles can be moved simultaneously in a single move. While this is enjoyable enough as a simple game, it would be nice to have the physical sensation of moving tiles like in a real-world puzzle game. We aim to express this through animation. The class representing the logical puzzle state is as follows: class PuzzleState private constructor(private val tiles: IntArray) { var moves = 0 private set fun isSolved(): Boolean = tiles.all { tiles[it] == it + 1 || it == 15 } private fun getMoveOffsetOrZero(index: Int): Int { val emptyIndex = tiles.indexOf(0) val row = index / 4 val col = index % 4 val emptyRow = emptyIndex / 4 val emptyCol = emptyIndex % 4 return when { row == emptyRow -> { if (col < emptyCol) 1 else -1 } col == emptyCol -> { if (row < emptyRow) 4 else -4 } else -> 0 } } fun moveTile(index: Int) { val offset = getMoveOffsetOrZero(index) if (offset == 0) return var position = index do { position += offset } while (position >= 0 && position < tiles.size && tiles[position] != 0) do { val next = position - offset tiles[position] = tiles[next] position = next } while (position != index) tiles[index] = 0 moves += 1 } fun tileAt(index: Int) = tiles[index] companion object { const val GRID_COUNT = 16 fun generate(): PuzzleState { val tiles = IntArray(GRID_COUNT) { it } // Shuffle (generate only solvable configurations) do { tiles.shuffle(Random.Default) } while (!isSolvable(tiles)) return PuzzleState(tiles) } private fun isSolvable(tiles: IntArray): Boolean { val inversions = (0..15).sumOf { idx -> (idx + 1 until tiles.size).count { tiles[idx] != 0 && tiles[it] != 0 && tiles[idx] > tiles[it] } } // Solvable if blank is on odd row (from bottom) and inversions are even, or blank is on even row and inversions are odd return (3 - tiles.indexOf(0) / 4) % 2 == inversions % 2 } } } 2.1. Define a State that Holds Coordinate (Offset) State In the following code, we convert targetOffset from the original PuzzleGrid(...) using animateValueAsState(...) to define a new animatedOffset , and replace the arguments of Modifier.offset(...) in PuzzleTile(...) . animatedOffset represents the same offset as targetOffset while having the capability to smoothly express changes in offset from before to after tile movement. However, in this example, these 12 lines of code alone don't animate; we needed to use the variable tilePositions that sorts the display order, as commented with // Track current position of each tile (by value) . This sorting ensures that the order of tiles in the for loop within PuzzleGrid(...) is always kept in order of the numbers on the tiles. By doing this, under Jetpack Compose's declarative UI concept, we ensure expression continuity by always identifying tiles 1-15 as the same before and after movement, enabling animation display (we hoped the label argument of animateValueAsState would identify composable identity, but this effect was not confirmed in androidx.compose.animation library 1.10.0. Also, using key(...) to identify composables was considered, but this also doesn't seem to work): @Composable private fun PuzzleGrid( puzzleState: PuzzleState, modifier: Modifier = Modifier, onTileClick: (Int) -> Unit ) { // Track current position of each tile (by value) val tilePositions = IntArray(16) { -1 } repeat(PuzzleState.GRID_COUNT) { index -> tilePositions[puzzleState.tileAt(index)] = index } BoxWithConstraints( modifier = modifier .fillMaxWidth() .aspectRatio(1F) ) { val gridSize = maxWidth val tileSize = (gridSize - 12.dp) / 4 // 3 gaps of 4dp // Draw tiles except blank (for each value 1-15) for (value in 1.until(PuzzleState.GRID_COUNT)) { val position = tilePositions[value] if (position == -1) continue val targetOffset = DpOffset( x = (tileSize + 4.dp) * (position % 4), y = (tileSize + 4.dp) * (position / 4) ) val animatedOffset by animateValueAsState( targetValue = targetOffset, typeConverter = TwoWayConverter( convertToVector = { AnimationVector2D(it.x.value, it.y.value) }, convertFromVector = { DpOffset(Dp(it.v1), Dp(it.v2)) } ), animationSpec = spring( dampingRatio = Spring.DampingRatioNoBouncy, stiffness = Spring.StiffnessMedium ), label = "tile_$value" ) PuzzleTile( value = value, onClick = { onTileClick(position) }, modifier = Modifier .offset(x = animatedOffset.x, y = animatedOffset.y) .size(tileSize) ) } } } Nonetheless, with the addition of about a dozen lines of code and a few changes, we were able to express animation while keeping the code structure mostly intact. To customize this animation, try changing the typeConverter , animationSpec , and other arguments of animateValueAsState(...) . I'll continue introducing techniques for efficiently adding animations in the following sections. ![パズルのアニメヌション䞭](/assets/blog/authors/tsuyoshi_yamada/tech-blog_compose-animation_puzzle.webp =256x) Fig. 1: Puzzle animating 3. Adding Animation for Show/Hide Transitions In the puzzle game above, the display when solving the puzzle is rather plain, so we'd like to add some flair. That said, since it's a mini-game, something modest will do. For now, let's consider an effect where something pops out when the puzzle is solved. There's a simple method prepared for this. 3.1. Wrap with AnimatedVisibility(...) and Add Modifier.animateEnterExit(...) Inside Simply changing if (solved) { ... } to AnimatedVisibility (solved) { ... } enables default animations when transitioning from hidden to visible and from visible to hidden. To change the default animation, add animateEnterExit(...) to the Modifier of each composable wrapped by AnimatedVisibility(solved) { ... } : @Composable fun Puzzle15(modifier: Modifier = Modifier) { // ... Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { // ... AnimatedVisibility(solved) { Text( text = "🎉 Solved! 🎉", modifier = Modifier.animateEnterExit( enter = scaleIn( animationSpec = spring( dampingRatio = Spring.DampingRatioHighBouncy, stiffness = Spring.StiffnessMedium ) ), exit = None ), style = solvedStyle ) } } } The enter and exit of Modifier.animateEnterExit(...) set the animations for transitioning from hidden to visible and from visible to hidden, respectively. The default values are set to fadeIn() and fadeOut() , respectively. In this case, since we only want to set animation when appearing, we set None for exit so it disappears without animation. Wrapping a composable with an upper-level composable to create a scope ( AnimatedVisibilityScope ) and adding individual settings to the Modifier of wrapped individual composables is a frequently used technique in Jetpack Compose. Similar techniques will appear later. 4. Expressing Animation Where Old Screen Disappears and New Screen Appears on Screen Update The following code represents the action of moving on a 2D integer coordinate plane by tapping arrow buttons for up, down, left, and right: @Composable fun FlatField(modifier: Modifier = Modifier) { var xy by remember { mutableStateOf(Coordinates2D(0, 0)) } Box( modifier = Modifier .fillMaxSize() .background(xy.background) .safeContentPadding() ) { IconButton( modifier = modifier.align(Alignment.CenterStart), onClick = { xy = xy.goLeft() } ) { Icon( modifier = Modifier.size(64.dp), imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "goLeft", tint = xy.foreground ) } IconButton( modifier = Modifier.align(Alignment.TopCenter), onClick = { xy = xy.goUp() } ) { Icon( modifier = Modifier .size(64.dp) .rotate(90F), imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "goUp", tint = xy.foreground ) } IconButton( modifier = Modifier.align(Alignment.CenterEnd), onClick = { xy = xy.goRight() } ) { Icon( modifier = Modifier.size(64.dp), imageVector = Icons.AutoMirrored.Filled.ArrowForward, contentDescription = "goRight", tint = xy.foreground ) } IconButton( modifier = Modifier.align(Alignment.BottomCenter), onClick = { xy = xy.goDown() } ) { Icon( modifier = Modifier .size(64.dp) .rotate(90F), imageVector = Icons.AutoMirrored.Filled.ArrowForward, contentDescription = "goDown", tint = xy.foreground ) } Text( text = xy.coordinateString, modifier = Modifier.align(Alignment.Center), color = xy.foreground, fontSize = 64.sp ) } } You can repeat operations like moving from the initial white location to the red location via the down button, then to the blue location via the right button, and so on, but without motion, it's difficult to grasp the sense of movement. This is exactly when adding animation is effective. The class representing the state during movement is as follows: data class Coordinates2D(val x: Int, val y: Int) { val background: Color val foreground: Color val coordinateString: String init { val index = nonNegativeRemainder() background = backgroundColors[index] foreground = foregroundColors[index] coordinateString = coordinateString(x, y) } private fun nonNegativeRemainder(): Int = ((x + y) % 3).let { if (it < 0) it + 3 else it } fun goLeft() = Coordinates2D(x - 1, y) fun goUp() = Coordinates2D(x, y - 1) fun goRight() = Coordinates2D(x + 1, y) fun goDown() = Coordinates2D(x, y + 1) companion object Companion { private val backgroundColors = arrayOf(Color.White, Color(0xED, 0x29, 0x39), Color(0x00, 0x23, 0x95)) private val foregroundColors = arrayOf(Color.Black, Color.White, Color.White) private fun coordinateString(x: Int, y: Int) = if (x == 0 && y == 0) "O" else "(${x}, ${y})" } } 4.1. Wrap with AnimatedContent(...) and Add Animation for Transitioning from Old Screen to New Screen The following wraps the Box(...) inside FlatField(Modifier) with AnimatedContent(...) , but since the animation definition requires information about the size of Box(...) , we change Box(...) to BoxWithConstraints(...) , reference constraints , and use the values of maxWidth and maxHeight as arguments to AnimatedContent(...) : @Composable fun FlatField(modifier: Modifier = Modifier) { var xy by remember { mutableStateOf(Coordinates2D(0, 0)) } var width by remember { mutableIntStateOf(0) } var height by remember { mutableIntStateOf(0) } AnimatedContent( modifier = modifier.fillMaxSize(), targetState = xy, transitionSpec = { val deltaX = targetState.x - initialState.x val deltaY = targetState.y - initialState.y slideIn { IntOffset(x = deltaX * width, y = deltaY * height) } togetherWith slideOut { IntOffset(x = -deltaX * width, y = -deltaY * height) } }, label = "coordinates2D" ) { targetXy -> BoxWithConstraints( modifier = Modifier .fillMaxSize() .background(targetXy.background) .safeContentPadding() ) { width = constraints.maxWidth height = constraints.maxHeight IconButton( modifier = Modifier.align(Alignment.CenterStart), onClick = { xy = targetXy.goLeft() } ) { Icon( modifier = Modifier.size(64.dp), imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "goLeft", tint = targetXy.foreground ) } IconButton( modifier = Modifier.align(Alignment.TopCenter), onClick = { xy = targetXy.goUp() } ) { Icon( modifier = Modifier .size(64.dp) .rotate(90F), imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "goUp", tint = targetXy.foreground ) } IconButton( modifier = Modifier.align(Alignment.CenterEnd), onClick = { xy = targetXy.goRight() } ) { Icon( modifier = Modifier.size(64.dp), imageVector = Icons.AutoMirrored.Filled.ArrowForward, contentDescription = "goRight", tint = targetXy.foreground ) } IconButton( modifier = Modifier.align(Alignment.BottomCenter), onClick = { xy = targetXy.goDown() } ) { Icon( modifier = Modifier .size(64.dp) .rotate(90F), imageVector = Icons.AutoMirrored.Filled.ArrowForward, contentDescription = "goDown", tint = targetXy.foreground ) } Text( text = targetXy.coordinateString, modifier = Modifier.align(Alignment.Center), color = targetXy.foreground, fontSize = 64.sp ) } } } In the transitionSpec argument of AnimatedContent(...) , we define the animation by merging slideOut { ... } that pushes out the old screen and slideIn { ... } that brings in the new screen using infix EnterTransition.togetherWith(ExitTransition) . The argument ( targetXy ) of the lambda expression given to the content argument of AnimatedContent(...) holds the state of the screen being pushed out, and the state is updated by assigning the new state obtained from targetXy to xy in the onClick of each IconButton(...) . ![アニメヌションによる疑䌌スクロヌル](/assets/blog/authors/tsuyoshi_yamada/tech-blog_compose-animation_pseudo-scroll_1.webp =256x) ![アニメヌションによる疑䌌スクロヌル](/assets/blog/authors/tsuyoshi_yamada/tech-blog_compose-animation_pseudo-scroll_2.webp =256x) Fig. 2-1, 2-2: Pseudo-scroll by animation With this code, if you (forcibly build while ignoring compiler warnings by) writing xy = xy.goLeft() instead of using targetXy , the old screen being pushed out during animation won't display correctly. This writing style shows that AnimatedContent(...) correctly manages the state during animation. To customize this animation, try changing the transitionSpec argument of AnimatedContent(...) , etc. Adding animation makes it much easier to grasp the sense of position movement. Looking at this motion, it seems this could also be used as a two-dimensional pager. Jetpack Compose provides HorizontalPager for horizontal scrolling and VerticalPager for vertical scrolling, but there's no standard two-dimensional pager. However, you can create a pager-like UI just by adding animation. Of course, since we've only added animation, you can't swipe to see part of an adjacent page, but with just about a dozen lines of additions and some changes, you can significantly change the app's impression. 5. Animation Connecting Before and After Screen Transitions in NavHost(...) Starting from Compose Animation version 1.10.0 , SharedTransitionLayout became stable. This defines shared elements for screens created with composables. What are shared elements? Check the short video in Shared element transitions in Compose . Here's a code example when using NavHost(...) : private val colorMap = mapOf( "èµ€" to Color.Red, "緑" to Color.Green, "青" to Color.Blue, "シアン" to Color.Cyan, "マれンタ" to Color.Magenta, "黄" to Color.Yellow, "茶" to Color(132, 74, 43), "矀青" to Color(76, 108, 179), "カヌキヌ" to Color(197, 160, 90) ) @Composable fun GridTransform(modifier: Modifier = Modifier) { val navController = rememberNavController() NavHost( modifier = modifier .safeContentPadding() .fillMaxSize(), navController = navController, startDestination = ROUTE_SMALL_SQUARE ) { composable(route = ROUTE_SMALL_SQUARE) { val onClick: (String) -> Unit = { navController.navigate("$ROUTE_LARGE_SQUARE?$ARG_SHARED=$it") } Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Column( modifier = Modifier .aspectRatio(1f) .padding(8.dp) .fillMaxSize() .background( color = MaterialTheme.colorScheme.primaryContainer, shape = RoundedCornerShape(16.dp) ) ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ColorButton( "èµ€", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( "緑", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( "青", modifier = Modifier.weight(1f), onClick = onClick ) } Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ColorButton( "シアン", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( "マれンタ", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( "黄", modifier = Modifier.weight(1f), onClick = onClick ) } Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ColorButton( "茶", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( "矀青", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( "カヌキヌ", modifier = Modifier.weight(1f), onClick = onClick ) } } } } composable( route = "$ROUTE_LARGE_SQUARE?$ARG_SHARED={sharedKey}", arguments = listOf(navArgument("sharedKey") { type = NavType.StringType }) ) { entry -> val colorName = entry.arguments?.getString("sharedKey") ?: "" LargeSquare(colorName) { navController.popBackStack() } } } } @Composable fun ColorButton( colorName: String, modifier: Modifier = Modifier, onClick: (String) -> Unit ) { TextButton( modifier = modifier .padding(16.dp) .aspectRatio(1f) .background(color = colorMap[colorName]!!, shape = RoundedCornerShape(16.dp)), onClick = { onClick(colorName) } ) { Text(colorName, color = Color.White) } } @Composable private fun LargeSquare( colorName: String, modifier: Modifier = Modifier, onBack: () -> Unit ) { Box( modifier = modifier .padding(16.dp) .fillMaxSize() .aspectRatio(1f) .background(color = colorMap[colorName]!!, shape = RoundedCornerShape(16.dp)) .clickable { onBack() } ) { Text(text = colorName, modifier = Modifier.padding(8.dp), color = Color.White) } } Note: This code omits countermeasures against rapid tapping of the back button and 9-color buttons for simplicity. Please test while avoiding rapid tapping in short intervals. On the initial screen, 9 color buttons are displayed, and tapping a button shows a large square in the tapped button's color. When the large square is displayed, pressing the back button (or performing a back gesture) returns to the 9-color button screen. Here, you can see fade-in and fade-out animations when returning to the large square screen by button tap and when returning to the 9-color button screen by back button. This is specified by the default values of the enterTransition , exitTransition , popEnterTransition , popExitTransition , sizeTransform arguments of NavHost(...) . You can override this setting with animation that associates shared elements before and after specific screen transitions by adding code and making modifications as shown below for specific screen transitions. For implementing shared element animation in screen transitions that don't involve back stack changes via NavHost(...) , refer to Shared element transitions in Compose . During screen transitions from left to right and right to left in the table below, the animation visually expresses that the square on the right screen that appeared from the button tapped on the left screen (bottom right) is exactly the target content. 9-color button screen Large square screen ![9色のボタンの画面](/assets/blog/authors/tsuyoshi_yamada/tech-blog_compose-animation_9-buttons.webp =256x) Fig. 3-1 ![Large square screen](/assets/blog/authors/tsuyoshi_yamada/tech-blog_compose-animation_large-square.webp =256x) Fig. 3-2 5.1. Wrap with SharedTransitionLayout { ... } and Share Screen Elements Here we introduce the implementation of shared element animation before and after screen transitions via NavHost(...) : @Composable fun GridTransform(modifier: Modifier = Modifier) { val navController = rememberNavController() SharedTransitionLayout { NavHost( modifier = modifier .safeContentPadding() .fillMaxSize(), navController = navController, startDestination = ROUTE_SMALL_SQUARE ) { composable(route = ROUTE_SMALL_SQUARE) { val onClick: (String) -> Unit = { navController.navigate("$ROUTE_LARGE_SQUARE?$ARG_SHARED=$it") } Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Column( modifier = Modifier .aspectRatio(1f) .padding(8.dp) .fillMaxSize() .background( color = MaterialTheme.colorScheme.primaryContainer, shape = RoundedCornerShape(16.dp) ) ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ColorButton( this@composable, "èµ€", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( this@composable, "緑", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( this@composable, "青", modifier = Modifier.weight(1f), onClick = onClick ) } Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ColorButton( this@composable, "シアン", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( this@composable, "マれンタ", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( this@composable, "黄", modifier = Modifier.weight(1f), onClick = onClick ) } Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { ColorButton( this@composable, "茶", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( this@composable, "矀青", modifier = Modifier.weight(1f), onClick = onClick ) ColorButton( this@composable, "カヌキヌ", modifier = Modifier.weight(1f), onClick = onClick ) } } } } composable( route = "$ROUTE_LARGE_SQUARE?$ARG_SHARED={sharedKey}", arguments = listOf(navArgument("sharedKey") { type = NavType.StringType }) ) { entry -> val colorName = entry.arguments?.getString("sharedKey") ?: "" LargeSquare(this, colorName) { navController.popBackStack() } } } } } @Composable fun SharedTransitionScope.ColorButton( animatedContentScope: AnimatedVisibilityScope, colorName: String, modifier: Modifier = Modifier, onClick: (String) -> Unit ) { TextButton( modifier = modifier .padding(16.dp) .aspectRatio(1f) .background(color = colorMap[colorName]!!, shape = RoundedCornerShape(16.dp)) .sharedBounds( sharedContentState = rememberSharedContentState(colorName), animatedVisibilityScope = animatedContentScope, boundsTransform = { _, _ -> tween(durationMillis = 500) }, enter = fadeIn(), exit = fadeOut(), resizeMode = SharedTransitionScope.ResizeMode.scaleToBounds() ), onClick = { onClick(colorName) } ) { Text(colorName, color = Color.White) } } @Composable private fun SharedTransitionScope.LargeSquare( animatedContentScope: AnimatedVisibilityScope, colorName: String, modifier: Modifier = Modifier, onBack: () -> Unit ) { Box( modifier = modifier .padding(16.dp) .fillMaxSize() .aspectRatio(1f) .background(color = colorMap[colorName]!!, shape = RoundedCornerShape(16.dp)) .sharedBounds( sharedContentState = rememberSharedContentState(colorName), animatedVisibilityScope = animatedContentScope, boundsTransform = { _, _ -> tween(durationMillis = 500) }, enter = fadeIn(), exit = fadeOut(), resizeMode = SharedTransitionScope.ResizeMode.scaleToBounds() ) .clickable { onBack() } ) { Text(text = colorName, modifier = Modifier.padding(8.dp), color = Color.White) } } Wrapping the outer layer with SharedTransitionLayout { ... } and using Modifier.sharedBounds(...) within SharedTransitionScope to associate shared elements is the same as for screen transitions that don't use NavHost(...) . For the animatedVisibilityScope argument of Modifier.sharedBounds(...) , we use AnimatedContentScope ( this@composable ) derived from NavGraphBuilder.composable(...) . This enables displaying animation between shared elements during screen transitions via NavHost(...) . In SharedTransitionScope.ColorButton(...) and SharedTransitionScope.LargeSquare(...) , verify that screen elements are shared before and after screen transitions by using the button's color name as the key argument of rememberSharedContentState(Any) . The new coding required to set up shared element animation is: Wrap with SharedTransitionLayout { ... } Set sharedBounds(...) (or sharedElement(...) ) to define shared elements and match the key between shared elements Pass the two scopes SharedTransitionScope and AnimatedVisibilityScope required for 2. to the composable These can be implemented without significantly changing the structure of the code before animation settings. If it's difficult to apply with minimal changes to existing code, try refactoring to a structure that's easier to modify. Shared element animation is beautiful when it fits well, but animation that perfectly matches the screen design image may be difficult. In that case, try adjusting the enter , exit , boundsTransform , resizeMode arguments of Modifier.sharedBounds(...) , etc. 5.2. Relationship with Predictive Back Shared element animation overrides the default screen transition animation of NavGraphBuilder.composable(...) . Additionally, when predictive back animation is enabled, that is, when android:enableOnBackInvokedCallback="true" is specified in AndroidManifest.xml for API levels 33-35, or when android:enableOnBackInvokedCallback="false" is not specified in AndroidManifest.xml for API level 36 or higher, it also overrides the back animation via NavHost(...) . Build the app with predictive back animation enabled, set the device to gesture navigation mode, and slowly perform the back gesture on the large square screen above, and you can easily confirm that the shared element animation slowly reverses. Also, on API level 36 or higher and Android OS 16 or higher, setting to button navigation mode and long-pressing the back button should show the shared element reverse animation. Thus, the back animation of NavHost(...) affects the predictive back animation settings. With this in mind, you need to decide whether to enable predictive back animation settings. As of API level 36, you can disable predictive back animation by specifying android:enableOnBackInvokedCallback="false" . 6. Conclusion This article introduced 4 examples of techniques for implementing practical animations in Jetpack Compose with minimal changes. Animation within apps is not essential functionality in most cases, so implementation tends to be omitted especially in development projects with tight schedules. But depending on usage, it has the potential to bring significant usability improvements and greatly enhance the app's impression. If there are abundant means to achieve this with minimal effort, you can easily try implementation. Many APIs in Compose Animation are designed to be declarative , meaning you can add animations with the feeling of declaring that you'll animate UI elements, making it easy to avoid the complexity of having to define behavior through detailed procedural descriptions. I hope these can be utilized to improve the quality of many apps. 7. References Android API reference Quick guide to Animations in Compose Animation modifiers and composables Add support for predictive back animations
アバタヌ
This article is the entry for day 7 in the KINTO Technologies Advent Calendar 2025 🎅🎄 Introduction Hello, I'm Tada from the Cloud Security Group at KINTO Technologies. I usually work at the Osaka Tech Lab . Many of the services we develop are built on Amazon Web Services. However, with the growing adoption of generative AI, we're increasingly using Microsoft Azure alongside OpenAI. In this article, I'll explain the need for workload protection in Azure Container Apps, the limitations of Microsoft Defender for Cloud, and a practical protection approach using Sysdig Serverless Agent. What Is Azure Container Apps? Azure Container Apps (ACA) is a serverless container execution environment provided by Microsoft. For more details about ACA, please refer to Microsoft's documentation . From a security perspective, ACA is a Kubernetes-based managed service where Microsoft is responsible for securing the infrastructure layer (nodes, network, OS). However, security at the application layer (container workloads) is the user's responsibility. This article focuses on how to achieve workload protection at the application layer within this shared responsibility model. Why Is Workload Protection Necessary? Even in serverless environments, the following security risks still exist: Vulnerabilities in container images Runtime threats Misconfigurations and excessive permissions In particular, for runtime threats, you need to detect and respond to threats such as: Detecting and preventing cryptocurrency mining Preventing container drift (unauthorized changes) Detecting and preventing unauthorized network communications Blocking reverse shell execution Detecting fileless execution To address these threats, continuous monitoring and threat detection at runtime are essential. For more information about ACA's security features, please refer to this documentation . Can Microsoft Defender for Cloud Provide Workload Protection? The short answer is: As of November 2025, Defender for Containers does not support ACA. Microsoft Defender for Containers supports Azure Kubernetes Service, Azure Container Registry, AWS EKS, Google GKE, and more. For detailed support coverage, please refer to this page . This means that to achieve workload protection at the application layer, adopting third-party products is recommended. Workload Protection with Sysdig Serverless Agent At KINTO Technologies, we use Sysdig Secure for cloud security operations, including detective guardrails (CSPM). We've published several blog posts about how we use Sysdig Secure, so feel free to search for them. The most recent one is AI-SPM Initiatives for Securing LLM Applications . We're also working on protecting ACA workloads using the Serverless Agent provided by Sysdig Secure. What Is Sysdig Serverless Agent? Sysdig Serverless Agent is a runtime security agent designed for serverless environments. It can monitor container workloads and detect threats. For installation and configuration of Serverless Agent on ACA, please refer to SCSK Corporation's blog , which provides a detailed explanation. It will give you a good understanding of the Serverless Agent. The Serverless Agent performs user-space level monitoring in serverless environments where it cannot access the host kernel. For detailed architecture information, please refer to Sysdig's documentation . An important point about this mechanism is that only the process tree started by the container's ENTRYPOINT is monitored. Therefore, shells or child processes spawned via docker exec are created outside this monitored tree and are not detected at the system call level. Blind Spots in Serverless Agent Detection As mentioned above, Serverless Agent monitors the process tree started by ENTRYPOINT . If an attacker gains access to the Azure console or CLI through some method (vulnerability exploitation, credential theft, etc.), they can access the container interior with the following command: az containerapp exec --name hogehoge-containerapp --resource-group hogehoge-resourcegroup --exec-command "/bin/bash" Once inside the container, unauthorized activities can be performed without being detected by the Serverless Agent. How Do We Detect Attacks via exec? Since attacks via exec cannot be detected by the Serverless Agent, we detect signs of attacks by monitoring the exec operations themselves recorded in Azure Activity Log (audit logs). Sysdig Secure has a feature called Cloud Detection and Response that can monitor audit logs in real time. Sysdig's Cloud Detection and Response performs threat detection using Falco . When the az containerapp exec command is executed or exec is performed via the Azure console, the following event is recorded in Azure Activity Log: Microsoft.App/containerApps/getAuthToken/action By detecting this event with a Falco rule, you can detect exec operations in real time. The Falco rule is as follows, and since it can detect exec via both the Azure console and CLI, you can respond by implementing operational procedures such as checking for unauthorized exec operations. rules: - rule: Detect Azure ContainerApp AuthToken Succeeded desc: Detect when Azure Activity Log shows Microsoft.App/containerApps/getAuthToken/action with status Succeeded condition: > evt.type = "open" and json.value["operationName.value"] = "Microsoft.App/containerApps/getAuthToken/action" and json.value["status.value"] = "Succeeded" output: > Azure ContainerApp AuthToken request succeeded (operation=%json.value["operationName.value"], status=%json.value["status.value"], caller=%json.value["caller"]) priority: WARNING source: json tags: [azure, containerapp, auth, security] Summary In this article, I explained a practical approach to workload protection in Azure Container Apps. Defender for Cloud does not support Azure Container Apps Workload protection with third-party products like Sysdig Serverless Agent is effective It's important to understand that Serverless Agent may have detection blind spots due to its architecture For blind spots, it's crucial to detect threats through defense in depth and increase coverage This article covered workload protection in Azure Container Apps. Our Cloud Security Group practices security in multi-cloud environments on a daily basis. We will continue to share our group's initiatives in the future. Thank you for reading to the end.
アバタヌ
この蚘事は KINTOテクノロゞヌズ Advent Calendar 2025 の7日目の蚘事です🎅🎄 はじめに こんにちは、KINTO テクノロゞヌズ Cloud Security グルヌプの倚田です。普段は 倧阪 (Osaka Tech Lab) で勀務しおいたす。 我々が開発する倚くのサヌビスは、Amazon Web Services 䞊で開発しおいたすが、昚今は生成 AI の掻甚も盛んで、OpenAI の利甚に䌎い、Microsoft Azure での開発も増えおきたした。 本蚘事では、Azure Container Apps におけるワヌクロヌド保護の必芁性から、Microsoft Defender for Cloud の限界、そしお Sysdig Serverless Agent を甚いた実践的な保護手法に぀いお、解説したす。 Azure Container Apps ずは Azure Container Apps以䞋、ACAは、Microsoft が提䟛するサヌバヌレス型のコンテナ実行環境です。ACA の詳现に぀いおは、Microsoft の ドキュメント を参照しおください。 セキュリティ䞊の特城ずしおは、Kubernetes ベヌスのマネヌゞドサヌビスであり、基盀レむダヌノヌド、ネットワヌク、OSのセキュリティは Microsoft の責任範囲ずなるこずです。䞀方で、アプリケヌション局コンテナワヌクロヌドのセキュリティはナヌザヌ偎の責任ずなりたす。 この「共有責任モデル」においおアプリケヌション局のワヌクロヌド保護をどう実珟するかが、本蚘事の内容ずなりたす。 なぜワヌクロヌド保護が必芁なのか サヌバレスな環境であっおも、以䞋のようなセキュリティリスクは䟝然ずしお存圚したす。 コンテナむメヌゞの脆匱性 ランタむムの脅嚁 蚭定ミスや過剰な暩限 特に、ランタむムの脅嚁に぀いおは、以䞋のような脅嚁を怜知し察凊する必芁がありたす。 暗号通貚マむニングの怜知・防止 コンテナドリフト䞍正な倉曎の防止 䞍正なネットワヌク通信の怜知・防止 リバヌスシェル実行のブロック ファむルレス実行の怜知 これらの脅嚁に察凊するため、 ランタむムでの継続的な監芖ず脅嚁怜知が䞍可欠ずなりたす。 ちなみに、ACA のセキュリティ機胜に぀いおは、 こちら を参照しおください。 Microsoft Defender for Cloud ではワヌクロヌド保護ができるのか 結論から蚀うず、 2025幎11月時点では、Defender for Containers は ACA をサポヌトしおいたせん。 Microsoft Defender for Containers は、Azure Kubernetes Service や Azure Container Registry、AWS EKS、Google GKE などに察応しおいたす。詳现なサポヌト範囲に぀いおは、 こちら を参照しおください。 ぀たり、 アプリケヌション局のワヌクロヌド保護を実珟するには、サヌドパヌティ補品の導入が掚奚される ずいうこずになりたす。 Sysdig Serverless Agent によるワヌクロヌド保護 KINTO テクノロゞヌズでは、発芋的ガヌドレヌルCSPMなど、クラりドセキュリティの運甚に Sysdig Secure を利甚しおいたす。 Sysdig Secure をどのように掻甚しおいるかは、過去にいく぀かブログを投皿しおいたすので、よろしければ怜玢しおみおください。䞀番新しいものだず、「 LLM アプリケヌションのセキュリティを保護する AI-SPM の取組み 」を投皿しおいたす。 ACA のワヌクロヌド保護に぀いおも、Sysdig Secure が提䟛する Serverless Agent を利甚しお保護する取組みを進めおいたす。 Sysdig Serverless Agent ずは Sysdig Serverless Agent は、サヌバレス環境向けに蚭蚈されたランタむムセキュリティ゚ヌゞェントです。コンテナワヌクロヌドの監芖、脅嚁怜知等を実斜するこずができたす。 ACA ぞの Serverless Agent のむンストヌルや蚭定に぀いおは、 SCSK 株匏䌚瀟さんのブログ で䞁寧に解説されおいたすので、そちらを参照しおください。Serverless Agent に぀いおむメヌゞが぀くず思いたす。 Serverless Agent は、ホストのカヌネルにアクセスできないサヌバレス環境においお、 ナヌザスペヌスレベル の監芖を行いたす。 詳现なアヌキテクチャに぀いおは、Sysdig の ドキュメント を参照しおください。 この仕組みの重芁なポむントは、コンテナの ENTRYPOINT で起動されたプロセスツリヌのみが監芖察象ずなる点です。そのため、 docker exec 経由で生成されたシェルや子プロセスはこの監芖察象ツリヌの倖郚で生成されるため、システムコヌルレベルの 挙動ずしお怜知されたせん。 Serverless Agent の怜知の盲点 前述の通り、Serverless Agent は ENTRYPOINT で起動されたプロセスツリヌを監芖察象ずしおいたす。攻撃者が䜕らかの方法脆匱性悪甚、認蚌情報搟取等で、Azure コン゜ヌルや CLI ぞのアクセス暩を取埗した堎合、以䞋のコマンドでコンテナ内郚にアクセスできたす。 az containerapp exec --name hogehoge-containerapp --resource-group hogehoge-resourcegroup --exec-command "/bin/bash" このように、コンテナ内郚にアクセスできれば、Serverless Agent に怜知されるこずなく、䞍正なアクティビティが可胜ずなりたす。 では、exec 経由の攻撃をどう怜知するか exec 経由の攻撃は、Serverless Agent では怜知できないため、Azure Activity Log監査ログに蚘録される exec 操䜜そのものを怜知するこずで、攻撃の予兆を怜知したす。 Sysdig Secure には、 Cloud Detection and Response ず呌ばれる機胜があり、監査ログをリアルタむムに監芖するこずができたす。 Sysdig の Cloud Detection and Response は、 Falco による脅嚁怜知を実斜しおいたす。 az containerapp exec コマンドの実行や、Azure コン゜ヌル経由での exec を実斜するず、Azure Activity Log には、以䞋のむベントが蚘録されたす。 Microsoft.App/containerApps/getAuthToken/action このむベントを Falco ルヌルで怜知するこずで、 exec 操䜜をリアルタむムに怜知できたす。Falco ルヌルは以䞋ずなり、Azure コン゜ヌル及び CLI 経由での exec を怜知できるので、無蚱可の exec 操䜜があれば確認するなどの運甚を実斜するこずで察応が可胜ずなりたす。 rules: - rule: Detect Azure ContainerApp AuthToken Succeeded desc: Detect when Azure Activity Log shows Microsoft.App/containerApps/getAuthToken/action with status Succeeded condition: > evt.type = "open" and json.value["operationName.value"] = "Microsoft.App/containerApps/getAuthToken/action" and json.value["status.value"] = "Succeeded" output: > Azure ContainerApp AuthToken request succeeded (operation=%json.value["operationName.value"], status=%json.value["status.value"], caller=%json.value["caller"]) priority: WARNING source: json tags: [azure, containerapp, auth, security] たずめ 本蚘事では、Azure Container Apps におけるワヌクロヌド保護の実践的なアプロヌチを解説したした。 Defender for Cloud は、Azure Container Apps に未察応 Sysdig Serverless Agent のようなサヌドパヌティ補品でのワヌクロヌド保護が有効 Serverless Agent には、仕組み䞊、怜知の盲点が存圚する堎合があるため、その理解が重芁 盲点に぀いおは、倚局防埡で脅嚁を怜知し、カバレッゞを高めるこずが倧切 今回は、Azure Container Apps におけるワヌクロヌド保護に぀いお蚘茉したした。 我々、Cloud Security グルヌプは、マルチクラりド環境におけるセキュリティに぀いお、日々実践しおいたす。今埌も圓グルヌプの取り組みをご玹介しおいきたいず思いたす。 最埌たでお読みいただきありがずうございたした。
アバタヌ
これは KINTOテクノロゞヌズ Advent Calendar 2025 の7日目の蚘事です🎄 1.はじめに KINTOテクノロゞヌズ、セキュリティ・プラむバシヌ郚のKa-Saiです。 私たちはトペタグルヌプの䞀員ずしお金融を含むモビリティサヌビスを提䟛するにあたり、お客様やパヌトナヌ䌁業からお預かりした個人情報や機密情報、そしおそれらを支えるシステムずいった「情報資産」を守るこずを最重芁テヌマの䞀぀ずしお䜍眮づけ、次のミッションずビゞョンを掲げお掻動しおいたす。 ミッション お客様に安心、安党なサヌビスを提䟛する。 私たちのミッションはブレヌキを螏むこずではなく、どうしたら安心・安党にアクセルを螏めるのかを考えるこずである。 ビゞョン セキュリティ・バむ・デザむン、プラむバシヌ・バむ・デザむンを浞透させ、安心、安党なサヌビスが圓たり前の䞖の䞭を䜜る。 ・・・・・ さお、セキュリティずいう蚀葉からは「スピヌドを萜ずすもの」「新しい挑戊を止めるもの」ずいうむメヌゞが先行しがちです。しかし私たちは セキュリティはビゞネスの“ブレヌキ”ではなく、“掚進力”になりうる ず考えおおり、この゚ントリヌでは、 なぜセキュリティがブロッカヌに芋えがちなのか その構造的な課題に察し、圓瀟がどのような哲孊ず蚭蚈で向き合っおいるか 具䜓的な組織・仕組み・取り組み そしお、私たちが芋据える未来 に぀いおご玹介したいず思いたす。 2. 課題意識埓来型セキュリティのゞレンマ 2-1. セキュリティはなぜ“遅くするもの”に芋えるのか 倚くの組織で、セキュリティは次のように捉えられがちです。 手続きが重く、レビュヌや承認でスピヌドが萜ちる 新しいツヌル、クラりドサヌビス、生成AIなどにストップがかかる リリヌス盎前に差し戻しが発生し、手戻りが倧きくなる コストセンタヌずしお扱われ、䟡倀が芋えにくい これらは、「埌付けのセキュリティ」「人に䟝存した個別刀定」「郜床盞談ベヌス」ずいった構造から生じる課題です。そしおもう䞀぀、私たちが匷く意識しおいるのが、 「ルヌルは存圚するだけで、暗黙のブロッカヌになりうる」 ずいう珟実です。これは、ルヌルが存圚するだけで、「なんずなく怖いからやめおおこう」「ここに觊れるのはやめおおこう」ずいう自己怜閲が働きたす。その結果、チャレンゞもむノベヌションも生たれにくくなりたす。 2-2. 飛躍成長に“スケヌルする”セキュリティぞ 圓瀟は、モビリティ×金融ずいう高いレギュレヌションず耇雑なビゞネス芁件が絡み合う領域で、事業の飛躍的成長を目指しおいたす。 新しい垂堎・囜・サヌビス圢態ぞの展開にあたっおは、セキュリティも同じスピヌドずスケヌル感で成長しなければなりたせん。 ここで重芁になるのが、 「セキュリティもリスクだが、ビゞネスの枛速もたた倧きなリスクである」 ずいう芖点です。 攻撃を受けるリスクだけでなく、 成長の掚進力を倱うリスク も、経営にずっおは無芖できたせん。 そこで私たちは、「いかに早く“セキュアなプロダクト”を䞖の䞭に出せるか」を重芁芖しおいたす。 ぀たり、最初の段階から䞀定氎準のセキュリティずコンプラむアンスを満たした状態で、玠早くマヌケットに到達できるかずいう芳点です。 新しいビゞネス・機胜を早く䞖に出す 同時に、金融・モビリティ領域に求められる厳しい安党基準を満たす この䞡方を満たすためには、「ビゞネスゎヌルに盎接貢献する目暙」ず「セキュリティの目暙」を切り離さず、同じテヌブルで蚭蚈するアプロヌチが必芁です。 2-3. 埓業員の負担をどう枛らすか セキュリティ・プラむバシヌ郚は党知党胜ではありたせん。すべおのコヌド、すべおの蚭定、すべおのデヌタフロヌを圓郚だけで確認するこずは珟実的ではなく、埓業員䞀人ひずりの協力が䞍可欠です。 しかし埓業員にはそれぞれ本来のミッションがありたす。プロダクト開発・運甚・ビゞネス偎のタスクも山積みです。 セキュリティ察応が「远加の仕事」ずしお乗っおくる 手動のチェックや蚌跡䜜業が増える 芁件理解に時間がかかり、本来の仕事が圧迫される 結果ずしお、過剰たたは非察称なかけた時間に察しおむンパクトが小さいセキュリティ䜜業が発生しがちです。だからこそ、圓瀟では CISOからのトップダりンな支揎 珟堎ぞの暩限移譲ず自埋的なボトムアップの行動 この䞡方のバランスを取り、埓業員の負荷を増やさずにセキュリティレベルを䞊げる蚭蚈を重芖しおいたす。 3. 圓瀟のセキュリティ哲孊Security as Momentum 䞊述の課題を螏たえ、圓郚がたどり着いた結論はシンプルです。 セキュリティは、正しくデザむンすれば、事業を加速させる掚進力になる。 この哲孊のもず、私たちは次のような考え方を採甚しおいたす。 3-1. “プラットフォヌム”ずしおのセキュリティ 人が䞀぀ひず぀チェックするのではなく、 仕組みやプラットフォヌムにセキュリティを埋め蟌む こずで、摩擊を最小化したす。 安党なクラりド蚭蚈・蚭定をガむドラむンずテンプレヌトに萜ずし蟌む CI/CD パむプラむンに自動チェックを組み蟌む セキュアなデフォルト倀を提䟛し、「䜕もしなければ安党」な状態を぀くる 3-2. “止める人”ではなく“実珟する人” セキュリティの圹割は「No」を突き぀けるこずではなく、「どうしたら安党にYesず蚀えるか」を䞀緒に考えるこずです。 䌁画段階からの盞談を歓迎し、実珟可胜な遞択肢を提瀺する “やっおはいけないこず”だけではなく、“こうすればできる”を瀺す 3-3. 開発者䜓隓ずしおのセキュリティ “セキュアな開発者の䜓隓” を敎えるこずは、結果的に開発組織党䜓の生産性向䞊に぀ながるため、開発者にずっおの「安心しおアクセルを螏める環境づくり」になっおいるかを垞に意識しおいたす。 「このテンプレヌトを䜿えばOK」ずいう明確なガヌドレヌル 面倒なセキュリティ評䟡の蚌跡取埗䜜業を自動化 盞談しやすいチャネルず、わかりやすいドキュメント 4. セキュリティ管理郚眲の組織䜓制ビゞネス成長ず速床を支えるための構造 圓瀟はトペタ自動車の子䌚瀟であるトペタファむナンシャルサヌビスTFSのグルヌプ䌚瀟に属しおいたす。TFSグルヌプではサむバヌセキュリティのリスクを最も重芁な経営課題の䞀぀ずしお䜍眮づけ、グルヌプ党䜓で察策を掚進しおおり、この方針のもず、圓瀟における情報セキュリティ管理は、TFSグルヌプのセキュリティプログラムを基盀ずしお運甚されおいたす。 4-1. GIS Standardグロヌバル基準に基づくセキュリティフレヌムワヌク そしおTFSグルヌプでは、NISTやISO27001などの囜際暙準をベヌスに、金融サヌビスに最適化された独自のセキュリティ芁件「GIS StandardGlobal Information Security Standard」を策定し、グルヌプ党䜓で運甚しおいたす。 このGIS Standardには ガバナンス オペレヌション テクニカルコントロヌル クラりドセキュリティ 生成AI などの新領域 ずいった倚岐にわたるドメむンをカバヌする300以䞊の管理項目が含たれおおり、圓瀟はこのGIS Standardを自瀟の暙準ずしお採甚し、 グロヌバル氎準の安党性ず信頌性を前提条件ずしお事業を進める こずを遞択しおいたす。 4-2. セキュリティ・プラむバシヌ郚の3぀の専門グルヌプ このGIS Standardずいうセキュリティフレヌムワヌクを珟堎で機胜させるため、セキュリティ・プラむバシヌ郚は以䞋の専門グルヌプで構成されおいたす。 1.クラりドセキュリティG クラりドにおける蚭蚈・蚭定暙準化ガむドラむン・ガヌドレヌル CNAPP / CSPM / CIEM などの導入・運甚 マルチクラりド環境のリスク監芖 2.サむバヌセキュリティG SOC業務ログ収集・分析・むンシデント察応 脆匱性管理・蚺断Red Team / Blue Team シャドヌIT察策 3.むンフォメヌションセキュリティG GIS StandardアセスメントのDX化 芏皋敎備・リスク評䟡 情報セキュリティ教育の高床化 プラむバシヌ圱響評䟡PIA AI利甚におけるデヌタ保護ガむドラむン策定 知的財産暩管理の仕組化 これらのグルヌプが連携しながら、プロダクトチヌム・コヌポレヌト郚門・グロヌバルの関連䌚瀟ず䌎走する䜓制を圢䜜っおいたす。 5. 圓瀟の具䜓的な取り組みセキュリティを掚進力ぞ倉える実装構造 5-1. プラットフォヌムセキュリティ仕組みに埋め蟌むセキュリティ (1) クラりドセキュリティの暙準化 AWS / Azure / GCPごずのセキュリティガむドラむン ガヌドレヌルの「カむれンガむド」 AIセキュリティガむドラむン を敎備し、「 これに沿っお蚭蚈・実装すればGIS Standardやベストプラクティスを自然に満たせる 」状態を目指しおいたす。 (2) CNAPP(Cloud-Native Application Protection Platform)の導入 クラりド蚭定の継続的評䟡 IAM暩限の過剰状態の怜知ず是正 クラりド䞊のワヌクロヌド保護 ログ収集・分析による脅嚁怜知 を自動化。「人が郜床チェックする」から、「システムが垞時監芖し、必芁に応じおアラヌトを䞊げる」䜓制ぞず進化し぀぀ありたす。 5-2. サむバヌディフェンス攻めず守りの䞡茪 (1) Red Team攻め 新芏プロゞェクトや蚺断未実斜プロダクトぞの積極的な脆匱性蚺断 SBOM・Secret管理・EOLなど、゜フトりェアサプラむチェヌンの芳点も含めた怜蚌 (2) Blue Team守り SIEM・EDR・Proxy・DNSなどを甚いたログ監芖・分析 むンシデント察応蚈画の敎備ず挔習 怜知ルヌルの継続的なチュヌニング これらの取り組みにより、「攻撃を受けおから慌おお察応する」のではなく、 事前の備えず継続的なモニタリングで、組織党䜓の“䜙癜”を生み出す こずを目指しおいたす。 5-3. セキュリティ・プラむバシヌアセスメントDXコンプラむアンスを“副産物”にする (1) セキュリティガバナンス GIS Standardぞの適合評䟡アセスメントの自動化 ゚ビデンス収集のダッシュボヌド化 リスクベヌスアプロヌチによるアセスメント察象の敎理 セキュリティ問い合わせの自動応答化 いわゆる”セキュリティガバナンス”を「DXデゞタルトランスフォヌメヌション」の察象ずしお捉え、 「監査察応のために蚌跡をかき集める」ような埌ろ向きの䜜業 を枛らし、「普段の運甚がそのたた蚌跡になる」状態ぞず近づけおいたす。 (2) プラむバシヌガバナンス / 知的財産の管理 プラむバシヌ圱響評䟡PIAの導入・運甚 AI利甚におけるデヌタ保護ガむドラむンの策定・浞透 ラむフサむクルに連動した網矅的な知財調査ずログ管理 これにより、 「安心しお䜿えるサヌビス」であるこずが、ビゞネスの遞ばれる理由になる状態 を目指しおいたす。 6. おわりにセキュリティを職人仕事から“暙準化”、そしお“掚進力”ぞ セキュリティ・プラむバシヌ郚のミッションは、お客様に安心・安党なサヌビスを提䟛するこずです。 その達成のため、セキュリティは単なる「リスクの最小化」ではなく、 ビゞネスの成長ず掚進力醞成にどう貢献できるか を垞にSpeedずQualityの䞡面から考えおいたす。 䞀方で、珟実には   急速なビゞネス成長ぞの察応 埓業員の負担軜枛 法什芁件ぞの効率的な準拠 ずいったテヌマのバランスをずるこずが、倧きなチャレンゞであるこずも事実です。私たちは、このチャレンゞに察しお 「職人仕事」から「暙準化」ぞ 䞀郚のセキュリティ゚キスパヌトだけに䟝存した属人的なセキュリティから、 誰もが同じ品質を出せる暙準化された仕組みぞ 埓業員䞭心蚭蚈Employee-Centered Design セキュリティのために人を酷䜿するのではなく、 埓業員が無理なく・誇りを持っお取り組めるように蚭蚈する 自動化䞭心蚭蚈Automation-First Design トむル自動化可胜な業務を枛らし、クリ゚むティブな仕事に集䞭できるようにする アゞャむルガバナンス 䞀床䜜ったルヌルも、“壊しながら”䜜り盎し続ける姿勢を持぀ ずいう芳点で取り組みを進めおおり、 私たちはQualityを高めるセキュリティを提䟛するだけでなく、Speedにも寄䞎し、事業を加速させる圢でセキュリティを掚進できる ず信じおこれからもビゞネス、開発、そしおお客様ずずもに歩んでたいりたす
アバタヌ
This is the Day 7 article of KINTO Technologies Advent Calendar 2025 🎄 1. Introduction I'm Ka-Sai from the Security and Privacy Division at KINTO Technologies. As a member of the Toyota Group, we provide mobility services including financial services. We consider protecting information assets such as personal information and confidential data entrusted to us by customers and partner companies, as well as the systems that support them, as one of our most important priorities. We operate under the following mission and vision: Mission Provide customers with safe and secure services. Our mission is not to apply the brakes, but to think about how we can safely and securely step on the accelerator. Vision Establish Security by Design and Privacy by Design to create a world where safe and secure services are the norm. ・・・・・ The word security often brings to mind images of slowing things down or blocking new attempts. However, we believe that security is not a brake on business but can become a driving force . In this entry, I would like to discuss: Why security tends to appear as a blocker How our company addresses these structural challenges through our philosophy and design Our specific organizational structure, systems, and initiatives The future we envision 2. Problem Awareness: The Dilemma of Traditional Security 2-1. Why Does Security Appear to Slow Things Down? In many organizations, security is often seen as: Procedures are cumbersome, and reviews and approvals slow things down New tools, cloud services, and generative AI get blocked Rollbacks occur just before release, causing significant rework Security is treated as a cost center, making its value hard to see These challenges arise from structures such as security being added after the fact, individual judgments dependent on specific people, and case-by-case consultation-based approaches. There's another reality we are keenly aware of: Rules can become implicit blockers simply by existing. When rules exist, people tend to self-censor, thinking I'd better not do that just to be safe or I should avoid touching this area. As a result, both new initiatives and innovation become less likely to emerge. 2-2. Toward Security That Scales for Breakthrough Growth Our company aims for breakthrough growth in a domain where mobility and finance intersect, a field characterized by strict regulations and complex business requirements. As we expand into new markets, countries, and service models, our security must grow at the same speed and scale. What becomes important here is the perspective that: Security is a risk, but slowing down business is also a significant risk. Not only the risk of being attacked, but also the risk of losing momentum for growth cannot be ignored from a management perspective. Therefore, we place great importance on how quickly we can deliver secure products to the world. In other words, from the initial stage, we focus on how quickly we can reach the market while meeting a certain level of security and compliance. Deliver new businesses and features to the world quickly At the same time, meet the strict safety standards required in the finance and mobility sectors To satisfy both requirements, we need an approach that designs business goals that directly contribute to business success and security goals at the same table, rather than separating them. 2-3. How to Reduce the Burden on Employees The Security and Privacy Division is not all‑knowing or all‑powerful. It is not realistic for our team alone to review every piece of code, every configuration, and every data flow, and the cooperation of each and every employee is essential. However, employees each have their own missions. They are also swamped with product development, operations, and business-side tasks. Security work piles on as additional work Manual checks and evidence collection increase Understanding the requirements takes time, which puts pressure on the time they have for their regular work. As a result, we often end up with excessive or disproportionate security work whose impact is small compared to the time invested. That's why at our company, we emphasize: Top-down support from the CISO Delegation of authority to the front lines and autonomous bottom-up actions We focus on designing systems that raise security levels without increasing the burden on employees by balancing both of these approaches. 3. Our Security Philosophy: Security as Momentum Based on the challenges described above, the conclusion our division reached is simple: When properly designed, security becomes a driving force that accelerates business. Under this philosophy, we have adopted the following approaches: 3-1. Security as a Platform Rather than having people check things one by one, we embed security into systems and platforms to minimize friction. Incorporate secure cloud design and configuration into guidelines and templates Build automated checks into CI/CD pipelines Provide secure baseline settings and ensure the system is safe without any extra steps. 3-2. Not Someone Who Stops, But Someone Who Enables The role of security is not to say "No" but to think together about how we can safely say "Yes". Welcome consultations from the planning stage and present feasible options Show not only what you shouldn't do but also how you can do it 3-3. Security as Developer Experience Building a secure developer experience ultimately leads to improved productivity across the entire development organization, so we constantly keep in mind whether we are creating an environment where developers can confidently step on the accelerator. Clear guardrails that say, "You’re good to go if you use this template." Automate tedious security assessment evidence collection work Easy-to-consult channels and clear documentation 4. Security Management Organization Structure: A Structure to Support Business Growth and Speed Our company belongs to the Toyota Financial Services (TFS) group, a subsidiary of Toyota Motor Corporation. The TFS Group positions cybersecurity risk as one of the most important management issues and promotes countermeasures across the entire group. Under this policy, information security management at our company operates based on the TFS Group's security program. 4-1. GIS Standard: A Security Framework Based on Global Standards The TFS Group has developed its own security requirements called the GIS Standard (Global Information Security Standard), optimized for financial services based on international standards such as NIST and ISO27001, and operates it across the entire group. The GIS Standard includes over 300 control items covering a wide range of domains such as: Governance Operations Technical controls Cloud security New areas such as generative AI Our company has adopted this GIS Standard as our own standard, choosing to conduct our business with global-standard safety and reliability as fundamental prerequisites . 4-2. Three Specialized Groups in the Security and Privacy Division To make this GIS Standard security framework in practice, the Security and Privacy Division consists of the following specialized groups: 1. Cloud Security Group Standardization of cloud design and configuration (guidelines and guardrails) Introduction and operation of CNAPP / CSPM / CIEM Risk monitoring of multi-cloud environments 2. Cyber Security Group SOC operations (log collection, analysis, incident response) Vulnerability management and assessment (Red Team / Blue Team) Shadow IT countermeasures 3. Information Security Group Digital transformation of GIS Standard assessments Policy development and risk assessment Enhancement of information security education Privacy Impact Assessment (PIA) Development of data protection guidelines for AI use Systematization of intellectual property rights management These groups work in coordination to form a structure that partners with product teams, corporate divisions, and related global companies. 5. Our Specific Initiatives: Implementation Structure to Transform Security into a Driving Force 5-1. Platform Security: Embedding Security into Systems (1) Standardization of Cloud Security We have developed: Security guidelines for each of AWS / Azure / GCP Kaizen Guides for guardrails AI security guidelines We aim for a state where designing and implementing according to these naturally meets GIS Standard and best practices . (2) Introduction of CNAPP (Cloud-Native Application Protection Platform) We are automating: Continuous evaluation of cloud configurations Detection and remediation of excessive IAM permissions Protection of workloads on the cloud Threat detection through log collection and analysis We are evolving from having people check things case by case to a system that constantly monitors and raises alerts as needed. 5-2. Cyber Defense: Both Offense and Defense (1) Red Team (Offense) Proactive vulnerability assessments for new projects and products that haven't been assessed Verification including software supply chain perspectives such as SBOM, secret management, and EOL (2) Blue Team (Defense) Log monitoring and analysis using SIEM, EDR, Proxy, DNS, etc. Development and exercises of incident response plans Continuous tuning of detection rules Through these initiatives, rather than scrambling to respond after being attacked, we aim to create organizational capacity through advance preparation and continuous monitoring . 5-3. Security and Privacy Assessment Digital Transformation: Making Compliance a Byproduct (1) Security Governance Automation of compliance assessments with GIS Standard Dashboarding of evidence collection Organization of assessment targets through a risk-based approach Automation of security inquiry responses We treat security governance as a key focus of our Digital Transformation efforts, reducing the reactive burden of scrambling to collect audit evidence after the fact and moving toward a state where daily operations naturally serve as audit trails. (2) Privacy Governance / Intellectual Property Management Introduction and operation of Privacy Impact Assessment (PIA) Development and dissemination of data protection guidelines for AI use Comprehensive intellectual property investigation and log management linked to the lifecycle Through this, we aim to make being a service that customers can use with peace of mind one of the reasons why they choose us . 6. Conclusion: From Craftsman's Work to Standardization, and Then to a Driving Force The mission of the Security and Privacy Division is to provide customers with safe and secure services. To achieve this, we constantly think about how security can contribute to business growth and momentum building from both Speed and Quality perspectives, rather than merely minimizing risk. On the other hand, balancing competing priorities such as: Responding to rapid business growth Reducing the burden on employees Ensuring efficient compliance with legal requirements is, in reality, a significant challenge. We are addressing this challenge through: From Craftsman's Work to Standardization From security dependent on specific security experts to standardized systems where anyone can produce the same quality Employee-Centered Design Rather than overworking people for security, design so that employees can engage without strain and with pride Automation-First Design Reduce toil (work that can be automated) so people can focus on creative work Agile Governance Maintain an attitude of continuously rebuilding while breaking down existing rules We believe that: We can not only provide security that enhances Quality, but also contribute to Speed and promote security in a way that accelerates business. We will continue to move forward with our business teams, our developers, and customers!
アバタヌ
この蚘事は KINTOテクノロゞヌズ Advent Calendar 2025 の 6 日目の蚘事です🎅🎄 はじめに こんにちは。KINTO テクノロゞヌズ Cloud Security グルヌプの枡邉です。 圓瀟では AWS Organizations ず Control Tower を利甚したマルチアカりント運甚を続けおいたすが、長幎の積み重ねにより、䞀郚の蚭蚈を芋盎す必芁が出おきたした。そこで、既存環境を前提にセキュリティガバナンス蚭蚈の再敎理を進めるこずにしたした。 本プロゞェクトでは、いきなり党䜓を䜜り盎すのではなく、圱響の倧きい領域から優先順䜍を付けお段階的に敎理しおいく方針を取っおいたす。そのうえで、安党性の刀断を優先し぀぀、新芏 OU や AWS のマネヌゞド機胜の掻甚など、将来の運甚改善に぀ながる倉曎も䞀郚取り入れおいたす。 プロゞェクトはただ蚭蚈フェヌズの段階であり、最終成果はこれからですが、本蚘事では珟時点での意思決定の流れず背景を共有したす。 ※ 本蚘事は AWS Organizations / AWS Control Tower / Security Hub CSPM / SCP / OU 蚭蚈に䞀定の理解がある読者を察象ずしおいたす。 ※ プロゞェクト前半である蚭蚈フェヌズ時点の内容をベヌスにしおおり、今埌の実装フェヌズで倉わる可胜性がありたす。 蚭蚈項目の棚卞し たずは既存環境のセキュリティガバナンス芁玠を敎理し、圱響床ず改善効果の芳点から、以䞋の 5 項目を優先的に棚卞ししたした。 最初の 3 項目は圱響範囲が広く、クラりドセキュリティ以倖のチヌムにも関係する領域です。埌半の 2 項目は、それらに付随しお怜蚎が必芁ずなる領域です。 OU 蚭蚈 └ OU 構造がそのたたガヌドレヌル蚭蚈に圱響するため 予防的ガヌドレヌル └ 望たしくない操䜜を事前にブロックする仕組みであり、既存アカりントに圱響するため 発芋的ガヌドレヌル └ 望たしくない蚭定を早期に怜出する仕組みであり、予防的ガヌドレヌルず盞互補完の関係にあるため 蚭定自動化ツヌル └ 新芏アカりントの初期蚭定を自動化する瀟内ツヌル アカりント発行フロヌ └ 新芏アカりント払い出しのプロセス 本蚘事では、それぞれの棚卞し過皋で芋えおきた課題ず刀断の背景を玹介したす。 AWS セキュリティガバナンス構成の敎理 この章では、圓瀟の AWS セキュリティガバナンスがどのようなレむダで構成されおいるかを敎理したす。 次の図は、 管理アカりントで適甚される蚭定 ( AWS Organizations / AWS Control Tower / AWS CloudFormation ) それずは別に、蚭定自動化ツヌルによっお管理アカりントおよびナヌザアカりントに远加される蚭定 が、ナヌザアカりント偎で 3 段階の予防ガヌドレヌル ( 1 段目 : Control Tower 暙準、2 段目 : 远加ガヌドレヌル、3 段目 : カスタムSCP ) 2 系統の怜出 ( Security Hub CSPM 系統、Control Tower 系統) 監芖・予防察象リ゜ヌスの事前適正化 (蚭定自動化ツヌルによる初期蚭定) ずしお䜜甚する党䜓構造を瀺したものです。 図のずおり、圓瀟環境では Control Tower の暙準ガヌドレヌルに加えお、蚭定自動化ツヌルで補完した远加ガヌドレヌルやカスタム SCP により、3 段階の予防コントロヌルを構成しおいたす。 たた、Security Hub CSPM 系統ず、Control Tower 系統ずいう 2 系統の怜出レむダ、そしお蚭定自動化ツヌルによるリ゜ヌスの事前適正化も組み合わせるこずで、ガバナンス党䜓を構築しおいたす。 これらは導入時期や目的が異なるため、OU や アカりント間で蚭定のばら぀きが生じおいる郚分もありたす。 この図における䞻芁な圹割分担は、次の 5 ぀に敎理できたす。 Control Tower 暙準ガヌドレヌル └ AWS が提䟛する予防・怜出のベヌスラむン 远加ガヌドレヌル (蚭定自動化ツヌルで有効化) └ 暙準だけではカバヌできない制玄を远加するための予防・怜出ガヌドレヌル カスタムSCP (蚭定自動化ツヌルから蚭定) └ 䟋倖的な芁件に察応するための圓瀟独自の制限 Security Hub CSPM 系統 ( CSPM 偎の怜出レむダ) └ AWS Config ず連携し、蚭定ミスやベストプラクティス違反を継続的に怜出するサヌビス Control Tower 系統 ( Control Tower 偎の怜出レむダ) └ AWS Config ず連携し、Control Tower のガヌドレヌルに玐づく怜出コントロヌルを実珟 こうした倚局構造は AWS ガバナンスでは珍しくない構成ですが、棚卞しを進めるうえでは、どのレむダがどのコントロヌルを提䟛し、各蚭定が Control Tower / Security Hub CSPM / 蚭定自動化ツヌルのどこに属しおいるのかを明確に敎理する必芁があり、䞀定の耇雑さを䌎いたした。 今回は、たず Control Tower の远加ガヌドレヌル、特に圱響の倧きい予防コントロヌルを最新の状態ぞ远埓させるこずを優先したした。レむダ間の重耇や圹割分担の最適化に぀いおは、今埌の改善テヌマずしお段階的に進めおいく方針ずしおいたす。 OU 蚭蚈の棚卞し OU 蚭蚈は Control Tower の動䜜ず密接に関係するため、蚭蚈倉曎時の圱響範囲を芋極めるのが特に難しい領域です。 特に圱響が倧きく、刀断を難しくしたのは以䞋の 3 点です。 䞀郚の動䜜がドキュメント化されおおらず、事前に挙動を読み切れない堎面がある点 └ 䟋えば、OU 名の倉曎埌に必芁ずなるランディングゟヌンのリセット時に、䜕が行われるのかに関する詳现仕様が公開されおいない点など OU ごずの差異に加え、過去の実装や運甚の積み重ねが圱響しおおり、OU 内のアカりントを別 OU に移動する際に、どの蚭定がどう再適甚されるかを個別確認する必芁がある点 本番アカりントや Control Tower の履歎を含む状態を怜蚌環境で正確に再珟できないため、怜蚌だけでは安党性を保蚌しきれない点 └ 䟋えば、本番アカりントにおいお、Control Tower の運甚に必芁なリ゜ヌスが、過去の運甚の䞭で䜕らかの理由により倉曎・削陀されおいるケヌスなど 䞊蚘を螏たえ、今埌䜜成されるアカりントの収容先ずしお、次の 3 パタヌンを比范したした。 ここでの 3 パタヌンは次のようなむメヌゞです。 既存 OU (珟状維持) : いた䜿っおいる OU 構造やガヌドレヌルを倉えずに、新芏アカりントを収容しおいく。 既存 OU (新ガヌドレヌル適甚) : いた䜿っおいる OU 矀に新しいガヌドレヌルを適甚し、新芏アカりントを収容しおいくこずで、既存アカりントも含めお䞀気に状態を揃える。 新芏 OU 矀 : 既存 OU 矀は珟状維持ずしお、新しいガヌドレヌルを適甚した OU 矀を新たに䜜成し、その OU に新芏アカりントを収容しおいく。 No 収容先 倉曎の圱響 長期の健党性 導入容易性 コメント 1 既存 OU (珟状維持) ◎ 既存ぞの圱響なし × 負債が残る ◎ 珟状維持で容易 䞀時的には安党だが長期負債が増える 2 既存 OU (新ガヌドレヌル適甚) × 既存党䜓ぞ圱響倧 ◎ 健党性が高い × 怜蚌負荷が倧きい 理想的だが圱響が重く段階移行が必芁 3 新芏 OU 矀 ◎ 既存ぞの圱響なし △ OU 分散リスク ◎ 導入・怜蚌が容易 OU 分散を埌続フェヌズで解消する必芁あり 今回は、既存環境ぞの圱響を避け぀぀も新たな仕組みの導入が容易な案 3 を採甚したした。 ただし、これは恒久的な解ではなく、既存 OU をいきなり組み替えずに新しいガヌドレヌル構成ず運甚モデルを怜蚌するための最初の䞀歩ずいう䜍眮付けです。 新芏 OU 矀で運甚実瞟ず怜蚌結果を蓄積したうえで、Sandbox OU など圱響の小さい既存アカりントから段階的に移蚭し、最終的には OU 構成ずガヌドレヌルを可胜な限り統䞀しおいくこずを䞭長期の方針ずしおいたす。 予防的ガヌドレヌルの棚卞し 予防的ガヌドレヌルは、望たしくない操䜜や構成を未然に防ぐための仕組みです。圓瀟環境では、AWS Control Tower の暙準ガヌドレヌルに加え、その䞍足分を補完するため、蚭定自動化ツヌルで远加のガヌドレヌル有効化・カスタム SCP を適甚しおいたす。 段 名称 䞻䜓 圹割 1 段目 暙準ガヌドレヌル AWS Control Tower AWS 暙準の予防コントロヌル 2 段目 远加ガヌドレヌル 蚭定自動化ツヌル ( CDK ) 暙準ガヌドレヌルでカバヌできない䞍足分の補完 3 段目 カスタムガヌドレヌル 蚭定自動化ツヌル ( CDK ) 圓瀟固有の芁件に合わせた独自の SCP 新芏アカりントを新蚭 OU に収容する方針ずしたため、新芏 OU に蚭定するガヌドレヌル远加に䌎う既存環境ぞの圱響はありたせん。そのため、初期導入埌に远加された Control Tower の新しい予防コントロヌルを有効化すべきかどうかを怜蚎したした。 しかしながら、AWS が提䟛する「重倧床」だけでは、以䞋に挙げる 3 ぀の䟋のように、なぜその評䟡になっおいるのか、実運甚でどのような圱響が出るのかたでは芋えたせんでした。 重倧床が高だが、導入刀断が぀かないものの䟋 (1) [CT.EC2.PV.4] Require that Amazon EBS direct APIs are not called (2) [CT.S3.PV.2] Require all requests to Amazon S3 resources use authentication based on an Authorization header 重倧床が䞭だが、導入しおも良いず思われるものの䟋 (3) [CT.EC2.PV.11] Disallow public sharing of Amazon Machine Images ( AMIs ) そこで、Amazon Q Developer Pro ※ を甚いお、各コントロヌルの SCP を、運甚圱響・掚奚床・導入プロセスの芳点で評䟡したした。䞊蚘 13 に぀いおは、次のような気付きがありたした。 EBS direct APIs を利甚する AWS Backup パヌトナヌ補品などのバックアップに圱響する可胜性があるため泚意が必芁 ( CT.EC2.PV.4 ) Presigned URL が䜿えなくなる ( CT.S3.PV.2 ) 導入は劥圓であるが、SCP ではなく DECLARATIVE_POLICY なので挙動が異なる点に泚意が必芁 ( CT.EC2.PV.11 ) こうした敎理を通じお、有効化が掚奚され、圱響が小さいものは、新芏 OU で積極的に有効化する方針ずしたした。 ※ Amazon Q Developer Pro を利甚した理由は、他の AI ず比范するず応答速床は遅いものの、AWS の公匏ドキュメントを郜床参照したうえで回答しおいるず掚察でき、仕様倉曎の倚い領域でも䞀定の安心感があったためです。 発芋的ガヌドレヌルの棚卞し 圓瀟環境では、セキュリティ基準の䞀元管理ず自動曎新性の芳点から Security Hub CSPM をセキュリティ監査の䞻軞ずしおいたす。 Control Tower の怜出コントロヌルは、Control Tower が提䟛するガヌドレヌルや共通基盀の構成に関する芳点を含むチェック矀であり、圓瀟では Security Hub CSPM を補完する仕組みずしお䜍眮付けおいたす。 今回の芋盎しでは、運甚開始埌に远加された Control Tower の怜出コントロヌルに぀いお、「重倧床重倧」たたは「ガむダンス匷く掚奚」に該圓するものを察象に、有効化の芁吊を確認したした。 その結果、䟋えば以䞋のようなコントロヌルは、Security Hub CSPM の基準にお既に監査可胜であるこずを確認できたため、Control Tower 偎では重耇しお有効化しない方針ずしたした。 [CONFIG.KMS.DT.1] Checks if AWS Key Management Service ( AWS KMS ) keys are not scheduled for deletion in AWS KMS [CONFIG.KMS.DT.2] Checks if the AWS KMS key policy allows public access 䞀方、以䞋のように、サヌビス固有の蚭定を扱う䞀郚のコントロヌルに぀いおは、圓瀟での実際の利甚状況や将来の利甚蚈画に応じお、必芁性を個別に怜蚎する方針ずしたした。 [CONFIG.EMR.DT.1] Checks if an account with Amazon EMR has block public access settings enabled 蚭定自動化ツヌルの棚卞し 圓瀟では、新芏アカりントの初期蚭定を自動化するため、蚭定自動化ツヌル ( CDK ベヌス) を開発・運甚しおいたす。長幎にわたり、このツヌルが新芏アカりントの暙準化や初期蚭定の抜け挏れ防止に倧きく寄䞎しおきたした。 今回の棚卞しでは、珟圚のアカりント芏暡やチヌム構成、AWS のマネヌゞド機胜の拡充状況を螏たえ、この仕組みをどこたでシンプルにできるかを敎理しおいたす。 䞀般的には自動化範囲を広げる事䟋も倚いですが、圓瀟では維持しやすさを優先し、必芁な郚分に絞る方向性ずしたした。 蚭定自動化ツヌルで実斜しおいる内容は以䞋の通りです。 远加の予防的ガヌドレヌル適甚 カスタム SCP の远加 Security Hub CSPM の重耇・䞍芁なアラヌム抑制 Security Hub CSPM 準拠を目的ずしたサヌビス蚭定 (䟋デフォルト暗号化やパブリックアクセスブロックの有効化など) その他のセキュリティ蚭定の自動適甚 珟時点の方針ずしおは、以䞋の 3 段構えで進める想定です。 AWS のマネヌゞド機胜に任せられる郚分は、できる限り移行する マネヌゞド機胜では眮き換えられない郚分は、宣蚀的 IaC ( CloudFormation、CloudFormation StackSets、Terraform など) での管理を優先する IaC にも寄せられない䟋倖的な凊理は、最小限のコヌドずしお残し、具䜓的な実装方匏は埌続フェヌズで刀断する 単にコヌドを枛らすこずが目的ではなく、組織ずしお長期的に持ち続けるべき責務だけをコヌドに残すこずを狙いずしおいたす。 特に項目 4 に぀いおは、 Security Hub CSPM の䞭倮蚭定 に移行するこずで、䞀郚の蚭定を AWS のマネヌゞド機胜に寄せられる可胜性がありたす。既存 OU ではコントロヌルの状態に個別差分が残っおおり、適甚には棚卞しが必芁ですが、新芏 OU から段階的に掻甚する予定です。 たた、5 の䞭で実斜しおいる S3 ブロックパブリックアクセス有効化の蚭定に぀いおも、先日公開された S3 ポリシヌ ぞの移行により、同様に AWS のマネヌゞド機胜に寄せられる可胜性がありたす。こちらも今埌、導入可吊に぀いおの調査を進めおいく予定です。 なお、蚭定自動化ツヌルには CDK による条件分岐など独自の匷みがあり、これが芋盎しにおける刀断ポむントずなる可胜性がありたす。匕き続き、䞊蚘方針が適切かどうかを慎重に怜蚌しながら進めおいく予定です。 アカりント発行フロヌの棚卞し 圓瀟では、これたで新芏アカりント発行時にルヌトナヌザの MFA を有効化する運甚を行っおいたしたが、物理䜜業が䌎うため、発行の郜床䞀定の皌働が発生しおいたした。 2024幎末に メンバヌアカりントのルヌトアクセス䞀元管理 により、この運甚自䜓を芋盎せる可胜性がありたす。 今回の再蚭蚈ず䜵せお、アカりント発行フロヌもできる限りシンプルか぀安党な圢に敎理するこずを怜蚎しおいたす。 たずめ 今回の棚卞しでは、長幎の運甚で積み䞊がった蚭定や仕組みを前提に、将来の拡匵性ず保守性の䞡面から、どこを倉え、どこを維持すべきかを敎理したした。 既存 Organizations を維持したたた理想的な構成ぞ䜜り替えるこずは簡単ではありたせん。OU 蚭蚈、ガヌドレヌル、初期蚭定の自動化ツヌルずいった耇数レむダが盞互に䟝存しおいるため、どれか䞀぀を曎新するず他のレむダにも圱響が波及するからです。 そのため今回は、すべおを党面刷新するのではなく、本番を止めずに少しず぀負債を枛らしながら改善を進めるずいう方針で敎理を進めたした。特に Control Tower の挙動や䞀郚のガヌドレヌルの圱響範囲は、公開情報だけでは読み切れない郚分もあるため、リスクを分割しながら段階的に怜蚌する進め方が䞍可欠だず感じおいたす。 今埌は、AWS が提䟛するマネヌゞド機胜を積極的に掻甚し぀぀、既存環境ずの敎合を取りながら倉曎箇所を局所化し、段階的に改善を続けおいく方針です。 本蚘事が、既存環境を前提にガバナンスを再蚭蚈する方々にずっお、少しでも刀断材料や芖点のヒントになれば幞いです。
アバタヌ
This article is the entry for Day 6 in the KINTO Technologies Advent Calendar 2025 . Introduction Hello. I'm Watanabe from the Cloud Security Group, Security and Privacy Division at KINTO Technologies. Our company has been operating a multi-account environment using AWS Organizations and Control Tower. However, after years of changes, we found it necessary to revisit some of our design decisions. We therefore decided to reorganize our security governance design based on the existing environment. In this project, rather than rebuilding everything from scratch, we adopted an approach of prioritizing the affected areas due to the rebuild and addressing them gradually. While prioritizing safety, we also incorporated some changes that will lead to future operational improvements, such as creating new OUs and leveraging AWS managed features. The project is still in the design phase, and the final outcomes are yet to come. In this article, I'll share the decision-making process and background up to this point. Note: This article is intended for readers with a certain level of understanding of AWS Organizations, AWS Control Tower, Security Hub CSPM, SCP, and OU design. Note: The content is based on the design phase, which is the first half of the project and may change during the implementation phase. Design Element Review and Analysis First, we organized the security governance elements of our existing environment and prioritized the following five areas for review and analysis based on their impact and improvement potential. The first three areas have a broad scope of impact and involve other areas that affect teams beyond cloud security. The latter two areas require consideration in conjunction with the former ones. OU design -> OU structure directly affects guardrail design Preventive guardrails -> This is a mechanism to proactively block undesirable operations and affects existing accounts Detective guardrails -> This is a mechanism to detect undesirable configurations early and complements preventive guardrails Configuration automation tool -> An internal tool that automates initial setup for new accounts Account issuance Flow -> The process for provisioning new accounts In this article, I'll introduce the issues and background of decision-making processes that emerged in reviewing and analyzing each of these areas. Organizing the AWS Security Governance Structure In this chapter, I'll organize how our company's AWS security governance is structured across different layers. The following diagram shows: Settings applied in the management account (AWS Organizations / AWS Control Tower / AWS CloudFormation) Settings additionally applied to the management account and user accounts by the configuration automation tool And how these settings work for the user account side as: Three-tier preventive guardrails (Tier 1: Control Tower standard, Tier 2: additional guardrails, Tier 3: custom SCPs) Two detection methods (using Security Hub CSPM or Control Tower) Pre-optimization of monitored/protected resources (initial settings by the configuration automation tool) As shown in the diagram, our environment consists of three tiers of preventive controls: Control Tower's standard guardrails, additional guardrails supplemented by the configuration automation tool, and custom SCPs. Additionally, we have two detection layers using Security Hub CSPM and Control Tower as well as pre-optimization of resources by the configuration automation tool. The combination of these tools establishes our overall governance structure. Since they were introduced at different times and for different purposes, there are some variations in settings between OUs and accounts. The main roles in this diagram can be organized into the following five categories: Control Tower standard guardrails -> Baseline for preventive and detective controls provided by AWS Additional guardrails (enabled by the configuration automation tool) -> Preventive and detective guardrails to supplement constraints not covered by the standard Custom SCPs (configured via the configuration automation tool) -> Company-specific restrictions for exceptional requirements Security Hub CSPM Stream (detection layer on the CSPM side) -> A service that integrates with AWS Config to continuously detect misconfigurations and best practice violations Detection using Control Tower (detection layer on the Control Tower side) -> Implements detective controls linked to Control Tower guardrails in coordination with AWS Config While this multi-layer structure is not uncommon in AWS governance, the review and analysis process required clearly organizing which layer provides which controls and whether each setting belongs to Control Tower, Security Hub CSPM, or the configuration automation tool. This involved a certain level of complexity. For this effort, we focused on bringing Control Tower's additional guardrails—especially the high-impact preventive controls—up to date. We plant to optimize overlaps and role allocation between layers as an improvement topic into the future to be addressed gradually. Review and Analysis of OU Design OU design is closely related to Control Tower's behavior, making it particularly difficult to assess the scope of impact in changing designs. The following three points have specifically large impacts and made the assessment difficult: Some operations are not documented, making us hard to fully predict behavior in advance -> For example, detailed specifications about what happens to a landing zone are not shared at the timing of the zone reset required after the change in an OU name In addition to differences between OUs, past implementations and iterated operations have a large impact, requiring individual verification of which settings are reapplied and how the reapplication is performed when moving accounts within an OU to a different OU Since accounts in our production environment and Control Tower record cannot be accurately reproduced in a testing environment, safety cannot be fully ensured through testing alone -> For example, in terms of accounts in the production environment, there are cases where resources necessary for Control Tower operations have been modified or deleted for some reason during past operations Based on the above, we compared the following three patterns for where to place newly created accounts. The three patterns are as follows: Existing OU (with its current state maintained): Continue placing new accounts in the current OU structure and guardrails without changes. Existing OU (applied to new guardrails): Apply new guardrails to the existing OU group and place new accounts there, aligning the state of the accounts with that of the existing ones all at once. New OU group: Maintain the existing OU group as it is while creating a new OU group with new guardrails applied, and place new accounts in that OU. No Placement Impact of Change Long-term soundness Ease of Introduction Comment 1 Existing OU (with its current state maintained) Excellent: No impact on existing environment Poor: Technical debt remains Excellent: Easy to implement with the current state maintained Temporarily safe but increases long-term debt 2 Existing OU (applied to new guardrails) Poor: Major impact on all existing environment Excellent: High soundness Poor: High verification burden Ideal but heavy impact, which requires gradual migration 3 New OU group Excellent: No impact on existing environment Fair: Risk of OU separation Excellent: Easy to implement and verify Need to resolve OU separation in subsequent phases This time, we adopted Option 3, which avoids impact on the existing environment while making it easy to introduce new frameworks. That said, this is not a permanent solution but the first step to verify new guardrail configurations and operational models without immediately reorganizing existing Ous all at once. After gaining operational experiences and verification results with the new OU group, we plan to gradually migrate existing accounts with smaller impact, such as Sandbox OUs, and ultimately unify the OU structure and guardrails as much as possible as our medium- to long-term policy. Review and Analysis of Preventive Guardrails Preventive guardrails are frameworks to proactively prevent undesirable operations and configurations. In our environment, along with AWS Control Tower's standard guardrails, we enable additional guardrail and use custom SCPs through the configuration automation tool to supplement any gaps. Tier Name Major tool Role Tier 1 Standard guardrails AWS Control Tower AWS standard preventive controls Tier 2 Additional guardrails Configuration automation tool (CDK) Supplements gaps not covered by standard guardrails Tier 3 Custom guardrails Configuration automation tool (CDK) SCPs tailored to our company’s specific requirements Since we are going to place new accounts in newly created OUs, adding guardrails to new OUs does not affect the existing environment. Therefore, we examined if we should enable new preventive controls added to Control Tower after initial deployment. However, only in terms of the severity level provided by AWS, we could not find why a particular evaluation was given or what operational impact might occur, as illustrated by the following three examples. Examples of where severity is high with the adoption undetermined: (1) [CT.EC2.PV.4] Require that Amazon EBS direct APIs are not called (2) [CT.S3.PV.2] Require all requests to Amazon S3 resources use authentication based on an Authorization header Examples where severity is medium but seemingly worth adopting: (3) [CT.EC2.PV.11] Disallow public sharing of Amazon Machine Images (AMIs) Therefore, we used Amazon Q Developer Pro* for evaluating each control's SCP from the perspectives of operational impact, recommendation level, and adoption process. For the above items from (1) to (3), we gained the following insights: Caution is needed due to potential impacts on backups using AWS Backup partner products that are applied to EBS direct APIs(CT.EC2.PV.4) Presigned URLs will no longer work (CT.S3.PV.2) Adoption is appropriate, but the behavior of a DECLARATIVE_POLICY differs from that of an SCP (CT.EC2.PV.11) Through this organizing process, we decided to actively enable controls in new OUs whose activation are recommended with its lower impacts. *We adopted Amazon Q Developer Pro because it appears to reference official AWS documentation for each response. This gives us a sense of security at a certain level even in areas with frequent specification changes, while the service response speed is slower compared to other AI tools. Review and Analysis of Detective Guardrails In our environment, we use Security Hub CSPM as the main pillar of security auditing from the perspectives of centralized management of security standards and automatic updates. Control Tower's detective controls are a set of checks that include perspectives on guardrails and common infrastructure configurations provided by Control Tower. We set this as a framework that complements Security Hub CSPM. In this review process, we examined Control Tower's detective controls added after operations began to determine whether we should enable the controls by targeting those with its severity critical or its guidance strongly recommended. As a result, we confirmed that controls, such as the ones listed below, can be audited under Security Hub CSPM standards, deciding not to enable them redundantly on the Control Tower side: [CONFIG.KMS.DT.1] Checks if AWS Key Management Service (AWS KMS) keys are not scheduled for deletion in AWS KMS [CONFIG.KMS.DT.2] Checks if the AWS KMS key policy allows public access On the other hand, for some controls that handle service-specific settings like the following, we decided to individually examine their necessity based on our actual usage and future plans: [CONFIG.EMR.DT.1] Checks if an account with Amazon EMR has block public access settings enabled Review and Analysis of the Configuration Automation Tool Our company has developed and operates a configuration automation tool (based on CDK) to automate initial setup for new accounts. For many years, this tool has greatly contributed to standardizing new accounts and preventing omissions in initial settings. In this review and analysis, we assessed how much we can simplify this framework, considering the current account scale, team structure, and the expansion of AWS managed features. In general, many cases expand the scope of automation, but we focused on maintainability to decide to narrow the scope down to necessary parts. The configuration automation tool currently handles the following: Applying additional preventive guardrails Adding custom SCPs Suppressing duplicate/unnecessary Security Hub CSPM alarms Setting services focused on Security Hub CSPM compliance (e.g., default encryption and activation of public access blocks) Automatically applying other security settings Currently, we are going to proceed with a three-tier approach: Shift to the automation of as many processes that can be handled by AWS managed features as possible For parts irreplaceable by managed features, prioritize management with declarative IaC (CloudFormation, CloudFormation StackSets, Terraform, etc.) Leave exceptional processing that cannot be shifted to IaC as minimal code, with specific implementation methods to be determined in subsequent phases This doesn’t simply aim to reduce code but to record limited responsibilities that the organization should maintain long-term in code. For the above item 4 in particular, through a migration to Security Hub CSPM central configuration , some settings may be able to leverage AWS managed features. In terms of existing OUs, individual differences in control states remain, so the review and analysis process is required for their application, but we plan to gradually utilize OUs from new ones. Additionally, for the S3 Block Public Access settings currently implemented as part of item 5, migration to the recently released S3 policies may similarly allow us to leverage AWS managed features. We plan to examine if we can adopt it, going forward. Note that the configuration automation tool has unique strengths, such as CDK-based conditional branching, which may become decision-making points in this review. We plan to continue carefully verifying whether the above policy is appropriate. Review and Analysis of the Account Provisioning Flow Our company has previously operated with MFA enabled for root users when issuing new accounts. However, this involves physical work, requiring a certain amount of effort each time an account was issued. With centralized root access management for member accounts released at the end of 2024, there is potential to update this operation itself. In conjunction with the current redesign, we are considering organizing the account issuance flow into a form that is as simple and secure as possible. Conclusion In this review and analysis process, we organized what to change and what to maintain from both extensibility and maintainability perspectives, based on settings and frameworks repeatedly updated over years of operation. It is not easy to rebuild our existing Organizations environment into an ideal configuration while maintaining it. This is because multiple layers—OU design, guardrails, and initial setup automation tools—are interdependent, and updating any one of them can affect other layers. Therefore, rather than completely overhauling everything, we proceeded with this organization under the policy of gradually reducing technical debt while continuing improvements without stopping production. In particular, since we were not able to fully understand Control Tower's behavior and the scope of impact of some guardrails, according to public information alone, I feel that it is essential to take a step-by-step verification approach diversifying risks. Going forward, we plan to actively leverage AWS managed features while focusing on areas to update in line with the existing environment and continuing gradual improvements. For those redesigning governance based on existing environments, I hope this article provides some materials helping their decision-making processes and perspectives.
アバタヌ