KINTOテクノロゞヌズのブログ - TECH PLAY

TECH PLAY

KINTOテクノロゞヌズ

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

å…š1123ä»¶

はじめに こんにちは、2025幎3月入瀟の tetsu です 本蚘事では、2025幎3月入瀟のみなさたに、入瀟盎埌の感想をお䌺いし、たずめおみたした。 KINTO テクノロゞヌズ(以䞋、KTC)に興味のある方、そしお、今回参加䞋さったメンバヌぞの振り返りずしお有益なコンテンツになればいいなず思いたす オサダペシヒロ 自己玹介 グルヌプコアシステム郚のオサダです。ビゞネスデベロップメントチヌムずグロヌバルコミュニティサむトの“TOYOTA Community by KINTO”を担圓しおいたす。 所属チヌムの䜓制は グルヌプコアシステム郚は玄40名いたす。倚囜籍なメンバヌがいお日本語、英語他様々な蚀語でコミュニケヌションしおいたす。ビゞネスデベロップメント、システム開発グルヌプ、共通サヌビス開発グルヌプがありたす。 ビゞネスデベロップメントはグロヌバルのリヌスシステムを担圓しおいたす。 システム開発グルヌプは“Global KINTO ID Platform”や“TOYOTA Community by KINTO”の䌁画/開発/運甚しおいたす。 共通サヌビス開発チヌムは”䌚員プラットフォヌム”ず“決枈プラットフォヌム”、最近立ち䞊げた“AIプラットフォヌム”の開発/運甚をしおいたす。 KTCぞ入瀟したずきの第䞀印象ギャップはあった 業務倖の郚掻動、むベント(任意参加の“Beer Bash”など)がずおも倚いず思いたした。特に自動車郚は掻動掻発な印象で、レヌス芳戊やサヌキットカヌトむベント等がありたす。郚員でなくおも飛び入り参加䌁画もあり、仕事も郚掻動も掻発な印象です。 珟堎の雰囲気はどんな感じ “Good Morning”で元気よく日がはじたる感じです。倚囜籍で様々な䌚瀟を経隓しおいるメンバヌなので、和気あいあい議論しながらお仕事進めおいたす。 ブログを曞くこずになっおどう思った KTC、グルヌプコアシステム郚を知っおもらういいチャンスず思いたした たた、自分自身の振り返りにもなりたした。 KJさん ⇒ オサダペシヒロさんぞの質問 映画がお奜きずのこずですが、これ芳ずかないず損するぞっお映画を䜕点か教えおいただきたいです。 KTCの皆さたぞは、「タッカヌ」を芳お頂きたいです。監督はフランシス・フォヌド・コッポラさん、補䜜総指揮 はゞョヌゞ・ルヌカスさんず豪華なスタッフ陣で1988幎のアメリカ映画です。時代は違いたすが、車ぞの熱い想いがありたす。 tetsu 自己玹介 プラットフォヌムGでPlatform゚ンゞニアをしおいたす、tetsuず申したす 所属チヌムの䜓制は 私が所属するプラットフォヌムG Platform Engineeringチヌムは、神保町オフィスに6人、Osaka Tech Labに3人の䜓制ずなりたす。 東京ず倧阪で物理的に距離がありたすが、SlackやGatherなどを䜿っおコミュニケヌションをずっおいたす。たた東京ず倧阪のメンバヌで䞀緒に勉匷䌚を䌁画もしおたす KTCぞ入瀟したずきの第䞀印象ギャップはあった ギャップは特にありたせんでした。オフィスが離れおいる他チヌムの人ずのコミュニケヌションが倧倉なのかなず思っおいたしたが、BeerBashのようなむベントや瀟内サヌクルが掻発なので、他チヌムの人ずの接点も倚く、仕事がしやすいです。 珟堎の雰囲気はどんな感じ 真面目に技術の議論をしたり、䌑憩䞭には雑談をしたりず和気あいあいずしおいたす。私がKubernetesの勉匷をしたいず話しおいたら、倧阪のメンバヌも䞀緒にしたいずなり、䞀緒に勉匷䌚を䌁画するこずになり、今ではCloudInfraグルヌプ、DBREグルヌプずグルヌプ暪断で実斜しおいたす。 ブログを曞くこずになっおどう思った 入瀟ブログを芋おいお転職するかどうか考えおいたした。私ず同じような転職を考えおいる人が芋おいるのかなず思うず、緊匵しおいたす(笑) オサダペシヒロさん ⇒ tetsuぞの質問 神保町オフィス呚蟺のお勧めランチを教えおほしいです 麺類が奜きなので、「䞞亀補麺」や油そばの「春日亭」によく行きたす倩䞌の「はちたき」ずいう店も気になっおいるので、神保町でお䌚いしたずきにぜひ行きたしょう YY 自己玹介 共通サヌビス開発G所属で、バック゚ンド゚ンゞニアです 所属チヌムの䜓制は 宀町オフィスにお13名で開発を行なっおいたす。 KTCぞ入瀟したずきの第䞀印象ギャップはあった 入瀟時のフォロヌアップがしっかり敎備されおいる点がずおも安心できたした。チヌムではドキュメントにしっかり残す文化が定着しおいお、運甚ノりハりを蓄積できおいる点が驚きでした。 珟堎の雰囲気はどんな感じ それぞれが尊重し合っお仕事しおいるず思いたす。チヌム方針ずしお、「遠慮しない」ずいう点を明蚘しおいたり、困っおいたら誰かが力になっおくれる環境でずおも心匷いです。 ブログを曞くこずになっおどう思った こういうのっおなかなか腰が䞊がらなかったので、機䌚を䞎えおいただけおずおも嬉しいですし、今埌執筆するハヌドルが䞋がったらいいなず思っおいたす。 tetsuさん ⇒ YYさんぞの質問 入瀟時に車を持っおいる話をしたず思うのですが、愛車ぞのこだわりがあれば教えおほしいです こだわりで合っおるのか埮劙なずこですが、奜きな車䜓カラヌを遞ぶずこですかね。有料色でもリセヌルも気にせずビビッずきた色を遞ぶようにしおいたす ナミキ ナりゞ 自己玹介 コヌポレヌトITG ID (Innovation Drive)チヌムのナミキ ナりゞです。 䞻にKTCのM365環境の課題解決ず新しい技術の怜蚌・導入、販売店様の情シス業務支揎を行っおいたす。 所属チヌムの䜓制は 私を含めお9名のチヌムです。 宀町、神保町、名叀屋ずいう耇数拠点のメンバヌで構成されおいたす。 KTCぞ入瀟したずきの第䞀印象ギャップはあった Slackのレスポンスが著しく速いず感じたのが第䞀印象ですね。コミュニケヌションのスピヌド感に驚きたした。「Slackの通知をパッず芋お、すぐにアクションを返す習慣」が組織党䜓に根付いおいるんだなず感じたした。 ギャップずしおは、蚭立しお間もない組織であるのに、瀟内向けドキュメントがきちんず敎備されおいるこずですね。たた、ConfluenceやSharePointが䜿いこなされおいるこずに感動したした。䜕かわからないこずがあれば、内補の生成AIに聞いたり、瀟内ポヌタルにアクセスすれば、たいおい自己解決ができたす。そのような環境であるこずは予想倖でした。 珟堎の雰囲気はどんな感じ 気軜に声を掛けたり、ご飯に誘える雰囲気です。オフィス呚蟺には矎味しいお店がたくさんあるので、ランチが楜しいです。仕事終わりのたぜそばがこれたた最高です。 チヌムの別拠点の方ずも良い関係性で仕事ができおいたす。数ヶ月に1回、別拠点の方ずも盎接お䌚いしお仕事できる機䌚があるこずが倧きいのかなず思っおいたす。 たた、瀟内むベントを通じお他郚眲の方ずも気軜に亀流できおいるこずが嬉しいです(ただ入瀟3ヶ月目ですが、5070人近くの他郚眲の方ず亀流できおいたす。嬉しい) ブログを曞くこずになっおどう思った ゚ンゞニアブログ運営チヌムに盎接声をかけおもらっお、玠盎に嬉しいず思いたした。入瀟埌は技術ブログを積極的に曞きたいなず思っおいたしたし、入瀟同期ず再び亀流する機䌚にもなったので。これを機に、今埌も継続しお技術ブログを投皿しおいきたいず思いたす。(めざせ月むチ投皿) YYさん ⇒ ナミキ ナりゞさんぞの質問 同じサりナ郚ですが、今気になっおるサりナ斜蚭があれば教えお欲しいです 今幎の5月にオヌプンした 毎日サりナ越谷店 です 1号店の前橋店、2号店の八王子店に次ぐ3号店ずなるのですが、越谷店には毎日サりナ初のお颚呂(しかも薬草泡颚呂)があるずのこずで、メチャメチャ気になっおいたす。サりナ郚で行きたいですね KJ 自己玹介 ゎルフが倧奜きでした。血豆ができるたで緎習したした。30代埌半から始めたのですがシニアプロになりたいず半ば本気で思っおたした(笑)。ただ、コロナを境にプレヌ頻床が枛っお緎習もしなくなり䞋手になりたした。2025幎4月、マスタヌズでのマキロむのキャリアグランドスラム達成に感動し、もう䞀床、出盎そうず思っおいたす。 所属チヌムの䜓制は 出向先のKINTOでは業務PJ改善Tずいうリヌス業務の改善を行うチヌムに所属しおおり、そこは4人䜓制です。KTCでは郚付きです。 KTCぞ入瀟したずきの第䞀印象ギャップはあった 官僚的・瞊割りな組織ではなく、䌚瀟党䜓を芋回し、そのうえで自身で出来るこず、すべきこずを自立的に考えるこずができる人が倚い組織だなずいうのが第䞀印象です。 良い意味でトペタらしさが無いこずがギャップでした。 珟堎の雰囲気はどんな感じ KINTOサヌビスの根幹であるリヌス業務を回す郚眲なのでキッチリカッチリした雰囲気がある半面、メンバヌの方々は倚様性あふれる面癜い人ばかりです。 どうすれば業務の品質が䞊がり、工数/リヌドタむムが削枛できるだろう、ず日々考えおおり、良い意味で珟状を疑う雰囲気を持っおいるず思いたす。 ブログを曞くこずになっおどう思った 面癜い取り組みだず思いたした。䞀般的に埋もれやすい新入瀟員にスポットラむトを圓おおもらえるのはありがたいですし、応募・入瀟怜蚎䞭の方々にずっおも近しい存圚の発信ずしお参考になる情報だず思いたす。 ナミキ ナりゞさん ⇒ KJさんぞの質問 他郚眲のメンバヌずの関わりなどどのようにされおいたすか 自郚眲では1人だけの名叀屋採甚で、普段は宀町オフィスではなく名叀屋オフィスにいたす。名叀屋オフィスのKTCメンバヌは宀町に比べるずかなり少ないですが、少数がゆえの距離感の近さもあり他郚眲の方々ずはよく仕事の話や雑談をさせおもらっおいたす。䞀緒にランチに行くこずも倚いです。たた、私はKINTOの業務郚に出向させおいただいおおり、リヌス業務を通しお亀わる人も埐々に増えおきいたす。向こう1-2幎くらいで友達100人を達成したいです(笑)。 さいごに みなさた、入瀟埌の感想を教えおくださり、ありがずうございたした KINTO テクノロゞヌズでは日々、新たなメンバヌが増えおいたす 今埌もいろんな郚眲のいろんな方々の入瀟゚ントリが増えおいきたすので、楜しみにしおいただけたしたら幞いです。 そしお、KINTO テクノロゞヌズでは、ただたださたざたな郚眲・職皮で䞀緒に働ける仲間を募集しおいたす 詳しくは こちら からご確認ください
Hi, this is Nakanishi from the QA Group (though I also wear a few other hats at the Developer Relations Group and the KINTO FACTORY Development Group ^^) This year at KINTO Technologies, we're embracing an "AI First, Release First" mindset. As part of this shift, our QA team has been exploring ways to make the most of AI to speed up our release cycles. This time, a group of QA members who shared the same passion came together for a lively brainstorming session. "Wouldn't it be awesome if we could do this?" "I really want to try something like this!" Together, we discussed ideas and possibilities. In this article, I'll be sharing some of the most exciting concepts that emerged out of the session, exploring how AI can help transform the future of QA. Issues That Emerged from Our Discussion QA teams produce a huge volume of documents every day, but the sheer amount of information makes it hard to find what's actually needed. Specification formats also vary by project or person, which complicates sharing across teams. On top of that, there's no solid system for reviewing incidents or implementing preventive measures—making it tough to stop issues from recurring. The review process itself is also a heavy workload, and there's growing demand to streamline it. A Future Made Possible by AI Effective Information Use (RAG) RAG (Retrieval-Augmented Generation) is a cutting-edge method for retrieving and analyzing information using the latest in generative AI technology. It quickly pulls key insights from vast archives of documents and incident data, delivering the right information to users when they need it. For instance, when an incident occurs, AI can instantly scan and analyze similar past cases to suggest effective solutions on the spot. It's like having a top-tier assistant who remembers every past experience and offers instant advice right when you need it. Already in use across industries like finance and customer support, it's dramatically speeding up response times and boosting problem-solving efficiency. Organizing and Supporting Specifications and Designs AI helps identify inconsistencies and omissions in your specifications, clearly highlighting and organizing any issues. By analyzing the inputted specifications, it can also automatically generate suitable test scenarios. For example, if you provide the specs for an e-commerce site cart feature, the AI can instantly create a scenario like: "Add product → Change quantity → Payment → Order confirmation." It can even generate additional scenarios, such as error handling flows and boundary value tests. This drastically cuts down the time and effort spent on manual scenario creation, boosting both the accuracy and efficiency of QA tasks. Automate and Streamline Your QA Process AI analyzes user operation logs to catch even the small mistakes that humans might miss. Specifically, it detects frequent user errors and unusual operations, like "errors triggered during specific screen transitions" or "fields often filled in incorrectly on input forms." With this, you can refine your test scenarios and address potential problem areas in advance. AI also automates the hassle of managing test case numbering on Conflu, cutting down on manual mistakes and saving a significant amount of time. Incident Analysis and Prevention AI that analyzes past incidents and offers concrete measures to prevent them from happening again. For example, it thoroughly reviews cases like "display issues on specific browsers" or "payment system failures" on e-commerce sites. Based on the findings, it suggests actionable steps such as "regularly checking browser behavior by version" or "enhancing error handling before and after payment processing." When a critical issue arises, the AI immediately assesses the risk level and sends automatic alerts to the relevant teams, enabling swift, real-time response and resolution. Streamlining Test Data Creation AI instantly generates the data required for testing. From new vehicle and used car details to user information, it can quickly produce large volumes of diverse data tailored to realistic business scenarios. In addition, by integrating AI with browser automation tools like Selenium and Appium, tasks that once required manual input can now be automated. With just a few simple settings, you can generate massive amounts of test data in no time. This integration not only reduces human error but also slashes the workload required for data creation, greatly improving the overall efficiency of your QA process. Tool Integration and Process Automation Connect Slack with tools like JIRA or Asana to receive timely, automated updates on what matters. Streamline your workflow by centralizing information from various tools in one place. Let AI serve as the bridge between platforms, smoothing out your entire process flow. Using AI Models for QA We're exploring the use of ChatGPT fine-tuned specifically for QA tasks. By building our own in-house AI model, we dramatically improved the response speed of the AI. Furthermore, we're working to create an environment where developers can easily use AI for quick self-checks. Future Action Plans Prioritize organizing and consolidating information using AI. AI-assisted reviews will help us work more efficiently and lighten the human load. Continuous data collection for the development of dedicated AI models. Actively utilizing AI-based incident analysis for process improvement. Automation between various tools will lead to further improvements in efficiency. Even when something feels too big to handle alone, new paths can open up when we think together. Inspired by the ideas from this brainstorming session, we'll launch a range of QA initiatives powered by AI. If you're a QA engineer interested in exploring new possibilities with AI or taking on fresh challenges with us, we'd love to connect. Casual chats and info sessions are always welcome. Feel free to reach out!
Hi, this is Nakanishi from the QA Group (though I also wear a few other hats at the Developer Relations Group and the KINTO FACTORY Development Group ^^) This year at KINTO Technologies, we're embracing an "AI First, Release First" mindset. As part of this shift, our QA team has been exploring ways to make the most of AI to speed up our release cycles. This time, a group of QA members who shared the same passion came together for a lively brainstorming session. "Wouldn't it be awesome if we could do this?" "I really want to try something like this!" Together, we discussed ideas and possibilities. In this article, I'll be sharing some of the most exciting concepts that emerged out of the session, exploring how AI can help transform the future of QA. Issues That Emerged from Our Discussion QA teams produce a huge volume of documents every day, but the sheer amount of information makes it hard to find what's actually needed. Specification formats also vary by project or person, which complicates sharing across teams. On top of that, there's no solid system for reviewing incidents or implementing preventive measures—making it tough to stop issues from recurring. The review process itself is also a heavy workload, and there's growing demand to streamline it. A Future Made Possible by AI Effective Information Use (RAG) RAG (Retrieval-Augmented Generation) is a cutting-edge method for retrieving and analyzing information using the latest in generative AI technology. It quickly pulls key insights from vast archives of documents and incident data, delivering the right information to users when they need it. For instance, when an incident occurs, AI can instantly scan and analyze similar past cases to suggest effective solutions on the spot. It's like having a top-tier assistant who remembers every past experience and offers instant advice right when you need it. Already in use across industries like finance and customer support, it's dramatically speeding up response times and boosting problem-solving efficiency. Organizing and Supporting Specifications and Designs AI helps identify inconsistencies and omissions in your specifications, clearly highlighting and organizing any issues. By analyzing the inputted specifications, it can also automatically generate suitable test scenarios. For example, if you provide the specs for an e-commerce site cart feature, the AI can instantly create a scenario like: "Add product → Change quantity → Payment → Order confirmation." It can even generate additional scenarios, such as error handling flows and boundary value tests. This drastically cuts down the time and effort spent on manual scenario creation, boosting both the accuracy and efficiency of QA tasks. Automate and Streamline Your QA Process AI analyzes user operation logs to catch even the small mistakes that humans might miss. Specifically, it detects frequent user errors and unusual operations, like "errors triggered during specific screen transitions" or "fields often filled in incorrectly on input forms." With this, you can refine your test scenarios and address potential problem areas in advance. AI also automates the hassle of managing test case numbering on Conflu, cutting down on manual mistakes and saving a significant amount of time. Incident Analysis and Prevention AI that analyzes past incidents and offers concrete measures to prevent them from happening again. For example, it thoroughly reviews cases like "display issues on specific browsers" or "payment system failures" on e-commerce sites. Based on the findings, it suggests actionable steps such as "regularly checking browser behavior by version" or "enhancing error handling before and after payment processing." When a critical issue arises, the AI immediately assesses the risk level and sends automatic alerts to the relevant teams, enabling swift, real-time response and resolution. Streamlining Test Data Creation AI instantly generates the data required for testing. From new vehicle and used car details to user information, it can quickly produce large volumes of diverse data tailored to realistic business scenarios. In addition, by integrating AI with browser automation tools like Selenium and Appium, tasks that once required manual input can now be automated. With just a few simple settings, you can generate massive amounts of test data in no time. This integration not only reduces human error but also slashes the workload required for data creation, greatly improving the overall efficiency of your QA process. Tool Integration and Process Automation Connect Slack with tools like JIRA or Asana to receive timely, automated updates on what matters. Streamline your workflow by centralizing information from various tools in one place. Let AI serve as the bridge between platforms, smoothing out your entire process flow. Using AI Models for QA We're exploring the use of ChatGPT fine-tuned specifically for QA tasks. By building our own in-house AI model, we dramatically improved the response speed of the AI. Furthermore, we're working to create an environment where developers can easily use AI for quick self-checks. Future Action Plans Prioritize organizing and consolidating information using AI. AI-assisted reviews will help us work more efficiently and lighten the human load. Continuous data collection for the development of dedicated AI models. Actively utilizing AI-based incident analysis for process improvement. Automation between various tools will lead to further improvements in efficiency. Even when something feels too big to handle alone, new paths can open up when we think together. Inspired by the ideas from this brainstorming session, we'll launch a range of QA initiatives powered by AI. If you're a QA engineer interested in exploring new possibilities with AI or taking on fresh challenges with us, we'd love to connect. Casual chats and info sessions are always welcome. Feel free to reach out!
はじめに こんにちは。KINTOテクノロゞヌズ以䞋KTCプラットフォヌムグルヌプ Platform Engineeringチヌムで内補ツヌルの開発・運甚を担圓しおいる山田です。普段はアプリケヌション゚ンゞニアずしお、JavaずSpring Bootを䜿ったバック゚ンドや、JavaScriptずReactを䜿ったフロント゚ンドでCMDBConfiguration Management Databaseの開発をしおいたす。ここ1幎ほどは生成AIブヌムに乗り、CMDBにRAGやText-to-SQLを掻甚したチャットボットの開発にも取り組んでいたす。 こちらはText-to-SQLに぀いお曞いた前回の蚘事です。ご興味ある方はぜひご芧ください https://blog.kinto-technologies.com/posts/2025-01-16-generativeAI_and_Text-to-SQL/ 今回は生成AI関連で、2025幎5月20日にGAされたSpring AIを詊しおみた内容をご玹介したいず思いたす。 Spring AIの抂芁 2025幎5月20日にGAされたSpring゚コシステムの䞀぀で、生成AI関連のフレヌムワヌクです。生成AI分野ではPythonベヌスのLlamaIndexやLangChainが有名ですが、既存のSpringアプリケヌションに生成AI機胜を远加したい堎合や、Javaで生成AI開発をやっおみたい方にずっおの遞択肢になるかず思いたす。 https://spring.pleiades.io/spring-ai/reference/ 怜蚌内容 今回はSpring AIを䜿っお、以䞋の2぀の機胜を実装しおみたした。 チャット機胜LLM察話 : AWS BedrockのClaude 3.7 Sonnetモデルを利甚した察話機胜 Embedding機胜 : Cohereの゚ンベディングモデルずChromaベクトルデヌタベヌスを組み合わせた文曞埋め蟌み・類䌌文曞怜玢機胜 技術スタック Spring Boot 3.5.0 Java 21 Spring AI 1.0.0 Gradle Chroma 1.0.0 AWS Bedrock LLMモデルAnthropic Claude 3.7 Sonnet EmbeddingモデルCohere Embed Multilingual v3 環境構築 䟝存関係の蚭定 たずは build.gradle にSpring AIを䜿うための䟝存関係を远加したす。 plugins { id 'java' id 'org.springframework.boot' version '3.5.0' id 'io.spring.dependency-management' version '1.1.7' } java { toolchain { languageVersion = JavaLanguageVersion.of(21) } } ext { set('springAiVersion', "1.0.0") } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.ai:spring-ai-starter-model-bedrock-converse' implementation 'org.springframework.ai:spring-ai-starter-model-bedrock' implementation 'org.springframework.ai:spring-ai-bedrock' implementation 'org.springframework.ai:spring-ai-starter-vector-store-chroma' testImplementation 'org.springframework.boot:spring-boot-starter-test' } dependencyManagement { imports { mavenBom "org.springframework.ai:spring-ai-bom:${springAiVersion}" } } アプリケヌション蚭定 application.yml でAWS Bedrockの認蚌情報やモデル遞択、ベクトルストアの接続情報を蚭定したす。 spring: application: name: spring-ai-sample ai: bedrock: aws: region: ap-northeast-1 access-key: ${AWS_ACCESS_KEY_ID} secret-key: ${AWS_SECRET_ACCESS_KEY} session-token: ${AWS_SESSION_TOKEN} converse: chat: options: model: arn:aws:bedrock:ap-northeast-1:{account_id}:inference-profile/apac.anthropic.claude-3-7-sonnet-20250219-v1:0 cohere: embedding: model: cohere.embed-multilingual-v3 model: embedding: bedrock-cohere vectorstore: chroma: client: host: http://localhost port: 8000 initialize-schema: true 蚭定はこれだけです。あずはアプリケヌション内で必芁なクラスを簡単にDIできるようになりたす。 実装䟋 1. 生成AILLMずの察話機胜 Spring AIでは ChatClient むンタヌフェヌスを䜿っお、簡単にLLMずの察話を実装できたす。 サヌビス局の実装 ChatServiceクラスでLLMずの察話機胜を実装したす。 @Service public class ChatService { private final ChatClient chatClient; public ChatService(ChatClient.Builder builder) { this.chatClient = builder.build(); } public String generate(String message) { return this.chatClient.prompt(message).call().content(); } } ChatClient.Builder をDIするこずで、蚭定ファむルに基づいたクラむアントを自動的に構築できたす。 コントロヌラヌの実装 RESTコントロヌラヌでAPI゚ンドポむントを提䟛したす。 @RestController public class ChatController { private final ChatService chatService; private final EmbeddingService embeddingService; public ChatController(ChatService chatService, EmbeddingService embeddingService) { this.chatService = chatService; this.embeddingService = embeddingService; } @PostMapping("/generate") public ResponseEntity<String> generate(@RequestBody ChatRequest request) { return ResponseEntity.ok(chatService.generate(request.getMessage())); } } これで /generate ゚ンドポむントにメッセヌゞをPOSTするず、Claude 3.7 Sonnetによる応答を受け取るこずができたす。 以䞋が呌び出し䟋です。 curl -X POST http://localhost:8080/generate -H "Content-Type: application/json" -d '{"message": "こんにちわわ"}' こんにちは䜕かお手䌝いできるこずはありたすか 2. Embedding怜玢機胜の実装 次に、ドキュメントをベクトル化しお怜玢する機胜を実装したす。 Embeddingサヌビスの実装 このサヌビスでは、サンプルテキストを Document オブゞェクトずしおベクトル化し、Chromaに保存したす。そしお「Spring」ずいうク゚リに察しお類䌌床の高いドキュメントを怜玢したす。この凊理の裏偎では、Cohere Embed Multilingual v3モデルによるテキストのベクトル倉換が行われおいたす。 @Service public class EmbeddingService { private final VectorStore vectorStore; public EmbeddingService(VectorStore vectorStore) { this.vectorStore = vectorStore; } public List<Document> embed() { List<Document> documents = List.of( new Document("Spring AI is a framework for building AI applications with the familiar Spring ecosystem and programming model."), new Document("LlamaIndex is a data framework for LLM applications to ingest, structure, and access private or domain-specific data."), new Document("LangChain is a framework for developing applications powered by language models through composability.") ); vectorStore.add(documents); return vectorStore.similaritySearch(SearchRequest.builder().query("Spring").topK(5).build()); } } API゚ンドポむントの実装 @GetMapping("/embedding") public ResponseEntity<List<Document>> embedding() { return ResponseEntity.ok(embeddingService.embed()); } この実装により、 /embedding ゚ンドポむントにアクセスするず、サンプルドキュメントのベクトル化ず怜玢が行われ、その結果が返されたす。 以䞋が呌び出し䟋です。「Spring」ずいう蚀葉が入ったドキュメントの類䌌床scoreが䞀番高い結果になっおいたすね。 curl http://localhost:8080/embedding [ { "id": "af885f07-20c9-4db4-913b-95406f1cb0cb", "text": "Spring AI is a framework for building AI applications with the familiar Spring ecosystem and programming model.", "media": null, "metadata": { "distance": 0.5593532 }, "score": 0.44064682722091675 }, { "id": "5a8b8071-b8d6-491e-b542-611d33e16159", "text": "LlamaIndex is a data framework for LLM applications to ingest, structure, and access private or domain-specific data.", "media": null, "metadata": { "distance": 0.6968217 }, "score": 0.3031783103942871 }, { "id": "336b3e07-1a70-4546-920d-c4869e77e4bb", "text": "LangChain is a framework for developing applications powered by language models through composability.", "media": null, "metadata": { "distance": 0.71094555 }, "score": 0.2890544533729553 } ] さいごに 簡単ではありたすが、今回はSpring AIを䜿った生成AI機胜に぀いおご玹介したした。Spring AIを詊しおみお、Javaのシステムに生成AI関連の凊理を組み蟌む堎合には遞択肢の䞀぀になるかなず思いたした。たた、今回ご玹介したチャット機胜やEmbedding怜玢機胜を組み合わせるこずで、RAG機胜も比范的簡単に実装できるず感じおいたす。 珟時点では、生成AI関連の機胜や゚コシステムはLlamaIndexやLangChainずいったPython系フレヌムワヌクの方が充実しおいる印象ですが、Spring AIはリリヌスされたばかりなので今埌の機胜远加に期埅したいず思いたす
Introduction Hello! I'm Momoi ( @momoitter ), a designer at KINTO Technologies. I belong to the Creative Office where I work on projects like the corporate website and Kumobii (KINTO's official mascot) related sites, incorporating cutting-edge web design along the way. In November 2024, our company hosted an internal event called the CHO All-Hands Meeting, and I was in charge of creating the opening movie for it and I used three generative AIs to create a female character who kicks off the event with a voice announcement. Actual Video https://www.youtube.com/watch?v=pVj_UQ_3-tg When asked at the event start, "Are you ready?", she answers "Of course!" In this article, I'll share the process of creating this original talking character and my thoughts along the way. How I wanted to create our own character that talks About incorporating AI to easily create a memorable video If you're like me, then definitely keep reading! Background The request from the art director overseeing the event's overall creative direction was to "re-edit the video used in our corporate website 's key visual and turn it into a one-minute opening movie." But just re-editing existing footage felt a bit too familiar for employees, and I wanted something more eye-catching, something that instantly energizes the event from the start. That's when I turned to our AI chatbot in our company Slack. I thought, what if I used AI to bring our chatbot to life as a surprise? A personified version in the video could definitely catch everyone's eye. AIs Used To create a talking character, I used the following three AI tools: Adobe Firefly (character image generation) TTSMaker (text-to-speech conversion) Runway (character animation with voice) From here on, I'll show you how I used these AIs to make the video. 1. Character Image Generation Adobe Firefly An image generation AI tool provided by Adobe. Since Adobe Firefly is trained on copyright-free images like Adobe Stock images, it can be used without worrying about copyright issues. Many of the well-known image generation AIs claim to be copyright-free, but some operate in a gray area, such as being able to generate images that closely resemble anime characters. Since this was a corporate event, we wanted to avoid any copyright concerns, so we chose an AI that can be used without such worries. Adobe Firefly Image Generation This character is displayed on our company's Slack with an icon like this: From the icon we established that: The pink color of the icon led us to give her pink hair She's an AI chatbot so we wanted to give her a smart, digital vibe in her overall look And by doing so we expanded the character's image. On-screen Operations When you open Firefly, you'll see a screen like this. Roughly speaking, you enter the prompts to generate an image in the input area below, and then use the menu on the left to adjust the aspect ratio, composition, style, tone, etc. This time, after much trial and error, I generated the character using the prompt "3D character, female, pink hair, white background, upper body, white simple digital clothing, facing forward." Mass Generation Once the prompt was more solidified, it was a matter of luck whether I would get a good result, so I just generated 100 to 200 sheets. Selection To give the event a fresh start, I aimed for a character that felt like an "AI operator" with an official and trustworthy vibe. So, I filtered out these images: The ones looking too young Having weird clothing Scary faces Selected Image After carefully narrowing down the options, I chose this image because it felt cool yet approachable. 2. Text-to-Speech Conversion TTSMaker An AI voice generator that converts typed text into speech. There are many similar AI-based text-to-speech services, but many of them are paid services or require crediting the source if they are free. I went with this tool because it's free to use without any credit attribution. TTSMaker On-screen Operations When you open TTSMaker, you'll see a screen like this. The procedure is as follows: Select a language Enter the text you want to convert to speech Listen to sample voices and choose the tone Set the details like speed and pitch Convert I aimed for a voice that felt like an "AI operator" with an official and trustworthy vibe. After comparing sample voices, I chose "406 - Yuki Tsumiyuki -🇯🇵 Japanese female" and had her read the line: "Mochirondesu. Cho-honbukai o hajimemasu." ("Of course. We'll now start the CHO All-Hands Meeting.") Actual Audio https://www.youtube.com/watch?v=r4Zw2by669I 3. Character Animation with Voice Runway An AI-powered tool that makes it easy to create and edit high-quality videos. I chose this tool for its "Lip Sync Video" feature, which syncs character images with voice audio. Runway On-screen Operations 1.Open "Lip Sync Video" under the "Generative Audio" section, then drag and drop the previously created character image. 2. Check that the facial range of the character image is recognized correctly, and if there are no problems, click "Upload Audio." 3. Drag and drop the previously generated voice, then click "Generate." Generated Video https://www.youtube.com/watch?v=usY4yB9Z1YA A video of the character speaking in sync with the audio was generated. Bonus Tip 1 https://www.youtube.com/watch?v=raYsnhwZONo By uploading a song, the character can actually be made to sing. Bonus Tip 2 https://www.youtube.com/watch?v=3edVClgoLug In this way, it's also possible to make a still image of a real person talk. At a recent internal study session (held in Tokyo), the speaker was suddenly unable to make the business trip from Osaka to attend, so we asked him to prepare still images and voice memos, and we used this AI-generated video to make our presentation. 4. Final Touches That's all for how to create a talking character video. What comes next is a little something extra. Actually, getting a character to talk using AI has become so easy that anyone can do it with the AIs I introduced above. But since I'm a designer in the Creative Office, I wanted to go beyond what any other department could produce. So as a final touch, I added a 3D balloon-style CG made in Illustrator, gave it a soft floating motion in After Effects, and composited it into the video. This added a polished finish and added the value only a creator could bring. Final Video https://www.youtube.com/watch?v=pVj_UQ_3-tg By adding one final touch, the video evolved from just a talking character to something with added graphical expression. Conclusion How it looked when projected at the event Each creative generative AI has its own characteristics and limitations. By understanding and combining those characteristics, I was able to create a level of quality that wouldn't have been possible with just one tool. On the day of the event, this character was projected on a large screen, and I was grateful to hear comments like: "That was amazing! How did you make it?" "The quality was so high I thought it was outsourced!" It felt great to see the impact it made, just as I aimed for. All tools used are simple enough that even non-creators can use it. As long as you have an idea, you can create memorable videos like this. If this article sparked your interest, definitely give it a try! Thank you for reading till the end.
Introduction Hello! I'm Momoi ( @momoitter ), a designer at KINTO Technologies. I belong to the Creative Office where I work on projects like the corporate website and Kumobii (KINTO's official mascot) related sites, incorporating cutting-edge web design along the way. In November 2024, our company hosted an internal event called the CHO All-Hands Meeting, and I was in charge of creating the opening movie for it and I used three generative AIs to create a female character who kicks off the event with a voice announcement. Actual Video https://www.youtube.com/watch?v=pVj_UQ_3-tg When asked at the event start, "Are you ready?", she answers "Of course!" In this article, I'll share the process of creating this original talking character and my thoughts along the way. How I wanted to create our own character that talks About incorporating AI to easily create a memorable video If you're like me, then definitely keep reading! Background The request from the art director overseeing the event's overall creative direction was to "re-edit the video used in our corporate website 's key visual and turn it into a one-minute opening movie." But just re-editing existing footage felt a bit too familiar for employees, and I wanted something more eye-catching, something that instantly energizes the event from the start. That's when I turned to our AI chatbot in our company Slack. I thought, what if I used AI to bring Sherpa to life as a surprise? A personified Sherpa in the video could definitely catch everyone's eye. AIs Used To create the original talking character, I used the following three AI tools: Adobe Firefly (character image generation) TTSMaker (text-to-speech conversion) Runway (character animation with voice) From here on, I'll show you how I used these AIs to make the video. 1. Character Image Generation Adobe Firefly An image generation AI tool provided by Adobe. Since Adobe Firefly is trained on copyright-free images like Adobe Stock images, it can be used without worrying about copyright issues. Many of the well-known image generation AIs claim to be copyright-free, but some operate in a gray area, such as being able to generate images that closely resemble anime characters. Since this was a corporate event, we wanted to avoid any copyright concerns, so we chose an AI that can be used without such worries. Adobe Firefly Image Generation "Sherpa," the original inspiration for this character, is displayed on our company's Slack with an icon like this: From the icon we established that: The "pa" sound in Sherpa inspired a feminine feel The pink color of the icon led us to give her pink hair She's an AI chatbot so we wanted to give her a smart, digital vibe in her overall look And by doing so we expanded the character's image. On-screen Operations When you open Firefly, you'll see a screen like this. Roughly speaking, you enter the prompts to generate an image in the input area below, and then use the menu on the left to adjust the aspect ratio, composition, style, tone, etc. This time, after much trial and error, I generated the character using the prompt "3D character, female, pink hair, white background, upper body, white simple digital clothing, facing forward." Mass Generation Once the prompt was more solidified, it was a matter of luck whether I would get a good result, so I just generated 100 to 200 sheets. Selection To give the event a fresh start, I aimed for a character that felt like an "AI operator" with an official and trustworthy vibe. So, I filtered out these images. Look too young Weird clothing Scary face Selected Image After carefully narrowing down the options, I chose this image because it felt cool yet approachable. 2. Text-to-Speech Conversion TTSMaker An AI voice generator that converts typed text into speech. There are many similar AI-based text-to-speech services, but many of them are paid services or require crediting the source if they are free. I went with this tool because it's free to use without any credit attribution. TTSMaker On-screen Operations When you open TTSMaker, you'll see a screen like this. The procedure is as follows: Select a language Enter the text you want to convert to speech Listen to sample voices and choose the tone Set the details like speed and pitch Convert I aimed for a voice that felt like an "AI operator" with an official and trustworthy vibe. After comparing sample voices, I chose "406 - Yuki Tsumiyuki -🇯🇵 Japanese female" and had her read the line: "Mochirondesu. Cho-honbukai o hajimemasu." ("Of course. We'll now start the CHO All-Hands Meeting.") Actual Audio https://www.youtube.com/watch?v=r4Zw2by669I 3. Character Animation with Voice Runway An AI-powered tool that makes it easy to create and edit high-quality videos. I chose this tool for its "Lip Sync Video" feature, which syncs character images with voice audio. Runway On-screen Operations 1.Open "Lip Sync Video" under the "Generative Audio" section, then drag and drop the previously created character image. 2. Check that the facial range of the character image is recognized correctly, and if there are no problems, click "upload audio." 3. Drag and drop the previously generated voice, then click "Generate." Generated Video https://www.youtube.com/watch?v=usY4yB9Z1YA A video of the character speaking in sync with the audio was generated. Bonus Tip 1 https://www.youtube.com/watch?v=raYsnhwZONo By uploading a song, the character can actually be made to sing. Bonus Tip 2 https://www.youtube.com/watch?v=3edVClgoLug In this way, it's also possible to make a still image of a real person talk. At a recent internal study session (held in Tokyo), the speaker was suddenly unable to make the business trip from Osaka to attend, so we asked him to prepare still images and voice memos, and we used this AI-generated video to make our presentation. 4. Final Touches That's all for how to create a talking character video. What comes next is a little something extra. Actually, getting a character to talk using AI has become so easy that anyone can do it with the AIs I introduced above. But since I'm a designer in the Creative Office, I wanted to go beyond what any other department could produce. So as a final touch, I added a 3D balloon-style CG of Sherpa made in Illustrator, gave it a soft floating motion in After Effects, and composited it into the video. This added a polished finish and added the value only a creator could bring. Final Video https://www.youtube.com/watch?v=pVj_UQ_3-tg By adding one final touch, the video evolved from just a talking character to something with added graphical expression. Conclusion How it looked when projected at the event Each creative generative AI has its own characteristics and limitations. By understanding and combining those characteristics, I was able to create a level of quality that wouldn't have been possible with just one tool. On the day of the event, this character was projected on a large screen, and I was grateful to hear comments like: "That was amazing! How did you make it?" "The quality was so high I thought it was outsourced!" It felt great to see the impact it made, just as I aimed for. All tools used are simple enough that even non-creators can use it. As long as you have an idea, you can create memorable videos like this. If this article sparked your interest, definitely give it a try! Thank you for reading to the end.
Introduction Hello! I'm Alex, a Generative AI Engineer on the Generative AI Development Project team at KINTO Technologies. Lately, there's been a growing interest in building multi-agent systems using large language models (LLMs). So in this article, I'd like to share a case where I built a Supervisor-style multi-agent system in less than 30 minutes using the latest LangGraph update, langgraph_supervisor. This system allows a central supervisor agent to coordinate and manage multiple specialized agents. It can be applied to a wide range of use cases, from automating workflows to generating customizable proposal scenarios. What is LangGraph? LangGraph is a Python library designed to simplify the development of AI agents and Retrieval-Augmented Generation (RAG) systems. Combined with LangChain, complex workflows and tasks can be designed and implemented efficiently. It supports state persistence, tool invocation, and features like human-in-the-loop and post-task validation through a centralized persistence layer which served as the foundation for this Supervisor-style system. What is langgraph-supervisor? langgraph-supervisor is a Python library for building hierarchical multi-agent systems using LangGraph, which was recently released by LangChain. A central supervisory agent coordinates task assignments and facilitates communication among specialized agents. This enables the development of adaptable systems that can tackle complex tasks with ease and efficiency. Key Features Supervisor agent creation: Manages multiple specialized agents and orchestrates the overall workflow. Tool-based agent handoff mechanism: Provides a mechanism for achieving smooth communication between agents. Flexible message history management: Enables easy control over conversation flow by managing message history dynamically. @ card What is a Supervisor-style Multi Agent System? Source: https://langchain-ai.github.io/langgraph/tutorials/multi_agent/agent_supervisor/ A Supervisor-style multi-agent system is a structure where a central controlling agent called the Supervisor coordinates with tool-enabled LLM agents, deciding which agent to call, when to do so, and what arguments to pass along. Building a Multi-Agent System with langgraph-supervisor The following steps outline how to build a multi-agent system using langgraph-supervisor. In this example, we’ll create a system that recommends a car and engine type based on simple, anonymized customer information. Additionally, the agent will retrieve car and engine information from the locally stored "Vehicle_Information.csv" file. Environment Setup Prepare Azure OpenAI API keys This time, we'll be using GPT-4o via Azure OpenAI. Depending on your situation, you can also use the OpenAI API, or Anthropic API, etc. And set Azure OpenAI API keys and endpoint as environment variables. os.environ["AZURE_OPENAI_API_KEY"] = "YOUR API KEY" os.environ["AZURE_OPENAI_ENDPOINT"] = "YOUR ENDPOINT" os.environ["AZURE_OPENAI_API_VERSION"] = "YOUR API VERSION" os.environ["AZURE_OPENAI_DEPLOYMENT"] = "YOUR DEPLOYMENT NAME" Install LangGraph and LangChain pip install langgraph pip install langchain pip install langchain_openai Install langgraph-supervisor pip install langgraph-supervisor Setup of tool functions used by LLM and each Agent Define the model using Azure OpenAI's GPT-4o. Next, define the tool functions for agents. from langchain_openai import AzureChatOpenAI import pandas as pd # LLMの初期化 llm = AzureChatOpenAI( azure_deployment=os.getenv("AZURE_OPENAI_DEPLOYMENT"), api_version=os.getenv("AZURE_OPENAI_API_VERSION"), ) car_information_path = "/xxx/xxx/車䞡情報.csv" # ツヌル関数の定矩䟋 # CSVファむルから車䞡情報を読み蟌み、候補を生成する䟋 def get_car_features(): """The python code to get car information.""" path = car_information_path # CSVファむルのパスを指定 df = pd.read_csv(car_information_path) car_features = df[["車皮名", "ボディタむプ", "説明"]].drop_duplicates() return car_features.to_dict(orient="records") # 遞択された車皮に察しお゚ンゞンタむプを抜出する䟋 def get_engine_type(selected_car): """The python code to get engine type and engine information.""" path = car_information_path df = pd.read_csv(car_information_path) engine_types = list(df[df["車皮名"] == selected_car]["゚ンゞンタむプ"].unique()) return engine_types, "゚ンゞンに関する補足情報" Defining Each Agent We use LangGraph's "create_react_agent" to define each specialized agent (car model recommendation, engine type selection). from langgraph.prebuilt import create_react_agent # 車皮掚薊゚ヌゞェント car_agent = create_react_agent( model=llm, tools=[get_car_features], name="car_agent", prompt=""" # Instructions Based on the recommended pattern, choose a car model to recommend and explain the reasoning in about 200 characters. """ ) # Engine type selection agent engine_agent = create_react_agent( model=llm, tools=[get_engine_type], name="engine_agent", prompt=""" # Instructions Choose the most suitable engine type for the recommended car and explain the reasoning in about 200 characters. """ ) Defining the Supervisor Create a Supervisor to oversee each agent and generate a final recommendation based on customer information. One improvement we made here was modularizing the prompt input to the Supervisor, allowing for greater versatility. By changing the contents of the role and task variables and the associated agent, the system can easily be used for other tasks. from langgraph_supervisor import create_supervisor # Create the contents of each module in the prompt role = "車のセヌルスマン" task = "顧客情報をもずに、最適な車ず゚ンゞンタむプを提案しおください。" guideline = """ - 出力は必ず䞊蚘JSON圢匏で行っおください。 - 各根拠は200文字皋床の豊かな文章で蚘述しおください。" """ output_format = """ { "提案内容": { "提案する車皮", "車皮の根拠", "遞択した゚ンゞンタむプ", "゚ンゞン遞定理由" } } """ # Create a prompt system_prompt = f""" ## Role あなたは優れた{role}です。 ## Task {task} ## Guidelines {guideline} ## 最終生成物のフォヌマット {output_format} """ # Create the Supervisor workflow = create_supervisor( # 先ほど䜜成した゚ヌゞェントず玐づく [car_agent, engine_agent], model=llm, prompt=system_prompt ) # Compile the graph app = workflow.compile() Example Run from langchain.schema import HumanMessage import time # Example of customer information (add more details as needed) customer_info = "顧客情報: Age 35, prioritizes fuel efficiency, currently drives a compact car. # Example run start_time = time.time() result = app.invoke({ "messages": [ {"role": "user", "content": customer_info} ] }) end_time = time.time() # Display the final output print("最終提案:") print(result["messages"][-1].content) print("実行時間: {:.3f}秒".format(end_time - start_time)) Response from the Supervisor 最終提案: { "提案内容": { "提案する車皮": "ハむブリッド技術を採甚した最新コンパクトカヌ", "車皮の根拠": "顧客は珟圚コンパクトカヌに乗車䞭であり、燃費性胜の良さを重芖しおいたす。 ハむブリッド技術を採甚した車は、燃料䜿甚の効率が高く、経枈的負担や環境ぞの配慮が優れおいたす。 たた、ハむブリッドシステムは短距離や郜垂郚での走行にも最適です。 そのため、最新のハむブリッドコンパクトカヌが最適な遞択肢ずなりたす。", "遞択した゚ンゞンタむプ": "ハむブリッド゚ンゞン", "゚ンゞン遞定理由": "ハむブリッド゚ンゞンは燃費性胜が非垞に優れおおり、顧客のニヌズである燃料効率を最優先に考慮しおいたす。 さらに、コンパクトカヌずの盞性も良く、郜垂郚での利甚や日垞の移動においお高いパフォヌマンスを発揮したす。 この゚ンゞンの遞択は、快適性、経枈性、環境性胜を党お満たしたす。" } } Run Time: 21.938 seconds Impressions After Building the System Rapid Prototyping The complex inter-agent coordination and state management typically required in LangGraph were implemented with simple code using langgraph_supervisor, and a prototype was successfully built in under 30 minutes. A pretty impressive result. Flexibility and Scalability Each agent can be implemented with its own prompt and tool functions, allowing for easy customization to meet specific business needs. In addition, since state management is handled centrally, future improvements and feature additions are expected to be carried out smoothly. We Are Hiring! KINTO Technologies is looking for passionate colleagues to help drive AI adoption in our businesses. We're happy to start with a casual interview. If you’re even slightly interested, feel free to reach out via the link below or through X DMs . We look forward to hearing from you!! @ card Thanks for reading all the way through!
My name is Yuya Sakamaki from KINTO Technologies. I am usually involved in anything from data analysis to proposing strategies, and developing features using machine learning. Previously, I was in charge of AI functional development at Prism Japan . I conducted an internal comparison test of Cursor and GitHub Copilot, and I would like to share the results with you. Premise At KINTO Technologies, there's a policy that allows GitHub Copilot to be used as a standard tool. I will test whether using Cursor Editor can further improve productivity. Cursor An AI-powered code editor, created as a fork of Visual Studio Code. Github Copilot It’s a tool co-developed by GitHub and OpenAI, available as a plug-in for various IDEs such as Visual Studio Code, JetBrains, Eclipse, and more. Disclaimer This article contains many of my own opinions. This is not meant to undermine the usefulness of Cursor. Tested Plans Copilot Enterprise ... $39 / month Cursor Business ... $40 / month Conclusion As of February 2025 , I feel that there is almost no difference in functionality between GitHub Copilot and Cursor. As of December 2024 , I would have liked to recommend Cursor, but with the incredible speed at which Copilot has progressed, I no longer feel the need to choose Cursor Editor again. Evaluation Period December 2024 to February 2025 Comparison Table (Copilot vs. Cursor) I have put together a table of some of the most common points that came up in the discussions using Copilot and Cursor together. The details of each item will be provided later. Item GitHub Copilot Cursor UI/Operability - Inline suggestions and chat ability in VSCode - Many operations by right-clicking - AI-powered shortcuts are displayed instantly - Inline menus are easy to understand QuickFix (completion of import, etc.) - VSCode standard quick fixes are powerful - Sometimes it is unstable and doesn't work - Fix in Composer etc., is a little troublesome Automatic reflection of similar corrections - Need to start writing something first - Tabs predict and suggest the next correction to make (useful for making corrections to multiple places) Model selection - Can be changed, but the variety is limited - Abundant additions and selections (multiple AI models can be used) Rule file - Can be done by changing the settings in .github/copilot-instructions.md - The .cursorrules file enables you to apply rules per project Loading documents (such as @Docs) - Supported by plug-ins, etc. - The @Docs feature enables you to load documents for frameworks and libraries Agent functions - Similar functions available in Copilot Chat / Copilot CLI - Automatic execution in agent mode, try & error Automatic test code generation - Generation is possible (although accuracy varies) - Can be generated in the same way, but the accuracy is questionable. Corrections are needed. Price (Business/Enterprise) $39 $40 *The content of the evaluation is subjective as of February 2025. Pros of Cursor (when compared to GitHub Copilot) AI-powered shortcuts are displayed immediately Since AI-powered shortcuts are displayed automatically when you select a code, the need to remember special operations can be eliminated. Is there something similar in Copilot? Inline chat is possible. However, there is no COMPOSE mode to reference other files, and you need to call it up from the right-click menu, so it requires a little bit of effort. Suggests similar corrections together When you want to apply similar corrections to multiple places, Cursor will predict "where and how to fix next" in order on the tab. Is there something similar in Copilot? It doesn't make predictions until you start writing something first, so it is difficult for it to provide bulk suggestions as smoothly as with Cursor. A similar function is now available in Copilot *There were some changes as I was writing this article. Flexibility with selecting and adding models Cursor is designed to make it easy to add and select any model you want. Is there something similar in Copilot? Copilot Chat also enables model switching, but the scope of what can be done is currently limited. The @Docs feature enables you to load documents for frameworks and libraries Having it read the documents in advance will improve the accuracy of its answers. Is there something similar in Copilot? It is possible to achieve something similar using plug-ins, but the standard features are not that extensive. Automatic execution of try & error in agent mode In agent mode within Cursor, the AI will automatically execute commands under a certain level of authority and perform trial and error. Is there something similar in Copilot? Similar features are starting to appear in Copilot CLI and Copilot Chat, but they still require some fine tuning. While still just a preview version, agent mode is now available in Copilot . Cons of Cursor (when compared to GitHub Copilot) Import completion is a bit troublesome VSCode + Copilot will automatically complete imports, but Cursor will not import unless you hover the mouse cursor over it and select a quick fix. Copilot offers greater stability and overall superiority Automatic test code generation is not very accurate Automatically generated tests often don’t pass on the first run and usually require some adjustments. The same is true for Copilot, but I didn't get the impression that Cursor was much of an improvement. There are still many parts that are not suitable for operation Depending on the app being developed, Cursor contained more AI functions than needed, which confused some team members. The Difference between Cursor's "Composer" and "Chat" Cursor is divided into two main modes: Composer and Chat . Since there are differences in usage and the handling of context, I have put together a quick summary of the results of the internal comparison. Functional Items Composer Chat Context understanding Automatically links to the current file. Auto-suggests related files. Initially the context is empty. Must be shared manually as needed Main uses Mainly code generation and editing. Easy to correct suggested content immediately using inline Mainly used for receiving general questions and explanations. Suitable for longer exchanges History management Auto-saves in the control panel Chat history is selectable UI Also usable in inline menu. Can also be operated from the side menu Side menu only Code block execution Not possible Possible (execute commands via Chat in the side menu) When to use Composer Code corrections with simple context When you want to generate and edit code quickly When to use Chat Code corrections with larger context Analyzing error messages, general programming questions When you want to work while maintaining context for a long period of time Conclusion Again As of February 2025, there are no huge functional differences between Copilot and Cursor In fact, Copilot's progress has been faster than expected, and it seems that within a few months, Copilot filled the gap that I thought Cursor was going to win as of December 2024. There are certainly pros to using Cursor As an AI-powered IDE, Cursor still has its strengths, such as dedicated shortcuts and agent mode. However, since Copilot has also been making progress in supporting these features, the pros of newly introducing it may be somewhat diminishing. Which one will you use in the end? If GitHub Copilot is already available as standard equipment within the company, you will likely be able to get by with just Copilot for the time being. That said, if you're wanting to embrace large-scale code corrections and chat-driven development, it's worth giving Cursor's Composer / Chat features a try, even though the Github Copilot AI agent is currently available to VSCode Insiders. Since they are almost the same in terms of price, it is good idea to choose based on the UI and ease of use. Development App Prism Japan - iOS Prism Japan - Android References Cursor - The AI Code Editor Getting code suggestions in your IDE with GitHub Copilot The above are the results of my extensive use of Cursor and GitHub Copilot. The speed of product updates is accelerating, so I would like to continue to test them regularly.
はじめに はじめたしお。KINTOテクノロゞヌズでAndroidアプリ開発を担圓しおいるJongSeokです。 ある日、資料を敎理しおいお、Google Sheets に内容を移しながら敎えおいるず、ふずこう思いたした。 「これ、めっちゃ面倒くさくない  」 同じような内容を䜕床も入力しお、セルのフォヌマットも敎えお   難しくはないけれど、これっお本圓に人間がやるべきこずなんだろうかず感じたした。 そこで、最近よく目にするAIツヌルで自動化できないか調べおみたずころ、 出䌚ったのが MCPModel Context Protocol でした。 いく぀かのツヌルを詊しおみた結果、 なんず自然蚀語の「䞀行だけ」で Google Sheets を操䜜できたした。 この䜓隓は、正盎かなり衝撃的でした。 MCPずは MCPは「Model Context Protocol」の略です。 名前は少し堅く聞こえるかもしれたせんが、実際はずおも盎感的な圹割を持っおいたす。 簡単に蚀うず、 AIが実際のツヌルやサヌビスを自由に操䜜できるようにする「通蚳」のような存圚です。 この蚘事ではその䞭でも、Googleサヌビスず連携する事䟋にフォヌカスしお玹介しおいきたす。 もっずわかりやすく蚀うず 普段䜿っおいるGmailやGoogle Drive、Google Sheetsなどのサヌビスは、人がクリックしお操䜜したす。 MCPは、そういったサヌビスを AIが自動で操䜜できるようにするものです。 たずえば、こんなこずができたす。 Google Sheetsに䜕かを蚘録したい時、通垞はこんな感じかず思いたす。 シヌトを開いお セルをクリックしお デヌタを入力する MCPは、そういったサヌビスをAIが自動で操䜜できるようにするものです。 それでは、実際のデモを芋おみたしょう。 https://www.kinto-technologies.com/products/ 次のWebペヌゞを参考にしお、新しいGoogleスプレッドシヌトを䜜成し、玹介されおいる補品・サヌビスを敎理しおください。 䞊蚘のように指瀺した堎合の実際の操䜜むメヌゞが、以䞋のデモ動画です。 ![demo](/assets/blog/authors/jongseok/mcp/demo.gif =1080x) このように䞀文で指瀺するだけで、AIがGoogle Sheets APIを呌び出し、シヌトに自動でデヌタを入力しおくれたす。 本圓に簡単にデヌタ敎理ができおしたいたした。 MCP最近流行っおるの 技術的に可胜ずいうこずず、実際に人々が関心を持っおいるずいうのは別の話。 そこで、Google Trendsで「MCP」ずいうキヌワヌドの怜玢トレンドをチェックしおみたした。 2025幎3月から5月たでのデヌタを芋るず、 特に4月䞭旬から怜玢数が急激に増加しおいるのが分かりたす。 これは単なる興味を超えお、 開発者だけでなく䞀般ナヌザヌたでがMCPを実際に「䜿い始めおいる」こずを瀺しおいるずも蚀えたす。 自分もその波に乗った、ずいう感じです。 では、実際にMCPを詊しおみたい堎合、どのような方法があるのでしょうか MCPを掻甚するには、自然蚀語の呜什を受け取り、それを実行できる環境が必芁です。 実際、ClaudeAnthropicなど、MCPず連携できるAI゚ヌゞェントはいく぀か存圚したすが、今回私が遞んだのは、AI機胜が組み蟌たれたコヌド゚ディタ「Cursor」でした。 Cursorずは Cursorは䞀蚀で蚀えば、AI機胜が組み蟌たれたコヌド゚ディタです。 自然蚀語でコヌドを䟝頌すれば、AIが自動で提案・修正・説明などをしおくれたす。 MCP の呜什を曞く際にも、Cursorを䜿えばよりスムヌズに蚘述できたす。 Cursorに぀いおもっず詳しく知りたい方は、公匏サむトやブログを参考にするのがおすすめです。 https://www.cursor.sh それでは、䞀緒に始めおみたしょう MCPずGoogle Sheetsを連携しお実際に自動化を䜓隓するには、たずいく぀かの準備が必芁です。 難しい知識は䞍芁なので、安心しおください。䞀぀ず぀ゆっくり進めおいきたしょう。 事前準備 自動化を始める前に、以䞋の項目を準備しおおきたしょう。 MCPをサポヌトする゚ディタのむンストヌル今回はCursorを䜿甚 Googleアカりント 自動化したいGoogleサヌビスDriveやSheetsなど MCP Server( https://github.com/xing5/mcp-google-sheets ) ←本蚘事ではこれを利甚したす。 簡単な自然蚀語での呜什文を考える準備 Google Cloud Platform (GCP)の蚭定 たず、Google Sheets APIを利甚するためにGCP偎の蚭定を行いたす。 1-1. プロゞェクトを䜜成 GCP コン゜ヌルにアクセスし、新しいプロゞェクトを䜜成したす。 ![Create Project1](/assets/blog/authors/jongseok/mcp/mcp_01_01.png =1080x) ![Create Project2](/assets/blog/authors/jongseok/mcp/mcp_01_02.png =360x) 1-2-1. サヌビスアカりントを䜜成 AIがGoogle Sheetsにアクセスするための「サヌビスアカりント」を䜜成したす。 ![Service Account1](/assets/blog/authors/jongseok/mcp/mcp_02_01.png =1080x) Service AccountsのCreate service accountを抌したす。 ![Service Account2](/assets/blog/authors/jongseok/mcp/mcp_02_02.png =360x) Service account nameを入力しおDoneを抌したす。 1-2-2. Permission远加 ![Service Account3](/assets/blog/authors/jongseok/mcp/mcp_02_03.png =1080x) Permission→Manage access→RoleをEditorにしおSaveを抌したす。 1-2-3. Keys远加 ![Service Account](/assets/blog/authors/jongseok/mcp/mcp_02_04.png =1080x) Keys→Add Keyに抌しおJSONを遞択しおCreateしたす。 そうしたら認蚌ファむルがDownloadされたす。 ![Service Account5](/assets/blog/authors/jongseok/mcp/mcp_02_05.png =1080x) ファむルの䞭身のこんな感じになりたす。 これでサヌビスアカりント発行は終わりです。 このファむル client_email は埌で䜿いたす。 1-3. Googleサヌビスを蚭定 ![Service Account5](/assets/blog/authors/jongseok/mcp/mcp_03_01.png =1080x) APIS & ServicesのLibraryを抌したす。 ![Service Account5](/assets/blog/authors/jongseok/mcp/mcp_03_02.png =1080x) 今回利甚したいServiceが芋えたすね。 Drive Sheets 二぀のServiceをEnableを抌したす。 2-1. GoogleDriveの蚭定 ![Google Drive1](/assets/blog/authors/jongseok/mcp/mcp_04_01.png =1080x) Google Driveに入っおAIを利甚するFolderを䜜りたす。 䟋Sheets For MCPで䜜りたした → その埌ShareのShareを抌したす。 ![Google Drive2](/assets/blog/authors/jongseok/mcp/mcp_04_02.png =360x) 䞊の欄には 1-2. サヌビスアカりントを䜜成 したJSONファむルに䞭にある client_email をcopyしお入力したす。 ![Google Drive3](/assets/blog/authors/jongseok/mcp/mcp_04_03.png =360x) 远加されたか確認しおDoneを抌したす。 2-2. Folder IDを取埗 ![Google Drive4](/assets/blog/authors/jongseok/mcp/mcp_04_04.png =1080x) 蚭定が終わったら Folder ID を取埗したす。 これで蚭定に必芁な物は党郚準備できたした。 実際に蚭定しお䜿っおみたしょう MCP蚭定(Cursor&Terminal) Windowsでも可胜ですが、ここではMacを基準に説明したす。 MCPのセットアップには簡単なCloudServerを利甚する方法もありたすが、今回はLocalServerでやっおみたす。 たずはuv,uvxが必芁なのでTerminalでむンストヌルしたしょう。 uvx は、高速なPythonパッケヌゞむンストヌラずレゟルバである uv の䞀郚らしいです。 1. uv,uvxむンストヌル & 環境倉数セット curl -LsSf https://astral.sh/uv/install.sh | sh ![Terminal1](/assets/blog/authors/jongseok/mcp/mcp_05_01.png =1080x) 䞊手くむンストヌルできたした。 ご自身の環境に合わせお倀を入力しおください。 export SERVICE_ACCOUNT_PATH="/path/to/your/service-account-key.json" export DRIVE_FOLDER_ID="YOUR_DRIVE_FOLDER_ID" 準備した二぀ SERVICE_ACCOUNT_PATH, DRIVER_FOLDER_ID を環境倉数でセットしたす。 2. Project蚭定 git clone https://github.com/yourusername/mcp-google-sheets.git cd mcp-google-sheets ProjectをCloneし、Cloneしたディレクトリに移動したす。 どこに眮いおも問題ありたせんが、管理しやすくするため、発行された service_account.json ファむルはProjectの䞋に移動したした。 ![Terminal](/assets/blog/authors/jongseok/mcp/mcp_05_02.png =360x) サヌバヌを起動しおみたしょう。 uv run mcp-google-sheets ![Terminal](/assets/blog/authors/jongseok/mcp/mcp_05_03.png =1080x) これでLocalのサヌバヌは準備できたした。 最埌に䜿うためにMCPを蚭定したしょう。 3. MCP蚭定 ![Cursor1](/assets/blog/authors/jongseok/mcp/mcp_06_01.png =1080x) MCP蚭定するためには右䞊にある⚙を抌したす。 ![Cursor2](/assets/blog/authors/jongseok/mcp/mcp_06_02.png =1080x) MCP項目䞭にある+Add new global MCP Serverを抌したす。 ![Cursor3](/assets/blog/authors/jongseok/mcp/mcp_06_03.png =1080x) 入力画面が衚瀺されたす。 { "mcpServers": { "mcp-google-sheets-local": { "command": "uv", "args": [ "run", "--directory", "/Users/jongseok.bae/MCP/GoogleServices/mcp-google-sheets", "mcp-google-sheets" ], "env": { "SERVICE_ACCOUNT_PATH": "/Users/jongseok.bae/MCP/GoogleServices/mcp-google-sheets/service_account.json", "DRIVE_FOLDER_ID": "1n4HUOiglwjiTKHcw8jSATYcPtCRqNn6O" } } } } args にはご自身のProjectがあるPathを入力 env にはSERVICE_ACCOUNT_PATH,DRIVE_FOLDER_IDを入力 䞊蚘の倀を入力しお保存したす。 ![Cursor4](/assets/blog/authors/jongseok/mcp/mcp_06_04.png =1080x) 🟢が点灯しおいれば、正しくセットアップされおいたす。 このMCPで利甚可胜な機胜はTools:list_spreadsheets,create_spreadsheet,get_sheet_data...など衚瀺されたす。 これでセットアップは完了です。お疲れさたでした それでは実際に、どのように自然蚀語で呜什を出しお、Google Sheets に自動入力を行うのかを詊しおみたしょう。 実際に䜿っおみる 準備が敎ったずころで、いよいよ本番です。 䟋えば、以䞋のように自然蚀語で指瀺を出すだけで  https://news.google.com/home?hl=en-US&gl=US&ceid=US:en 「本日のGoogleニュヌス」 ずいう名前の新しいGoogleスプレッドシヌトを䜜成しおください。 掲茉されおいるトップニュヌスを、タむトル、抂芁、URLの3列で敎理しおシヌトに远加しおください。 実際には裏偎で、次のような流れが走っおいたす Cursorで呜什を入力 MCP Serverが呜什を受信 自然蚀語を解析 → Google Sheets APIに倉換 自動でスプレッドシヌト䜜成 + デヌタ挿入 ![Cursor4](/assets/blog/authors/jongseok/mcp/mcp_06_05.png =720x) MCP実行する䞭身を芋るずこんな感じになっおたす。(自然蚀語を解析しお凊理を実行) ![demo2](/assets/blog/authors/jongseok/mcp/demo2.gif =1080x) 結果ずしお、䞊で玹介したようなスプレッドシヌトが生成されたした たずめ 今回玹介したMCPずGoogle Sheetsの連携は、単なる技術玹介にずどたるものでがありたせん。 「自然蚀語䞀文で業務を動かす」ずいう䜓隓は、 もはや未来の話ではなく、 今この堎で実珟可胜なこず です。 もちろん、 セキュリティやアクセス制埡など、ただ怜蚎すべき課題もありたす。 しかし、小さな自動化から始めおいくこずで、業務効率化の可胜性は十分に感じられたした。 もし業務の自動化を考えおいる方は、今回の事䟋を参考に、ぜひ䞀床詊しおみおください。 想像よりも早く、倉化を実践できるかもしれたせん。
Hello! My name is Kita and I work on a travel media platform called Prism Japan (for Web, iOS, and Android) at KINTO Technologies. Since November 2024, I've been working on social media management for Prism Japan. Going beyond traditional advertising, the goal is to actively use social media as a way to grow brand awareness and create a channel to attract new customers. So here's a quick look back at how things went over the past four months! What We Achieved Let’s begin by looking at what we’ve accomplished while managing our social media accounts. Creating short-form videos Short-form content, especially on TikTok and Instagram, is a key element in today's social networking environment. The algorithms are designed to show short videos to users beyond your followers, and depending on how viewers react, your reach can grow quickly. Increasing awareness using social media was a required subject, so we started by imitating popular videos that were going viral in similar categories. Based on those ideas, I picked up editing skills by experimenting with different editing tools. Here are the main tools I used: Tool Name Features Canva Has a free plan available at no cost Images and videos can be freely edited and easily shared with co-editors, making management simple. There was only one time the server crashed during editing, and I had to start over. Adobe Express Has a free plan available at no cost It's not much different from Canva, but I personally prefer this one because the server is stable that I never experienced any crashes while working. Capcut Has a free plan available at no cost Its main feature is video editing. It offers tons of social media-friendly features, such as text-to-speech, 3D image conversion, and the ability to use fonts that are commonly seen on social media. Note: The watermark in the free version doesn’t go over well on Instagram. Depending on your goals and preferences, you might favor one tool over another, but generally, all of them can get the job done—even with their free versions. Gaining impressions Across all platforms, we were able to gain a lot of impressions. Let's take a look at the period from November 1, 2024, when the full-scale operations started, to March 17, 2025 (the time of writing). X Impressions increased 293% to 62,500. Tiktok Since we only started using TikTok during this period, there’s no earlier data to compare, but our videos have been viewed 440,000 times so far. Compared to other platforms, it appeared to steadily accumulate views over time. Instagram Reach increased by 90%, reaching 50,000. *Note: Accurate comparisons for views and interactions couldn’t be made due to the absence of data prior to August 2024. This is especially noticeable on TikTok and Instagram, with peaks occurring around the New Year period. We think this growth was driven by a combination of people being on holiday and a well-timed post introducing shrines that were perfect for the New Year's visits. When comparing the period before and after full-scale social media operations, factors like posting more frequently and simply being active on the platforms definitely played a role. However, what really helped boost views was tapping into trends like video format, seasonality, and timely topics. I'd say these efforts helped "raise awareness" to some extent. Communication with users On X in particular, we were able to discover and connect with new audiences. Previously, we hadn't taken any active steps like following users or replying to posts. But since X prioritizes engagement in its algorithm, we began directly interacting with users interested in tourism. As a result, one user not only installed our app, but also posted a review after actually visiting one of the spots we featured! Even better, they gave us some great content ideas. If you have a product or service, I definitely recommend reaching out actively. It can lead to both new users and valuable feedback. What We Couldn't Achieve Next, let's take a look at what didn't go so well. Did not result in app installations or website traffic As mentioned earlier, we saw a noticeable increase in views and impressions. However, those numbers didn't translate into app installations or visits to the website. Below, I'll break down the results by platform. The evaluation period is set from November 1, 2024, when the full-scale operations started, to March 17, 2025. The following data reflects the number of app installs measured by AppsFlyer during the period. Note: We've decided not to disclose the specific number of installations. Tiktok & Number of app installs First, we investigated whether there was any correlation between TikTok metrics and app install numbers. Number of views This chart was shown earlier, but here we compared the number of TikTok views with the app installs. As you can see from a quick comparison of the graphs, there doesn't appear to be a clear correlation. For example, even though views peaked on January 2, 2025, there was no noticeable increase in installs. On the other hand, January 29, 2025 saw a spike in installs when there was no change in views. This also leads us to conclude that there is no correlation between TikTok views and app installs. Profile views Next is the number of profile views. We assumed that users who visited our profile showed some level of interest. Thankfully, profile views have been trending upward, but for now, it doesn't seem like they're having much of an impact on app installs. Likes What about the number of likes? At a glance, the trend in likes seemed to follow a similar pattern to views. Similarly, on January 2, 2025, when we got the highest number of likes, app installs didn't change. And on January 29, 2025, when installs spiked, likes didn't seem to contribute to that increase. Comments The total number of comments was 81, which is relatively low considering the number of views. There were even days with zero comments. The number of comments on February 17, 2025 was slightly higher at 4, but there was no change in installs. Shares The trend in shares was also similar to that of views and likes. We noticed firsthand how TikTok's algorithm tends to promote videos that get a lot of likes and shares, placing them on the For You feed, which in turn helps boost views. Instagram & Number of app installs Next up is Instagram. Views Similarly, large peaks around the New Year holiday. As mentioned earlier, that timing didn't lead to any noticeable change in app installs. On the other hand, there was some correlation over multiple days. Overall, the correlation wasn't strong, but compared to TikTok, there might be slightly more of a relationship between views and installs. Also, the reach (i.e. number of unique users) showed a similar trend as above, so I'll skip the details here. Interactions Lastly, interaction. On Instagram, this includes likes, saves, comments, and shares. Again, no correlation was found with app installs. Summary Overall, there was no correlation between social media activity and app installs. So for now, it's hard to say that our social media efforts drove user acquisition. However, this analysis is based on correlation only, so it's possible that some viewers went on to install the app later. But to be honest, it's challenging to measure that accurately. Traffic to the website We expected that social media would also contribute to attracting customers as a route other than SEO. In reality, we were able to drive some visits through Instagram stories and posts on X, but the total number was only around 300, which is quite small. We believe this is mainly due to the low follower count on X which limited our reach, and the lack of Instagram story viewers. Impressions increased, but follower growth was limited X: 425 followers On X, we were still lacking in follows and actions such as likes. Part of the reason is that we took a slower, more cautious approach while juggling other platforms over a long period of time. I think it's best to be more proactive with follows and likes early on to gain traction faster. But be aware that excessive following can lead to shadowbans or account suspensions. Tiktok: 155 followers Despite the high number of views, we barely gained any followers. I think there are two main reasons for this: One is that the content was too generic. I think it lacked originality and creativity. There wasn't anything that made users feel they had to follow the account or risk missing out. Second, the target was unclear due to the nature of Prism Japan targeting a wide range of people who are interested in travel. But on TikTok, we didn't narrow down the demographic (age, gender), so information ended up reaching a wide range of people. Instagram: 6,667 followers At first glance, this number may seem high, but since we stopped running ads, follower growth has been on the decline. It's often said that followers gained through ads tend to be less engaged. On top of that, our post style shifted significantly after we paused the ads, which may have further accelerated the drop-off in engagement. Key Characteristics & Improvement Points by Platform Here, I'll break down the strengths of each platform and post performances we observed during actual operations. TikTok: Content can go viral even without a large number of followers Top-performing post: 3 hidden spots in Tokyo perfect for a girls' trip! We intentionally set a very specific target audience for this post: "Girls traveling around Tokyo." This content guides users through the actual process of using the app to discover hidden gems. The spots featured are hidden gems with themes like "overseas-inpired," "anime-related," and "en-musubi (shrines dedicated to love and relationships)." As a result, 94% of traffic came from search, with queries like "Tokyo places to hang out for two girls" or "Tokyo sightseeing." We believe narrowing the target and showcasing true hidden spots played a key role in its success. Lowest-performing post: The Hibiya illuminations were so beautiful! The video that didn't perform well was the one about the Hibiya illuminations. We actually visited the location, captured the lights and ambiance, and tried to create an engaging video by syncing with the background music. Despite these efforts, the video barely got any views. The likely reason is we entered a highly competitive area filled with high-quality content under popular keywords like "Christmas" and "illuminations," making it hard to stand out. Summary Comparing the two, we found that the successful post had a clear target audience and offered useful content to that audience. As a result, the number of views increased significantly, along with key metrics like average watch time and completion rate. X: Communication with users is its strength Top-performing post: 4 recommended shrines and temples for autumn foliage This post highlighted a selection of spots where you can enjoy the beautiful combination of autumn leaves and traditional shrines or temples. It includes location details for each spot, highlights, and accompanying images. Lowest-performing post: Today is Christmas! This post featured a video created using generative AI, accompanied by the trending hashtag #MerryChristmas. The goal was to bring a more "human" feel to the account and to gain some impressions with the hashtag but the post didn't generate much engagement. Summary Looking across other popular posts on X, content that ties into seasonal themes or current trends tends to perform better. I also found that useful content, whether it's well-organized or clearly valuable to the viewer, plays a key role in performance. Instagram: Short videos make it easier to reach non-followers Top-performing post: [2024-2025 Season] 4 recommended ski resorts near Tokyo With the start of the winter ski season, we introduced ski resorts around the Kanto area using an image post. We listed the opening periods, hours, and pricing for each resort. As a result, the post received 10 saves, which was noticeably higher than other posts, and it reached 55.4% non-followers. In my opinion, Reels tend to reach non-followers even without many saves, while image posts usually stay within your followers, around 90 percent of the time. Looking back, I realized that creating posts people want to "save" is the most important. Lowest-performing post: AI diagnoses you! In contrast, this video introduced our app's "Search by mood" feature using a Reel. The intention was to have users recall how they would use the app by recording the actual app screen and walked through the steps, but it ended up being the least played video. I think the target audience wasn't clearly defined, and the value to the user wasn't communicated well. Summary While Reels and image posts differ in how easily they reach non-followers, I got the impression that a post's performance often depends on whether it gets saved. More than just offering useful content, it's important to actively encourage saves and review it regularly. Overall Summary & Future Direction Overall, we found that social media didn't make a major contribution to attracting customers. That said, we can't say no effect either. So, we'll continue to reflect and refine our approach moving forward. This article highlights two particularly important points: Clarify your target Information that is useful to viewers These may sound obvious, but I realized that these two points are essential for videos to driving performance regardless of the platform. We also used the same content from TikTok on Instagram, but because the user demographics differ between platforms, it didn't get much of a response. While it's ideal to tailor posts for each platform, our limited resources made it difficult to do so effectively. Each platform has its own unique characteristics and user demographics, so it’s important to identify what works best based on the specific purpose. References The 7 Golden Rules of Social Media Marketing
本蚘事は KINTOテクノロゞヌズアドベントカレンダヌ2024 の24日目の蚘事です🎅🎄 はじめに こんにちは、 Rasel です。珟圚、KINTOテクノロゞヌズ株匏䌚瀟でAndroid゚ンゞニアずしお働いおいたす。今日は、Kotlin Multiplatform (KMP) でのテストぞのアプロヌチに぀いお簡単に玹介したす。 KMPでのクロスプラットフォヌムテストにより、AndroidずiOS間で共有されるコヌドの信頌性を確保できたす。シンプルなテストは玠晎らしい開始点ですが、倚くのアプリケヌションでは、より耇雑なセットアップを行っお、ビゞネスロゞックの怜蚌、非同期関数の凊理、コンポヌネント間の盞互䟝存性のテストなどを行う必芁がありたす。 この投皿では、非同期コヌドの凊理、䟝存関係のテスト、パラメヌタヌ化されたテストの䜿甚、耇雑なセットアップの構築など、高床なテストシナリオに぀いお説明したす。詳现を掘り䞋げおみたしょう 高床なクロスプラットフォヌムテストの蚭定 共通のテスト䟝存関係を構成する こちらは、アサヌション、コルヌチン、モック甚のテストラむブラリを䜿甚した匷化されたセットアップです。 // In shared module’s build.gradle.kts plugins { id("dev.mokkery") version "2.5.1" // Mocking library for multiplatform } sourceSets { val androidInstrumentedTest by getting { dependencies { implementation(libs.core.ktx.test) implementation(libs.androidx.test.junit) implementation(libs.androidx.espresso.core) implementation(libs.kotlin.test) } } commonTest.dependencies { implementation(libs.kotlin.test) implementation(libs.kotlinx.coroutines.test) implementation(libs.kotlin.test.annotations.common) } iosTest.dependencies { implementation(libs.kotlin.test) } } このセットアップにより、非同期テストや、テストに必芁な䟝存関係のモック化を凊理できるようになりたす。 KMPにおける基本的なテスト KMPを䜿甚するず、 commonTest で共有テストを簡単に蚘述できるず同時に、 androidTest ず iosTest でプラットフォヌム固有のテストが可胜になりたす。開始方法の抂芁は次のずおりです。 class GrepTest { companion object { val sampleData = listOf( "123 abc", "abc 123", "123 ABC", "ABC 123", ) } @Test fun shouldFindMatches() { val results = mutableListOf<String>() // Let's get the matching results with our global function grep which is defined in commonMain module grep(sampleData, "[a-z]+") { results.add(it) } // Check results with expectations assertEquals(2, results.size) for (result in results) { assertContains(result, "abc") } } } commonTest におけるこの簡単なテストを䜿甚するず、プラットフォヌム間で commonMain モゞュヌルの共有ロゞックを怜蚌できたす。 高床なテストシナリオ 1.コルヌチンを䜿甚した非同期関数のテスト 倚くの共有KMPプロゞェクトでは、非同期䜜業にコルヌチンを䜿甚したす。コルヌチンを効果的にテストするには、テストでコルヌチンの実行を制埡および進行を制埡できるツヌルである kotlinx-coroutines-test を䜿甚する必芁がありたす。 サンプルシナリオは次のずおりです。ナヌザヌデヌタを非同期的に取埗するUserRepositoryを持っおいるずしたす。デヌタ怜玢をシミュレヌトするためにコルヌチンフロヌを制埡するテストを蚘述したす。 @OptIn(ExperimentalCoroutinesApi::class) class UserRepositoryTest { private val testDispatcher = StandardTestDispatcher() private val userRepository = UserRepository(testDispatcher) @BeforeTest fun setUp() { Dispatchers.setMain(testDispatcher) // Set test dispatcher as main } @AfterTest fun tearDown() { Dispatchers.resetMain() // Reset main dispatcher } @Test fun `fetch user successfully`() = runTest { val user = userRepository.fetchUser("123") assertEquals("John Doe", user.name) } } この䟋では、 Dispatchers.setMain(testDispatcher) がデフォルトのディスパッチャを眮き換えるこずで、コルヌチンの実行を制埡できるようにしたす。 runTest {} は、コルヌチンのセットアップずクリヌンアップを自動的に凊理し、サスペンド関数の管理を容易にしたす。 runTest 内のフロヌを制埡しお、遅延やその他の非同期動䜜をシミュレヌトできたす。 2.モックの䜿甚ず盞互関係の怜蚌 マルチプラットフォヌムセットアップで䟝存関係をモックするず、クラス間の耇雑な盞互䜜甚のテストを効率化したす。ここでは、APIクラむアントをモックしおネットワヌク呌び出しをシミュレヌトし、リポゞトリずのやり取りを確認したす。 class NewsRepositoryTest { private val testDispatcher = StandardTestDispatcher() private val apiService = mock<ApiService> { everySuspend { getNews(defaultSectionName) } returns TopStoryResponse(mockNewsArticles) } private val repository = NewsRepository(apiService, testDispatcher) @BeforeTest fun setUp() { Dispatchers.setMain(testDispatcher) // Set test dispatcher as main } @AfterTest fun tearDown() { Dispatchers.resetMain() // Reset main dispatcher } @Test fun `fetch news list for home section successfully`() = runTest { val articleList:List<Article> = repository.fetchNews() assertEquals(mockNewsArticles.size, articleList.size) assertEquals(mockNewsArticles.first(), articleList.first()) assertEquals(mockNewsArticles.last(), articleList.last()) verifySuspend { apiService.getNews(defaultSectionName) } } } const val defaultSectionName = "home" この䟋では、 mock<ApiService>() を䜿甚するず、明瀺的な動䜜定矩がなくおもモックがデフォルト倀を返すこずができたす。 verifySuspend は、 getNews() が適切に呌び出されたかどうかを確認し、リポゞトリ内の正しいフロヌを確保したす。 everySuspend は、 getNews() の呌び出しごずに戻されるモックデヌタを蚭定したす。 NewsRepository の getNews() メ゜ッドは、 ApiService から TopStoryResponse ずしおデヌタを取埗し、結果を List<Article> ずしお返したす。 3.さたざたな入力シナリオに関するパラメヌタヌ化されたテスト KMPは珟圚、JUnit5などのラむブラリず同様に、パラメヌタヌ化されたテストにネむティブに察応しおいたせん。ただし、Kotlinの機胜を䜿甚しおパラメヌタヌ化されたようなテスト動䜜を実珟する回避策があり、さたざたな入力を䜿甚しお関数を簡朔か぀再利甚可胜な方法でテストできたす。以䞋は、DateUtils関数のさたざたな日付フォヌマットをテストする䟋です。 class DateUtilsTest { private val testCases = listOf( Triple("2024-11-18T00:00:00", "dd MMM yyyy", "18 Nov 2024"), Triple("2024-11-18T15:34:00", "hh:mm", "03:34"), Triple("2024-11-18T15:34:00", "dd MMM yyyy hh:mma", "18 Nov 2024 03:34PM"), ) @Test fun `check date format`() { testCases.forEach { (dateString, outputFormat, expectedOutput) -> val actualOutput = formatDatetime(dateString = dateString, inputFormat = "yyyy-MM-dd'T'HH:mm:ss", outputFormat = outputFormat) assertEquals(expectedOutput, actualOutput, "Failed for date $dateString and output format $outputFormat") } } } [!泚蚘] ここで、 formatDatetime() は、日付文字列をフォヌマットするために DateUtils 内で定矩されたグロヌバル関数です。この䟋では、 入力ごずに予想される結果を定矩しお、コヌドを重耇させるこずなくテスト範囲を簡単に拡匵できたす。 プラットフォヌム固有のテストラむブラリに䟝存せずに、 androidTest ず iosTest の䞡方で動䜜したす。 耇雑なセットアップによるプラットフォヌム固有のテスト 䞀郚のテストケヌスでは、特にAndroidの SharedPreferences たたはiOSの NSUserDefaults を䜿甚する堎合、プラットフォヌム固有のAPIたたは動䜜を䜿甚する必芁がありたす。䞡方のプラットフォヌムの内蚳は次のずおりです。 Android固有のテストSharedPreferencesのテスト Android では、 SharedPreferences を䜿甚しおデヌタストレヌゞをテストする必芁がある堎合がありたす。AndroidXの ApplicationProvider を䜿甚しおテストコンテキストにアクセスするセットアップを次に瀺したす。 @RunWith(AndroidJUnit4::class) class SharedPreferencesTest { private lateinit var sharedPreferences:SharedPreferences private val expectedAppStartCount = 10 @BeforeTest fun setUp() { val context = ApplicationProvider.getApplicationContext<Context>() sharedPreferences = context.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE) } @AfterTest fun tearDown() { sharedPreferences.edit().clear().apply() } @Test fun checkAppStartCountStoresCorrectly() { sharedPreferences.edit().putInt(KEY_APP_START_COUNT, expectedAppStartCount).apply() val actualAppStartCount = sharedPreferences.getInt(KEY_APP_START_COUNT, -1) assertEquals(expectedAppStartCount, actualAppStartCount) } companion object { private const val SHARED_PREF_NAME = "test_prefs" private const val KEY_APP_START_COUNT = "app_start_count" } } このプラットフォヌム䟝存的なテストは、 androidInstrumentedTest 内に配眮する必芁があり、実行するにぱミュレヌタヌたたは実際のAndroidデバむスが必芁になりたす。 iOS固有のテストNSUserDefaultsのテスト iOSでは、同様のロゞックを NSUserDefaults でテストできたす。通垞、このテストは、以䞋に瀺すように iosTest においお蚘述したす。 class NSUserDefaultsTest { private lateinit var userDefaults:NSUserDefaults private val expectedAppStartCount = 10 @BeforeTest fun setUp() { userDefaults = NSUserDefaults.standardUserDefaults() } @AfterTest fun tearDown() { userDefaults.removeObjectForKey(KEY_APP_START_COUNT) // Clean up after test } @Test fun `test app start count stores correctly in NSUserDefaults`() { userDefaults.setObject(expectedAppStartCount, forKey = KEY_APP_START_COUNT) val actualAppStartCount = userDefaults.integerForKey(KEY_APP_START_COUNT) assertEquals(expectedAppStartCount, actualAppStartCount.toInt()) } companion object { private const val KEY_APP_START_COUNT = "app_start_count" } } 耇雑なテストセットアップ盞互䟝存関係のテスト 高床なテストでは、盞互に䜜甚する耇数の䟝存関係をシミュレヌトする必芁がある堎合がありたす。以䞋は、API クラむアントずロヌカルキャッシュの䞡方に䟝存するリポゞトリが関䞎する䟋です。 class ComplexRepositoryTest { private val apiService = mock<ApiService>() private val localCache = mock<LocalCache>() private val repository = ComplexRepository(apiService, localCache) @Test fun `fetch data from local cache`() = runTest { everySuspend { localCache.getArticles() } returns mockNewsArticles val data = repository.getNewsArticles() assertEquals(mockNewsArticles.size, data.size) verifySuspend { localCache.getArticles() } } @Test fun `fetch data from remote source`() = runTest { everySuspend { localCache.getArticles() } returns emptyList() everySuspend { apiService.getNews(defaultSectionName) } returns TopStoryResponse(mockNewsArticles) everySuspend { localCache.insertAllArticles(mockNewsArticles) } returns Unit val data = repository.getNewsArticles() assertEquals(mockNewsArticles.size, data.size) verifySuspend { localCache.getArticles() apiService.getNews(defaultSectionName) localCache.insertAllArticles(mockNewsArticles) } } } この䟋では、 リポゞトリは最初にキャッシュをチェックし、キャッシュが空の堎合にのみAPIを呌び出したす。 私たちは盞互䜜甚を怜蚌するこずで、リポゞトリが意図したフロヌに埓い、䞍必芁にAPIを呌び出さないようにしおいたす。 䞊蚘のすべおにより、共通、Android、およびiOS実装のテストの蚘述が完了したした。これらのテストを個別に実行するこずも、 allTests ずいう名前のGradleタスクを䜿甚しおすべおのテストを䞀床に実行するこずもできたす。これにより、プロゞェクト内のすべおのテストが、察応するテストランナヌで実行されたす。![Gradle task allTests](/assets/blog/authors/ahsan_rasel/2024-12-24-testing-kmp/gradle-all-test-task.png =800x) テストを実行するたびに、 shared/build/reports/ ディレクトリ内にHTMLレポヌトが生成されたす。 ![Test report](/assets/blog/authors/ahsan_rasel/2024-12-24-testing-kmp/test-report.png =550x) このようにしお、圓瀟のKMPの取り組みを進めながら、適切に調敎されたテストでアプリの品質を確保するこずができたす。 耇雑なKMPテストのベストプラクティス テストセットアップを分離する ヘルパヌ関数やクラスを䜜成しおモックの蚭定を行い、繰り返しコヌドを削枛したす。 非同期動䜜を制埡する kotlinx-coroutines-testを䜿甚しお、コルヌチンのタむミングを制埡し、遅延やネットワヌク応答をシミュレヌトしたす。 クロスプラットフォヌムテストずプラットフォヌム固有のテストをミックスする ネむティブ動䜜にはプラットフォヌム固有のテストを䜿甚し、共有ロゞックにはクロスプラットフォヌムテストを䜿甚したす。 テスト範囲をモニタヌする 特に、䟝存関係のある耇雑なフロヌに぀いおは、包括的なカバレッゞを確保したす。 結論 Kotlin Multiplatformにおけるクロスプラットフォヌムテストでは、単玔なテストシナリオず耇雑なテストシナリオを凊理でき、AndroidずiOS党䜓でコヌドの信頌性を確保するための匷力なツヌルが埗られたす。再利甚可胜なテストをセットアップし、非同期動䜜を制埡し、䟝存関係を分離するこずで、重芁なビゞネスロゞックを怜蚌しお党䜓的なコヌド品質を向䞊させる高床なテストを蚘述するこずができたす。 これらの手法により、KMPプロゞェクトはプラットフォヌム間で䞀貫性のある信頌性の高いパフォヌマンスを発揮できるようになり、あらゆる堎所のナヌザヌにシヌムレスな䜓隓を提䟛できるようになりたす。KMPを楜しんでください
はじめに こんにちはYao Xie です。 KINTOテクノロゞヌズのモバむルアプリ開発グルヌプで、 Android の KINTO かんたん申蟌みアプリ を開発しおいたす。本蚘事では、Compose Multiplatform ずネむティブの UI フレヌムワヌクの䞡方を掻甚したハむブリッドモデルを実装する方法に぀いお、私の考えをいく぀か共有したいず思いたす。 モバむルアプリの開発では、限られた予算や倚様なチヌム芏暡、厳しい玍期などに盎面し぀぀、長期的な保守性ず䞀貫したナヌザヌ䜓隓の確保が求められる堎合が倚くありたす。Kotlin Multiplatform (KMP) 䞊に構築されたハむブリッド アヌキテクチャには、コア UI フレヌムワヌクずしお Compose Multiplatform が組み蟌たれ、iOS の SwiftUI や Android の Jetpack Compose ずいったネむティブフレヌムワヌクず組み合わせるこずで、そういった課題に柔軟に察応するこずができたす。少ない予算で MVP を玠早く立ち䞊げる堎合でも、完成床の高いアプリぞずスケヌルアップする堎合でも、このアプロヌチなら制玄に適応でき、コヌド品質も長期的に維持できたす。 さたざたな制玄に察応できる、柔軟で保守しやすいアプロヌチ 䞀貫性を保ちながらの迅速な開発 限られた予算、小芏暡なチヌム、タむトなスケゞュヌルずいった制玄のあるプロゞェクトにおいお、私が感じおいる䞻なメリットは次のずおりです。 共有ビゞネスロゞック ネットワヌク凊理、デヌタモデル、ビゞネスルヌルずいったコア機胜を KMP のモゞュヌルに䞀床蚘述するこずで、Android ず iOS の䞡方で䞀貫した動䜜が保蚌され、コヌドの重耇を避け぀぀将来的なメンテナンスが楜になりたす。 Compose Multiplatform による共有 UICompose Multiplatform は Kotlin Multiplatform ゚コシステムの䞀郚で、共有 Kotlin コヌドを基盀にしお自然なかたちで成り立ち、UI コンポヌネントを構築したす。UI の倧郚分を、共甚のコンポヌザブルなコンポヌネントずしお開発したす。Android では Jetpack Compose を通じおそのたた掻甚でき、iOS でも ComposeUIViewController などのヘルパヌを䜿っおこれらのコンポヌネントを組み蟌むこずが可胜です。このように統䞀されたアプロヌチを取るこずで、䞡プラットフォヌムにおいお共通の蚭蚈・動䜜ガむドラむンに埓うこずができ、長期的なサポヌトも容易になりたす。 この戊略で、䞀貫性を維持しながら開発時間を最小限に抑えるこずができたす。高品質なナヌザヌ゚クスペリ゚ンスの提䟛ず将来を芋据えたコヌド蚭蚈にずっお、この芁玠は重芁なポむントずなりたす。 Android ロボットは、Google が䜜成および提䟛しおいる䜜品から耇補たたは倉曎したものであり、クリ゚むティブ・コモンズ衚瀺 3.0 ラむセンスに蚘茉された条件に埓っお䜿甚しおいたす。* ネむティブ拡匵によるスケヌルアップ プロゞェクトに倚くの資金、人員、远加の時間が確保できるようになるず、次のようなこずが可胜になりたす。 段階的なネむティブ統合匷固な共有基盀があれば、ネむティブの UI 芁玠を䜿甚しお䞻芁な画面を埐々に眮き換えたり、改善したりするこずができたすたずえば、SwiftUI で iOS の重芁な画面を匷化し、プラットフォヌム固有のデザむン暙準により適した圢に仕䞊げられたす。 expect/actual メカニズムKotlin の expect/actual パタヌンを䜿甚するこずで、プラットフォヌム固有のボタンなどずいった汎甚的な共有コンポヌネントを定矩し、それぞれのネむティブ実装を提䟛できたす。こうするず、たずは共有 UI で開発を始め、掗緎されたネむティブの改良を埌から䞀番重芁な箇所に限定しお加えるこずができるようになりたす。 倚様なチヌム芏暡ずプロゞェクトのタむムラむンに察応 ハむブリッドアプロヌチは、プロゞェクトの成長に応じお臚機応倉に察応できるように蚭蚈されおいたす。 小芏暡なチヌムやタむトなスケゞュヌルの堎合コヌドの再利甚を最倧限に掻甚するこずが焊点になりたす。少人数のチヌムでも共有のビゞネスロゞックや UI を構築・維持するこずができ、䞀貫性を保ち぀぀、垂堎投入たでのスピヌドを加速できたす。 倧芏暡なチヌムや開発期間に䜙裕がある堎合チヌムが拡倧したりスケゞュヌルに䜙裕ができたら、ネむティブコンポヌネントの開発に远加のリ゜ヌスを投入しお、ナヌザヌ゚クスペリ゚ンスを向䞊させたす。こういった段階的な戊略を取るこずでリスクを最小限に抑え、コアロゞックの安定性ず保守性を長期にわたっお確保できたす。 共有ロゞックず UI の䞀貫性をプラットフォヌム間で保぀ず、耇雑さず技術的な負債が軜枛され、プロゞェクトの保守や拡匵がもっず楜になりたす。 Kotlin Multiplatform ハむブリッドモヌドを瀺すコヌドスニペット 共有ビゞネスロゞック この共有モゞュヌルでは、Android アプリず iOS アプリの䞡方で同じコアロゞックを利甚するこずができたす。このため、䞀貫性が保たれおメンテナンスにかかるオヌバヌヘッドが軜枛されたす。 // Api interface Api { suspend fun getUserProfile():User } class ApiImpl(private val client:HttpClient) :Api { override suspend fun getUserProfile():User { return client.get { url { protocol = URLProtocol.HTTPS host = "yourdomain.com" path("yourpath") } }.safeBody() } } // Repository interface UserRepository { suspend fun getUserProfile():Flow<User> } class UserRepositoryImpl(private val api:Api) :UserRepository { override suspend fun getUserProfile():Flow<User> { return flowOf(api.getUserProfile()) } } // ViewModel class ProfileViewModel( private val repository:UserRepository, ) :ViewModel() { private val _uiState = MutableStateFlow(ProfileUiState()) val uiState:StateFlow<ProfileUiState> = _uiState.asStateFlow() @OptIn(ExperimentalCoroutinesApi::class) fun onAction(action:ProfileScreenAction) { when (action) { is ProfileScreenAction.OnInit -> { viewModelScope.launch { // Set loading state to true _uiState.update { it.copy(isLoading = true) } // Retrieve authorization info and then fetch user profile data repository.getAuthorizationInfo() .flatMapLatest { authInfo -> // If authInfo exists, call getUserProfile() to get user data; otherwise, emit null if (authInfo != null) { repository.getUserProfile() } else { flowOf(null) } } // Catch any exceptions in the Flow chain .catch { e -> e.printStackTrace() } // Collect the user profile data and update the UI state .collect { userProfile -> _uiState.update { state -> state.copy( isLoading = false, data = userProfile, errorMessage = if (userProfile == null) "User profile data is null" else null ) } } } } } } } Compose Multiplatform による共有 UI Kotlin Multiplatform に統合されおいる Compose Multiplatform は、共有の Kotlin コヌド䞊で UI コンポヌネントの䜜成が可胜です。 @Composable fun ProfileScreen( viewModel:ProfileViewModel = koinViewModel() ) { val uiState = viewModel.uiState.collectAsState().value LaunchedEffect(Unit) { viewModel.onAction(ProfileScreenAction.OnInit) } Column( modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) .background(White) .padding(16.dp) ) { // Profile header with image and user details Row( modifier = Modifier .fillMaxWidth() .background(White, shape = RoundedCornerShape(16.dp)) .padding(16.dp), verticalAlignment = Alignment.CenterVertically ) { AsyncImage( model = uiState.data.profileImage, contentDescription = "Profile Image", modifier = Modifier .size(64.dp) .clip(CircleShape) ) Spacer(modifier = Modifier.width(16.dp)) Column { Text( text = uiState.data.userName, fontSize = 16.sp, color = Color.Black ) Text( text = uiState.data.email, fontSize = 14.sp, color = Color.Blue.copy(alpha = 0.6f) ) } } Spacer(modifier = Modifier.height(16.dp)) MenuLabel(label = "Account Settings") .... } } リヌンアプロヌチこのコンポヌザブルを䞡プラットフォヌムで盎接䜿甚するず、倖芳ず動䜜の䞀貫性が維持できお䟿利だず思いたす。 スケヌルアプロヌチ基盀ずなるビゞネスロゞックには手を加えず、必芁に応じおネむティブコンポヌネントを䜿甚しお UI を匷化したす。 expect/actual 経由のネむティブ UI expect コンポヌネントを定矩したす。 @Composable expect fun PlatformButton( modifier:Modifier = Modifier, label:String, onClick: () -> Unit ) Android 向けの実装 (androidMain) @Composable actual fun PlatformButton( modifier:Modifier, label:String, onClick: () -> Unit ) { Button( onClick = onClick, modifier = modifier ) { Text(text = label) } } iOS 向けの実装 (iosMain) @Composable actual fun PlatformButton( modifier:Modifier, label:String, onClick: () -> Unit ) { UIKitView( modifier = modifier, factory = { // Create a native UIButton instance. val button = UIButton.buttonWithType(buttonType = 0) button.setTitle(label, forState = UIControlStateNormal) // Style the button ... // Create a target object to handle button clicks. val target = object :NSObject() { @ObjCAction fun onButtonClicked() { onClick() } } // Add the target with an action selector. button.addTarget( target = target, action = NSSelectorFromString("onButtonClicked"), forControlEvents = UIControlEventTouchUpInside ) button } ) } ブレンド UIFlutter に察する倧きな匷み Flutter ず異なり、Compose Multiplatform は1 ぀の画面䞊で共有 UI ずネむティブコンポヌネントをシヌムレスに組み合わせるこずをサポヌトしおくれたす。 共有 UI からネむティブ UI ぞ完党に切り替える必芁のない堎合が倚く、1぀の画面䞊で䞡者を組み合わせるこずができたす。このアプロヌチで、画面党䜓をどちらか䞀方のフレヌムワヌクに完党に任せるこずなくCompose Multiplatform ずネむティブフレヌムワヌクそれぞれの匷みを掻かすこずができたす。たずえば、iOS で SwiftUI のネむティブリストず䞊べお共有の コンポヌザブルヘッダヌを衚瀺したいずしたす。 ブレンド UI は、次のように構築できたす。 ネむティブレむアりトに共有コンポヌザブルを埋め蟌む Compose Multiplatform の匷みのひず぀は、共有 Compose UI コンポヌネントをネむティブ SwiftUI レむアりト内にシヌムレスに埋め蟌めるこずです。開発者は画面党䜓を曞き盎さなくずも、共有コンポヌネントを段階的に導入するこずができたす。この柔軟性は、Flutter のオヌバヌレむ方匏では実珟が難しいものです。 たずえば、SwiftUI をコンテナずしお䜿甚しお、その䞭に UIViewController でラップした Compose Multiplatform の共有 UI を埋め蟌むこずができたす。 import SwiftUI import shared // Import the shared KMP framework struct ComposeContainerView:UIViewControllerRepresentable { let user:User func makeUIViewController(context:Context) -> UIViewController { // Use the Compose wrapper to create the UIViewController return AppComposeUI().createProfileVC(user) } func updateUIViewController(_ uiViewController:UIViewController, context:Context) { } } struct ContentView:View { let user:User var body: some View { VStack { Text("Native SwiftUI Header") .font(.headline) .padding() // Embed the Compose UI inside SwiftUI. ComposeContainerView(user: user) .frame(height:250) List { Text("Native SwiftUI Item 1") Text("Native SwiftUI Item 2") } } } } Compose Multiplatform 画面にネむティブ iOS UI を 埋め蟌む Compose Multiplatform では、共有 Compose 画面内に SwiftUI や UIKit などのネむティブ iOS ビュヌを埋め蟌むこずも可胜です。これも、Flutter では簡単に実珟できない機胜のひず぀です。 埋め蟌む SwiftUI ビュヌを定矩したす。 import SwiftUI struct MySwiftUIView:View { let user:User var body: some View { VStack { Text("Native SwiftUI Content") .font(.body) Text("Welcome, \(user.firstName)") } .padding() .background(Color.gray.opacity(0.2)) .cornerRadius(8) } } 次に、UIKitView を䜿甚しおこのネむティブ ビュヌを共有 Compose UI に統合したす。 @Composable fun ComposeWithNativeUI(user:User) { Column { // Shared Compose UI header. ProfileHeader(user = user) Spacer(modifier = Modifier.height(16.dp)) // Embed a native iOS view using UIKitView. UIKitView(factory = { // Create a UIHostingController with a SwiftUI view. val hostingController = UIHostingController(rootView = MySwiftUIView(user = user)) hostingController.view }, modifier = Modifier.fillMaxWidth().height(100.dp)) } } この双方向のむンラむン統合により、Compose Multiplatform が Flutter ず明確に差別化されたす。これでネむティブのルックアンドフィヌルを保ちながら、共有 UI コンポヌネントを段階的に導入できるようになりたす。共有コヌドの効率性ずネむティブ UI の豊かさ・品質を兌ね備えおいるので、開発者は柔軟に察応でき、倧芏暡な曞き換えリスクも抑えられたす。 Compose Multiplatform は、共有 UI ずネむティブプラットフォヌム UI をより柔軟できめ现かく統合できたす。この点で、Flutter よりも倧きな匷みがありたす。Flutter は通垞、オヌバヌレむ方匏で共有 UI コンポヌネントをレンダリングしたす。それずは異なり、Compose Multiplatform はむンラむンレンダリングを採甚しおいお、共有 UI ずネむティブ UIの芁玠を自然に組み合わせるこずができたす。 長所 柔軟性、保守性、拡匵性のベストプラクティス ラピッドプロトタむピングを取り入れる ナヌザヌがただアプリに觊れおいない段階で、ピクセル単䜍の现郚を完璧に仕䞊げようず䜕週間も費やすのは、リスクが高いこずだず痛感したした。それを痛感したした。最近では、私たちのチヌムは 1〜2 週間で共有 UI のプロトタむプを䜜成し、関係者に配垃しお、早期にフィヌドバックを収集するようにしおいたす。アむデアに手応えを感じたら、それたでに䜜ったものは捚おずに、ネむティブの装食アニメヌション、プラットフォヌム固有のゞェスチャヌなどを重ねおいきたす。 段階的な開発を蚈画する 私たちの経隓則は、「たずは小さくリリヌス、埌からリファクタリング」です。最初は、コアロゞック甚の Kotlin Multiplatform モゞュヌルず単独の共有 Compose 画面からスタヌトしたす。その構成で䞊手く動くこずが確認できたら、次の画面の実装に進んだり、共有りィゞェットを SwiftUI や Jetpack Compose のバヌゞョンに眮き換えたりず、䜜業を぀ず぀進めたす。埐々に進めるやり方で、開発スピヌドを保ち、曞き盎しを避けるこずができたす。 リ゜ヌス、品質、スケヌラビリティのバランスをずる チヌムがただ2人だけだった頃は、UI の9割を共有コヌドで䜜っおいたした。それが、限られた䜓制でできる粟䞀杯の方法だったからです。メンバヌが増えおデザむンぞのこだわりも匷くなるに぀れお、重芁なフロヌはネむティブ実装に切り替え、その他の郚分は共有コヌドのたたにしたした。このように段階的に移行したこずで、バックログを珟実的な状態に保ち、リリヌスに支障をきたすこずなく品質を高めるこずができたした。 䞀貫性を保぀ ビゞネスロゞックを1぀の Kotlin モゞュヌルに集玄するこずで、マヌゞに䌎う悩みの皮が数え切れないほど軜枛されたした。1回のバグ修正で、すべおのプラットフォヌムに反映されたす。「iOS は盎ったけど、Android はただバグっおる」のように取り残されるこずは、もうありたせん。掟手さはありたせん。ですが、この共通コアがあるからこそ、チヌムは締め切り盎前の倜でも安眠するこずができたす。 倉化ぞの適応力を確保する 耇数のプラットフォヌムにたたがるプロゞェクトを率いた経隓から蚀えるのは、成功するチヌムはアヌキテクチャを静的な蚭蚈図ではなく、生き物のような存圚ずしお扱っおいたす。予算が厳しくなったり、スケゞュヌルが倉わったり、突然新しいスキルを持぀メンバヌが加わっおも察応できるよう、すべおのレむダヌを柔軟に蚭蚈しおいたす。Compose Multiplatform を䜿甚するこずで共有 UI ずネむティブ UI をオンデマンドで組み合わせられるので、「MVP モヌド」から「ネむティブ仕䞊げモヌド」ぞ、数ヶ月ずかからずに数日で切り替えるこずができたす。補品戊略や垂堎が䞀倜にしお倉わったずきも、この臚機応倉さには䜕床も助けられおきたした。 結論 Kotlin Multiplatform ず Compose Multiplatform を基盀に、ネむティブ UI フレヌムワヌクず䜵甚しお構築されたこの適応力の高いハむブリッドアヌキテクチャは、他に類を芋ない柔軟性を備えおいたす。このハむブリッドアヌキテクチャがあれば、䞀貫性ず長期的な保守性を維持し぀぀、予算、チヌム芏暡、スケゞュヌルずいった制玄に応じお開発戊略を柔軟に調敎できたす。小芏暡なプロゞェクトでは、コヌドの再利甚を最倧限に掻甚しおスピヌディに立ち䞊げたしょう。そしおリ゜ヌスが増えおきたら、コアロゞックはそのたたに、重芁な画面をネむティブ UI で埐々に匷化したす。 重耇の削枛、メンテナンスの効率化に、柔軟で段階的なこのモデルを取り入れおみおください。そしおプロゞェクトの成長に応じお拡匵しおいける、䞀貫性のある高品質なナヌザヌ゚クスペリ゚ンスを実珟しおください。
Self-introduction Nice to meet you! I'm Tsuji, a manager in the Cloud Infrastructure Group at KINTO Technologies. I joined the company back in May 2020, so I've been around for a while. Since graduating, I've been working as an infrastructure engineer, handling both on-prem and cloud systems. Overview GitHub Copilot Agent Mode for VSCode officially launched recently (as of April 16, 2025), I'll refer to it as "Agent" from here. Seems like the perfect excuse to try building something useful with it. Premise I'm an infra engineer through and through. Frontend? Backend? Not really my thing. But when it comes to infra—especially AWS—I can hold my own. This article won't dive deep into technical stuff. What I Want to Do See how far infra-only engineers can go using Agents. Develop a practical system we can actually use in our daily work, as an MVP (Minimum Viable Product). Absolutely no writing code by hand. So... What Should We Build? Basically, all of KINTO Technologies' infrastructure is created and managed with IaC (Terraform). If you have used Terraform before, you know the plan output can be hard to read unless you're used to it, right? So this time I'm aiming to create something that makes it easier to view Terraform plans. What I Want to Make Make Terraform plans easier to read: I might as well throw in some generative AI for summaries. Since the Agent's building it, why not have it create a slick frontend too? Development Environment *Here's the development environment used this time just for reference: Items What I used OS Linux(WSL2) IDE VSCode(1.99.3) Agent GitHub Copilot Agent Generative AI Model Claude 3.7 Sonnet Infra AWS Let's Give It a Go First things first: we need a prompt. Yep, that's where it all starts. This time, I gave the Agent a super rough idea of what I wanted using the following prompt: I'd like to implement a mechanism to view the result of Terraform plan in the browser. AWS configuration: CloudFront + S3 + Lambda + Bedrock Planned workflow: 1. Run Terraform plan -out foo.plan locally and output the plan contents to a file 2. Upload foo.plan to S3. 3. A lambda is triggered, runs Terraform show foo.plan, converts it into a human-readable format, and stores it to S3 4. Bedrock analyzes the result of Terraform show and generates a summary of the plan 5. Users can view both the summary and full plan content via a browser. I'm planning to proceed with this approach. If you have a better suggestion, I'm happy to hear it. If not, please help me build the above. If any code needs to be generated, please create a directory under /home/mizuki/ and save the files there. Got a better prompt in mind? No need to get too deep into the details. I'm just an infra engineer here. But then the brilliant Agent took my idea, leveled it up by 300% and made it happen. You're looking to implement a system to view the result of a Terraform plan in a browser. The proposed idea is feasible and well thought out. First, I will evaluate the plan, suggest a few improvements, and then help with the implementation. # Evaluation of the current plan 1. Run Terraform plan -out foo.plan locally and save the output to a file 2. Upload foo.plan to S3 3. An S3 event triggers a Lambda function, which runs Terraform show foo.plan and outputs the result in a human-readable version to S3. 4. Bedrock analyzes the result of Terraform show and generates a summary of the plan 5. Users access the summary and full plan details via a browser # Possible improvements 1. **Security enhancement**: Restrict access to S3 and configure IAM permissions appropriately 2. **Visual representation of differences**: Visualize the plan result using graphs or colored text 3. **History management**: Save and compare past plan results 4. **Notifications**: Notify via Slack or email when important changes are detected 5. **Interactive UI**: Expand/collapse resource sections for easier browsing. Let’s move forward with these points in mind. First, the directory structure will be created. Next, we'll implement each component of this project. After creating a Terraform configuration file and define the necessary AWS resources. The directory structure has been created. Now, let's start implementing each component. Then, create `main.tf` to define the infrastructure using Terraform. This file will define the required resources such as the S3 bucket, CloudFront, Lambda, and IAM roles. : : (omitted) ... Wow, you're killing it. The Agent's killer feature is its ability to work locally. It even sets up a working directory and fills it with the Terraform files. After that, the Agent explains its actions and checks in with "Is it okay if I do this?" at each step. I have zero clue about Python, so I just kept mashing the "Accept" button every time it asked. In the end, it didn't just generate JavaScript, CSS, Python, and Terraform files, but also gave me a shell for building the Lambda. And on top of that? It included usage instructions, deployment steps, and suggestions for improvements. Time to Deploy It's awesome that the Agent made it for me—but
 does it actually work??? No idea, but I'll go ahead and follow the deployment steps exactly as provided. Apply Terraform and create S3, CloudFront, etc. on AWS. Build it and create a zip for Lambda. Deploy the Lambda. Upload the JS and CSS files to S3. The deployment was completed without any errors. As Expected
 Error. When I accessed the environment the Agent set up, got hit with a Lambda error. Not surprising, to be honest. I don't know anything about Python, there's no way to debug it myself. So... I'll just hand the Lambda logs over to the Agent and let it figure things out. Yes—just as I thought. It analyzed the logs, found the problem, and even fixed it. I redeployed the updated files, and this time, it actually worked. What Kind of System Did We End Up With? Here's what the final system architecture looks like! Here's how the whole thing works: The user sends Terraform plan results to S3. That triggers a Lambda function via an event. Lambda sends the plan results to Bedrock for analysis and summarization. Place the generated plan summary and the summary page's HTML file to S3. Step Functions deletes CloudFront cache. The user just drops the plan file into S3, and everything else happens automatically. Let's Try Accessing It Looks super cool! But hey, did it actually summarize the Terraform plan results like we originally set out to do? Perfect... The indentation's a little wonky here and there, but, let's not get hung up on the details. What's Good About It? The number of created, updated, and deleted resources is clearly displayed at the top for easy viewing. It explains the specific changes being made to each resource. A risk summary is provided to help you grasp what could go wrong with this plan. It even points out things you might want to improve going forward. This is exactly what I was hoping for. Add Detailed Requirements After that, I had the Agent make a few minor tweaks here and there: Timestamps are in UTC, change to JST. Fix indentations that are off. Attach a screenshot. Once the plan is generated, clear the CloudFront cache. Stuff like that. Even with all those detailed requests, the Agent handled everything without breaking a sweat . My Impressions After Trying It Building this system was way easier than I expected. I put it together in a single day, and honestly, most of that time was just waiting for the Agent to do its thing. The actual hands-on time was just about an hour. Even someone like me, who's only ever touched infrastructure, managed to build out both the frontend and backend solo. Now, to be fair—when I looked at the Python code, even I could tell there were some parts that didn't need to be there. Definitely room for improvement. But for something at the Minimum Viable Product (MVP) stage, this is more than good enough. From here, it'll be easy to optimize the code or expand the features as needed. The important thing is that we were able to create a functioning system in a short period of time. This allows us to quickly shape our ideas and find areas for improvement through actual operation. The key point is this: I was able to build a working system by myself in a short amount of time. I think Agent is the best tool for building an MVP (Minimum Viable Product) Summary It might still take some time before we can build full-scale enterprise systems using only the Agent, but even as a beginner in writing prompts, I was able to develop a working system with ease. What surprised me the most was how smoothly the Agent handled everything. All I had to do was keep clicking the "accept" button, and it built the system for me. Up until now, I was used to copying and pasting suggestions from generative AI and running commands manually. But this time, I barely touched the terminal. I just kept pressing "accept." I was able to create a system that can reduce workloads and prevent mistakes just by pressing a button. Also, the system I built is already in use, and I plan to fully integrate it into our operational workflow. Finally The Cloud Infrastructure Group I belong to is looking for people to join us. Whether you're confident in your cloud skills or just getting started and eager to learn, we'd love to hear from you. Please feel free to contact us. For more details, please check here and here (in Japanese). We’ve also posted a group introduction on Wantedly! You can read more about the Cloud Infrastructure Group here ! (in Japanese)
Hello, I am Ito, an Administrative Assistant in the Global Development Group at KINTO Technologies. My role is to support team members with various tasks including answering their inquiries and translating documents. I love cats and reading novels. Lying down and reading with my cat used to feel like heaven. But ever since my cat passed on to another heaven some time ago, I’ve been spending my days reading alone. I have read 5 or 6 English novels this year. Reading in English used to be nothing but a struggle, but lately, I’ve started to enjoy experiencing them in their original language. However, I think the most enjoyable part of speaking foreign languages is having conversations. If you speak in another language, not just English, you definitely open yourself up to more opportunities and choices. Of course, there are challenges along the way. What should you do to be able to speak foreign languages? Unlike children, who can absorb things effortlessly, most adults need to put in a significant amount of effort. Effort to create many opportunities to speak, based on understanding basic grammar and vocabulary. I think this is essential to mastering a language. In this article, I would like to introduce the Language Skill Up Project, organized by the Business Enhance Team of the Global Development Group, which aims to help improve the language skills of working adults. Introduction Currently, the Global Development Group has almost sixty members from diverse backgrounds, including various nationalities, cultures, and languages. Among them, some aren’t very proficient in Japanese, while others aren’t used to speaking English due to limited use in their previous roles. Although the members share strong development skills, it would be a loss for the company if language barriers prevented effective communication. To help address this issue, the Language Skill-Up Project was launched, led primarily by the Business Enhance Team, whose mission is to maximize the members' potential. The Ministry of Internal Affairs and Communications defines global human resources as individuals who possess language proficiency, communication skills, and cultural awareness. The Global Development Group offers an environment that fosters the development of these qualities. One of the goals of this project is to cultivate global human resources by making use of this environment. People from outside of the Group can also join our study sessions. The key to language learning is not telling yourself that you can’t do it. Our goal is to help learners build confidence by first becoming comfortable speaking in English or Japanese. To support this, we organize and run the following events. What Shall We Do? What shall we do to help improve people's language proficiency? Everyone has different starting points. What needs to be done to learn languages? Focus on mastering basic vocabulary and grammar, such as junior high school-level English. Read (also read aloud) Write Listen Practice shadowing to improve your pronunciation and intonation Speak with others as much as possible I think you can do steps 1 through 5 on your own. However, number 6 requires you to take the initiative and create opportunities on your own, unless you're willing to spend money on language schools or online conversation lessons. Probably what many of our members are lacking is opportunities to speak the language. Since we could add steps 1 to 5 later if needed, we decided to start by providing speaking opportunities first. Japanese Cafe It is a casual meeting to enjoy conversations held in lunch time, fortnightly, also known as the pizza party. It's been nine months since we've started in April 2022. Since the event is conducted entirely in Japanese, it mainly attracts participants with intermediate to advanced Japanese proficiency. Having fun is key, and our goal is to help people communicate more smoothly in Japanese. Japanese cafe Japanese Study Sessions While providing opportunities to speak is essential, the Japanese Cafe alone cannot meet everyone's diverse needs. That's why we launched the Japanese study sessions in August 2022: 30-minute weekly sessions held in small groups. Beginner class - Learn greetings, Hiragana, Katakana, useful phrases for everyday life. Conversation Class (Beginner to Intermediate) - Practice role-playing situations like shopping or making phone calls. Use newly learned phrases in conversation and expand vocabulary with related words. Kanji class (Beginner to Intermediate) - Learn Kanji while practicing new phrases. Business Class (Intermediate to Advanced) - Learn business Japanese vocabulary and expressions using real examples from Slack communications. English Cafe It started in July 2022. Each session lasts 30 to 60 minutes and is held weekly in the late afternoon. The event is held at the Jimbocho office, but participants also join from outside the Global Development Team, including some who attend remotely from the Muromachi office. (Unfortunately, no pizza is provided.) So far, we've organized various activities such as English games, presentation practice, and group discussions. Similar to the Japanese Cafe, most participants are at an intermediate level or higher and are looking to practice conversation. However, since the sessions are typically held in small groups, we can adjust the level based on the participants each time. We also welcome beginner-level participants and those who want to discuss their concerns about learning English. English cafe (It's packed. People gathered for the photo shooting.) Individual English Sessions These 30-minute weekly sessions began in April 2022, designed for those who aren’t very familiar with English. For the first six months, the sessions were held twice a week. As participants grew more comfortable speaking English, the frequency was reduced to once a week.Participants have become noticeably more proactive in speaking English compared to when the sessions first began. They said, "I feel more comfortable speaking English," and "I have more confidence now." Having something to say is a key factor in learning a foreign language. I hope they will continue improving their skills. Reflections and Future Plans We started with the goal of enhancing communication among team members. Both the Japanese and English sessions have a friendly, relaxed atmosphere and have been very effective for team building. Even within the same group, some people rarely have the chance to talk to those they don’t work with directly. By attending the Japanese cafe or the English cafe, you can communicate with people you usually don’t have a chance to talk to. Participants come from diverse backgrounds, and some are native speakers of neither Japanese nor English. Through these conversations, you get the chance to explore a variety of topics and gain insights into different cultures. The Language Skill Up Project is still in its infancy and we are exploring more effective ways. I hope those who haven’t joined yet will give it a try. We also welcome your ideas and suggestions. I hope this can be a place that helps people stay motivated and inspires them to create more opportunities to speak outside of the sessions as well. There’s no magic potion to improve your foreign language skills. It all comes down to your own effort. In other words, you will be able to speak the language as long as you keep on doing it without giving up. If you don't try to create opportunities to speak the language after reaching a certain level, unfortunately it is easy to get rusty. There will always be something new to learn, so continuous study is essential. Once studying becomes a habit, it turns into a natural part of your life rather than just a task.
Hello Hello! My name is Nakagawara from the KINTO ONE Development Group. I work as a front-end engineer on a project, using Next.js and TypeScript for development. This time, I will talk about code reviews, which are essential for team-based development. I would like to introduce the points I pay attention to when performing code reviews, both as a reviewee or a reviewer. When Requesting a Code Review as a Reviewee Let's get straight to the point. First, I would like to share two things I pay attention to when creating a pull request (I'll call them PR from now) and requesting a code review. 1. Write clear commit messages I believe that by making an effort to write concise and clear commit messages, the granularity of commits will naturally improve. If necessary, I include supplemental explanations or reference links from the second line onward. I also add emoji prefixes to my commit messages. It makes it visually easier to understand the purpose of each commit , and since the emojis carry meaning, they naturally help discourage cramming too many changes into a single commit 🌈 Below is a commit template that the FE team actually uses. # ==== Format ==== # :emoji: PBI_id Subject # # Commit body... # ==== Emojis ==== # 🐛 :bug: Bug fixes # 👍 :+1: Functionality improvement # ✹ :sparkles: Partial feature addition # 🎉 :tada: A major feature addition worth celebrating # 🎚 :art: Visual additions and tweaks # 🔧 :wrench: Feature fix # ♻ :recycle: Refactoring # 🚿 :shower: Clean-up of deprecated or unused features # 📝 :pencil: Documentation and comment updates # 🚚 :truck: File relocation # 👕 :shirt: Lint fixes and style adjustments # 🀖 :robot: Test additions and fixes # 🚀 :rocket: Performance improvements # 🆙 :up: Updating dependencies and related packages # 👮 :cop: Security improvements and resolving warnings When creating the template, the following articles served as reference: atom Getting Fun and Beautiful Commits Using Emojis And here is an actual commit👇 I consciously make sure the purpose of the commit is clear when viewed in isolation. 2. Using a template to enrich PRs The FE team has a template available for PRs. Since it clarifies the perspectives from which the reviewer should check during a review, it is expected to improve review efficiency. Below is a template we actually use. Since we use JIRA for the ticket management of tasks, we include a link to the ticket , specify what this PR will and will not address , and outline what will become possible . ## Link to ticket * https://example.com ## What was done * What was accomplished in this pull request? ## What was not done * What is explicitly not included in this pull request? (If nothing, write "None". If excluded, indicate when it will be addressed.) ## What this enables * What new functionality or behavior does this pull request enable? (If none, write "None"). ## What this disables * What functionality or behavior is no longer possible due to this pull request? (If none, write "None"). ## Other notes * Additional context for reviewers (e.g., implementation concerns, areas to pay special attention to, etc.) When creating the template, the following articles served as reference: Let’s Create a Pull Request Template to Review Efficiently! In addition to the above, I consciously add information as needed. For example, in the case of a PR addressing a bug, I also include the cause , and if there is a UI change, I attach screenshots or videos showing the states before and after the fix . This is because I believe this will facilitate a smoother understanding of the intent of the PR and the code. When Reviewing Code as a Reviewer Next, I'd like to talk about three points I pay attention to when reviewing my team members' PRs. 1. Understanding the overview of a PR In the previous section, I mentioned using a template to write a PR carefully. So first, I make sure to read the overview carefully. I believe that understanding the background, intent, and what is not being addressed here , and then reviewing the code improves review efficiency and helps avoid off-target comments. 2. Check locally The code can be checked from a PR change file. However, for the following reasons, when there is a fix that affects behavior, I always pull the branch into my local environment to check it. To check the behavior and appearance To review the entire code To check the behavior and appearance By running the code myself, I can check whether the expected behavior and appearance have been achieved, as well as understand the purpose and intent of the change. If you only look at the code without understanding why the change was made, you may not be able to perform an appropriate review, and there is a risk of regression when you make future changes to that part. So, I try to follow the processing of the code with my own eyes as much as possible to better understand it. By doing this, I can catch overlooked issues or unintended side effects caused by fixing such issues, which helps prevent unexpected bugs from occurring .🐛 To review the entire code In addition to understanding the processing, you may also notice areas that could be optimized, such as "this and this perform similar processing, so it seems like they could be combined." 3. Labeling review comments I often add labels such as [imo] or [nits] at the beginning of comments to clarify their tone or nature. (though I still tend to forget this at times, so I want to make it a habit). Conclusion I've written a lot, but to sum it up: when doing code reviews, I try to stay mindful of what would make the review process easier, both from the reviewer’s and the reviewee’s perspective. My future challenges include not just being thorough but also improving the speed of my reviews and developing my own consistent set of review criteria to avoid variations in quality. It might also be valuable to align on these review perspectives as a team. I hope this article offered you some helpful insights into code review. Thank you for reading to the end!
0. はじめに Androidアプリ「 KINTO かんたん申し蟌み 」の開発を担圓しおいる Choi Garamoi です。 このアプリでは KMP を導入し、䞀郚のビゞネスロゞックを iOSアプリ ず共有しおいたす。 今回はよりスムヌズなKMPプロゞェクtの開発のため Tuist を詊した結果をたずめたした。 1. 抂芁 Android Studioでは、KMP Applicationプロゞェクトは新芏プロゞェクトりィザヌドを䜿っお䜜成したす。䜜成埌は以䞋のような Monorepo になりたす KmpProject/ ├── androidApp/ # Android専甚モゞュヌル(Kotlin/Android) ├── iosApp/ # iOS専甚モゞュヌル(Swift) └── shared/ # 共通ビゞネスロゞック(Kotlin/Multiplatform) Androidの Gradle ず同様に、iOSでもモゞュヌル化ずチヌム開発に適したビルド環境が重芁です。 本蚘事では、それを Tuist を䜿っお構築する方法を玹介したす。 2. Xcodeプロゞェクトの問題 Xcodeはアプリのビルドに必芁な情報を *.xcodeproj で管理しおいたすが、いく぀かの課題がありたす。 マヌゞコンフリクトが頻発する : Xcodeは蚭定を倉曎するず、 project.pbxproj ファむルを自動的に曎新したす。このファむルは構造化されおいないテキスト圢匏のため、耇数人が同時に線集するずGit䞊でコンフリクトが頻繁に発生したす。 実質的に意味のない差分が生成される : XcodeのGUI操䜜によっお、実質的な倉曎がなくおも倚くの差分が生じ、履歎が煩雑になりたす。 自動化が困難 : 倚くの蚭定がGUI䟝存であるため、CI/CDやスクリプトによるビルド自動化が困難です。 レビュヌし難い : project.pbxproj は可読性が䜎く、倉曎内容のレビュヌがしづらくなりたす。 拡匵性に限界がある : チヌム芏暡が倧きくなるず、耇数タヌゲットやビルド蚭定の管理が煩雑になりたす。 *.xcodeproj ディレクトリは、Androidプロゞェクトで蚀うずころの Gradle ず .idea ディレクトリ を合わせたようなもので、ロヌカルのXcode蚭定ずiOSアプリのビルド蚭定を分離できたせん。 Googleトレンド でも「xcode conflict」の怜玢数が「xcode dev」に比べお倚く、開発時の衝突が倚いこずがうかがえたす。 3. Tuist ずは Swift 蚀語で XcodeのProjectsずworkspaces を生成ず Xcode のタヌミナルツヌルを組み合わせおビルドも出来るツヌルです。 䞻な機胜は モゞュヌル化サポヌト 環境独立的ビルド(チヌム開発指向) 自動化サポヌト Swift Package Manager サポヌト です。 他のXcodeのビルドツヌルずしおは Swift Package Manager 、 XcodeGen 、 Bazel がありたす。 Swift Package Manager : Gradleの䟝存性管理機胜( dependencies ブロック)だけを提䟛したす。 XcodeGen : ツヌルの蚭定倀チェックが足りないため人的ミスが発生しやすいです。 Bazel : 倧芏暡プロゞェクトを察象にするため䜿い方が耇雑で、䞭小芏暡のプロゞェクトにはオヌバヌスペックです。 4. Tuist を導入する 以䞋は Migrate an Xcode project を基本に、最新情報を反映した手順です。 4-1. Tuistをむンストヌルする brew update brew upgrade tuist brew install tuist Homebrew 以倖のむンストヌル方法は マニュアル をご参照ください。 4-2. Tuist蚭定ファむルを远加する Tuist.swift 、 Project.swift 、 Tuist/Package.swift の3぀のファむルManifestファむルを远加したす。 KmpWithSwift/ ├── Tuist.swift ├── Tuist/ │ └── Package.swift ├── Project.swift ├── androidApp/ │ └── ... ├── iosApp/ │ └── ... └── shared/ └── ... 4-3. 蚭定にモゞュヌル Target を远加する Project.swift が䞻な蚭定ファむルで、他のファむルは Migrate an Xcode project のサンプルをそのたた利甚しおも問題ありたせん。 4-3-1. Tuist.swift import ProjectDescription let tuist = Tuist(project: .tuist()) 4-3-2. Project.swift タヌゲットの蚭定ずKMP共通モゞュヌルのビルドスクリプトを远加する。 infoPlist : 党䜓画面の蚭定。 scripts : KMP共通モゞュヌルをビルドするコマンド。 import ProjectDescription let project = Project( name: "KmpWithSwift", targets: [ .target( name: "App", destinations: .iOS, product: .app, bundleId: "ktc.garamoi.choi.kmp.with.tuist.App", infoPlist: .extendingDefault( with: [ "UILaunchScreen": [ "UIColorName": "", "UIImageName": "", ], ] ), sources: ["iosApp/iosApp/**"], resources: ["iosApp/iosApp/**"], scripts: [ .pre( script: """ cd "$SRCROOT" ./gradlew :shared:embedAndSignAppleFrameworkForXcode """, name: "Build KMP" ) ] ) ] ) 4-3-3. Tuist/Package.swift // swift-tools-version: 6.0 import PackageDescription #if TUIST import struct ProjectDescription.PackageSettings let packageSettings = PackageSettings( productTypes: [:] ) #endif let package = Package( name: "App", dependencies: [ ] ) 4-4. 叀いXcodeプロゞェクトを削陀する ./iosApp/iosApp.xcodeproj を削陀したす。 ./.gitignore に *.xcodeproj を远加したす。 4-5. 確認 Tuistの蚭定が正しくできたか確認したす。 TuistのManifestファむルをXcodeで開けるこずを確認したす。 # KmpWithSwiftディレクトリで tuist edit TuistでXcodeプロゞェクトを生成したす。 # KmpWithSwiftディレクトリで tuist generate Xcodeが開いたらアプリを実行したす。 アプリが正垞に起動すれば完了です。 5. 共通機胜からiOS蚭定を分離する 共通モゞュヌルの ./shared/build.gradle.kts は、共通のビゞネスロゞックのビルド蚭定ずiOS専甚の XCFramework のビルドの責任範囲が適切に分離されおいたせん。 kotlin { // ... listOf( iosX64(), iosArm64(), iosSimulatorArm64() ).forEach { it.binaries.framework { baseName = "shared" isStatic = true } } // ... } 5-1. 察応 䞋蚘のiOSの XCFramework 蚭定を :shared から分離しお ios ぞ移動するず、より自然な圢で蚭定でき、マルチモゞュヌル化も楜になりたす。 it.binaries.framework { baseName = "shared" isStatic = true } 5-2. 手順 ./iosApp/shared モゞュヌルからXCFrameworkをビルドする。 App タヌゲット( ./iosApp/iosApp ディレクトリヌ)のスクリプトを曎新する。 5-2-1. :iosApp:shared モゞュヌル远加 ./iosApp/shared/build.gradle.kts ファむルを远加し、 ./settings.gradle.kts にモゞュヌルを远加したす。 Androidの蚭定は䞍芁です。 // ./iosApp/shared/build.gradle.kts plugins { alias(libs.plugins.kotlin.multiplatform) } kotlin { listOf( iosX64(), iosArm64(), iosSimulatorArm64() ).forEach { it.binaries.framework { baseName = "shared" isStatic = true export(projects.shared) } } sourceSets { commonMain.dependencies { api(projects.shared) } } } // ./settings.gradle.kts // ... 省略 ... rootProject.name = "KmpProject" include( ":androidApp", ":iosApp:shared", ":shared" ) ./shared/build.gradle.kts からXCFramework蚭定を削陀したす。 // ./shared/build.gradle.kts plugins { alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.androidLibrary) } kotlin { // ... 省略 ... iosX64() iosArm64() iosSimulatorArm64() // ... 省略 ... } // ... 省略 ... 5-2-2. Tuistタヌゲット曎新 Project.swift の scripts のGradleコマンドを曎新したす。 scripts のモゞュヌルを :shared から远加した :iosApp:shared ぞ倉曎したす( ./gradlew :shared:embedAndSignAppleFrameworkForXcode ➡ ./gradlew :iosApp:shared:embedAndSignAppleFrameworkForXcode )。 // ./Project.swift import ProjectDescription let project = Project( name: "KmpWithSwift", targets: [ .target( name: "App", destinations: .iOS, product: .app, bundleId: "ktc.garamoi.choi.kmp.with.tuist.App", infoPlist: .extendingDefault( with: [ "UILaunchScreen": [ "UIColorName": "", "UIImageName": "", ], ] ), sources: ["iosApp/iosApp/**"], resources: ["iosApp/iosApp/**"], scripts: [ .pre( script: """ cd "$SRCROOT" ./gradlew :iosApp:shared:embedAndSignAppleFrameworkForXcode """, name: "Build KMP" ) ] ) ] ) 6. マルチモゞュヌル化 アプリが成長するずフィヌチャヌモゞュヌル化が必芁になりたす。 %%{ init: { 'theme': 'neutral' } }%% graph TB App ==> FeatureA App ==> FeatureB FeatureA --> :iosApp:shared FeatureB --> :iosApp:shared しかし各フィヌチャヌが :iosApp:shared が必芁な堎合、Tuist蚭定は䞋蚘のようになりたす。 // ./Project.swift import ProjectDescription let project = Project( name: "KmpWithSwift", targets: [ .target( name: "App", destinations: .iOS, product: .app, bundleId: "ktc.garamoi.choi.kmp.with.tuist.App", infoPlist: .extendingDefault( with: [ "UILaunchScreen": [ "UIColorName": "", "UIImageName": "", ], ] ), sources: ["iosApp/iosApp/**"], resources: ["iosApp/iosApp/**"], dependencies: [ .target("FeatureA"), .target("FeatureB") ] ), .target( name: "FeatureA", destinations: .iOS, product: .framework, bundleId: "ktc.garamoi.choi.kmp.with.tuist.FeatureA", infoPlist: .default, sources: ["iosApp/FeatureA/**"], resources: ["iosApp/FeatureA/**"], scripts: [ .pre( script: """ cd "$SRCROOT" ./gradlew :iosApp:shared:embedAndSignAppleFrameworkForXcode """, name: "Build KMP" ) ] ), .target( name: "FeatureB", destinations: .iOS, product: .framework, bundleId: "ktc.garamoi.choi.kmp.with.tuist.FeatureB", infoPlist: .default, sources: ["iosApp/FeatureB/**"], resources: ["iosApp/FeatureB/**"], scripts: [ .pre( script: """ cd "$SRCROOT" ./gradlew :iosApp:shared:embedAndSignAppleFrameworkForXcode """, name: "Build KMP" ) ] ) ] ) この蚭定では䞋蚘の2぀の倧きな課題がありたす。 共通のXCFrameworkがフィヌチャヌモゞュヌル :iosApp:shared の数の分ビルドされおしたいたす。 フィヌチャヌモゞュヌルのタヌゲット蚭定やビルドオプションによっおは、アプリが耇数バヌゞョンの :iosApp:shared を利甚しおしたう恐れが有りたす。 この問題を解決するために、 :iosApp:shared をTuistタヌゲットでラップしたす。 6-1. Wrappingタヌゲット远加 フィヌチャヌモゞュヌルが盎接にGradleの :shared モゞュヌルを䜿わず、Xcodeのタヌゲットを共有するように KmpCore タヌゲットを远加したす。 %%{ init: { 'theme': 'neutral' } }%% graph TB App ==> FeatureA App ==> FeatureB FeatureA ==> KmpCore FeatureB ==> KmpCore KmpCore --> :iosApp:shared ゜ヌスコヌドは iosApp/shared/** で :iosApp:shared ず同じですが、KMPで生成するネヌムスペヌスずカプセル化しおWrappingタヌゲットを䜿うように KmpCore にしたす。 この察応により、KMP共通コヌドの情報を持っおいるタヌゲットは KmpCore のみになりたす。 // ./Project.swift import ProjectDescription let project = Project( name: "KmpWithSwift", targets: [ .target( name: "App", destinations: .iOS, product: .app, bundleId: "ktc.garamoi.choi.kmp.with.tuist.App", infoPlist: .extendingDefault( with: [ "UILaunchScreen": [ "UIColorName": "", "UIImageName": "", ], ] ), sources: ["iosApp/iosApp/**"], resources: ["iosApp/iosApp/**"], dependencies: [ .target("FeatureA"), .target("FeatureB") ] ), .target( name: "FeatureA", destinations: .iOS, product: .framework, bundleId: "ktc.garamoi.choi.kmp.with.tuist.FeatureA", infoPlist: .default, sources: ["iosApp/FeatureA/**"], resources: ["iosApp/FeatureA/**"], dependencies: [.target(name: "KmpCore")] ), .target( name: "FeatureB", destinations: .iOS, product: .framework, bundleId: "ktc.garamoi.choi.kmp.with.tuist.FeatureB", infoPlist: .default, sources: ["iosApp/FeatureB/**"], resources: ["iosApp/FeatureB/**"], dependencies: [.target(name: "KmpCore")] ), .target( name: "KmpCore", destinations: .iOS, product: .framework, bundleId: "ktc.garamoi.choi.kmp.with.tuist.KmpCore", infoPlist: .default, sources: ["iosApp/shared/**"], resources: ["iosApp/shared/**"], scripts: [ .pre( script: """ cd "$SRCROOT" ./gradlew :iosApp:shared:embedAndSignAppleFrameworkForXcode """, name: "Build KMP" ) ] ) ] ) 6-2. KmpCore で shared を露出する 単玔に KmpCore タヌゲットが shared ぞ䟝存性を持぀だけでは FeatureA ず FeatureB から :shared のコヌドぞアクセスができたせん。 FeatureA ず FeatureB から KmpCore を経由しおKMP共通コヌド(Gradleの :shared モゞュヌル)ぞアクセスできるように远加蚭定が必芁です。 たずは KmpCore タヌゲットに settings 蚭定を远加したす。 // ./Project.swift import ProjectDescription let project = Project( name: "KmpWithSwift", targets: [ // ... 省略 ... .target( name: "KmpCore", destinations: .iOS, product: .framework, bundleId: "ktc.garamoi.choi.kmp.with.tuist.KmpCore", infoPlist: .default, sources: ["iosApp/shared/**"], resources: ["iosApp/shared/**"], scripts: [ .pre( script: """ cd "$SRCROOT" ./gradlew :iosApp:shared:embedAndSignAppleFrameworkForXcode """, name: "Build KMP" ) ], settings: .settings(base: [ "FRAMEWORK_SEARCH_PATHS": "iosApp/shared/build/xcode-frameworks/**", "OTHER_LDFLAGS": "-framework shared" ]) ) ] ) KmpCore タヌゲットが shared ネヌムスペヌスを KmpCore ネヌムスペヌスで露出するするように䞋蚘のSwiftファむルを远加したす。 // ./iosApp/shared/KmpCore.swift @_exported import shared 6-3. 確認 Xcodeでプロゞェクトをビルドしたら FeatureA ず FeatureB が import KmpCore したら :shared ぞアクセス出来たす。 䟋えば :shared モゞュヌルに SomeModel ( shared/src/commonMain/kotlin/ktc/garamoi/choi/kmp/with/tuist/SomeModel.kt )のクラスがある堎合 FeatureA から䞋蚘のようにアクセスできたす。 import Foundation import KmpCore public class SomeFeatureAClass { let model: SomeModel // ... } もしコンパむル゚ラヌが発生する堎合は、ビルド順やキャッシュの圱響で䞀床目のビルドが䞍安定になるこずがありたす。その堎合はクリヌンビルド又は耇数回のビルドを詊すこずで解決できたす。 7. 結論 Xcodeの *.xcodeproj は自動化ずチヌム開発に適しおいたせん。 Xcodeプロゞェクトの *.xcodeproj の代替ずしお Tuist の䜿甚を掚奚したす。 KMP共通モゞュヌルのXCFrameworkの生成をXcodeプロゞェクトのタヌゲットでラップするこずで、フィヌチャヌモゞュヌル化が容易になりたす。 8. 参考 Kotlin Multiplatform : Kotlin蚀語でクロスプラットフォヌム開発ができる色んなツヌルを提䟛するKotlin公匏プロゞェクト。 Gradle : Android、Javaプロゞェクトのde-factoビルドツヌル。 Tuist : Xcodeプロゞェクトのビルドツヌル。 Swift : AppleがObjective-Cの代わりに開発したOOP蚀語。 Xcode : Appleプラットフォヌム甚のIDE。 Xcode / Projects and workspaces Swift Package Manager : Swift 蚀語の公匏䟝存性管理ツヌル。 XcodeGen : YAMLずJSONで Xcode Project を生成するツヌル。 Bazel : Googleが開発したビルドツヌル。倧芏暡 Monorepo を察象にする。 Monorepo Explained : 耇数のSWを1぀のレポゞトリヌで管理する仕組み。 Google Trends : xcode conflict , xcode merge , xcode dev : Xcodeの開発党般的な怜玢に比べおXcodeのコンフリクトの怜玢の割合が高い。 What is project.pbxproj in Xcode Project configuration / Projects / Project settings : Android Studio, IntelliJ IDEAの .idea ディレクトリヌの説明。 Migrate an Xcode project : マニュアルで既存のXcodeプロゞェクトをTuistプロゞェクト化する手順。 Homebrew : macOSのシステムパッケヌゞ管理ツヌル。 Install Tuist Xcode / Bundles and frameworks / Creating a static framework Swift logo : 䞋段から公匏ロゎをダりンロヌド出来たす。 Kotlin logo Gradle logo Tuist logo KINTO かんたん申し蟌み : Androidアプリ KINTO かんたん申し蟌み : iOSアプリ Choi Garamoi
はじめに こんにちはセキュリティ・プラむバシヌG所属の たなちゅヌ です。 本蚘事では、匊瀟で最近発生した生成AIチャットツヌルに関連するセキュリティ事案に぀いおお話ししたす。技術的に特別新しいものではありたせんが、発生した状況が少し珍しいケヌスだったため、玹介させおいただきたす。 事案の抂芁 匊瀟では、生成AIチャットツヌルを党瀟員が気軜に利甚できる環境を敎えおいたす。ある日、そのツヌルを䜿甚しおいた瀟員が生成AIぞ質問した際に、回答ずしお提瀺されたリンクぞアクセスしたずころ、「サポヌト詐欺サむト」が衚瀺される事案が発生したした。 生成AIチャット むメヌゞ図 サポヌト詐欺サむト むメヌゞ図 セキュリティ補品でもブロックできず結果ずしおサポヌト詐欺サむトぞ誘導されたしたが、瀟員の冷静な刀断により、倧きな被害を防ぐこずができたした。 このこずから、ブラりザによるむンタヌネット怜玢ず同様ですが、生成AIが提瀺するリンクが垞に安党であるずは限らないこずを実感する事案ずなりたした。 事案の発生芁因 生成AIがサポヌト詐欺サむトを提瀺した芁因調査を目的に、むンタヌネットアヌカむブサヌビス「 WAYBACK MACHINE 」で生成AIが提瀺したWebサむトを怜玢したずころ、このWebサむトが過去に正芏ず思われるコンテンツを提䟛しおいるこずが確認されたした。 たた、このWebサむトを参考情報ずしお玹介しおいるサむトが数件、存圚するこずも確認されたした。 このこずから、問題ずなったWebサむトの過去のコンテンツ情報や玹介しおいるWebサむトの情報をもずに生成AIが孊習した結果、生成AIが誀った情報を提瀺するハルシネヌションに類する珟象が発生し、サポヌト詐欺サむトのリンクを提瀺した可胜性が考えられたす。 以䞋は調査結果をもずに問題ずなったWebサむトのコンテンツ倉遷を敎理した内容です。 2012幎2018幎前半 ドメむン名に合臎したコンテンツ履歎あり。この時点では信頌性のあるサむトず刀断されおいたず掚枬される。 2018幎埌半2019幎前半 ドメむン管理サヌビスの販売画面が衚瀺され、運営者がドメむンを手攟した可胜性がある。 2019幎埌半以降 ドメむン名に関連性のないコンテンツ病気、オンラむンカゞノ、停譊告画面、ドメむンパヌキングなどの履歎あり。 セキュリティ補品で怜知できなかった芁因調査に぀いおは、「 付録調査メモ 」をご芧ください。 類䌌事案ぞの察策 以䞋の芳点から、このような事案に察しお珟時点では根本的な察策を講じるこずは非垞に難しいず考えられたす。 生成AIの孊習の課題 この事案が発生した背景ずしお、問題ずなったWebサむトの過去のコンテンツ情報や玹介しおいるWebサむトの情報をもずに生成AIが孊習した可胜性がありたす。䞀床孊習されたWebサむトのコンテンツが倉曎されおも、そのセキュリティリスクが生成AIの回答に反映されるこずは難しいず考えられたす。 最倧の察策は「知るこず」 この事案から埗られる教蚓は、「生成AIが提瀺するリンクが垞に安党であるずは限らない」ずいうこずを知るこずです。事䟋を孊び、実際に遭遇したずきにどのように察凊すべきかを理解するこずが倧切です。 たずめ 今回の事案は、生成AIが提瀺するリンクが必ずしも安党ではないこずを瀺す、少し珍しいケヌスでした。䞍正サむトの特性によっおは、セキュリティ補品でも怜知が難しい堎合がありたす。たた、生成AIが孊習した埌にサむトコンテンツが倉曎されるず、そのリスクを反映できない可胜性もありたす。 珟時点では、根本的な察策は難しいず考えられたすが、こうした事䟋を知るこずで、生成AIを利甚する際のセキュリティ意識を高めるきっかけになればず思いたす。 付録調査メモ セキュリティ補品で怜知できなかった芁因調査のメモです。あくたでも簡単な調査ずなりたすので、参考皋床にご芧ください。 1. セキュリティベンダヌの怜知状況 匊瀟で利甚しおいるセキュリティ補品や「 VirusTotal 」で問題ずなったWebサむトのドメむンを怜玢したずころ、ほが党おのベンダヌが「安党」刀定ずなっおいたした。 2. Webサむトの゜ヌスコヌド 問題ずなったWebサむトの゜ヌスコヌドを確認したずころ、「domaincntrol[.]comc の埌ろに o 無し」ぞリク゚ストを送信埌、レスポンス情報をもずに、蚪問者の誘導先を動的に決定する仕組みが実装されおいるず考えられたす。 実際に安党な環境で数回アクセスを詊みたずころ、サポヌト詐欺サむトやドメむンパヌキングなど、異なるWebサむトぞ遷移するこずが確認されたした。これにより、セキュリティベンダヌによる悪性刀定を回避した可胜性がありたす。 3. サポヌト詐欺サむトのホスティング環境 最終的に衚瀺されるサポヌト詐欺サむトは「web.core.windows[.]net」ドメむンにホストされおおり、Microsoft Azure環境が利甚されおいるず掚枬されたす。Microsoft Azureに限らず、クラりドサヌビスを利甚した䞍正サむトは、環境構築の容易さや業務圱響の芳点からクラりドサヌビスのドメむンをブロックするこずが事実䞊䞍可胜であるこずから、セキュリティ補品でブロックするこずが難しいず考えられたす。 ※本蚘事公開時点で今回のサポヌト詐欺サむトが、Microsoft Azureから削陀されおいるこずを確認しおいたす。 4. PublicWWWでの調査結果 Webサむトの゜ヌスコヌドを怜玢できるツヌル「 PublicWWW 」を甚いお、問題ずなったWebサむトの特城的な文字列「domaincntrol[.]com/?orighost=」を怜玢したずころ、2䞇件以䞊のサむトでこの文字列を含むコヌドが䜿甚されおいるこずが確認されたした。たた、その䞭からいく぀かのサむトを調査した結果、同様にサポヌト詐欺サむトぞ誘導される挙動が確認されたした。
Introduction My name is Endo, and I am the leader of the QA group at KINTO Technologies. In this article, I'd like to give you a look into our daily QA work especially through our daily efforts on subjects that anyone involved in QA may have encountered in the course of their daily tasks. There are already a couple of articles about QA work: Manager Zume's Quality Assurance Group Introduction Team Member Okapi's Increased Awareness of QA So I hope you will read them as well. I hope this article sparks conversations like, 'Here’s how we do it at our workplace,' or 'How do you usually handle this kind of task? I'd love to hear your thoughts! QA Workflow and What We Focus On Our QA work mainly involves: QA for development projects QA for maintenance and updates Test Automation Internal QA improvements QA work improvement activities Study sessions   In this article, I'll walk you through the QA workflow for projects and share the key perspectives we keep in mind. Different Views on QA The outline of QA work is explained during the orientation when joining the company and at the kickoff of each project. However, since all project members are experienced professionals, they have their own ideas and expectations of QA based on their past experience. Because of that, we sometimes run into misunderstandings like, "Isn't QA supposed to check things down to this level?" Such gaps in understanding can even pop up among team members. However, despite differences in what people expect from QA, I think we're mostly aligned on one key point:  "We want to identify and resolve any lingering quality concerns during the QA phase." I think the key is to figuring out how to address those concerns, ease that uncertainty, and make sure the release goes smoothly. To start, we go over the following three main points during the project kickoff, so everyone involved has a clear understanding of QA. (1) Let's build quality together! (2) If you have any concerns about quality, don't hesitate to reach out. (3) QA's feedback isn't absolute, so let's consider whether it can be addressed as a project. Quality is something we build together! Point (1) might go without saying, but quality can't be improved by QA alone. As a result of the aforementioned misunderstandings, we sometimes get requests that lean more toward white-box testing, like: Checking the details at the unit level Checking with a focus on source and data flow And more. QA work mainly focuses on black-box testing, so when it comes to white-box testing, we usually explain that it's more suited to be performed by the development side. These requests often come from past experiences where QA helped before, or from a hope that QA will "definitely" catch issues they might have missed. While there's generally a shared understanding that QA handles things like system tests, acceptance tests, and checks at each phase, people's expectations can still vary depending on their past experience. Some may expect QA to dig into system-level checks like source and data flow, while others expect a more user-centered checks. In general, though, I think QA is widely seen as a team that supports and checks quality control using its own indicators, including the standardization of all development processes. While we in QA want to meet all those expectations, there are limits to what we can catch, and the testing time is not endless. So, it is necessary for everyone to approach quality as something we build "together," especially when working under tight timelines to achieve our quality goals. However, it's not just about QA verifying requirements, pointing out issues, and having them fixed as a routine task. We believe better results come when we're aligned on QA specifications, test plans, and test timing by matching requirements together , aligning test perspectives together , and considering improvements together . And through those thorough discussions, we can apply those insights to test design. Developer Concerns Are a Goldmine of Tips for Improving Quality In reviews from a testing perspective, we can usually identify specific concerns that the development team has. But sometimes, the feedback is more vague, like simply feeling risky about a certain process. Even if those concerns aren't clearly articulated, they're incredibly valuable for QA when defining test perspectives and designing tests. That vague sense of unease often comes from things like complex code, unclear requirements, or uncertainty about whether all the finer details were fully nailed down. Even when everything seems to be working fine, so it's hard to put into words, but developers still have that gut feeling that something might be off. Surprisingly, testing these areas can sometimes reveal unexpected issues, so these instincts shouldn't be taken lightly. As QA, we review the requirements and plan and design tests to address specific concerns. These instincts offer valuable hints that help us strengthen our testing and apply deeper coverage than originally planned. In the QA phase, our goal isn't really to catch unit- or integration-level bugs. Instead, it's about executing hundreds of test cases based on requirements and catching that one critical or fatal bug. That's where QA really shows its value. So, rather than worrying about whether a developer's gut feeling might lead to wasted effort, we try to create an environment where those instincts and hints can be freely shared. By encouraging open conversation, we can uncover areas to strengthen beyond the test perspectives which helps us design better tests and ultimately improve quality. For example, instead of ending a test perspective meeting like, "Here's how we plan to proceed. Please let us know if anything comes up." We try to add a simple question like, "Is there anything in this spec that makes you feel uneasy?" By adding this, the conversation can turn into something like, "Now that you mention it..." Even if you have concerns but can't put them into words, you may feel there's nothing worth sharing. But let's talk to QA anyway! By taking the aforementioned together approach, we can strengthen our test coverage and often uncover a goldmine of valuable insights in the process. Don't Get Distracted by QA Feedback, Stay Focused on the Original Goal If QA is seen as only working within a limited test scope, it can sometimes lead to misunderstandings such as thinking QA merely follows the requirements without understanding the code, focuses on overly detailed issues, and causes delays to the release schedule. However, by providing the above-mentioned explanation in advance, people start to see QA in a completely different light, seeing it as a team that builds quality "together." On the other hand, with the change in perspective, some people start to worry that everything QA "points out" must be addressed before the release can go live. What QA "points out" with testing fall into the following three categories:   Bugs: QA points out behavior (display) that differs from the specifications as understood by QA Improvement requests: There is no problem with the specifications, but QA suggests a change to improve the functionality Questions: Ask about unclear points in the specifications For bugs, QA points them out when we notice behavior that doesn't match the expected specifications. The development team reviews the issue, makes any necessary fixes, and then QA rechecks the fix. Improvement requests are suggestions where there is no issue with the specifications, but it might be better to improve them. For example, if most screens have a button in the top right, but one screen has it in the top left, there's no problem with the button's functionality, but QA might propose moving it for consistency. Questions arise when QA finds unclear parts of the specifications while testing. We ask for clarification first, before labeling anything as a bug. It doesn't mean that all of these points need to be addressed before release. Ideally, every issue should be addressed, and every question answered, but depending on the project's circumstances, it is not realistic to tackle everything before release. If it's difficult to address all of the issues, it's the project, not QA, that decides which ones to tackle before release, based on their importance and priority. QA's work is to conduct testing based on the idea of how things should be ideally according to the requirements. Naturally, even if the requirements are well-defined, there may be some parts of the specifications that are unclear. Ideally, everything would be addressed, but within the limited time available, it is important not to lose sight of the original goal by checking and organizing the final specifications through QA's feedback. This leads to point (3), as a project, it's crucial to align on what kind of service will be delivered, and when. With that shared understanding, we can work toward building quality to meet that goal. This is where it's important for QA to provide solid support in terms of quality. Now, this might sound like we're suggesting that, given the time constraints, it's okay to just meet the bare minimum requirements and compromise on quality to release the service, but that's not the case at all. As mentioned earlier, QA's work is to help the team move toward the project's defined goals by verifying whether the specified requirements are fully met. At the same time, if there are issues that could negatively impact the user experience, we will persistently discuss issues with stakeholders to address them. It's not about making compromises, nor is it about QA forcing our feedback onto the team. Instead, we focus on the project goals and the end users receiving the service, and we work together to decide how the project should respond and take action accordingly. If a critical issue were to occur after release, the impact could be significant. So, QA stays fully engaged to help ensure quality is upheld. However, in larger projects, potential concerns are typically addressed early through the interviews mentioned in point (2). And given the nature of the development process, it's rare for a critical issue to suddenly appear at the very end. As a result, it’s extremely uncommon for the release date to be delayed due to QA work. Ultimately, what matters most is working together to achieve the target quality by the target release date. So, to repeat the important point: QA doesn't just point out issues and ask for fixes. It's about staying focused on the project's original goal to build quality together . For example, delivering the intended service to customers within the planned timeframe while making sure users aren't affected by any inconvenience or negative impact. Conclusion In this article, I focused on our mindset as QA and the communication practices we value, but from a more technical perspective, QA is also the only team that can take a cross-functional, bird's-eye view across all projects and products. If the opportunity arises, I'd like to share how QA provides support along with our approaches to test planning, defining test perspectives, and test design. Sometimes, people approach us with QA requests a bit hesitantly. But the point is that we're in this together . We want to build a relationship where everyone feels comfortable collaborating without hesitation. After release, we often hear, "It was a huge help!" "Thanks so much!" At those times I always say, "Not at all! Thank you for taking QA's feedback seriously and responding with such care."I'm deeply grateful to everyone involved in the project and have great respect for their commitment. We strive every day to build trust by fully supporting the quality of the services we deliver. And when a service we've built together ends up being truly useful to users, I believe that's the true reward of working in QA. I hope this article has sparked some interest in working in QA. Also, if you're working in QA, I'd love to hear your thoughts and exchange ideas. Feel free to share your feedback on Twitter! https://twitter.com/KintoTech_Dev/status/1619979941856280577?s=20
UUIDずは䜕でしょう? どのバヌゞョンを䜿甚すればよいでしょうか? 最近、デヌタベヌス内のキヌが重耇しおいたためにサヌビスがダりンするずいうむンシデントに察応しなければなりたせんでした。私のチヌムず私は、これらがUUIDだったため頭を悩たせおいたした。ご存知のずおり、これらは「䞀意」の識別子です。どうしお重耇が生じるのでしょうか?結局、この問題は、同じUUIDが2回生成されたこずではなく、サヌビスが同じむベントを2回远加しようずしたこずが原因であるこずがわかりたした。この出来事がきっかけで、UUIDに぀いお考えるようになりたした。UUIDずは䜕でしょうか?UUIDはどのように生成されるのでしょうか?UUIDの䜿甚䟋は?そしお最も重芁なのは、どのバヌゞョンを䜿甚すべきかずいうこずです。 UUIDずは䜕でしょう? UUIDは通垞、リ゜ヌスのIDを提䟛するために䜿甚されたす。UUIDは「Universally Unique IDentifier汎甚䞀意識別子」の略称です。その名称を芋るず、生成される倀の䞀意性が匷く期埅されおいるようです。これには十分な理由がありたす。䟋えば、数千兆のUUIDなど、膚倧な量のUUIDを生成したずしおも、それらが䞀意である確率は99.999%です。これらの確率の背埌にある数孊に興味がある方は、 この非垞に優れた蚘事 を読むこずをお勧めしたす。 UUIDは「保蚌された䞀意性」ではなく「実質的な䞀意性」です。衝突の可胜性は非垞に小さいため、ほずんどのアプリケヌションでは、UUIDの衝突が発生する可胜性よりも、ハヌドりェアが故障するか、 宇宙線が原因でビットがマシンのメモリ内で反転する 可胜性の方が高くなりたす。 ただし、これらの確率は適切な乱数発生を前提ずしおいるこずに泚意しおください。乱数発生噚に欠陥があったり予枬可胜だったりするず、衝突の実際の確率ははるかに高くなる可胜性がありたす。この蚘事の埌半でもう少し詳しく説明したす。 ゜フトりェアに携わっおいる方であれば、UUIDがどのようなものかすでにご存知かず思いたすが、念のためUUIDは128ビット幅で、ハむフンで区切られた5぀の郚分で構成されたす。それらは通垞、16進数で衚され、次のようになりたす。 ccba8c00-cbed-11ef-ad79-1da827afd7cd 74febad9-d652-4f6b-901a-0246562e13a8 1efcbedf-13bf-61e0-8fb8-fe3899c4f6f1 01943a0e-dd73-72fd-81ad-0af7ce19104b でも埅っおくださいこれらのUUIDは実際には異なるバヌゞョンのUUIDを䜿甚しお生成されたした。䞊蚘のUUIDのリストにおいお、それらはバヌゞョン1、バヌゞョン4、バヌゞョン6、バヌゞョン7の順で䜿甚しお生成されたす。UUIDにおいおバヌゞョンがどこに瀺されおいるかを調べおみおください。 ヒント䞭間あたりにありたす。 UUIDのバヌゞョンは、UUIDの真ん䞭にある、UUIDの3番目の郚分の最初の文字に瀺されおいるこずにお気づきだず思いたす。4番目の郚分の最初の文字にもバリアントが瀺されおいたす。バヌゞョンはUUIDがどのように生成されたかを瀺すために䜿甚され、バリアントはそのUUIDのレむアりトを瀺すために䜿甚されたすが、おそらくバリアントに぀いお心配する必芁はなく、バヌゞョンが最も重芁です。 先ほど説明したように、UUID には耇数のバヌゞョンがありたす。先ほど発芋したバヌゞョンむンゞケヌタヌの他に、各バヌゞョンの違いは䜕でしょうか?それらはすべお、䞀意のUUIDを同様に生成できるでしょうか?たた、あるバヌゞョンを他のバヌゞョンよりも優先しお䜿甚する理由は䜕でしょうか?もちろん、最新か぀最良のUUIDバヌゞョンを䜿甚すべきですよねずおも良い質問ですUUIDの異なるバヌゞョンを芋おみたしょう。 バヌゞョン1ずバヌゞョン6 バヌゞョン1および6のUUIDは、UUIDを生成したコンピュヌタヌの珟圚の時刻ず MACアドレス を䜿甚しお生成されたす。タむムスタンプ郚分は UUIDの先頭にあり、コンピュヌタヌのCPUに応じおランダムビットたたは増分カりンタヌを含む堎合がありたす。MACアドレス郚分は最埌にあるため、同じコンピュヌタヌを䜿甚しおいれば、その郚分が倉化するこずはありたせん。興味深いこずに、MACアドレスはUUIDから取埗できるため、UUIDバヌゞョン1たたは6を生成するずプラむバシヌのリスクが生じたす。しかし、これはこのバヌゞョンのUUIDの利点の1぀でもあり、2台のコンピュヌタが同じUUIDを生成するこずはありたせん。そのため、これらのバヌゞョンは、グロヌバルな䞀意性が求められる分散システムで圹立ちたす。 バヌゞョン1ず6の違いは、UUIDでタむムスタンプの各郚分が䜿甚される順序です。バヌゞョン1ずは異なり、バヌゞョン6のUUIDは時系列で䞊べ替えるこずができるため、デヌタベヌス内での順序付けに圹立ちたす。 バヌゞョン1および6では予枬可胜な芁玠生成時刻ずMACアドレスを䜿甚するため、UUIDを掚枬可胜であり、UUIDを秘密にしおおく必芁がある甚途には適しおいたせん。 バヌゞョン2 バヌゞョン2は、タむムスタンプず、UUIDを生成するコンピュヌタヌのMACアドレスを䜿甚する点でバヌゞョン1ず䌌おいたす。ただし、バヌゞョン2では、POSIX UIDたたはGIDずいう远加の識別子デヌタも䜿甚したす。これにより、バヌゞョン2はバヌゞョン1および6よりもランダム性が䜎くなり、タむムスタンプの䜿甚が少なくなりたす。その結果、特定の時点で生成できるUUID v2の数は限られおおり、ほずんどの甚途においおあたり望たしくありたせん。これが䜿甚されるこずは皀であり、通垞、ほずんどのラむブラリでサポヌトされおいたせん。これは、UUID仕様にも蚘茉されおいたせん。 バヌゞョン3ず5 バヌゞョン3ず5は他のUUIDずはたったく異なりたす。他のバヌゞョンはランダム性を目指しおいたすが、バヌゞョン3ずバヌゞョン5は決定論的であるこずを目指しおいたす。これはどういう意味でしょういずれもハッシュアルゎリズムを䜿甚しおUUIDを生成するため、UUIDを再珟可胜にしたす。UUIDを生成するためにランダム性やタむムスタンプは䜿甚されず、䞎えられた入力は垞に同じUUIDを生成する必芁がありたす。バヌゞョン3ではMD5ハッシュアルゎリズムを䜿甚し、バヌゞョン5ではSHA1を䜿甚したす。 これらのバヌゞョンは、同じ入力デヌタから同じUUIDを繰り返し生成する必芁がある堎合に特に䟿利です。䟋えば、ナヌザヌの電子メヌルアドレスに基づいおナヌザヌのUUIDを䜜成するずしたす。異なるサヌバヌや時間にわたっおも、同じ電子メヌルで垞に同じUUIDが生成されるようにしたいずしたす。もう1぀の良い䟋ずしおは、重耇を避けるために䜕らかのデヌタに基づいお䞻キヌを生成する必芁があるが、デヌタ自䜓を䞻キヌずしお䜿甚するのは良い遞択肢ではない堎合が挙げられたす。 バヌゞョン3ずバヌゞョン5のいずれかを遞択する堎合、SHA1の方が少し安党ですが、蚈算負荷も倧きくなるこずに留意しおください。それがナヌスケヌスで懞念事項である堎合は、バヌゞョン3を䜿甚しおコンピュヌティングリ゜ヌスの䜿甚量を削枛するこずをお勧めしたすが、ほずんどの堎合、より安党なバヌゞョン5を遞択すべきです。たた、SHA1よりもMD5ず衝突が発生する可胜性が高くなりたすが、その確率は䟝然ずしお非垞に䜎いです。 バヌゞョン4 バヌゞョン4は、UUIDの最も広く䜿甚されおいるバヌゞョンです。バヌゞョン4はランダムビットを䜿甚しおUUIDを生成するため、UUIDは䞀意で予枬䞍可胜になりたす。これは乱数発生に倧きく䟝存しおいたすが、すべおの乱数発生噚が実際に真の乱数を生成できるわけではありたせん。衝撃的ですよね。 倚くのプログラミング蚀語では、疑䌌乱数発生噚(PRNG)ず呌ばれるものを䜿甚しおいたす。ほずんどの堎合はこれで問題ありたせんが、UUID生成の堎合は、システムが暗号論的にセキュアな疑䌌乱数生成噚(CSPRNG)を䜿甚しおいるこずを確認する必芁がありたす。 なぜかっお?通垞のPRNGは、出力を十分に分析すれば予枬可胜になる堎合がありたす。䞀方、CSPRNGは、攻撃者が以前に生成されたすべおの倀を知っおいる堎合でも、その出力を予枬するこずが事実䞊䞍可胜になるように特別に蚭蚈されおいたす。最近のUUIDラむブラリのほずんどがデフォルトでCSPRNGを䜿甚しおいたすが、念のため確認しおみる䟡倀はありたす。 他のバヌゞョンず同様に、予枬可胜な郚分はバヌゞョンむンゞケヌタヌのみなので、その郚分を掚枬しお友達を感心させおみたしょう。 これらは、倧量のUUIDを生成する必芁があり、埌で䞊べ替えたり再珟したりする必芁がない堎合など、ほずんどの甚途に最適です。これらは、デヌタベヌスにおいおキヌずしおよく䜿甚されたす。 バヌゞョン7 バヌゞョン7は、バヌゞョン4を時系列順に䞊べ替えられるバヌゞョンずしお蚭蚈されおいたす。バヌゞョン4ず同様に、バヌゞョン7はランダムビットを䜿甚したすが、タむムスタンプを含むため、UUIDは゜ヌト䞊び替え可胜か぀䞀意になりたす。䞀意性を保ち぀぀、䜜成時間によっお䞊べ替えたい堎合に、バヌゞョン7はバヌゞョン4の優れた代替手段ずなりたす。 バヌゞョン7でもタむムスタンプに゚ポックタむムを䜿甚したすが、バヌゞョン1ず6では1582幎10月15日以降、100ナノ秒間隔の数倀を䜿甚しおいたす。これにより、バヌゞョン7での䜜業が少し簡単になっおいたす。 バヌゞョン8 バヌゞョン8はカスタムなので少し特殊です。ベンダヌは垌望どおりに実装できたす。バヌゞョン8を自分で実装するこずもできたすが、UUIDの3番目の郚分にあるUUIDバヌゞョンを尊重する必芁がありたす。おそらくそれを䜿甚する必芁はないでしょう。 では、䜕を䜿甚すればよいでしょうか? ほずんどの人にずっお、バヌゞョン4になりたす。バヌゞョン4は、䞀意性の保蚌が最も倧きく、比范的安党です(乱数発生噚が予枬䞍可胜な限り)。UUIDを䜜成時間によっお䞊べ替えられるようにしたい堎合は、MACアドレスの挏掩によるプラむバシヌの懞念がない限り、バヌゞョン7たたはバヌゞョン6を䜿甚できたす。堎合によっおはバヌゞョン3ず5が䟿利ですが、ほずんどのアプリケヌションではそれらの䜿甚は制限されたす。 デヌタベヌスキヌ? デヌタベヌスキヌにUUIDを䜿甚するこずに関する議論を芋たこずがあるかもしれたせんが、デヌタベヌスキヌにUUIDを䜿甚するこずを怜蚎しおいる堎合は、芚えおおくべき事実がいく぀かありたす。 UUIDは倧きく、128ビットを占めたす。倧量のデヌタを保存する予定がない堎合は、UUID甚に远加で占有されるスペヌスが倧きくなる可胜性がありたす。あるいは、32ビットの自動増分敎数オヌトむンクリメント敎数では玄2147483647行が埗られたすが、それでも足りない堎合は、64ビットのBIGINTで最倧18446744073709551615になりたす。ほずんどのナヌスケヌスの堎合、これで十分でしょう。 䞀郚のデヌタベヌスでは、キヌにUUIDを䜿甚するず、挿入性胜が䜎䞋する可胜性がありたす。挿入性胜が懞念される堎合は、自動増分敎数の䜿甚を怜蚎するか、少なくずもUUIDを䜿甚しおデヌタベヌスの性胜をテストするこずをお勧めしたす。 UUIDは、デヌタの移行を容易にしたす。自動増分敎数を䜿甚するず衝突が発生したすが、UUIDではその問題は発生しないでしょう。 䞀郚のUUIDは゜ヌト䞊び替え可胜ですが、読みやすくはありたせん。2぀のUUIDに着目するず、どちらが先に来たのかを知るのは非垞に困難です。これは非垞に些现なこずですが、留意すべきです。 ほずんどのデヌタベヌスには、UUIDを生成するための䜕らかのモゞュヌルたたは関数があるため、デヌタベヌスのドキュメントをチェックしおUUIDの生成方法を確認できたす。UUIDを䜿甚する際に性胜䞊の問題や考慮すべき特別な事項がある堎合は、おそらくそこで刀明するでしょう。 結論 この蚘事を読む前よりも、UUIDずそれらのさたざたなバヌゞョンに぀いお少し理解が深たったず思いたす。 バヌゞョン4 UUIDは、ほずんどのアプリケヌションで䟝然ずしお定番です。バヌゞョン4 UUIDは、匷力な䞀意性保蚌ず予枬䞍可胜性を備えおおり、おそらくこれがUUIDに求められるものです。バヌゞョン4 UUIDは䞻に、デヌタベヌスキヌ、分散システム、および調敎なしでグロヌバルに䞀意な識別子が必芁なシナリオで䜿甚されたす。 バヌゞョン7は、ランダム性ず゜ヌト䞊び替え可胜性ずのバランスが取れおいるため、時系列的゜ヌトが望たしい堎合に適した代替手段です。 バヌゞョン1ず6は、グロヌバルな䞀意性が必芁な分散システムでは圹立ちたすが、MACアドレスが含たれるためプラむバシヌに関する懞念を䌎いたす。 バヌゞョン3ず5は、特定の入力からUUIDを再珟する必芁がある堎合に䟿利ですが、MD5はSHA1ほど安党ではないこずに泚意しおください。 自分のシステムでUUIDを䜿甚する予定の堎合は、UUIDバヌゞョンを遞択する際に次の芁玠を考慮しおください。 䞀意性に関する自身の芁件 時系列的゜ヌトが必芁か吊か プラむバシヌに関する懞念 (特に MACアドレスを含むバヌゞョンを䜿甚する堎合) ストレヌゞ スペヌスの制玄 (あなたのキヌに128ビットは必芁ないかもしれたせん) UUIDの衝突は理論的には起こり埗たすが、暗号的に安党な乱数発生噚を䜿甚した適切な実装をしおいる限り、その可胜性は非垞に䜎いため、システム蚭蚈においお倧きな懞念事項にはならないはずです。UUIDの衝突が発生した堎合(倩文孊的な確率を芆した堎合!)、実際のUUID生成衝突ではなく、重耇したむベント凊理などのアプリケヌションロゞック問題が原因である可胜性が高くなりたす。そのような堎合は、UUID生成自䜓に疑問を抱くよりも、アプリケヌションの䞀意性制玄の凊理を調べるこずに重点を眮いおください。
はじめに こんにちは、AIファヌストグルヌプのAlexです。 AI技術の急速な発展に䌎い、゚ヌゞェント開発の需芁も高たっおいたす。しかし、゚ヌゞェントに関する最新技術の知芋の共有䞍足や、開発リ゜ヌスの分散により、効率的な゚ヌゞェント開発を始めるこずが難しい状況にありたす。そこで私たちは、瀟内各所で開発したAI゚ヌゞェントを瀟内で共有し、技術・ノりハりを集玄するためのプラットフォヌム「Agent Store v1.0」をリリヌスしたした。 Agent Storeの目的 Agent Storeは以䞋の2぀の䞻芁な目的を持っおいたす 瀟内Agent開発の効率向䞊 既存Agentの再利甚により開発サむクルを短瞮 テンプレヌトを掻甚した迅速な開発を実珟 技術・ノりハりの蓄積 瀟内のAgent関連技術を䞀元管理 ベストプラクティスの暪展開を容易に 利甚圢態ず察象ナヌザヌ Agent Store は、瀟員が AI ゚ヌゞェントを自由に開発、共有、ダりンロヌドしお再利甚するプラットフォヌムです。 なお再利甚に関しおは、App Storeのように、ナヌザヌが゚ヌゞェントをダりンロヌドし、自身の環境にデプロむするこずを想定しおいたす。 Agent Storeは以䞋の芁玠で構成しおいたす。 瀟内で開発した゚ヌゞェントを共有するGithubリポゞトリ ゚ヌゞェント開発のCI/CDの仕組み Agent StoreのGithubリポゞトリ 利甚圢態 Agent Store v1.0では䞻にAWS Bedrock゚ヌゞェントをサポヌトしおいたす。 ゚ヌゞェントのCI/CDプロセスに関しおは、IaC (Infrastructure as Code)を基づいお蚭蚈したした。 Agent Storeで共有された゚ヌゞェントは、CloudformationでデプロむするためのSAMテンプレヌトの圢でAgent StoreのGithubリポゞトリ䞊で栌玍されおいたす。 ゚ヌゞェントを再利甚したいナヌザヌは、該圓する゚ヌゞェントのSAMテンプレヌトをダりンロヌドし、Cloudformation経由で自分の環境にデプロむする圢で利甚したす。 なお、デプロむに関しおはGithub Actionsで自動化しおいたす。 ゚ヌゞェントを新芏開発したいナヌザヌに関しおも、Agent Storeが提䟛しおいる空のSAMテンプレヌトを利甚し、玠早く゚ヌゞェント開発するこずが可胜です。 察象ナヌザヌv1.0 AWS Bedrockを利甚しお゚ヌゞェント開発を始めたい゚ンゞニア Bedrockで開発した゚ヌゞェントを瀟内で共有したい゚ンゞニア 既存の゚ヌゞェントを探しお掻甚したい゚ンゞニア 想定するナヌスケヌス Agent Storeは以䞋のような利甚シヌンを想定しおいたす AI゚ヌゞェントの新芏䜜成 Agent StoreのCI/CDフロヌを利甚するこずで開発の高速化を実珟 AI゚ヌゞェントの共有 自䜜゚ヌゞェントを瀟内で共有 共有されたAI゚ヌゞェントの再利甚 既存プロダクトにAI゚ヌゞェントを搭茉 瀟内業務効率化アプリの開発 䞀からの開発を避け、開発効率の向䞊を実珟 AI゚ヌゞェントのPoC 既存゚ヌゞェントをデプロむしお迅速にPoC実斜 効果怜蚌の時間短瞮 AI゚ヌゞェント開発ノりハりの取埗 類䌌事䟋の参照によるベストプラクティスの孊習 技術的な障壁の䜎枛 Agent Storeを掻甚した゚ヌゞェント開発、共有ず再利甚のフロヌ ゚ヌゞェントを新芏開発するフロヌ Agent Storeリポゞトリから空のSAMテンプレヌトを取埗し、蚘入した䞊でデプロむを行う流れずなりたす。 SAMに぀いおは こちら を参照しおください。 なお、゚ヌゞェントのAction Groupを利甚する堎合、①Lambda、②゚ヌゞェントの順番でテンプレヌト蚘入・デプロむを行う必芁がありたす。 ゚ヌゞェントを共有するフロヌ 開発した゚ヌゞェントのSAMテンプレヌトを甚意し、Agent Storeのリポにプルリクを実行したす。゚ヌゞェントのレビュヌ担圓者にお内容を確認埌、問題なければマヌゞを行いたす。 共有された゚ヌゞェントを新たに再利甚するフロヌ 基本の流れぱヌゞェントを新芏開発するフロヌず共通しおいたすが、Agent Storeで共有されおいる゚ヌゞェントのSAMテンプレヌトを取埗し、必芁に応じお修正・加筆を行った䞊でデプロむを行う流れになりたす。 ゚ヌゞェントのアヌキテクチャ ゚ヌゞェントのアヌキテクチャは以䞋です。 デプロむしたBedrock゚ヌゞェントは、必芁に応じでAction Groupずしお蚭定されたLambdaを呌び出し実行するこずができる。 たた、スタック管理はCloudFormationで行っおいる。 たた、耇数の゚ヌゞェントが協働するマルチ゚ヌゞェントコラボレヌションも構築するこずが可胜です。 今埌の展開蚈画 今埌は、Agent Storeの利甚促進のために、瀟内勉匷䌚、ワヌクショップ、ハッカ゜ンなどを倚数䌁画しおいたす。 たた、珟圚のv1.0は「AWS Bedrockの開発経隓がある゚ンゞニアタむプa」を察象ずしおいたすが、今埌は段階的に察象ナヌザヌを拡倧しおいく予定です ナヌザヌの皮類 詳现 サポヌト状況 ゚ンゞニア タむプa AWS Bedrockの開発経隓がある゚ンゞニア v1.0でサポヌト䞭 ゚ンゞニア タむプb AWS Bedrock以倖の゚ヌゞェント開発環境を利甚したい゚ンゞニア 怜蚎䞭 非゚ンゞニア、゚ヌゞェント開発初心者 開発・コヌディング経隓がない、非゚ンゞニアの瀟員 怜蚎䞭 たずめ Agent Store v1.0は、゚ヌゞェント開発の効率化ず知芋共有を実珟するプラットフォヌムです。珟時点ではAWS Bedrockナヌザヌ向けに機胜を提䟛しおいたすが、今埌はより幅広いナヌザヌ局ぞのサポヌトを拡倧し、様々な゚ヌゞェントフレヌムワヌクにも察応しおいく予定です。瀟内のAI開発リ゜ヌスを最倧限に掻かし、むノベヌションのペヌスを加速させるため、Agent Storeの機胜拡充ず進化に積極的に取り組んでいきたいず思いたす。