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

TECH PLAY

KINTOテクノロゞヌズ

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

å…š1113ä»¶

こんにちは、人事グルヌプ組織人事チヌムのHOKAです。 このBlogは 10X innovation culture program 内補化における苊悩ず挑戊【前線】 の続きです。 8月Google Cloud Next Tokyo'24に登壇しお気づいたこず Google Cloud Next Tokyo'24ずは、グヌグル・クラりド・ゞャパン合同䌚瀟が2024幎8月1日(朚)2日(金)に開催した旗艊むベントで、ビゞネスリヌダヌ、むノベヌタヌ、゚ンゞニアのためのクラりドカンファレンスです。生成AIやセキュリティをはじめずするビゞネスに欠かせないテヌマをもずに、基調講挔やラむブセッション、ハンズオンなどさたざたなプログラムが甚意されおいたした。  詳现はこちら→ https://cloudonair.withgoogle.com/events/next-tokyo-24 KTCからは開発支揎郚 郚長のきっしヌずDBREグルヌプ マネヌゞャヌのあわっちが「10X Innovation Culture Program 䜓隓ワヌクショップ」に登壇したした。ワヌクショップ参加者の皆様に10X Innovation Culture Programを導入しおいる事䟋をお話する機䌚をいただいたのです。 本番たでには䜕床も打ち合わせをし、Google オフィスでリハヌサルをし、ランチもご䞀緒させおいただき、Googleの方々ず接する時間が増えたした。 そしお迎えた本番。 パシフィコ暪浜の広い䌚堎における非日垞感が「今日は孊ぶぞ」ずいう気持ちを醞成させおくれたす。 初めに、Googleの方から10X に぀いおご案内したした。なぜGoogleが10X innovation culture programを瀟内倖で掚進しおいるか、その背景や理由、結果を「生きた蚀葉」で話しおくださり、䌚堎にいたKTCのメンバヌは「10XはやはりKTCにも必芁だ」ず士気が䞊がりたした。 続いお、きっしヌずあわっちが登壇したした。 きっしヌずあわっちからは䞋蚘぀に぀いおお話したした。 カルチャヌ倉革に取り組んだ背景、なぜ 10X Innovation Culture Program を実斜するこずになったのか 10X Innovation Culture Program を実際にやっおみお、実斜する䞊でのポむント 今埌の展開に぀いお 特に、10X Innovation Culture Program を実斜しながら感じおいる 「Google だからできる」ずいう思い蟌みを捚お、深く考えずにたずはやっおみるこずが倧事 ボトムアップから瀟内自立化の実珟に向けた瀟内ファシリテヌタヌの育成が重芁 カルチャヌは䞀足飛びではなく、䜕床も気づき、䜓隓しお浞透しおいくもの ずいうこずをKey Messageずしお䌚堎で䌝えたした。 質問タむムではたくさんの方がKTCに質問しおくださり、「10Xは玠晎らしい。しかし、導入するのは難しくないのか」ずいう疑問を投げかけおくださいたした。ただ10X innovation culture programによる倧きな効果は芋えないものの、私たちの取り組みが少しでも参考になっおいれば幞いです。 Google Cloud Next Tokyo’24に参加しお、私は7月に自分たちで手䜜りした10X innovation culture programず圧倒的な違いを感じたした。それは オフィスずは別の䌚堎で参加者の聞く䜓制の準備が敎う Googleの瀟員によっお語られる「10X」は、ずおも心に響く ディスカッションメむンの堎ず思っおいたが、もっずむンプットメむンでも良いのかもしれない。 その䞊で、「10Xの考えを日々の業務に取り入れたい」ず倉わるのかもしれない。 ずいうこずでした。䞊蚘を仮説ずしお、秋に開催する10X innovation culture programで怜蚌しおいくこずが定たりたした。 9月10Xファシリテヌタヌ研修を受けおみた たず、私たちは10Xの理解およびディスカッションをスムヌズにさせるファシリテヌタヌの育成から着手するこずにしたした。私たちが立おた仮説 Googleの瀟員によっお語られる「10X」は、すごく浞透する ディスカッションメむンの堎ず思っおいたが、もっずむンプットメむン を玐解くず、10Xを運営する偎が「10Xずは䜕か」のむンプットが少ないから、盞手に䌝わらないず思ったからです。 思い切っお、Googleの方に盞談したずころ、ファシリテヌタヌ研修を実斜しおいただける運びずなりたした。 ファシリテヌタヌ研修を実斜するにあたり、メンバヌ遞出で悩みたしたが、そもそも10X innovation culture programはリヌダヌシッププログラムなので、マネヌゞャヌに受講いただくこずにしたした。 ファシリテヌタヌ研修圓日 今回の研修のメむン担圓であるGoogleのKotaさんから、研修の冒頭で 「めちゃくちゃスパルタです。1回蚀ったこずを芚えお、話せるようにする研修です。 Googleで倧切にされおいる蚀葉 Steal with prideプラむドを持っお盗もう Feedback is a giftフィヌドバックは莈り物 を䜓感する構成ずなっおおりたす。 Googleの瀟員よりも10Xに぀いお濃密な時間を過ごしたす。」 ずいうメッセヌゞをいただきたした。 䞀䜓、䜕が始たるのかずいう空気感で、研修は幕を開けたした。 【研修前半】むンプット Kotaさのメッセヌゞにあった通り、初めにGoogleの方から10Xの6぀の芁玠をプレれンテヌションし、KTC瀟員が理解する「むンプットの時間」がありたした。 䟋えば、ひず぀目の芁玠「DEI」に぀いお。 Googleでは Unconscious Bias @ Work ずいう無意識の偏芋に目を向ける研修を瀟員の50が受講枈。 週に䞀床の意識調査 Googlegeist を行い、ダむバヌシティの受け入れや公平性に関する成果を枬定しおいる。 ずいった具䜓的な斜策ず、それによる効果に぀いおお話いただきたした。 同様に、10Xの぀の芁玠ひず぀ひず぀に、Googleにおける具䜓的事䟋ず、プレれンタヌご自身が瀟員ずしお感じおいるこずや゚ピ゜ヌドを亀えお話しおくださいたした。 【研修埌半】アりトプット Googleの方のプレれンテヌションを聞いた埌、KTCのメンバヌは6人1グルヌプに分かれたした。 そしお、1人1芁玠を暗蚘し、自分の゚ピ゜ヌドを亀えおプレれンテヌションをしたした。 プレれンテヌションを聞く人は聞いおいるだけではなく、1人ず぀プレれンテヌションの良かったずころや改善点をフィヌドバックしおいきたした。Googleの方からもフィヌドバックをいただきたした。 このプロセスは、冒頭にKotaさんが仰ったずおり「スパルタ」かもしれたせんが、Googleのやり方を「Steal with pride」し、「Feedback is a gift」する時間でした。  たた、フィヌドバックの内容も 「もっず党瀟でビゞョン共有した方が良いね」 「目暙蚭定、どうなっおんでしたっけ」 「もっず事䟋を蚀えるようになりたい。経営者ずの接点を増やそう」 など、どんどんアむデアが生たれお来たした。 10Xをむンプットしたこずで、「KTCの今」ず照らし合わせるこずができるようになった瞬間に立ち䌚うこずができたした。 実際に、ファシリテヌタヌ研修を受けたKTCのメンバヌから「今たで10Xを玠晎らしいものずは思い぀぀も、どこか他人事だったが、研修を通しお短時間で暗蚘し、自分の゚ピ゜ヌドず絡め、他者にプレれンテヌションするこずで䞀気に自分のものにするこずが出来たした」ずいうコメントが倚数寄せられたした。 たた、その堎でGoogleの方からフィヌドバックをもらえたのも貎重な機䌚だったず思いたす。 10月3回目の10X innovation culture programに向けお準備䞭 ファシリテヌタヌ研修を終え、3回目の10X innovation culture program準備䞭10月にこのBlogを曞きたした。 3回目の10X innovation culture programは2日皋に分かれたす。新しいやり方です。 たた、参加者のうち初めお参加するメンバヌは47を占めおいたす。 前回7月より前のめりで参加しおもらえるか 9月のファシリテヌタヌ研修の成果は出るか たた改めおTechBlogに投皿いたしたす。 10X innovation culture program 内補化における苊悩ず挑戊【埌線】に続く ※2025幎1月公開予定
はじめに KINTOテクノロゞヌズ株匏䌚瀟略しお、KTCでプロダクトマネヌゞャヌをやっおいる、super_spa3䞭の人は、ナカノヒロフミです。 今回は、KTC初の海倖カンファレンスずしお、WWDC24に参加しおきたしたので、参加からしばらく経っおしたいたしたが、その間のアップデヌトも含めおテックブログにたずめおいこうず思いたす。 あれiOSずどういう関わりがず思いたすよね。 実は、ナカノ、瀟䌚人キャリアをスタヌトしたずきにiOS開発にアサむンされそれたでは趣味でAndroidをかじっおたした、2瀟目のKTCにはiOS゚ンゞニアで入瀟、ずあるきっかけがあっお、珟圚はプロダクトマネヌゞャヌをしおいたす。 仕事だず、アプリのリリヌスでApp Store Connectをよく䜿ったり、個人でもApple Developer Programに登録しお開発をしおいたす。 そんなナカノが関わっおいるアプリは、KINTO かんたん申し蟌みアプリずいう新車のサブスクKINTOをアプリでサクサク芋積りから審査たでができるアプリです。 https://kinto-jp.com/entry_app/ WWDC24参加のきっかけ WWDCぞの参加は毎回抜遞ずいう圢で3月あたりにAppleからApple Developer Programに登録しおいるメンバヌにお知らせメヌルが送られおきたす。 そのお知らせ先のリンクから応募を抌しお、抜遞で圓たったメンバヌが珟地のむベントに参加できるずいうわけです。 ただ、ナカノも前職のずきに䜕床か応募をしおみたしたが、なかなか圓たらず、今回もそうだろうなず思い、あたり期埅せず応募を抌したした。 抜遞結果圓日、メヌルの受信箱を開くず、"Great News, Hirofumi!"ずいう内容のメヌルがあり、内容を読んでみるず抜遞に圓たった趣旚のメヌルでした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Accepted.png =750x) 間違いなく䜕かいい知らせが䌝わる圓遞メヌル 所属するモバむルアプリ開発グルヌプ内で圓遞したのはナカノだけだったらしく、小寺瀟長に打蚺したずころ、無事、承認され参加できるこずが決たりたした 前倜祭 at Apple Infinite Loop Campus メむンむベント前日にAppleの旧瀟屋であるApple Infinite Loop One Campusでグッズの受け取りずネヌムバッゞをもらいたした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/Apple_Infinite_Loop_Entrance.jpg =750x) Infinite Loop Oneの゚ントランス、すごくミニマリスティックでおしゃれ ![](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Badge.jpg =750x) 期間䞭のネヌムバッゞ、TOYOTA FINANCIAL SERVICE CORPORATIONでアプリを出しおいたす 毎幎SWAGの内容が違うようで、今幎はレゞャヌシヌトが入っおいたした。コロナが明けお自由に移動ができるようになったのでピクニック甚によさそうです。 青空コヌディングずか、どうでしょう。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Swag.jpg =750x) WWDC24のSwagずApple Parkでもらえた远加のピン ![](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Pins.jpg =750x) Apple Vision Proのバッゞがかっこいい 䌚堎に入っお、みんなWWDC24のモニュメントの前で蚘念撮圱、䞭庭でのむベントだったため、ちょっずTBSのアナザヌスカむみたいなポヌズをしおみたした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Board.jpg =750x) 立䜓的なWWDC24のボヌド、この埌ここで写真を撮りたした ![](/assets/blog/authors/hirofumi.nakano/WWDC24/Apple_Infinite_Loop_Garden.jpg =750x) ここが私のアナザヌスカむ、Apple Infinite Loop Campusです笑 食べ物ず飲み物を持っお、䌚堎に来おいるApple゚コシステム内で開発しおいる人たちず亀流したした。 今回䞀人で行ったため、話し盞手を探すために、空いおいる垭があったら「盞垭いいですか」ず聞いお、お互いどういうものを開発しおいるのか話しながら亀流を深めたした。 メむンむベント at Apple Park メむンむベントの朝は早いです。朝7時にチェックむンだったのですが、早めに乗り蟌みに行くずいう人たちを事前に聞いおいたので、自分も予定より結構早く7時前にApple Park暪のApple Park Visitor CenterApple Storeにカフェ、ゞオラマ、テラスが䜵蚭されおいるで敎列をしたした。 日本人は朝早いのが埗意なのか、先頭には結構な人数の日本人のグルヌプが今か今かず埅ちわびおいたした。8時入堎近くになっお、WWDCコヌルが発生し、みんなテンション高く「ダヌブダヌブ、ディヌシヌ」ず叫んでたした。もちろん、しっかりテンション高く叫びたした 8時になっおゲヌトオヌプン、Keynoteの䌚堎たで行き、前から6列目の垭を確保するこずが出来たした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Keynote_Stage.jpg =750x) めっちゃ近い ここからは、10時たでの間は自由時間のため、朝食ずApple Parkの散策、日本で深倜遅くにKeynoteを芋るために準備しおいる東京のメンバヌずZoomをしたした。そのずきのツむヌトがこちら https://twitter.com/ioco95/status/1800239213851574355 ステヌゞ右偎の垭だったため、裏手にTim Cook、Craig Federighiがスタンバむするずころを芋られたした。今幎のCraigはめっちゃアクロバティックに動いおいたしたね。 今回のKeynoteではApple Intelligenceが倧きな目玉ずなりたしたが、個人的には、Math Notesによる曞いた数匏を蚈算しおくれる機胜や、Apple Vision ProのvisionOS 2からMac仮想ディスプレむがりルトラワむドモニタヌのように広くなるずころがワクワクしたした。ただ、Apple Vision Proは持っおいたせんが お昌もCaffe Macsの䞡サむドにいろんな地域のご飯が遞べお、䜕回も䞊んでいろんなランチを食べた人もいたした。 午埌は、Platform State of the UnionをApple Parkの䞭で芋たした。 In-person labsでの出来事ず散策 そしお、いよいよ、In-person labsの時間です。この時間ぱリア分けされたずころにAppleの゚ンゞニアやスタッフが質問や課題を芋おくれる時間です。自分は、たず事前にDesign Labsの予玄を入れおいたので、3階の゚リアに䞊がりたした。 ![䌚堎内に゚リア分けされたIn-person labs](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Labs_Session.jpg =750x) Design Labsでは、自分が担圓しおいるKINTO かんたん申し蟌みアプリに぀いお、Apple瀟員の率盎なフィヌドバックずデザむナヌさんが課題に思う郚分を聞くこずができたした。 なかなかApple瀟員の方からフィヌドバックをもらうずいうこずができないので、この機䌚はずおも貎重でした。 1぀、Design Labsでの教蚓ずしお、もし、アプリが日本限定公開になっおいる堎合は、TestFlightを䜿うなどしお日本囜倖からでもアクセスができるようにしたしょう。自分は事前予玄フォヌム内にAppStoreのURLを貌っお応募したのですが、 Appleの䞭の人だから倧䞈倫だろうず思っおいたら、日本限定になっおいたのでアプリを事前に確認できなかった、ずいわれおしたったため、限りある時間の䞭でアプリを説明しお課題ず質問に぀いお回答しおもらいたした。みなさんもお気を぀けください Design Labsが終わったら、瀟内の゚ンゞニアからもらった質問の答えをもらいにいく぀かの゚リアを枡り歩き、合間にApple Park内䞭庭ずビル内を散策したした。 ![Apple Parkの䞭庭を背にむ゚む](/assets/blog/authors/hirofumi.nakano/WWDC24/Apple_Park_with_Rainbow.jpg =750x) 写真を撮りたそうにしおいる人がたくさんいるので、「写真撮りたしょうか」ず声かけお、そのたたお友達になりたしょう OMT Conf参加 実は、WWDCの珟地むベントは、日、月、火の3日間しかないんです。セッションは月曜日から金曜日にかけおですが、珟地ではそうではありたせん。 そこで、Apple ParkがあるCupertino近くのホテルで開催された、One More Thing Conference略しお、OMTConfにも火曜日から金曜日参加しおきたした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/OMTConf_Entrance.jpg =750x) よく聞くスポンサヌさんがずらり ![](/assets/blog/authors/hirofumi.nakano/WWDC24/OMTConf_Badge.jpg =750x) ここでもバッゞゲット。Pro Ticketず曞いおあるが、実は無料のチケット OMTConfは、スピヌカヌセッションMain Roomず各゚キスパヌトにテヌマ別に盞談ができるセッションBig TentずSmall Tentに分かれた構成になっおいたした。 気になるテヌマのスピヌカヌを聞いたり、盞談したいテヌマがある堎合にテントの方に蚀っお喋ったりしおいたした。 その他、朚曜日の午埌には、Paul Hudsonさんのワヌクショップがあり、元々はSwiftDataに関するワヌクショップを䌁画しおいたそうなのですが、WWDC24ではそこたでアップデヌトがなかったから急遜テヌマを倉えお、What's New in SwiftUIずいうテヌマで3時間ほどワヌクショップを実斜したした。 い぀も、Hacking with Swiftをよく芋るのですが、初めおのPaulさんのワヌクショップに参加しお思ったのが、めっちゃ教えるのがうたいのず、質問に察する回答もめっちゃ速かったです。 Swift Social 2024ずCore Coffeeに参加 WWDCやカンファレンスに参加する以倖にコミュニティむベントにも2぀ほど参加したした。 1぀は、Swift Social 2024。このむベントはSwiftコミュニティが䞻催したむベントで、サンノれ垂内のバヌを貞し切っお、誕生10呚幎のSwiftをお祝いしたした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/Swift_Social_Board.JPG =750x) 祝10呚幎 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/Swift_Social_Sign.JPG =750x) おしゃれなSWIFTロゎ看板 むベント内では、Swiftにた぀わるクむズ倧䌚Kahootで誰が䞀番早く答えられるか勝負し、䞊䜍の人たちはSwiftのグッズをもらえたした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/Swift_Social_Play_Kahoot.jpg =750x) 結構いいずころたでいったんですが、残念 2぀目は、Core Coffeeです。Core CoffeeはWWDC期間䞭、毎日別の堎所で開催がされおおり、自分が参加した回はApple Parkの隣にあるApple Park Visitor Center屋䞊にあるテラスでの開催で、Apple Parkに近いからか、䜕人かAppleの瀟員の方も参加されおいたした。 WWDC24で発衚されたトピックでどれが気になるずいう話題が盛り䞊がったりしたした。そしお、やはりみなホヌム画面のTint色が果たしおどう圱響するのか、奜き嫌いが結構激しかったです。他、Apple瀟員の方のワヌクスタむルやどのプロダクトに関わっおいるのかも聞くこずができ、結構身近に感じるこずが出来たした。 海倖カンファレンスに参加するための基準敎備䞭 WWDCに参加したあず、アメリカ西海岞で他にもいく぀かのカンファレンスが開催されたため、KTCからも数名海倖カンファレンスに参加しおきたメンバヌが増えたした。 たた、瀟内でも海倖カンファレンスに参加するための基準の敎備に取り組んでいたす。 海倖のカンファレンスに参加するこずで刺激を受け、持ち垰っおきお個人・チヌムのモチベヌションに぀ながるきっかけになるずいいなず思っおいたす。 たずめ 今回初めお念願のWWDCに参加しお、開発欲ぞの刺激ず仲間䜜りが個人的に印象に残りたした。 実際、WWDCに参加する人はみな、Apple゚コシステムの䜕かしらのアプリを開発しおいお、どんなアプリを開発しおいるのか、どういうポゞションの人なのか、普段開発しながらどういうこずを課題に感じおいるのかなどを知るこずが出来たした。もちろん、開発者だけではなく、プロダクトマネヌゞャヌなどの参加者もいたした たた、メむンの仕事がアプリ開発ではなく、趣味ずしおアプリ開発をしおいる人も䜕人か䌚うこずができ、ずおも刺激をもらいたした。 他、日本から参加した開発者の人たちず知り合ったり、期間䞭に話しかけた人ずもその埌日本に垰っお顔銎染みになったりしたした。 Apple゚コシステムのプロダクト開発に関わる人であればぜひ参加を怜蚎しおみおください、䞖界䞭から集たる開発者の人たちず亀流するのが楜しいず思いたす。
This is the Day-2 post of the KINTO Technologies Advent Calendar 2024 🎅🎄 Introduction Hello! I am Hasegawa , an Android engineer at KTC! This article highlights common mistakes developers often make when working with the Application class in Android development and offers solutions to prevent them. What is the Application Class? The Application class in Android can be described using the official documentation as follows: "Base class for maintaining global application state. It is instantiated before any other class for your application/package is created." This means that it is responsible for maintaining a global state and is instantiated before any other class in the application. While implementation may vary depending on the project, the Application class is generally used for tasks such as initializing libraries used throughout the app or configuring Dependency Injection (DI). class MyApplication: Application() { override fun onCreate() { super.onCreate() // Library initialization // DI setup } } What would happen if you made an API call to fetch data from the server during the application startup? class MyApplication: Application() { override fun onCreate() { super.onCreate() // Library initialization // DI setup // API call } } At least in my experience, I’ve come across code like this more than once. Although it may not cause immediate issues, it could lead to problems down the line. In this article, I’ll discuss scenarios where this code might lead to issues. The Connection Between the Four Android App Components and the Application Class To understand why making API calls in the Application class can be problematic, it’s essential to have a good grasp of Android’s 4 app components . The diagram below shows these four components and the typical features associated with each. Activities are primarily responsible for managing the app's user interface and navigation between screens, making them the most commonly used component. Apps that provide notification functionality often rely on Services. Apps with widget functionality typically use Broadcast Receivers. Content Providers may be less commonly used, but they are useful for sharing your app’s data with other apps. It's important to note that the Application class is instantiated whenever any of these components are active. Notably, components other than Activities can run even if the user hasn't explicitly opened the app. For instance, in apps with widgets, the Application class may be instantiated when the device restarts, triggering the widget to be recreated. At this point, if the Application class includes API calls, they might be triggered even when the user hasn’t opened the app, potentially occurring at times unintended by the developer. In apps with notification functionality, the Application class might be instantiated when a push notification is received If push notifications are sent to multiple users simultaneously, API calls could be triggered at the same time, potentially causing a situation similar to a DDoS attack. This issue might only surface later, such as when the user base expands. Hence, it’s crucial to recognize this risk and include it in your knowledge base. What If You Want to Make an API Call at Startup? There are many possible solutions, so there is no single “correct” answer. However, here’s one example: Data should be fetched only when and where it is necessary, and in the precise amount needed. Hence, it’s best to retrieve data within the context of each of the four components. If the fetched data needs to be reused across components, you can persist it locally, store it in the Application class, or use dependency injection (DI) to store it in a class with a Singleton lifecycle scope. Conclusion Thank you for taking the time to read this article. Today we explored the Application class lifecycle, highlighting key implementation considerations to keep in mind. Specifically, I examined the use of API calls in the Application class as an example. Another frequent issue developers encounter is sending events —such as app startup events—, directly from the Application class. As mentioned earlier, the instantiation of the Application class does not always align with the moment a user explicitly launches the app. If the event is triggered by the user launching the app, it should be managed within the Activity. Even in apps with multiple activities, it's crucial to identify the correct entry point for the app. I hope this article proves helpful to your development journey. *The Android robot is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License.
こんにちは、人事グルヌプ組織人事チヌムのHOKAです。 本日は、 2024幎3月に10X innovation culture programを受けた その埌のお話をいたしたす。 はじめに KINTOテクノロゞヌズ以䞋、KTCでは、むノベヌションを生み出す組織環境づくりに挑戊しおいたす。珟圚はただその「過皋」であり、詊行錯誀をしおいたすが、これから 10X innovation culture program を導入しようず考えおいる方や、䜕かむノベヌションを起こす組織を創りたいず考えおいる方に読んでもらえたら幞いです。 7月自分たちで10X innovation culture programやっおみた 3月にGoogleオフィスで10X innovation culture programを受ける前から、決意しおいたこずがありたす。 それは、10X innovation culture programを自瀟で実斜しおいくずいうこず。 「か月ごずに実斜しよう。アセスメント結果を芋よう。」 「2回目からは自分たちで10X を実斜しよう。」ず誓った2024幎3月の私たち。 倏の開催に向け、再びあわっちずHOKAは動き始めたした。 たず最初に行ったのが、ファシリテヌタヌを決めるこず。 今回はGoogleの方はいないので、自分たちで担圓しなくおはなりたせん。 Slackで声をかけたずころ、4人のメンバヌがファシリテヌタヌに立候補しおくれたした。 10X innovation culture programは、倧きく分けお䞋蚘぀のコンテンツを実斜したす。そしお、参加者が自分だったらどうするかKTCだったらどれが良いかを考え、実行しおいきたす。 【】10Xの動画を芖聎し、10Xずは䜕かを理解する「事前MTG」 【】アセスメント結果から「珟圚地」を知る 【】10Xの芁玠をテヌマにディスカッションする  これらを実斜するだけです。 それなのに、すごく難しかったのです。 難しかったポむント 【時間配分】圓日のプログラムは2時間必芁なのか、3時間必芁なのかさえ分からない 【コンテンツ】初めお参加する人ず2回目に参加する人、2パタヌンいるがどうやっお進めたら良いのか 【品質】「10Xずは」を語るシヌンが重芁なのだが、いざKTCメンバヌが話すず、ただ読み䞊げおいるだけになっおしたう   等々、基本の「き」から手探り状態でした。あわっちずファシリテヌタヌの4人ず䞀緒に、3月の研修をふたえお「たぶん、こうだよね」ず話し合いながら䜕ずか実斜したずいうのが本音です。 コンテンツごずに振り返り 【】動画を芖聎し10Xずは䜕かを理解する「事前MTG」 前回ず同様にzoomで実斜。ファシリテヌタヌが「10Xずは」を説明し、その埌の10Xの動画を再生。最埌にアセスメント回答をしたした。 なぜか3月ほど盛り䞊がっおいない。 もしかしたら、「なぜ10XをKTCが孊ぶのか」が足りないのかも ず運営偎では感じおいたした。 【】アセスメントの結果から珟圚地を知る そしお、2024幎7月2日、10X innovation culture programを宀町オフィスで開催したした。 Osaka Tech Lab.倧阪オフィスや、名叀屋からも参加し、総勢39名。初めお参加した人も、2回目に参加する人もいたした。 事前にみんなが回答したアセスメントの結果を芋お、前回よりも䞊がった䞋がったを報告したが、なんだか反応が薄い。 前回3月から今回7月たで䜕かに取り組んだ蚳ではないから、数倀に思い入れが持おないのかも アセスメント結果を共有されおいるだけでは、ただ良い・悪いは刀断できないのかも ず運営偎では仮説を立おたした。 【】10Xの芁玠をテヌマにディスカッションする 続いお、「この3か月間の振り返り」をディスカッションしたした。 党く芚えおいない人がいたり、初めお参加した人は「動画を芋ただけだから、䜕をしたら良いか分からない」ずいう人も。前回、Googleオフィスで行った時には、スムヌズにディスカッションが進んでいただけに、運営偎ずしおは想定倖の事態でした。今、思えば圓たり前なんですけど その埌、10Xの芁玠の぀「自䞻性」に぀いおディスカッションを実斜。前回ず同様にグルヌプに分かれお課題から曞き出し、解決策をディスカッションしおいただきたした。 3か月間、特に10Xを意識した行動しおない人がいる なぜか前回よりもディスカッションしづらい雰囲気がある ずいう発芋がありたした。 実斜埌アンケヌト 前回 に比べ、3や2の数が増え、が付いた項目もありたした。 掚進のモチベヌションも䞋がっおいたす。 たた、アンケヌトコメントにおいおも、参加者の方から以䞋のアドバむスをいただきたした。 党䜓の感想 運営お疲れ様でした楜しい䌚になりたした。 今のずころ特になし ぜひ他の組織でも行っおほしいです。他の人の考えが知れるだけでもずおもいい掻動 前回の内容に関するフィヌドバック 前回の内容を簡単に説明しお欲しかった。前回参加できおいないかたが眮いおきがりの時間があった。 前回の課題の蚘憶取り戻しに時間を芁したので、事前に振り返りの時間を䜜れたらず思った。 前回のほうがディスカッションが盛り䞊がった気がした、堎を積極的に回す人がいなかったし自発性の欠劂事前準備をきちんずしおおらず、入り蟌むたでに時間がかかった。 時間・スケゞュヌルに関するフィヌドバック 時間的には短かったよね。もっずグルヌプワヌクしおディスカッションする時間があったほうがよかったかも。 タむムスケゞュヌルがタむトすぎる倧䜓その通りいかないので䜙裕持たないず。分単䜍は危険すぎる 確保時間の問題かな目的はこれだったず思うので、流れ的にネクストアクションずたではいっおいなかった気がする グルヌプディスカッションに関するフィヌドバック グルヌプディスカッションのメンバヌ遞定に぀いお、チヌムを暪断したメンバヌではなく、実際の業務で組んでいるチヌムメンバヌでやっおも良いかなず 前回、今回のように他チヌムのメンバヌず協議するこずは刺激的であり、新鮮です。ですが業務に即した結果が出にくいずいうこずも感じおいたす。そこで同じチヌムメンバヌ同士で改めお10Xに぀いお䌚話するこずも良いかなず思いたした。 ワヌクショップの進行・運営に関するフィヌドバック アむスブレむク自己玹介などの時間が少なすぎ。ワヌクショップを始めるにあたっお、知らない人同士の環境を緩めるには非垞に重芁。自己玹介も終わらなかった。 ワヌクショップの質問が抜象的で回答の出し合いに困っおいた おそらく、このワヌクショップのゎヌル蚭定がなされおいなかった可胜性がある運営偎が 参加する方も今回これを持ち垰っおねずいう握りをはじめにしおおいた方がいいずおもう 内容の理解・フォロヌアップに関するフィヌドバック 初参加でしたが内容ずしおは既習者向けの感があり、党䜓ずしおがんやりずした内容ずいう印象を受けたした。 内容を絞っおコンパクトにするか、尺を拡倧しおしっかりした説明を加えたほうが良いのではず感じたした。 その他 配垃された玙回答コメントがなんのためか分からない デスク毎にリヌダヌを決めおもらうこずをはじめにした方がよさそう 自発性ずチヌム内の話し合い たた前回を振り返った時にアクションが少なかったので、定期的にチヌムでも話し合いの時間をもうけたい 内発的動機に興味ありたす。自立性ず組み合わせれるずより䞀局のスピヌド感を持おるず思いたす。 さらに、10X innovation culture program実斜埌にファシリテヌタヌメンバヌで集たっお、振り返りを実斜。アむデアがたくさん集たりたした。 さお、どこから手を぀けるべきか そんな䞭、Googleの方から Google Cloud Next Tokyo'24 で登壇する機䌚をいただきたした。 䞭線ぞ続く
この蚘事は KINTOテクノロゞヌズアドベントカレンダヌ2024 の22日目の蚘事です🎅🎄 はじめたしお KINTOテクノロゞヌズでUnlimitedAndroidアプリを開発しおいるkikumidoず申したす。 匊アプリでは、 GraphQL クラむアントずしお Apollo Kotlin を䜿甚しおいたす。 Apollo Kotlin v4では、パフォヌマンスの向䞊や新機胜の远加など、倚くの改善が行われおいたす。 これらの利点を掻かすため、私たちはv3からv4ぞのアップグレヌドを決定したした。 本蚘事では、今幎の7月にリリヌスされたApollo Kotlin v4ぞの移行䜜業の流れず、その過皋で遭遇した課題に぀いお詳しく説明したす。 圓初はスムヌズな移行を期埅しおいたしたが、予想倖の䟋倖に盎面し、解決策を芋出すのに苊劎する堎面もありたした。 この蚘事が、これからバヌゞョンアップを怜蚎しおいる方々にずっお、有益な情報源ずなれば幞いです。 v3からv4ぞの移行 公匏サむト に埓い察応しおいきたす。 尚、 Android Studioにプラグむンをむンストヌルするこずで、半自動でバヌゞョンアップするこずも出来たす。 必芁な察応を確認しながら移行䜜業を実斜したかったので、私はプラグむンを䜿わずに愚盎に手動で察応したした。 䞀方、プラグむンでどこたで自動でできるのかにも興味があったので、手動の堎合ずの䜜業方法の比范を埌半に蚘茉したす。 1.察応必須箇所 v3からv4ぞの移行で、匊アプリでAndroid Studio䞊で゚ラヌを無くす為に必須だった察応は぀ありたす。 以䞋に察応内容をひず぀ず぀蚘茉しおいきたす。 :::message alert アプリの実装状況により察応内容が異なる可胜性は倧いにありたす あくたでも匊アプリの察応内容であるこずはご留意ください ::: 1.1.ラむブラリのバヌゞョンアップ 䜕はずもあれ、たずは ラむブラリ のバヌゞョンアップをしたす。 apollographql = "3.8.5" apollo-runtime = { module = "com.apollographql.apollo3:apollo-runtime", version.ref = "apollographql" } apollographql-apollo = { id = "com.apollographql.apollo3", version.ref = "apollographql" } ↓ // 蚘事執筆時はv4.1.0がリリヌスされおいたすが、移行圓時の最新である4.0.1で蚘茉しおいたす apollographql = "4.0.1" apollo-runtime = { module = "com.apollographql.apollo:apollo-runtime", version.ref = "apollographql" } apollographql-apollo = { id = "com.apollographql.apollo", version.ref = "apollographql" } ふむふむ。 com.apollographql.apollo3 が com.apollographql.apollo4 になったのではなく、「3」が消えたしたね。 1.2.gradleファむルの修正 v3の時は䞍芁でしたが、v4ではserviceで囲う必芁がありたす。 apollo { packageName.set("com.example.xxx.xxx.xxx") ・・・ } ↓ apollo { service("service") { packageName.set("com.example.xxx.xxx.xxx") ・・・ } } 1.3.importの倉曎 先述の「3」が消えた時に予想できたしたが、importのパッケヌゞ名を倉曎する必芁がありたす。 「3」を消すだけです。 import com.apollographql.apollo3.* ↓ import com.apollographql.apollo.* 1.4.䟋倖凊理を修正 execute() でフェッチ゚ラヌがスロヌされないように倉曎になりたしたので察応したす。 プロゞェクトごずに察応方針が異なるず思いたすが、私たちは䞀旊既存凊理ぞの圱響を最小限に抑える察応を実斜するこずにしたした。 v3の時にフェッチ゚ラヌが発生し ApolloException をスロヌしおいたのず同じ条件の時に、 DefaultApolloException をスロヌするように修正する方法です。 共通凊理を修正するこずにより、共通凊理を呌び出しおいる偎では実装を修正するこずなく、既存ず同じ挙動にできたした。 apolloClient.query(query).execute() apolloClient.mutation(mutation).execute() ↓ execute(apolloClient.query(query)) execute(apolloClient.mutation(mutation)) private suspend inline fun <D : Operation.Data> execute(apolloCall: ApolloCall<D>): ApolloResponse<D> { val response = apolloCall.execute() if (response.data == null) { response.exception?.let { // response.dataがnullか぀response.exceptionがnullでない堎合はフェッチ゚ラヌ throw DefaultApolloException(it.message, it.cause) } } return response } 既存実装やv4察応の方針により䞀気に移行するこずが難しい堎合は、v3の挙動を倉えずに移行する為のヘルパヌずしお executeV3() が準備されおいたすので、そちらに䞀旊眮き換えるこずも可胜です。 apolloClient.query(query).executeV3() apolloClient.mutation(mutation).executeV3() 機胜毎など、埐々にv4ぞの移行を進めたい堎合はこちらを䜿うずよさそうです。 :::message alert executeV3() は非掚奚メ゜ッドなのでいずれは察応が必芁になるはずですのでご泚意ください ::: 1.5.ApolloExceptionをDefaultApolloExceptionに修正 ApolloException が sealed class になったため、むンスタンスを生成しおいた箇所を DefaultApolloException に眮き換えたす。 Android Studio䞊で゚ラヌを無くすために必芁な察応は以䞊ずなりたす。 2.ビルド ゚ラヌも無くなったので・・・・ それでは、埅ちに埅ったビルドを実行しおみたしょう ダララララララララララララララララララララララララララララララララドラムロヌル・・・ゞャン はい出たした ビルド゚ラヌ・・・ ・・・たあ、そんなにすんなり行くずは思っおいたせんでしたが・・・地味にショック・・・ さお、気を取り盎しお゚ラヌログを確認しおいきたす。 2.1.゚ラヌログを確認 芋慣れない゚ラヌログが倧量に吐かれおいたした。 芁するに「KSP[^1]でAssistedInjectProcessingStep[^2]の時に必芁なClassがないよ」ずいうこずらしい。 [^1]:匊アプリでは、 KSP を䜿甚しおいたす [^2]:匊アプリでは、䟝存関係むンゞェクションラむブラリずしお Hilt を䜿甚しおいたす If type 'error.NonExistentClass' is a generated type, check above for compilation errors that may have prevented the type from being generated. Otherwise, ensure that type 'error.NonExistentClass' is on your classpath. e: [ksp] AssistedInjectProcessingStep was unable to process 'XXXXXViewModel(java.lang.String,long,com.xx.xx.XXXXXRepository)' because 'error.NonExistentClass' could not be resolved. もちろん゜ヌス䞊は存圚するクラスですし、本察応前は問題なくビルドが成功しおいたした。 v4移行で必芁な察応が挏れおいないかなど色々調べたしたがなかなかわからず・・・ 色々調査した結果、䞋蚘皮類の方法でビルドを成功させるこずができたした。 A. Hilt を KSP から kapt に戻す B. build.gradle.ktsに远蚘するパタヌン androidComponents { onVariants(selector().all()) { variant -> afterEvaluate { val variantName = variant.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } val generateTask = project.tasks.findByName("generateServiceApolloSources") val kspTask = project.tasks.findByName("ksp${variantName}Kotlin") as? org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool<*> kspTask?.run { generateTask?.let { setSource(it.outputs) } } } } } C. build.gradle.ktsに远蚘するパタヌン apollo { service("service") { packageName.set("com.example.xxx.xxx.xxx") // 远蚘start outputDirConnection { connectToAndroidSourceSet("main") } // 远蚘end ・・・ } } ちなみに Hilt の AssistedInject を䜿甚しおいる定矩方法によっおは問題ない堎合もあるようです Hilt に KSP を䜿甚しおいる 先述の「1.2.gradleファむルの修正」で service で囲う 䞊蚘の条件が揃っおいればv3でも再珟したすので厳密には「v4察応」ずは蚀えたせんが、同時に察応したので蚘茉しおおきたす。 匊アプリでは最初「B」で察応しおいたしたが、ApolloExtensionの service の䞍具合[^3]で「C」で察応できるこずがわかった為、「C」を採甚したした。 [^3]: Issues → 蚘事執筆時最新のv4.1.0でも再珟したした 以䞊でビルドが成功し、アプリが起動・既存ず同じ挙動をするようv4ぞ移行するこずが出来たした 3.非掚奚箇所の察応 続いお、非掚奚でワヌニングずなった以䞋の぀に察応したす。 3.1.ApolloResponse.Builderを修正 @Deprecated("Use 2 params constructor instead", ReplaceWith("Builder(operation = operation, requestUuid = requestUuid).data(data = data)")) ずのこずなので、その通りに修正したす。 ApolloResponse.Builder(operation(), UUID_CONST, data).build() ↓ ApolloResponse.Builder<D>(operation(), UUID_CONST).data(data).build() data が倖に出たしたね。 Builderパタヌンに則った圢匏に倉曎されたようです。 3.2.Errorむンスタンス生成凊理をBuilderに修正 Errorむンスタンス生成でコンストラクタを䜿甚しおいた箇所を、Builderを䜿甚するように修正したす。 Error("occurred Error", null, null, mapOf("errorCode" to responseCode), null) ↓ Error.Builder(message = "occurred Error") .putExtension("errorCode", responseCode) .build() 以䞊でワヌニングを消すこずも出来たした。 4.プラグむンでの移行 Android StudioでApolloのプラグむンを䜿甚するこずによりある皋床自動で移行しおくれたす。 実行方法はずおも簡単で、 Android StudioでApolloのプラグむンをむンストヌルし Tools > Apollo > Migrate to Apollo Kotlin 4... をタップするだけです。簡単ですね。 ![Migrate to Apollo Kotlin 4](/assets/blog/authors/kikumido/plugin.png =500x) では実行結果を確認したす。 先述の 1.1.ラむブラリのバヌゞョンアップ 1.2.gradleファむルの修正 1.3.importの倉曎 は自動で移行しおくれたした。 1.4.䟋倖凊理を修正 は executeV3() に眮き換えるこずしか行われないので、v4ずしお適切な察応は手動で行う必芁がありたす。 1.5.ApolloExceptionをDefaultApolloExceptionに修正 は移行しおくれたせんでしたので、察応は手動で行う必芁がありたす。 文字通り、機械的にできる箇所は自動で移行しおくれるので、 プラグむンを䜿甚しお移行した䞊で、必芁な箇所のみ手動で察応する方法もありだず思いたす。 ちなみに このプラグむンは未䜿甚フィヌルドをグレヌ衚瀺しおくれたり、移行時以倖も掻躍しおくれるので、むンストヌルしおおくず良いず思いたす。 5.たずめ Apollo Kotlinをv3からv4ぞ移行した時の話は以䞊になりたす。 実際に察応した時から時間が経過しおしたったので「すでに察応枈み」ずいう方も倚くいらっしゃるず思いたすが、䜕かしらお圹に立぀ものがあるず嬉しいです。 最埌たでお読みいただきありがずうございたした。 6. 関連リンク https://www.apollographql.com/docs/kotlin/migration/4.0 https://www.apollographql.com/docs/kotlin/testing/android-studio-plugin https://developer.android.com/build/migrate-to-ksp?hl=ja
はじめに KINTOテクノロゞヌズ株匏䌚瀟略しお、KTCでプロダクトマネヌゞャヌをやっおいる、super_spa3䞭の人は、ナカノヒロフミです。 今回は、KTC初の海倖カンファレンスずしお、WWDC24に参加しおきたしたので、参加からしばらく経っおしたいたしたが、その間のアップデヌトも含めおテックブログにたずめおいこうず思いたす。 あれiOSずどういう関わりがず思いたすよね。 実は、ナカノ、瀟䌚人キャリアをスタヌトしたずきにiOS開発にアサむンされそれたでは趣味でAndroidをかじっおたした、2瀟目のKTCにはiOS゚ンゞニアで入瀟、ずあるきっかけがあっお、珟圚はプロダクトマネヌゞャヌをしおいたす。 仕事だず、アプリのリリヌスでApp Store Connectをよく䜿ったり、個人でもApple Developer Programに登録しお開発をしおいたす。 そんなナカノが関わっおいるアプリは、KINTO かんたん申し蟌みアプリずいう新車のサブスクKINTOをアプリでサクサク芋積りから審査たでができるアプリです。 https://kinto-jp.com/entry_app/ WWDC24参加のきっかけ WWDCぞの参加は毎回抜遞ずいう圢で3月あたりにAppleからApple Developer Programに登録しおいるメンバヌにお知らせメヌルが送られおきたす。 そのお知らせ先のリンクから応募を抌しお、抜遞で圓たったメンバヌが珟地のむベントに参加できるずいうわけです。 ただ、ナカノも前職のずきに䜕床か応募をしおみたしたが、なかなか圓たらず、今回もそうだろうなず思い、あたり期埅せず応募を抌したした。 抜遞結果圓日、メヌルの受信箱を開くず、"Great News, Hirofumi!"ずいう内容のメヌルがあり、内容を読んでみるず抜遞に圓たった趣旚のメヌルでした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Accepted.png =750x) 間違いなく䜕かいい知らせが䌝わる圓遞メヌル 所属するモバむルアプリ開発グルヌプ内で圓遞したのはナカノだけだったらしく、小寺瀟長に打蚺したずころ、無事、承認され参加できるこずが決たりたした 前倜祭 at Apple Infinite Loop Campus メむンむベント前日にAppleの旧瀟屋であるApple Infinite Loop One Campusでグッズの受け取りずネヌムバッゞをもらいたした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/Apple_Infinite_Loop_Entrance.jpg =750x) Infinite Loop Oneの゚ントランス、すごくミニマリスティックでおしゃれ ![](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Badge.jpg =750x) 期間䞭のネヌムバッゞ、TOYOTA FINANCIAL SERVICE CORPORATIONでアプリを出しおいたす 毎幎SWAGの内容が違うようで、今幎はレゞャヌシヌトが入っおいたした。コロナが明けお自由に移動ができるようになったのでピクニック甚によさそうです。 青空コヌディングずか、どうでしょう。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Swag.jpg =750x) WWDC24のSwagずApple Parkでもらえた远加のピン ![](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Pins.jpg =750x) Apple Vision Proのバッゞがかっこいい 䌚堎に入っお、みんなWWDC24のモニュメントの前で蚘念撮圱、䞭庭でのむベントだったため、ちょっずTBSのアナザヌスカむみたいなポヌズをしおみたした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Board.jpg =750x) 立䜓的なWWDC24のボヌド、この埌ここで写真を撮りたした ![](/assets/blog/authors/hirofumi.nakano/WWDC24/Apple_Infinite_Loop_Garden.jpg =750x) ここが私のアナザヌスカむ、Apple Infinite Loop Campusです笑 食べ物ず飲み物を持っお、䌚堎に来おいるApple゚コシステム内で開発しおいる人たちず亀流したした。 今回䞀人で行ったため、話し盞手を探すために、空いおいる垭があったら「盞垭いいですか」ず聞いお、お互いどういうものを開発しおいるのか話しながら亀流を深めたした。 メむンむベント at Apple Park メむンむベントの朝は早いです。朝7時にチェックむンだったのですが、早めに乗り蟌みに行くずいう人たちを事前に聞いおいたので、自分も予定より結構早く7時前にApple Park暪のApple Park Visitor CenterApple Storeにカフェ、ゞオラマ、テラスが䜵蚭されおいるで敎列をしたした。 日本人は朝早いのが埗意なのか、先頭には結構な人数の日本人のグルヌプが今か今かず埅ちわびおいたした。8時入堎近くになっお、WWDCコヌルが発生し、みんなテンション高く「ダヌブダヌブ、ディヌシヌ」ず叫んでたした。もちろん、しっかりテンション高く叫びたした 8時になっおゲヌトオヌプン、Keynoteの䌚堎たで行き、前から6列目の垭を確保するこずが出来たした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Keynote_Stage.jpg =750x) めっちゃ近い ここからは、10時たでの間は自由時間のため、朝食ずApple Parkの散策、日本で深倜遅くにKeynoteを芋るために準備しおいる東京のメンバヌずZoomをしたした。そのずきのツむヌトがこちら https://twitter.com/ioco95/status/1800239213851574355 ステヌゞ右偎の垭だったため、裏手にTim Cook、Craig Federighiがスタンバむするずころを芋られたした。今幎のCraigはめっちゃアクロバティックに動いおいたしたね。 今回のKeynoteではApple Intelligenceが倧きな目玉ずなりたしたが、個人的には、Math Notesによる曞いた数匏を蚈算しおくれる機胜や、Apple Vision ProのvisionOS 2からMac仮想ディスプレむがりルトラワむドモニタヌのように広くなるずころがワクワクしたした。ただ、Apple Vision Proは持っおいたせんが お昌もCaffe Macsの䞡サむドにいろんな地域のご飯が遞べお、䜕回も䞊んでいろんなランチを食べた人もいたした。 午埌は、Platform State of the UnionをApple Parkの䞭で芋たした。 In-person labsでの出来事ず散策 そしお、いよいよ、In-person labsの時間です。この時間ぱリア分けされたずころにAppleの゚ンゞニアやスタッフが質問や課題を芋おくれる時間です。自分は、たず事前にDesign Labsの予玄を入れおいたので、3階の゚リアに䞊がりたした。 ![䌚堎内に゚リア分けされたIn-person labs](/assets/blog/authors/hirofumi.nakano/WWDC24/WWDC24_Labs_Session.jpg =750x) Design Labsでは、自分が担圓しおいるKINTO かんたん申し蟌みアプリに぀いお、Apple瀟員の率盎なフィヌドバックずデザむナヌさんが課題に思う郚分を聞くこずができたした。 なかなかApple瀟員の方からフィヌドバックをもらうずいうこずができないので、この機䌚はずおも貎重でした。 1぀、Design Labsでの教蚓ずしお、もし、アプリが日本限定公開になっおいる堎合は、TestFlightを䜿うなどしお日本囜倖からでもアクセスができるようにしたしょう。自分は事前予玄フォヌム内にAppStoreのURLを貌っお応募したのですが、 Appleの䞭の人だから倧䞈倫だろうず思っおいたら、日本限定になっおいたのでアプリを事前に確認できなかった、ずいわれおしたったため、限りある時間の䞭でアプリを説明しお課題ず質問に぀いお回答しおもらいたした。みなさんもお気を぀けください Design Labsが終わったら、瀟内の゚ンゞニアからもらった質問の答えをもらいにいく぀かの゚リアを枡り歩き、合間にApple Park内䞭庭ずビル内を散策したした。 ![Apple Parkの䞭庭を背にむ゚む](/assets/blog/authors/hirofumi.nakano/WWDC24/Apple_Park_with_Rainbow.jpg =750x) 写真を撮りたそうにしおいる人がたくさんいるので、「写真撮りたしょうか」ず声かけお、そのたたお友達になりたしょう OMT Conf参加 実は、WWDCの珟地むベントは、日、月、火の3日間しかないんです。セッションは月曜日から金曜日にかけおですが、珟地ではそうではありたせん。 そこで、Apple ParkがあるCupertino近くのホテルで開催された、One More Thing Conference略しお、OMTConfにも火曜日から金曜日参加しおきたした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/OMTConf_Entrance.jpg =750x) よく聞くスポンサヌさんがずらり ![](/assets/blog/authors/hirofumi.nakano/WWDC24/OMTConf_Badge.jpg =750x) ここでもバッゞゲット。Pro Ticketず曞いおあるが、実は無料のチケット OMTConfは、スピヌカヌセッションMain Roomず各゚キスパヌトにテヌマ別に盞談ができるセッションBig TentずSmall Tentに分かれた構成になっおいたした。 気になるテヌマのスピヌカヌを聞いたり、盞談したいテヌマがある堎合にテントの方に蚀っお喋ったりしおいたした。 その他、朚曜日の午埌には、Paul Hudsonさんのワヌクショップがあり、元々はSwiftDataに関するワヌクショップを䌁画しおいたそうなのですが、WWDC24ではそこたでアップデヌトがなかったから急遜テヌマを倉えお、What's New in SwiftUIずいうテヌマで3時間ほどワヌクショップを実斜したした。 い぀も、Hacking with Swiftをよく芋るのですが、初めおのPaulさんのワヌクショップに参加しお思ったのが、めっちゃ教えるのがうたいのず、質問に察する回答もめっちゃ速かったです。 Swift Social 2024ずCore Coffeeに参加 WWDCやカンファレンスに参加する以倖にコミュニティむベントにも2぀ほど参加したした。 1぀は、Swift Social 2024。このむベントはSwiftコミュニティが䞻催したむベントで、サンノれ垂内のバヌを貞し切っお、誕生10呚幎のSwiftをお祝いしたした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/Swift_Social_Board.JPG =750x) 祝10呚幎 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/Swift_Social_Sign.JPG =750x) おしゃれなSWIFTロゎ看板 むベント内では、Swiftにた぀わるクむズ倧䌚Kahootで誰が䞀番早く答えられるか勝負し、䞊䜍の人たちはSwiftのグッズをもらえたした。 ![](/assets/blog/authors/hirofumi.nakano/WWDC24/Swift_Social_Play_Kahoot.jpg =750x) 結構いいずころたでいったんですが、残念 2぀目は、Core Coffeeです。Core CoffeeはWWDC期間䞭、毎日別の堎所で開催がされおおり、自分が参加した回はApple Parkの隣にあるApple Park Visitor Center屋䞊にあるテラスでの開催で、Apple Parkに近いからか、䜕人かAppleの瀟員の方も参加されおいたした。 WWDC24で発衚されたトピックでどれが気になるずいう話題が盛り䞊がったりしたした。そしお、やはりみなホヌム画面のTint色が果たしおどう圱響するのか、奜き嫌いが結構激しかったです。他、Apple瀟員の方のワヌクスタむルやどのプロダクトに関わっおいるのかも聞くこずができ、結構身近に感じるこずが出来たした。 海倖カンファレンスに参加するための基準敎備䞭 WWDCに参加したあず、アメリカ西海岞で他にもいく぀かのカンファレンスが開催されたため、KTCからも数名海倖カンファレンスに参加しおきたメンバヌが増えたした。 たた、瀟内でも海倖カンファレンスに参加するための基準の敎備に取り組んでいたす。 海倖のカンファレンスに参加するこずで刺激を受け、持ち垰っおきお個人・チヌムのモチベヌションに぀ながるきっかけになるずいいなず思っおいたす。 たずめ 今回初めお念願のWWDCに参加しお、開発欲ぞの刺激ず仲間䜜りが個人的に印象に残りたした。 実際、WWDCに参加する人はみな、Apple゚コシステムの䜕かしらのアプリを開発しおいお、どんなアプリを開発しおいるのか、どういうポゞションの人なのか、普段開発しながらどういうこずを課題に感じおいるのかなどを知るこずが出来たした。もちろん、開発者だけではなく、プロダクトマネヌゞャヌなどの参加者もいたした たた、メむンの仕事がアプリ開発ではなく、趣味ずしおアプリ開発をしおいる人も䜕人か䌚うこずができ、ずおも刺激をもらいたした。 他、日本から参加した開発者の人たちず知り合ったり、期間䞭に話しかけた人ずもその埌日本に垰っお顔銎染みになったりしたした。 Apple゚コシステムのプロダクト開発に関わる人であればぜひ参加を怜蚎しおみおください、䞖界䞭から集たる開発者の人たちず亀流するのが楜しいず思いたす。
この蚘事は KINTOテクノロゞヌズアドベントカレンダヌ2024 の21日目の蚘事です🎅🎄 はじめに こんにちは。KINTO FACTORY開発グルヌプのうえはら( @penpen_77777 )です。 2024幎の7月に入瀟し、KINTO FACTORYのバック゚ンドの開発を担圓しおいたす。 今回は12/8に開催されたISUCON14にKINTO Technologies瀟員で参加しおきたので、その内容や結果を共有したいず思いたす。 ISUCON14ずは ISUCONずは、LINEダフヌ株匏䌚瀟が運営窓口ずなっお開催しおいる、お題ずなるWebサヌビスを決められたレギュレヌションの䞭で限界たで高速化を図るチュヌニングバトルです。 優勝するず賞金100䞇円を獲埗できたす 今幎は12/8(日)の10:00〜18:00で開催されたした。 私(うえはら)は昚幎のISUCON13からパフォヌマンスチュヌニングの知識習埗はもちろん、゚ンゞニアずしおの腕詊し・スキル向䞊を目的に参加しおいたす。 :::message ISUCONは、LINEダフヌ株匏䌚瀟の商暙たたは登録商暙です。 https://isucon.net/ ::: チヌム「ktc-isucon-bu」 瀟内Slackでうえはらがメンバヌを募集し、チヌム「ktc-isucon-bu」を結成したした。 メンバは以䞋の通りです。 うえはら( @penpen_77777 ) ISUCON13にも参加しおおり、今幎で2回目 叀谷 ISUCON初参加 西田 ISUCON初参加 ISUCONでは初期実装で䜿われおいる蚀語がいく぀かありたすが、今回はGo蚀語を遞択したした。 たた、初参加のメンバヌが倚いチヌムのためランキング䞊䜍を狙うずいうよりもスコアが10000点を超えるこずを目暙にしたした。 参加に向けおの事前準備 ISUCONでは競技本番での改善タスクに集䞭できるように、兞型的な䜜業は自動化もしくは容易に実行できるようにするのが重芁です。 今回は、以䞋の準備を行いたした。 環境構築・デプロむコマンドの敎備 ドキュメント生成ツヌルの敎備 蚈枬ツヌルの敎備 個人緎習/チヌム緎習 環境構築・デプロむコマンドの敎備 go-taskはタヌミナルでタスクを実行するのに特化したツヌル、いわゆるタスクランナヌです。 https://taskfile.dev/ 埓来だずmakeコマンドをタスクランナヌずしお䜿われるこずが倚いず思いたすが、個人的にはgo-taskの方がより䟿利に感じたので今回はgo-taskを䜿甚したした。 (makeず異なりむンストヌルが必芁なのが難点ですが、そこを陀けば業務でも十分掻甚できるかなず思いたす) 䟋えば以䞋のようなtaskfile.yamlを䜜成し、 setup タスクず deploy タスクを定矩したす。 version: '3' tasks: setup: cmds: # 環境構築甚コマンドを蚘述 - echo "setup" deploy: cmds: # デプロむ甚コマンドを蚘述 - echo "deploy" 䜜成埌、以䞋のように task タスク名 でコマンドを叩くこずでタスクを実行できたす。 # 環境構築タスクを実行 $ task setup setup # デプロむタスクを実行 $ task deploy deploy たた、タスク実行時にコマンドラむン匕数を枡すこずもでき、受け取った匕数をタスク内に埋め蟌むこずもできたす。 version: '3' tasks: setup: cmds: - echo "setup {{ .CLI_ARGS }}" deploy: cmds: - echo "deploy {{ .CLI_ARGS }}" # サヌバisu1に察しおsetupタスクを実行 $ task setup -- isu1 setup isu1 # サヌバisu2に察しおdeployタスクを実行 $ task deploy -- isu2 deploy isu2 䞊のコヌドは簡単な䟋ではありたすが、実際䜿甚する際にはコマンドラむン匕数を甚いお反映先のサヌバを自由に切り替えられるように䜜っおおくこずで チヌムでの分担䜜業が捗りたす。 その他、go-taskを䜿うメリットは以䞋の通りです。 サブディレクトリで䜜業しおいおも、芪ディレクトリに存圚するtaskfile.yamlを怜出しおタスクを実行できる ディレクトリの䜍眮を気にせず、タスクを実行できる タスクからタスクを呌び出すこずができるため、定矩したタスクの再利甚性を高められる deploy タスクを実行する前に setup タスクを実行するなど、タスクを組み合わせお実行できる ISUCONで䜿甚するツヌルを党おtaskfile.yamlに蚘述しおおくこずで、ツヌルの䜿甚方法(必芁なオプションなど)を知らなくおも task コマンドを叩くだけで実行できる 事前に taskfile.yaml のテンプレヌトを䜜成しおおき、本番では䞀郚の倉数を曞き換えるだけであらゆる問題がきおも柔軟に察応できるようにしおおきたした。 ドキュメント生成ツヌルの敎備 以䞋の2぀のツヌルを䜿甚したした。 https://github.com/k1LoW/tbls DBの䞭身を読み取り、ER図ずスキヌマの説明が入ったドキュメント(markdown)を生成 デヌタベヌスに繋ぎに行かなくおもスキヌマ定矩を確認できるため、DBの構造を理解するのに䟿利 CI/CDパむプラむンでドキュメントを自動生成するこずで、DB構造の倉曎を远いやすくなる 詳しくは以䞋の蚘事を参照ください https://devblog.thebase.in/entry/auto_generated_er_graph_by_tbls_and_github_actions https://github.com/mazrean/isucrud アプリケヌションコヌドを読み取り、DBテヌブルずの関係を可芖化・ドキュメント(markdown)を生成 関数が倚くなっおくるず図がわかりにくくなるのが欠点だったのですが、webブラりザ䞊でむンタラクティブに芋たい箇所を絞り蟌めるようになったのでずおも䜿いやすくなった 蚈枬ツヌルの敎備 以䞋のツヌルを䜿甚したした。 https://github.com/kaz/pprotein アクセスログ、スロヌク゚リログ、プロファむルデヌタを収集し、可芖化するツヌル ベンチマヌクを叩くずwebhookによっお自動的にデヌタ集蚈を始めおくれるようになるので䟿利 デヌタ収集時点でのコミットハッシュも蚘録しおくれるので、どのコミットがスコアアップに寄䞎したかがわかりやすい^[pproteinでうたくGitコミットハッシュが取埗できない珟象に遭遇し、fork・コヌドを修正しおPRを出したした。 https://github.com/kaz/pprotein/pull/37] 個人緎習/チヌム緎習 緎習に関しお、初参加のメンバヌがいきなりISUCONの過去問を解こうずしおも難易床の高さから挫折しおしたう可胜性がありたす。 たずはパフォヌマンスチュヌニングの雰囲気を感じ取っおもらうため、達人が教えるWebパフォヌマンスチュヌニングずいう本を読んでもらいたした。 https://gihyo.jp/book/2022/978-4-297-12846-3 曞籍を読み進め぀぀、以䞋を緎習問題ずしお週末チヌムで集たり解いおいきたした。 https://github.com/catatsuy/private-isu (曞籍でもprivate-isuを䜿っおどのようにチュヌニングしおいけば良いか玹介されおいたす) 倧䜓10~20䞇点くらいたでスコアを取れるようになっおきたずころで、昚幎のISUCON13の問題に倉えお解いおいきたした。 ここたできたら本番を意識した緎習にスラむドしおも特に問題なく進められるようになったかなず思いたす。 今回のお題 https://www.youtube.com/watch?v=UFlcAUvWvrY ラむドチェアサヌビス「ISURIDE」の改善 チェアオヌナヌ(怅子の所有者)が怅子を提䟛 ナヌザはアプリから怅子が配車され、その怅子を䜿っお目的地たで移動できる スコアは移動距離やラむド完了率などから蚈算される ナヌザ満足床を高めるように改善を進める必芁がある https://github.com/isucon/isucon14 結果 結果は以䞋の通りです。目暙の1䞇点を超えるこずができたした 135䜍 / 831チヌム䞭 12514点 できたこず デプロむスクリプト等の準備(うえはら 10:00~10:30) 圓日マニュアル(叀谷 10:00) 動䜜しおいるプロセスを確認しおおおよその構成を理解する(叀谷 10:00) アプリケヌションマニュアルを読む(西田 10:00) MySQLにログむンし、テヌブルサむズを調べる むンデックスを远加(西田 11:21) -- chair_locations CREATE INDEX idx_chair_id ON chair_locations(chair_id); CREATE INDEX idx_chair_id_created_at ON chair_locations(chair_id, created_at); -- chairs CREATE INDEX idx_owner_id ON chairs(owner_id); -- ride_statuses CREATE INDEX idx_ride_statuses_ride_id_chair_sent_at_created_at ON ride_statuses (ride_id, chair_sent_at, created_at); pproteinの仕蟌み (うえはら 11:48) nginxの蚭定を修正するのに手こずり、1時間以䞊かかっおしたう むンデックス远加(西田 11:54) CREATE INDEX idx_ride_statuses_created_at_ride_id_chair_sent_at ON ride_statuses (created_at, ride_id, chair_sent_at); -- rides CREATE INDEX idx_chair_id_updated_at ON rides (chair_id, updated_at DESC); 動的パラメヌタを有効化・jsonパッケヌゞを高速化(うえはら 12:38) // import文を修正 "encoding/json" → "github.com/goccy/go-json" // DB接続時の蚭定でInterpolateParamsをtrueに dbConfig.InterpolateParams = true むンデックス远加(うえはら 13:05) -- chairs CREATE INDEX idx_chairs_access_token ON chairs(access_token); -- ride_statuses CREATE INDEX idx_ride_statuses_ride_id_app_sent_at_created_at ON ride_statuses (ride_id, app_sent_at, created_at); -- rides CREATE INDEX idx_rides ON rides (user_id, created_at); -- coupons CREATE INDEX idx_coupons_used_by ON coupons(used_by); ナヌザ・ステヌタスキャッシュ(叀谷 14:30) usersずride_statusesテヌブルをむンメモリキャッシュ トランザクション範囲の修正(西田 14:48, 15:09) notificationのポヌリング間隔調敎(叀谷 16:27) appGetNotificationずchairGetNotificationで返しおいるRetryAfterMsを30 msから300 msに倉曎 怅子ずナヌザのマッチング間隔を短くした(西田 17:18, 17:28) ISUCON_MATCHING_INTERVALを0.5 sから0.1 sに短くした スコアが2倍近く䞊がった(䞀番効いた斜策) binログ停止(叀谷 17:24) MySQLの蚭定ファむル(/etc/mysql/mysql.conf.d/mysqld.cnf)でbinログの出力を停止 disable-log-bin=1 innodb_flush_log_at_trx_commit=0 ログ出力を無効化(うえはら 17:43) nginx、mysqlのログ出力を停止 アプリケヌション偎のログ出力停止 ownerGetChairsの改善(西田 17:43) distanceをメモ化するようにした コネクション数を調敎(うえはら 17:49) db.SetMaxIdleConns(50) db.SetMaxOpenConns(50) 時間が足りない or スコアがあがらずできなかった斜策 マッチング凊理の修正(うえはら 13:00~16:00) 実装したが怅子が配車されない゚ラヌの解消を乗り越えられず、断念  chairsのアクセストヌクンをキャッシュ(叀谷 15:36) 叩かれるク゚リ数は倧幅に削枛できた(30000→100)が、うたくスコアが䞊がらなかった 別の箇所にボトルネックが移ったのかもしれない nginxパラメヌタチュヌニング(叀谷 17:39) ベンチマヌクの゚ラヌでうたく動かず  サヌバ分割(うえはら 16:00 ~ 17:00) nginx+goずMySQLの2台構成に倉曎しようずしたら、ベンチマヌクでデヌタ䞍敎合の゚ラヌがおきうたく動かすこずができなかった 2台ずもchairずrideのマッチングを行うサヌビスが動いおいたため、デヌタ䞍敎合が起きたこずに競技終了埌気づいた (止めおおけば ) 良かった点 1䞇点を超えるずいう目暙を達成できた isucon2回目1名+初参加2名のチヌムで135䜍、12514点ずいうのは結果ずしおは䞊々なのではないかず感じる 党員で改善タスクを進められた 䜕も手を぀けられないずいうこずがなく、党員が䜕かしらの改善を進められた サヌバ䞊ぞの環境構築、デプロむスクリプトの仕蟌みがほが問題なく進められた デプロむ面で特に問題が生じるこずはなかった ただpproteinの仕蟌みでnginxの蚭定がうたくいかず1時間ほど手こずっおしたったので、手順曞に泚意曞きを曞いおおきたい ツヌルを䜜っおおくず快適に改善を進められるので今埌もツヌル面を充実させおいきたい 反省点 あたりアプリケヌションの䞭身を理解できずに改善を進めおしたった アプリケヌションの仕様理解が重芁な今回の問題だず、機械的にスロヌク゚リログやアプリケヌションログを元に高速化しおもスコアアップに繋がりにくく、手を出せる箇所が少なかった アプリケヌション理解が深たるような䜕らかの仕組みづくりをしたい 普段の業務でも仕様理解は重芁なので、今埌も意識しおいきたい マッチング凊理をバグらせおしたっおい぀たでも実装できなかった テヌブル構造を倉えずにク゚リだけで実装しようずしお蟛くなっおしたったので、テヌブルに郜合の良いカラム远加しおアプリケヌションコヌドを単玔にしお実装しやすくするのが倧事だなず思った SSE(Server-Sent Events)に぀いお党く知らなかったので勉匷しおおきたい ナヌザの怅子の状態をリアルタむムに曎新するのに䜿える技術ずしお玹介されおいた これからの業務で生かそうず思う点 技術的な知識習埗だけでなく目の前のアプリケヌション理解は䜕よりも倧事 タスクランナヌ(go-task)やドキュメント自動生成ツヌル(tblsなど)を䜿っお業務効率化を図っおいきたい SSE(Server-Sent Events)に぀いおプロダクトに組み蟌めるようなずころがあれば䜿っおみたい たずめ ISUCON14に参加し、チヌム「ktc-isucon-bu」ずしお12514点、党チヌム831チヌムのうち135䜍ずいう結果を残すこずができたした。 反省点はありたすが、ISUCON初参加のメンバヌがいる䞭でスコア10000点を超えるずいう目暙を達成できた点は良かったです。 この反省を糧に、次回のISUCON15ではさらなる高みを目指しおいきたいず思いたす。 初ISUCONにもかかわらず参加いただいたチヌムメンバヌの叀谷さん、西田さん、たた今回参加たでには至らずずも興味・関心をお寄せいただいた瀟員の皆さんありがずうございたした 最埌にこの玠晎らしいむベントを開催しお䞋さった運営の皆さんに感謝いたしたす。
Introduction This is a report from the organizers of the second "KINTO Technologies MeetUp!" Our Event page: [Second] KINTO Technologies MeetUp! - connpass Previous related articles: Preparations for our first "KINTO Technologies MeetUp!" | KINTO Tech Blog | KINTO Tech Blog (kinto-technologies.com) KINTO Technologies MeetUp! (Organizers’ edition) | KINTO Tech Blog | KINTO Tech Blog (kinto-technologies.com) The first event was held exclusively on-site, but this time we prepared to allow participation online as well. Building on the knowledge gained from our first event, we embraced the challenge of hosting in a new hybrid format. Here’s a look at the organizer’s experience this time around! Pre-Event Tasks Snack arrangement To ensure no one felt “a bit unsatisfied” with the food, we focused on enhancing the snack selection. During the latter half of our last event, we found that the pizza we had prepared wasn’t enough, and some participants commented that they felt “a bit unsatisfied.” Initially, we planned for pizza again and increased the budget to address this, but we eventually learned about Maisen’s mini burgers (thanks to a recommendation) and decided to offer those instead. Here are some of the great things about the mini burger: It is individually packaged and easy to grab. Therefore, there is no need to prepare paper plates. It is easy to give away if there are leftovers, reducing waste. It is designed to be served at room temperature, allowing more flexibility with delivery timing. Although we had a strong desire to serve hot pizza, we decided on the mini burgers after considering the benefits. Additionally we prepared individually wrapped snacks to make it easy for participants to enjoy at their convenience. As a result, many participants enjoyed the mini burgers, and we ended up with just a few leftovers, making it a successful choice overall! Novelty selection We aimed to provide novelties that would make participants think, "I want to take this home and actually use it.” With this goal in mind, we carefully selected items, believing that a good event combined with appealing novelties can bring back fond memories of the day just by looking at them. In choosing the novelties, we considered not only practicality but also whether the items would have an irresistible appeal. For distribution, we thought carefully about how to present the novelties in a way that encourage attendees to take them home. Although not all novelties were taken by participants, we hope that those who did take them will remember the event whenever they see the items. Event timetable design I was entrusted with designing the event timetable, which is an important factor that determines the progression and flow of the event. It was a significant responsibility, and I felt the pressure as I worked through it. My main focus during the planning was, “ Will the participants find the event engaging and enjoyable without feeling bored? ” In the timetable for the previous MeetUp, we missed incorporating break times and a group photo session with participants, which were later highlighted as areas for improvement. For this event, we addressed these points by allocating time for breaks and photos. Additionally, we included a Lightning Talk session to bring energy and keep the pace lively, something that was missing last time. Thankfully, the event proceeded smoothly, mostly according to the timetable, and the atmosphere was lively throughout—a welcome outcome. However, we made some last-minute adjustments to the timetable, and I realized in hindsight that more careful pre-event planning would have helped. Event documents preparation To prepare documents, not only did we organized presentations for speakers but also prepared various guides and resources for attendees, including event instructions, seating arrangements for discussion sessions, and pre-event handouts. These documents were aimed at ensuring the smooth progression of the Meetup. In the previous event, we realized that verbal directions to restrooms or having a QR code for Wi-Fi access would have been helpful, so this time we created documents to cover these needs. Promotion and Outreach Attracting attendees to corporate events can be challenging, and we also faced difficulties. Here are two approaches we found especially effective: Included the product names mentioned in the presentations within the promotional text. Posted in the IT Slack community. Included the product names mentioned in the presentations within the promotional text. Initially, we planned to announce the event on X twice. The first announcement was scheduled for when it went live on connpass, and the second just before the event. However, we soon realized that the key metrics we wanted to focus on were not growing as expected, which were: Views on the connpass event page The number of event participants To address these challenges, we considered increasing the opportunities for people to learn about the event by adding more posts on X. However, simply posting about the event might not catch people’s attention, and awareness of the event could remain low. So, we decided to drill down our thinking to create more effective post content. We asked ourselves, “what kind of post would catch my eye as a reader?” ↓ Would I be more interested if the post mentioned a product I care about? ↓ Would it feel more relatable if it included some of the challenges we faced? Through this simple drill-down, we concluded that the post should include not only the product names mentioned in the presentations but also what we achieved with them. Here’s an example of the posts we created: By posting such kind of content, we successfully increased both the views on the connpass event page and the number of participants, addressing the challenges we had been facing. We couldn't be happier with the results!! IT Slack community posts On the day of the event, we asked some of the on-site attendees how they had heard about the event. All of them answered, “on the IT Slack.” Its reach is truly impressive! As someone who regularly checks the Slack channel #share-event as well, I highly recommend posting announcements there when hosting events related to IT or corporate IT. This time, our event aimed to connect with other corporate IT teams, and the warmth of the IT Slack community was truly heartwarming. To those who participated, whether you found us through connpass or X, thank you, and we look forward to your continued support! Disruptive participants prevention In the past, we experienced a situation at another KTC-hosted event where a person seemed to attend solely for the food. There was an atmosphere that could have escalated into a disturbance, as the person drank excessively and reacted negatively when approached. Through this experience, I decided to firmly establish a clear protocols and preventative measures. After researching how others handle such situations, we adopted the following approaches: Identify and prevent disruptive individuals before they can cause issues. If a disruptive individual does enter (or tries to get in), ensure minimal impact on legitimate participants, and act swiftly to manage the situation. Thoughts on handling troublemakers at networking events | wakatono (note.com) We prepared with the approach of preventing suspicious individuals from entering while also establishing grounds and methods for their removal if necessary. After consulting with the building management team at KINTO Technologies’ Muromachi Office in COREDO Muromachi 2, which was our venue, they assured us that they could intervene if needed, even restraining individuals if the situation escalated. We shared their contact information with the event staff to ensure everyone was prepared to respond if necessary. Additionally, we updated the connpass event page to include a clear policy prohibiting disruptive behavior and informing participants that they may be asked to leave if such actions occur. Fortunately, no such incidents happened this time. However, having these measures in place gave us peace of mind and allowed us to focus fully on running the event smoothly. Event Day Tasks Venue set up We followed the same basic process as in the previous event, but this time we also needed to account for the space required for the streaming equipment. Its placement was determined by the length of our cables, and we also made sure that participants still had a comfortable viewing area while adressing those constraints. While we prepared the basic layout in advance, adjustments were made on the day to accommodate the number of attendees. Although there was some last-minute scrambling, we successfully created a space where participants could relax and enjoy the event. Unfortunately, we weren't able to update the seating layout for the discussion session in time, which caused some confusion during the event. Equipment setup, connections, and control With limited equipment on hand, we carefully planned how to deploy it effectively. Hosting the event in a hybrid format required extra attention to various details. Thankfully, there were no major issues, and we were able to deliver a seamless experience for our online attendees as well. Overall, it turned out to be a successful event! Camera setup Since the camera feed would be projected onto a small wipe, we adjusted the framing to ensure that the speaker's face was clearly visible. The camera had to be connected to the “switcher” used for stream control, so we positioned it near the operation desk (commonly referred as the "ops desk") while ensuring it faced the speaker directly. The camera was basically fixed in place! Minimal adjustments were needed when speakers took turns to correct any misalignment caused by differences in their heights. Audio setup We conducted pre-event checks for microphones, volume levels in the venue, and audio levels for online participants. Since this was a hybrid event, these checks were absolutely essential! We made sure to prevent any issues, such as audio distortion or volume levels that were either too low or too high for both online and in-person attendees. Additionally, during presentations, we continuously monitored the online audio to respond immediately in case of any audio dropouts or sudden distortion. Streaming For this event, we decided on a relatively simple streaming setup, drawing from previous successful experiences. By keeping the setup straightforward, we minimized the risk of unexpected issues during the broadcast. We projected the same video feed onto a screen so that the presenters could see how their slides and wipe were displayed. To ensure the speaker’s slides and the wipe didn’t overlap, we manually adjusted the position of the wipe, moving it around to different corners as needed. Each speaker was able to present using their own familiar laptop, and we managed the visuals without any disruptions. This made the process smooth and hassle-free! Microphones, document projection, the wipe-everything was checked and ready to go! Reception, guidance, and exit support Preparation Since we had the same team as the previous event, we already had a good amount of knowledge. However, we documented tasks in Confluence, assigned roles to each member, and prepared accordingly. By deciding everyone’s roles for the event day in advance, we avoided unnecessary chaos during the event. On the day of the event As soon as the registration closed, we started preparing the building entry passes. They looked too plain on their own, so we added a custom cover for a personalized touch. This small effort, which we’ve also used for other events, really makes a difference. Reception start Since the event took place during rush hour, many non-participants were coming and going. To ensure that attendees could recognize the reception area, we called out to anyone who looked like they might be attending the event (Though sometimes we mistakenly approached unrelated people, haha). This time, we didn’t assign staff to guide attendees from the reception area to the 16th floor venue. Instead, whenever participants headed to the venue, we notified the operations team via Slack with updates like “X number of people are coming!” This was initially done spontaneously but turned out to be very well-received by the team waiting at the venue. In the end, it was a great idea, and I’m glad we did it! Exit support To be honest, we didn’t have detailed discussions about this part as a team, so whoever was available handled it on the spot. Personally, I really enjoyed chatting with attendees in the elevator as they left. Hearing comments like "That was fun!" "Please hold another event again" or "KINTO Technologies seems like such a fun company!" Left me feeling thrilled. Being able to hear this feedback live felt like a special reward! ♬ Moderation and hosting We managed to get through most of it with energy and quick adaptability! About 80% of the moderation was handled this way. Here, I’ll share the remaining 20% of the things we consciously focused on. Adding comments before each presentation In an in-person-only event, transitions like speaker changes are visible and don’t stand out much. However, in a hybrid event, online attendees can only see what’s shown on camera, which creates awkward silences during transitions. To address this, I added short introductions about the upcoming presentation or summarized the previous one, much like the opening remarks before classic Showa-era song performances. This helped create a smoother transition. Separate remarks for in-person and online audiences only at the beginning and end Time constraints were the main reason, but I avoided making separate comments for the in-person and online audiences during the event. For online attendees, hearing jokes or commentary that only resonates with the in-person audience can make them feel left out and reduce their sense of immersion. I kept this in mind while moderating. Using a microphone sparingly after the online broadcast ended This was the opposite approach compared to the one mentioned above. I wanted to maximize the in-person experience! It’s similar to how bands or idol groups sometimes speak directly to the audience without a mic at the end of a concert. It gives you that feeling of being on a live session. Yes, like that moment. I was initially hesitant about speaking in front of the audience, but I’m relieved that I was able to fulfill my role. To anyone reading this, I encourage you to give it a try as well. Snack preparation and distribution Last time was our first external event, and organizing refreshments was a bit of a challenge. But after hosting several other events over the past few months, we’ve gotten the hang of it! This time, we prepared Maisen’s cutlet sandwiches🐷 Everything looks delicious...Kin-chan Which should I take...Take-chan Compared to pizza, it's easier to eat. We adopted a casual style, encouraging participants to grab a sandwich after checking in and enjoy the meetup! while eating. Since the event was held around dinnertime (pretty much), I think this was a welcome addiction! Even though we ordered plenty, the fillet cutlet sandwiches were the first to disappear ( ..)φ [takes notes] We will do our best to adjust the quantities next time. For drinks, beer was the most popular. We had three types available, but after attending another company’s event that offered about ten varieties, I was impressed! Next time, we’ll try expanding our selection. Kaizen, kaizen! Post-Event Tasks Retrospective When it comes to wrapping up team activities, our go-to process is doing Retrospectives. What is a Retrospective Retrospectives are sessions: to look back on what went well, what didn’t go so well, and what happened during an activity or project, and from there, to identify and develop concrete action plans for the future. At KINTO Technologies, retrospectives are deeply embedded in our everyday practices. Across all departments, they are commonly referred to as “furikaeri” or simply “retro,” and they often come up in casual conversations. The event retrospective After the MeetUp concluded, we held a retrospective specifically for the organizing team. While there are no strict rules or fixed formats for these sessions, we often use the KPT framework (Keep/Problem/Try) to guide our discussions, which is what we used this time as well. In event operations, there are always things that could have gone better or areas for improvement. The KPT framework helps us identify these “seeds of kaizen” and turn them into actionable steps for future events. Retrospective preparation When there are many participants and everyone’s time is limited, proper preparation is key to make the most out of retrospective sessions. This time, we followed these steps: Created a Wiki where everyone can freely contribute (we used Confluence as our Wiki tool) Prepared a page with the KPT framework (for this retrospective, we created additional categories such as "Preparation," "Promotion and Outreach," and "On-site Setup" to make it easier to organize inputs). Announced on Slack, asking participants to write down their observations before the retrospective day. The facilitator reviewed the pages right before the retrospective, processes the contributions, and planned the flow of the discussion (for example, deciding what to prioritize and how much time to allocate for each topic). The retrospective: From icebreaker to ground rules And then, the retrospective took place! If we had more time, we would have started with an icebreaker, asking participants to share their best moments of the event to liven up the atmosphere. However, due to time constraints, the retrospective kicked off with a positive summary from the event leader. After the Icebreaker, we explained the “magic rules” (ground rules) to make it easier for everyone to share their thoughts and ensure the best retrospective experience. The following rules were read aloud to all participants: Be active in the conversation! No matter how trivial it may seem, don't hesitate to share it! Don't monopolize the conversation! Do not interrupt others while they’re speaking! Remember that even those who are quiet have something valuable to contribute Trust that everyone did their best Focus on finding causes, not assigning blame Frame it as “the problem versus us” Appreciate the opportunity to learn from mistakes and celebrate our growth! After reading the ground rules, the main retrospective began. The retrospective: KPT implementation Thanks to the contributions made by participants beforehand, we were able to start the session with a clear sense of direction. We began by reviewing the submitted entries one by one. An essential part of the process is having the person who wrote each entry read it aloud. While the facilitator could do this, it’s important for the group to understand the intent and emotions behind the words. That’s why we prioritize self-reading as much as possible. Process: The author reads their entry aloud. The facilitator reflects on the content, organizes it, and opens the floor for comments, additions, and feedback. Consolidate the input and update the Wiki to keep everything organized. For any proposed actions, achieve consensus and add them as a “Try” item. We followed this flow and kept the discussion lively and engaging for as long as time allows. At the end, we celebrated the completion of the event by finalizing the Wiki, enriched with action items (“Try”). A retrospective built together Reflecting on the retrospective Through this retrospective, we were able to create actionable items for the next similar event, leaving a legacy for our future selves to build upon. At the same time, we believe the retrospective served as a space to improve the “quality of relationships” and the “quality of thinking” among participants. By repeating these collaborative events, we aim to create a “positive cycle of success”. Better actions will lead to better results, ultimately strengthening the organization as a whole. Closing thoughts Thanks to the autonomy and dedication of each team member, we were able to host another enjoyable event with no major issues, just like last time! Now that we have established a track record of holding offline/online hybrid events, we plan to leverage this knowledge for future opportunities. This time, we replicated the approach from the first event to achieve the same results with less effort. However, it made me reflect on balancing "standardization" with "creativity." If a task is merely "something to do" without requiring creativity, it's better to standardize it through manuals (as we did this time). However, with each event held by KINTO Technologies, whether it’s managing the reception or arranging light meals, I’ve seen firsthand how creativity and ingenuity make these processes more attractive and efficient. Rather than attempting to overly systematize everything, perhaps it’s more important to create an environment where individuals are empowered to grow through their own autonomy and ingenuity. We also incorporated online participation to reach as many people as possible. However, I found it incredibly valuable to share challenges with other companies’ IT teams during in-person social gatherings. As we move forward, I would like to continue hosting events while carefully considering whether to stick with the hybrid format or focus solely on on-site events.
This article is the entry for day 21 in the KINTO Technologies Advent Calendar 2024 🎅🎄 Introduction Hello everyone! My name is DL, and I’m part of the Business Development Group team in the Group Core System Division at KINTO Technologies (KTC) . Currently, we’re collaborating with KINTO divisions in Latin America to implement an in-house system for KINTO One, a car leasing business with additional services like insurance. As a Business Analyst (BA), I focus on analyzing KINTO's operations and crafting IT solutions to streamline workflows and enhance efficiency. Before business analysis became part of the global team, system designs often fell short to meet KINTO’s global business expectations for enterprise-level solutions that addressed their daily operational intricacies. This is where a BA becomes indispensable in capturing the daily operational processes and addressing pain points, making Business Analysis a strategic pillar for adding value to global projects. Today, I want to invite you into the often-misunderstood world of the BA. You might think, “Isn’t that just a numbers person?” or “Aren’t they the ones writing down what others say?” But being a BA is far more—it’s about problem-solving, strategy, and communication. At its core, a BA bridges the technical and business worlds. Whether improving efficiency, streamlining operations, or adopting technology, the BA steps in to listen, analyze, and design practical, impactful solutions. By engaging stakeholders from executives to end-users, the BA becomes the crucial translator, turning business needs into effective technical solutions. Story 1 - The Power of Listening: A Business Analyst (BA)’s Role One critical skill for a BA is listening—not just to words, but to the underlying needs. In one project, I tackled a financial company’s inefficient reporting process. Business units worldwide submitted quarterly reports via email, creating a bottleneck with over 100 daily emails. Files were manually downloaded, consolidated, and checked for errors—a time-consuming, error-prone process. Witnessing this firsthand, I worked with stakeholders to identify pain points. Collaborating with IT, we developed a secure LAN directory structure for direct submissions. Automated batch and VBA scripts streamlined checking, copying, and aggregating data, reducing manual effort by 70% and enabling more valuable analysis. The solution’s success led to its adoption across the department. Story 2 - A Lesson in Overlooking Stakeholders Afterwards, a SaaS product was introduced without the BA and users’ full review. It was selected for its cost savings and dashboards, but it couldn’t support existing automated workflows, forcing teams back to manual processes... Despite complaints, the decision was final, leaving users frustrated and dissatisfied. This experience underscored the importance of involving a BA early to align solutions with real user needs. The Story Continues
 Although Story 2 might initially seem like a letdown, it offers an important lesson: whether we’re introducing process changes or developing new products, the key to success lies in listening to and truly understanding the needs of the end users. This brings us to the critical role a BA plays in KTC’s global project. As mentioned earlier, the global team is working with KINTO divisions in Latin America to implement an in-house system for KINTO One business (a car leasing business with additional services, e.g., insurance). Developing a global product/system means addressing diverse specifications across countries and languages. The challenge lies in creating a system that is flexible enough to accommodate each country’s varying needs. So, how do we approach this? Business users in each country are experts in their own processes and the processes are different country by country. Engineers are tasked with the challenge of building a flexible system that can accommodate all the differences. This is where the BA steps in, bridging the gap between business users and engineers. As a BA, we take a systematic approach: Gathering Business Processes: We carefully document the processes unique to each country. As the BA, this step is highly critical. The BA basically needs to become the expert of the business processes and fully understand every detailed step to ensure no steps are missed. To accomplish this step, our BAs in KTC have visited and been on-site at the businesses in Latin America, which is essential for grasping the nuances of each process. Moreover, the key in this step is to understand the businesses’ current pain points. Why? Because the system KTC develops should address these pain points to add tangible value to the business users’ daily workflows. By addressing the pain points, the business users can see a decrease in manual work, increase in productivity and effectiveness. And this can be measured in terms of hours of work reduced, reduction in lead time, and general welfare of the business users. Conducting Gap Analysis: This analysis highlights the differences and commonalities across these processes for each country. As the BA, there are two critical considerations in this step: Order of Operations: If the countries have similar order of operation, then that’s great news! However, if one country has a reverse order of operation, then this becomes much more complex when designing a system that can accommodate both. For example, to perform a repair on a vehicle, in case 1: the repair is approved first as a KINTO service, and then the execution of service is carried out. However, in case 2: the execution of service is carried out first, then the service is verified if it’s included as a KINTO service. Such differences in the order of operation adds complexity to the system design. External Systems Integration: Another critical consideration in this step is to note the external systems/platforms that are currently being used by the different countries. For example, one country may be using SAP as their accounting system, another country may be using another type of accounting system. This adds complexity to the integration needed for the global product. Collaborating on Solutions: Using the gap analysis, the BA works closely with the engineers to design the flexibility needed to meet the requirements of all countries involved. In this step, the BA is now trying to solve a complex puzzle with the help of the engineers. As the BA, this step is highly critical because the BA basically represents the business users of both countries and needs to design a system that can accommodate both. As an analogy, maybe one country is like a sedan, and the other country is like a van, so the BA works with the engineers to come up with an SUV?... lol... something along those lines. This step involves looking at the details of every step of the process and making sure that every step can accommodate both countries. Then after that, making sure that all the steps can be stitched together to create a cohesive and flexible system. It’s a lot of fun to solve such complex problems! The result is a collaborative effort that ensures the global product not only aligns with business needs but also has the right balance of system flexibility. This demonstrates just how essential the role of a BA is in the success of a global project. The Impact of a Business Analyst (BA) What does it mean to be a BA? It means being a problem solver, a communicator, and a strategist—having the curiosity to ask questions, the patience to listen, and the persistence to find answers. Ultimately, it’s about making a real difference in how organizations run, how people work, and how decisions are made. BAs may not always be in the spotlight, but our work shapes outcomes, saves resources, and makes lives easier. We are the bridge that turns ideas into reality, translating needs into solutions. If there’s one takeaway, it’s this: Never underestimate the power of listening. Whether you’re a BA, a stakeholder, or someone striving to make a difference, real progress comes from listening, translating, and connecting. Thank you!
この蚘事は KINTOテクノロゞヌズアドベントカレンダヌ2024 の21日目の蚘事です🎅🎄 はじめに こんにちは。KINTO FACTORY開発グルヌプのうえはら( @penpen_77777 )です。 2024幎の7月に入瀟し、KINTO FACTORYのバック゚ンドの開発を担圓しおいたす。 今回は12/8に開催されたISUCON14にKINTO Technologies瀟員で参加しおきたので、その内容や結果を共有したいず思いたす。 ISUCON14ずは ISUCONずは、LINEダフヌ株匏䌚瀟が運営窓口ずなっお開催しおいる、お題ずなるWebサヌビスを決められたレギュレヌションの䞭で限界たで高速化を図るチュヌニングバトルです。 優勝するず賞金100䞇円を獲埗できたす 今幎は12/8(日)の10:00〜18:00で開催されたした。 私(うえはら)は昚幎のISUCON13からパフォヌマンスチュヌニングの知識習埗はもちろん、゚ンゞニアずしおの腕詊し・スキル向䞊を目的に参加しおいたす。 :::message ISUCONは、LINEダフヌ株匏䌚瀟の商暙たたは登録商暙です。 https://isucon.net/ ::: チヌム「ktc-isucon-bu」 瀟内Slackでうえはらがメンバヌを募集し、チヌム「ktc-isucon-bu」を結成したした。 メンバは以䞋の通りです。 うえはら( @penpen_77777 ) ISUCON13にも参加しおおり、今幎で2回目 叀谷 ISUCON初参加 西田 ISUCON初参加 ISUCONでは初期実装で䜿われおいる蚀語がいく぀かありたすが、今回はGo蚀語を遞択したした。 たた、初参加のメンバヌが倚いチヌムのためランキング䞊䜍を狙うずいうよりもスコアが10000点を超えるこずを目暙にしたした。 参加に向けおの事前準備 ISUCONでは競技本番での改善タスクに集䞭できるように、兞型的な䜜業は自動化もしくは容易に実行できるようにするのが重芁です。 今回は、以䞋の準備を行いたした。 環境構築・デプロむコマンドの敎備 ドキュメント生成ツヌルの敎備 蚈枬ツヌルの敎備 個人緎習/チヌム緎習 環境構築・デプロむコマンドの敎備 go-taskはタヌミナルでタスクを実行するのに特化したツヌル、いわゆるタスクランナヌです。 https://taskfile.dev/ 埓来だずmakeコマンドをタスクランナヌずしお䜿われるこずが倚いず思いたすが、個人的にはgo-taskの方がより䟿利に感じたので今回はgo-taskを䜿甚したした。 (makeず異なりむンストヌルが必芁なのが難点ですが、そこを陀けば業務でも十分掻甚できるかなず思いたす) 䟋えば以䞋のようなtaskfile.yamlを䜜成し、 setup タスクず deploy タスクを定矩したす。 version: '3' tasks: setup: cmds: # 環境構築甚コマンドを蚘述 - echo "setup" deploy: cmds: # デプロむ甚コマンドを蚘述 - echo "deploy" 䜜成埌、以䞋のように task タスク名 でコマンドを叩くこずでタスクを実行できたす。 # 環境構築タスクを実行 $ task setup setup # デプロむタスクを実行 $ task deploy deploy たた、タスク実行時にコマンドラむン匕数を枡すこずもでき、受け取った匕数をタスク内に埋め蟌むこずもできたす。 version: '3' tasks: setup: cmds: - echo "setup {{ .CLI_ARGS }}" deploy: cmds: - echo "deploy {{ .CLI_ARGS }}" # サヌバisu1に察しおsetupタスクを実行 $ task setup -- isu1 setup isu1 # サヌバisu2に察しおdeployタスクを実行 $ task deploy -- isu2 deploy isu2 䞊のコヌドは簡単な䟋ではありたすが、実際䜿甚する際にはコマンドラむン匕数を甚いお反映先のサヌバを自由に切り替えられるように䜜っおおくこずで チヌムでの分担䜜業が捗りたす。 その他、go-taskを䜿うメリットは以䞋の通りです。 サブディレクトリで䜜業しおいおも、芪ディレクトリに存圚するtaskfile.yamlを怜出しおタスクを実行できる ディレクトリの䜍眮を気にせず、タスクを実行できる タスクからタスクを呌び出すこずができるため、定矩したタスクの再利甚性を高められる deploy タスクを実行する前に setup タスクを実行するなど、タスクを組み合わせお実行できる ISUCONで䜿甚するツヌルを党おtaskfile.yamlに蚘述しおおくこずで、ツヌルの䜿甚方法(必芁なオプションなど)を知らなくおも task コマンドを叩くだけで実行できる 事前に taskfile.yaml のテンプレヌトを䜜成しおおき、本番では䞀郚の倉数を曞き換えるだけであらゆる問題がきおも柔軟に察応できるようにしおおきたした。 ドキュメント生成ツヌルの敎備 以䞋の2぀のツヌルを䜿甚したした。 https://github.com/k1LoW/tbls DBの䞭身を読み取り、ER図ずスキヌマの説明が入ったドキュメント(markdown)を生成 デヌタベヌスに繋ぎに行かなくおもスキヌマ定矩を確認できるため、DBの構造を理解するのに䟿利 CI/CDパむプラむンでドキュメントを自動生成するこずで、DB構造の倉曎を远いやすくなる 詳しくは以䞋の蚘事を参照ください https://devblog.thebase.in/entry/auto_generated_er_graph_by_tbls_and_github_actions https://github.com/mazrean/isucrud アプリケヌションコヌドを読み取り、DBテヌブルずの関係を可芖化・ドキュメント(markdown)を生成 関数が倚くなっおくるず図がわかりにくくなるのが欠点だったのですが、webブラりザ䞊でむンタラクティブに芋たい箇所を絞り蟌めるようになったのでずおも䜿いやすくなった 蚈枬ツヌルの敎備 以䞋のツヌルを䜿甚したした。 https://github.com/kaz/pprotein アクセスログ、スロヌク゚リログ、プロファむルデヌタを収集し、可芖化するツヌル ベンチマヌクを叩くずwebhookによっお自動的にデヌタ集蚈を始めおくれるようになるので䟿利 デヌタ収集時点でのコミットハッシュも蚘録しおくれるので、どのコミットがスコアアップに寄䞎したかがわかりやすい^[pproteinでうたくGitコミットハッシュが取埗できない珟象に遭遇し、fork・コヌドを修正しおPRを出したした。 https://github.com/kaz/pprotein/pull/37] 個人緎習/チヌム緎習 緎習に関しお、初参加のメンバヌがいきなりISUCONの過去問を解こうずしおも難易床の高さから挫折しおしたう可胜性がありたす。 たずはパフォヌマンスチュヌニングの雰囲気を感じ取っおもらうため、達人が教えるWebパフォヌマンスチュヌニングずいう本を読んでもらいたした。 https://gihyo.jp/book/2022/978-4-297-12846-3 曞籍を読み進め぀぀、以䞋を緎習問題ずしお週末チヌムで集たり解いおいきたした。 https://github.com/catatsuy/private-isu (曞籍でもprivate-isuを䜿っおどのようにチュヌニングしおいけば良いか玹介されおいたす) 倧䜓10~20䞇点くらいたでスコアを取れるようになっおきたずころで、昚幎のISUCON13の問題に倉えお解いおいきたした。 ここたできたら本番を意識した緎習にスラむドしおも特に問題なく進められるようになったかなず思いたす。 今回のお題 https://www.youtube.com/watch?v=UFlcAUvWvrY ラむドチェアサヌビス「ISURIDE」の改善 チェアオヌナヌ(怅子の所有者)が怅子を提䟛 ナヌザはアプリから怅子が配車され、その怅子を䜿っお目的地たで移動できる スコアは移動距離やラむド完了率などから蚈算される ナヌザ満足床を高めるように改善を進める必芁がある https://github.com/isucon/isucon14 結果 結果は以䞋の通りです。目暙の1䞇点を超えるこずができたした 135䜍 / 831チヌム䞭 12514点 できたこず デプロむスクリプト等の準備(うえはら 10:00~10:30) 圓日マニュアル(叀谷 10:00) 動䜜しおいるプロセスを確認しおおおよその構成を理解する(叀谷 10:00) アプリケヌションマニュアルを読む(西田 10:00) MySQLにログむンし、テヌブルサむズを調べる むンデックスを远加(西田 11:21) -- chair_locations CREATE INDEX idx_chair_id ON chair_locations(chair_id); CREATE INDEX idx_chair_id_created_at ON chair_locations(chair_id, created_at); -- chairs CREATE INDEX idx_owner_id ON chairs(owner_id); -- ride_statuses CREATE INDEX idx_ride_statuses_ride_id_chair_sent_at_created_at ON ride_statuses (ride_id, chair_sent_at, created_at); pproteinの仕蟌み (うえはら 11:48) nginxの蚭定を修正するのに手こずり、1時間以䞊かかっおしたう むンデックス远加(西田 11:54) CREATE INDEX idx_ride_statuses_created_at_ride_id_chair_sent_at ON ride_statuses (created_at, ride_id, chair_sent_at); -- rides CREATE INDEX idx_chair_id_updated_at ON rides (chair_id, updated_at DESC); 動的パラメヌタを有効化・jsonパッケヌゞを高速化(うえはら 12:38) // import文を修正 "encoding/json" → "github.com/goccy/go-json" // DB接続時の蚭定でInterpolateParamsをtrueに dbConfig.InterpolateParams = true むンデックス远加(うえはら 13:05) -- chairs CREATE INDEX idx_chairs_access_token ON chairs(access_token); -- ride_statuses CREATE INDEX idx_ride_statuses_ride_id_app_sent_at_created_at ON ride_statuses (ride_id, app_sent_at, created_at); -- rides CREATE INDEX idx_rides ON rides (user_id, created_at); -- coupons CREATE INDEX idx_coupons_used_by ON coupons(used_by); ナヌザ・ステヌタスキャッシュ(叀谷 14:30) usersずride_statusesテヌブルをむンメモリキャッシュ トランザクション範囲の修正(西田 14:48, 15:09) notificationのポヌリング間隔調敎(叀谷 16:27) appGetNotificationずchairGetNotificationで返しおいるRetryAfterMsを30 msから300 msに倉曎 怅子ずナヌザのマッチング間隔を短くした(西田 17:18, 17:28) ISUCON_MATCHING_INTERVALを0.5 sから0.1 sに短くした スコアが2倍近く䞊がった(䞀番効いた斜策) binログ停止(叀谷 17:24) MySQLの蚭定ファむル(/etc/mysql/mysql.conf.d/mysqld.cnf)でbinログの出力を停止 disable-log-bin=1 innodb_flush_log_at_trx_commit=0 ログ出力を無効化(うえはら 17:43) nginx、mysqlのログ出力を停止 アプリケヌション偎のログ出力停止 ownerGetChairsの改善(西田 17:43) distanceをメモ化するようにした コネクション数を調敎(うえはら 17:49) db.SetMaxIdleConns(50) db.SetMaxOpenConns(50) 時間が足りない or スコアがあがらずできなかった斜策 マッチング凊理の修正(うえはら 13:00~16:00) 実装したが怅子が配車されない゚ラヌの解消を乗り越えられず、断念  chairsのアクセストヌクンをキャッシュ(叀谷 15:36) 叩かれるク゚リ数は倧幅に削枛できた(30000→100)が、うたくスコアが䞊がらなかった 別の箇所にボトルネックが移ったのかもしれない nginxパラメヌタチュヌニング(叀谷 17:39) ベンチマヌクの゚ラヌでうたく動かず  サヌバ分割(うえはら 16:00 ~ 17:00) nginx+goずMySQLの2台構成に倉曎しようずしたら、ベンチマヌクでデヌタ䞍敎合の゚ラヌがおきうたく動かすこずができなかった 2台ずもchairずrideのマッチングを行うサヌビスが動いおいたため、デヌタ䞍敎合が起きたこずに競技終了埌気づいた (止めおおけば ) 良かった点 1䞇点を超えるずいう目暙を達成できた isucon2回目1名+初参加2名のチヌムで135䜍、12514点ずいうのは結果ずしおは䞊々なのではないかず感じる 党員で改善タスクを進められた 䜕も手を぀けられないずいうこずがなく、党員が䜕かしらの改善を進められた サヌバ䞊ぞの環境構築、デプロむスクリプトの仕蟌みがほが問題なく進められた デプロむ面で特に問題が生じるこずはなかった ただpproteinの仕蟌みでnginxの蚭定がうたくいかず1時間ほど手こずっおしたったので、手順曞に泚意曞きを曞いおおきたい ツヌルを䜜っおおくず快適に改善を進められるので今埌もツヌル面を充実させおいきたい 反省点 あたりアプリケヌションの䞭身を理解できずに改善を進めおしたった アプリケヌションの仕様理解が重芁な今回の問題だず、機械的にスロヌク゚リログやアプリケヌションログを元に高速化しおもスコアアップに繋がりにくく、手を出せる箇所が少なかった アプリケヌション理解が深たるような䜕らかの仕組みづくりをしたい 普段の業務でも仕様理解は重芁なので、今埌も意識しおいきたい マッチング凊理をバグらせおしたっおい぀たでも実装できなかった テヌブル構造を倉えずにク゚リだけで実装しようずしお蟛くなっおしたったので、テヌブルに郜合の良いカラム远加しおアプリケヌションコヌドを単玔にしお実装しやすくするのが倧事だなず思った SSE(Server-Sent Events)に぀いお党く知らなかったので勉匷しおおきたい ナヌザの怅子の状態をリアルタむムに曎新するのに䜿える技術ずしお玹介されおいた これからの業務で生かそうず思う点 技術的な知識習埗だけでなく目の前のアプリケヌション理解は䜕よりも倧事 タスクランナヌ(go-task)やドキュメント自動生成ツヌル(tblsなど)を䜿っお業務効率化を図っおいきたい SSE(Server-Sent Events)に぀いおプロダクトに組み蟌めるようなずころがあれば䜿っおみたい たずめ ISUCON14に参加し、チヌム「ktc-isucon-bu」ずしお12514点、党チヌム831チヌムのうち135䜍ずいう結果を残すこずができたした。 反省点はありたすが、ISUCON初参加のメンバヌがいる䞭でスコア10000点を超えるずいう目暙を達成できた点は良かったです。 この反省を糧に、次回のISUCON15ではさらなる高みを目指しおいきたいず思いたす。 初ISUCONにもかかわらず参加いただいたチヌムメンバヌの叀谷さん、西田さん、たた今回参加たでには至らずずも興味・関心をお寄せいただいた瀟員の皆さんありがずうございたした 最埌にこの玠晎らしいむベントを開催しお䞋さった運営の皆さんに感謝いたしたす。
This article is the entry for day [21] in the KINTO Technologies Advent Calendar 2024 🎅🎄 Introduction Hey there! I’m Viacheslav, an iOS engineer, and today’s article is part of the Advent Calendar 2024 event at KINTO Technologies. This year, I had the opportunity to work on a new feature in our Unlimited app called "これなにガむド" (Kore Nani Gaido, meaning "What's This Guide"). Kore Nani Gaido is an augmented reality (AR) manual that allows users to "scan" their car's dashboard and displays virtual markers over a car's buttons, switches, and other elements. By selecting a marker corresponding to a specific button, users can access a detailed manual page for that control. Today, I’d like to share a short and simple solution to one of the challenges I encountered while working on this feature: accurately capturing the coordinates of a physical object recognized by Vision framework on the screen and converting them into 3D coordinates within an AR scene. What initially seemed like a trivial task turned out to be more complex than expected. After exploring several approaches and performing a lot of manual calculations, I finally arrived at a solution that is both straightforward and surprisingly concise. I wish I’d known about it when I started, as there is relatively little information available about ARKit and CoreML integration. So, let’s add to that knowledge base! A Couple of Preconditions Before we get to the actual code, let's clearly define the environment we’ll be working with: ARSCNView This is a view that displays the video feed from the device's camera, capturing the real-world environment and allowing 3D objects to "blend in" for an AR experience. ARSCNView is part of Apple's ARKit , built on top of SceneKit , which handles rendering 3D objects in an AR scene. Core ML Object Detection Model Before we can determine the coordinates of an object, we first need to recognize it within the video feed frames provided by the device's camera. Vision framework utilizes Core ML Object detection models for that purpose. For this article, I’ll assume you already have a model ready to use. If not, there are many pre-trained models available for download, such as YOLOv3-Tiny , which you can find here . And that’s all you need for a bare-bones solution! We’ll capture video frames from ARSCNView , use the Core ML model to detect the object’s position within the ARSCNView viewport, and apply a technique called "hit-testing" to determine the object’s coordinates in 3D AR space. Capturing the Coordinates of a Recognized Object in ARSCNView When performing recognition requests with Vision, a typical setup you might have is described below. You initialize a Core ML model and a VNCoreMLRequest to handle recognition using that model. let vnModel = try! VNCoreMLModel(for: myCoreMLModel) let vnRequest = VNCoreMLRequest(model: vnModel) { [weak self] request, _ in guard let observations = request.results else { return } // Observations handling } request.imageCropAndScaleOption = .centerCrop You then keep a reference to vnRequest in a suitable place, ready to be performed with the next set of arguments. The argument types depend on where you’re capturing video feed frames from. In our scenario, we are passing frames from an ARSCNView , which should be captured in the session(_:didUpdate:) method of ARSessionDelegate . This delegate method is called whenever a new frame is available for ARSCNView to display. func session(_ session: ARSession, didUpdate frame: ARFrame) { guard let vnRequest else { return } // 1 let options: [VNImageOption: Any] = [.cameraIntrinsics: frame.camera.intrinsics] // 2 let requestHandler = VNImageRequestHandler( cvPixelBuffer: frame.capturedImage, // 3 orientation: .downMirrored, // 4 options: options ) try? requestHandler.perform([vnRequest]) // 5 } Breaking Down the Code: Reference to VNCoreMLRequest : Once we receive a new frame, we are ready to perform the request we have initialized earlier. Camera Intrinsics : frame.camera.intrinsics provides camera calibration data to help Vision interpret the geometric properties of the scene. Image Input : VNImageRequestHandler accepts raw image data as a CVPixelBuffer , obtained from the AR frame. Image Orientation : The .downMirrored orientation accounts for the inverted coordinate system of the camera feed compared to Vision's default orientation. Performing the Request : The prepared request is executed using the request handler. Once you start passing frames to Vision, object detection results are returned as arrays of VNRecognizedObjectObservation objects in the VNCoreMLRequest completion handler. While you might filter these results by confidence level or perform other processing, today we’ll focus on extracting the coordinates of a specific recognized object. Extracting Bounding Box Coordinates At first, this might seem straightforward since VNRecognizedObjectObservation has a boundingBox property — a CGRect enclosing the recognized object. However, there are a few complications: The boundingBox is in a normalized coordinate system relative to the input image of the object recognition model (meaning that the coordinates' values are between 0 and 1) which also has inverted Y-axis. The sizes and aspect ratios of the camera feed, Core ML model input, and the ARSCNView viewport differ from each other. This means that a series of coordinate conversions and rescaling steps are required to transform the boundingBox into the ARSCNView viewport's coordinate system. Doing those conversions manually might be cumbersome and mistake-prone. Fortunately, there’s an embarrassingly simple way to handle this using CGAffineTransform . Here’s how: let sceneView: ARSCNView func getDetectionCenter(from observation: VNRecognizedObjectObservation) -> CGRect? { guard let currentFrame = sceneView.session.currentFrame else { return nil } let viewportSize = sceneView.frame.size // 1 let fromCameraImageToViewTransform = currentFrame.displayTransform(for: .portrait, viewportSize: viewportSize) let viewNormalizedBoundingBox = observation.boundingBox.applying(fromCameraImageToViewTransform) // 2 let scaleTransform = CGAffineTransform(scaleX: viewportSize.width, y: viewportSize.height) let viewBoundingBox = viewNormalizedBoundingBox.applying(scaleTransform) return viewBoundingBox } Explanation: Transforming to View Coordinates : Using displayTransform(for:viewportSize:) the detected bounding box is converted from the normalized coordinate system of the input image to a normalized coordinate system of ARSCNView . Scaling to Pixel Dimensions : The normalized bounding box is scaled to match the size of the ARSCNView viewport, resulting in a bounding box in screen pixel dimensions. And that’s it! You now have the bounding box in the coordinate system of the ARSCNView viewport. Getting the Third Coordinate I promised that we will get the coordinates of the recognized object within the 3D coordinate space of the AR scene. To do that, we are going to utilize a technique called "hit-testing." It allows us to measure the distance to the closest physical object at an arbitrary point in the viewport. You can imagine this technique as casting a straight ray from your device to the first intersection with a physical object at the selected point of the viewport and then measuring the length of that ray. This functionality is a part of ARKit and is really easy to use. Here is how we can find the 3D coordinates of the perceivable center of the object we detected earlier. func performHitTestInCenter(of boundingBox: CGRect) -> SCNVector3? { let center = CGPoint(x: boundingBox.midX, y: boundingBox.midY) // 1 return performHitTest(at: center) } func performHitTest(at location: CGPoint) -> SCNVector3? { guard let query = sceneView.raycastQuery( // 2 from: location, allowing: .estimatedPlane, // 3 alignment: .any // 4 ) else { return nil } guard let result = sceneView.session.raycast(query).first else { return nil } // 5 let translation = result.worldTransform.columns.3 // 6 return .init(x: translation.x, y: translation.y, z: translation.z) } Explanation: Here, we calculate the center of the bounding box from the previous step, as we need a single point to perform the hit-testing. Creates a raycast query starting from the given 2D point. Allows hit-testing to consider non-planar surfaces or planes about which ARKit can only estimate. Enables hit-testing for both horizontal and vertical surfaces (default is horizontal only). Executes the raycast query using the AR session. Returns nil if there’s no intersection. Each ARRaycastResult contains a worldTransform , which is a 4x4 matrix representing the 3D transformation of the detected point in world space. The columns.3 contains the translation vector, which specifies the 3D position of the intersection. This translation is returned as an SCNVector3 , which ARKit/SceneKit uses to represent 3D positions. Done! You now have the 3D coordinates of an object detected by Vision. Feel free to use them for your purposes. :) Conclusion In the Unlimited app, we use these 3D coordinates to display AR manual markers in a car. Of course, there are many additional techniques we employ to make the user experience smoother and the marker positions more stable, but this is one of the core techniques. That said, this same method can be used for any other purpose you can think of. I hope you find it helpful. Finally, here’s a tiny sneak peek into our testing process and how our AR manual markers are displayed after object detection. That's it for today—thanks for reading! Wishing you the Merriest Christmas and the Happiest New Year!
Introduction This is a report from the organizers of the second "KINTO Technologies MeetUp!" Our Event page: [Second] KINTO Technologies MeetUp! - connpass Previous related articles: Preparations for our first "KINTO Technologies MeetUp!" | KINTO Tech Blog | KINTO Tech Blog (kinto-technologies.com) KINTO Technologies MeetUp! (Organizers’ edition) | KINTO Tech Blog | KINTO Tech Blog (kinto-technologies.com) The first event was held exclusively on-site, but this time we prepared to allow participation online as well. Building on the knowledge gained from our first event, we embraced the challenge of hosting in a new hybrid format. Here’s a look at the organizer’s experience this time around! Pre-Event Tasks Snack arrangement To ensure no one felt “a bit unsatisfied” with the food, we focused on enhancing the snack selection. During the latter half of our last event, we found that the pizza we had prepared wasn’t enough, and some participants commented that they felt “a bit unsatisfied.” Initially, we planned for pizza again and increased the budget to address this, but we eventually learned about Maisen’s mini burgers (thanks to a recommendation) and decided to offer those instead. Here are some of the great things about the mini burger: It is individually packaged and easy to grab. Therefore, there is no need to prepare paper plates. It is easy to give away if there are leftovers, reducing waste. It is designed to be served at room temperature, allowing more flexibility with delivery timing. Although we had a strong desire to serve hot pizza, we decided on the mini burgers after considering the benefits. Additionally we prepared individually wrapped snacks to make it easy for participants to enjoy at their convenience. As a result, many participants enjoyed the mini burgers, and we ended up with just a few leftovers, making it a successful choice overall! Novelty selection We aimed to provide novelties that would make participants think, "I want to take this home and actually use it.” With this goal in mind, we carefully selected items, believing that a good event combined with appealing novelties can bring back fond memories of the day just by looking at them. In choosing the novelties, we considered not only practicality but also whether the items would have an irresistible appeal. For distribution, we thought carefully about how to present the novelties in a way that encourage attendees to take them home. Although not all novelties were taken by participants, we hope that those who did take them will remember the event whenever they see the items. Event timetable design I was entrusted with designing the event timetable, which is an important factor that determines the progression and flow of the event. It was a significant responsibility, and I felt the pressure as I worked through it. My main focus during the planning was, “ Will the participants find the event engaging and enjoyable without feeling bored? ” In the timetable for the previous MeetUp, we missed incorporating break times and a group photo session with participants, which were later highlighted as areas for improvement. For this event, we addressed these points by allocating time for breaks and photos. Additionally, we included a Lightning Talk session to bring energy and keep the pace lively, something that was missing last time. Thankfully, the event proceeded smoothly, mostly according to the timetable, and the atmosphere was lively throughout—a welcome outcome. However, we made some last-minute adjustments to the timetable, and I realized in hindsight that more careful pre-event planning would have helped. Event documents preparation To prepare documents, not only did we organized presentations for speakers but also prepared various guides and resources for attendees, including event instructions, seating arrangements for discussion sessions, and pre-event handouts. These documents were aimed at ensuring the smooth progression of the Meetup. In the previous event, we realized that verbal directions to restrooms or having a QR code for Wi-Fi access would have been helpful, so this time we created documents to cover these needs. Promotion and Outreach Attracting attendees to corporate events can be challenging, and we also faced difficulties. Here are two approaches we found especially effective: Included the product names mentioned in the presentations within the promotional text. Posted in the IT Slack community. Included the product names mentioned in the presentations within the promotional text. Initially, we planned to announce the event on X twice. The first announcement was scheduled for when it went live on connpass, and the second just before the event. However, we soon realized that the key metrics we wanted to focus on were not growing as expected, which were: Views on the connpass event page The number of event participants To address these challenges, we considered increasing the opportunities for people to learn about the event by adding more posts on X. However, simply posting about the event might not catch people’s attention, and awareness of the event could remain low. So, we decided to drill down our thinking to create more effective post content. We asked ourselves, “what kind of post would catch my eye as a reader?” ↓ Would I be more interested if the post mentioned a product I care about? ↓ Would it feel more relatable if it included some of the challenges we faced? Through this simple drill-down, we concluded that the post should include not only the product names mentioned in the presentations but also what we achieved with them. Here’s an example of the posts we created: By posting such kind of content, we successfully increased both the views on the connpass event page and the number of participants, addressing the challenges we had been facing. We couldn't be happier with the results!! IT Slack community posts On the day of the event, we asked some of the on-site attendees how they had heard about the event. All of them answered, “on the IT Slack.” Its reach is truly impressive! As someone who regularly checks the Slack channel #share-event as well, I highly recommend posting announcements there when hosting events related to IT or corporate IT. This time, our event aimed to connect with other corporate IT teams, and the warmth of the IT Slack community was truly heartwarming. To those who participated, whether you found us through connpass or X, thank you, and we look forward to your continued support! Disruptive participants prevention In the past, we experienced a situation at another KTC-hosted event where a person seemed to attend solely for the food. There was an atmosphere that could have escalated into a disturbance, as the person drank excessively and reacted negatively when approached. Through this experience, I decided to firmly establish a clear protocols and preventative measures. After researching how others handle such situations, we adopted the following approaches: Identify and prevent disruptive individuals before they can cause issues. If a disruptive individual does enter (or tries to get in), ensure minimal impact on legitimate participants, and act swiftly to manage the situation. Thoughts on handling troublemakers at networking events | wakatono (note.com) We prepared with the approach of preventing suspicious individuals from entering while also establishing grounds and methods for their removal if necessary. After consulting with the building management team at KINTO Technologies’ Muromachi Office in COREDO Muromachi 2, which was our venue, they assured us that they could intervene if needed, even restraining individuals if the situation escalated. We shared their contact information with the event staff to ensure everyone was prepared to respond if necessary. Additionally, we updated the connpass event page to include a clear policy prohibiting disruptive behavior and informing participants that they may be asked to leave if such actions occur. Fortunately, no such incidents happened this time. However, having these measures in place gave us peace of mind and allowed us to focus fully on running the event smoothly. Event Day Tasks Venue set up We followed the same basic process as in the previous event, but this time we also needed to account for the space required for the streaming equipment. Its placement was determined by the length of our cables, and we also made sure that participants still had a comfortable viewing area while adressing those constraints. While we prepared the basic layout in advance, adjustments were made on the day to accommodate the number of attendees. Although there was some last-minute scrambling, we successfully created a space where participants could relax and enjoy the event. Unfortunately, we weren't able to update the seating layout for the discussion session in time, which caused some confusion during the event. Equipment setup, connections, and control With limited equipment on hand, we carefully planned how to deploy it effectively. Hosting the event in a hybrid format required extra attention to various details. Thankfully, there were no major issues, and we were able to deliver a seamless experience for our online attendees as well. Overall, it turned out to be a successful event! Camera setup Since the camera feed would be projected onto a small wipe, we adjusted the framing to ensure that the speaker's face was clearly visible. The camera had to be connected to the “switcher” used for stream control, so we positioned it near the operation desk (commonly referred as the "ops desk") while ensuring it faced the speaker directly. The camera was basically fixed in place! Minimal adjustments were needed when speakers took turns to correct any misalignment caused by differences in their heights. Audio setup We conducted pre-event checks for microphones, volume levels in the venue, and audio levels for online participants. Since this was a hybrid event, these checks were absolutely essential! We made sure to prevent any issues, such as audio distortion or volume levels that were either too low or too high for both online and in-person attendees. Additionally, during presentations, we continuously monitored the online audio to respond immediately in case of any audio dropouts or sudden distortion. Streaming For this event, we decided on a relatively simple streaming setup, drawing from previous successful experiences. By keeping the setup straightforward, we minimized the risk of unexpected issues during the broadcast. We projected the same video feed onto a screen so that the presenters could see how their slides and wipe were displayed. To ensure the speaker’s slides and the wipe didn’t overlap, we manually adjusted the position of the wipe, moving it around to different corners as needed. Each speaker was able to present using their own familiar laptop, and we managed the visuals without any disruptions. This made the process smooth and hassle-free! Microphones, document projection, the wipe-everything was checked and ready to go! Reception, guidance, and exit support Preparation Since we had the same team as the previous event, we already had a good amount of knowledge. However, we documented tasks in Confluence, assigned roles to each member, and prepared accordingly. By deciding everyone’s roles for the event day in advance, we avoided unnecessary chaos during the event. On the day of the event As soon as the registration closed, we started preparing the building entry passes. They looked too plain on their own, so we added a custom cover for a personalized touch. This small effort, which we’ve also used for other events, really makes a difference. Reception start Since the event took place during rush hour, many non-participants were coming and going. To ensure that attendees could recognize the reception area, we called out to anyone who looked like they might be attending the event (Though sometimes we mistakenly approached unrelated people, haha). This time, we didn’t assign staff to guide attendees from the reception area to the 16th floor venue. Instead, whenever participants headed to the venue, we notified the operations team via Slack with updates like “X number of people are coming!” This was initially done spontaneously but turned out to be very well-received by the team waiting at the venue. In the end, it was a great idea, and I’m glad we did it! Exit support To be honest, we didn’t have detailed discussions about this part as a team, so whoever was available handled it on the spot. Personally, I really enjoyed chatting with attendees in the elevator as they left. Hearing comments like "That was fun!" "Please hold another event again" or "KINTO Technologies seems like such a fun company!" Left me feeling thrilled. Being able to hear this feedback live felt like a special reward! ♬ Moderation and hosting We managed to get through most of it with energy and quick adaptability! About 80% of the moderation was handled this way. Here, I’ll share the remaining 20% of the things we consciously focused on. Adding comments before each presentation In an in-person-only event, transitions like speaker changes are visible and don’t stand out much. However, in a hybrid event, online attendees can only see what’s shown on camera, which creates awkward silences during transitions. To address this, I added short introductions about the upcoming presentation or summarized the previous one, much like the opening remarks before classic Showa-era song performances. This helped create a smoother transition. Separate remarks for in-person and online audiences only at the beginning and end Time constraints were the main reason, but I avoided making separate comments for the in-person and online audiences during the event. For online attendees, hearing jokes or commentary that only resonates with the in-person audience can make them feel left out and reduce their sense of immersion. I kept this in mind while moderating. Using a microphone sparingly after the online broadcast ended This was the opposite approach compared to the one mentioned above. I wanted to maximize the in-person experience! It’s similar to how bands or idol groups sometimes speak directly to the audience without a mic at the end of a concert. It gives you that feeling of being on a live session. Yes, like that moment. I was initially hesitant about speaking in front of the audience, but I’m relieved that I was able to fulfill my role. To anyone reading this, I encourage you to give it a try as well. Snack preparation and distribution Last time was our first external event, and organizing refreshments was a bit of a challenge. But after hosting several other events over the past few months, we’ve gotten the hang of it! This time, we prepared Maisen’s cutlet sandwiches🐷 Everything looks delicious...Kin-chan Which should I take...Take-chan Compared to pizza, it's easier to eat. We adopted a casual style, encouraging participants to grab a sandwich after checking in and enjoy the meetup! while eating. Since the event was held around dinnertime (pretty much), I think this was a welcome addiction! Even though we ordered plenty, the fillet cutlet sandwiches were the first to disappear ( ..)φ [takes notes] We will do our best to adjust the quantities next time. For drinks, beer was the most popular. We had three types available, but after attending another company’s event that offered about ten varieties, I was impressed! Next time, we’ll try expanding our selection. Kaizen, kaizen! Post-Event Tasks Retrospective When it comes to wrapping up team activities, our go-to process is doing Retrospectives. What is a Retrospective Retrospectives are sessions: to look back on what went well, what didn’t go so well, and what happened during an activity or project, and from there, to identify and develop concrete action plans for the future. At KINTO Technologies, retrospectives are deeply embedded in our everyday practices. Across all departments, they are commonly referred to as “furikaeri” or simply “retro,” and they often come up in casual conversations. The event retrospective After the MeetUp concluded, we held a retrospective specifically for the organizing team. While there are no strict rules or fixed formats for these sessions, we often use the KPT framework (Keep/Problem/Try) to guide our discussions, which is what we used this time as well. In event operations, there are always things that could have gone better or areas for improvement. The KPT framework helps us identify these “seeds of kaizen” and turn them into actionable steps for future events. Retrospective preparation When there are many participants and everyone’s time is limited, proper preparation is key to make the most out of retrospective sessions. This time, we followed these steps: Created a Wiki where everyone can freely contribute (we used Confluence as our Wiki tool) Prepared a page with the KPT framework (for this retrospective, we created additional categories such as "Preparation," "Promotion and Outreach," and "On-site Setup" to make it easier to organize inputs). Announced on Slack, asking participants to write down their observations before the retrospective day. The facilitator reviewed the pages right before the retrospective, processes the contributions, and planned the flow of the discussion (for example, deciding what to prioritize and how much time to allocate for each topic). The retrospective: From icebreaker to ground rules And then, the retrospective took place! If we had more time, we would have started with an icebreaker, asking participants to share their best moments of the event to liven up the atmosphere. However, due to time constraints, the retrospective kicked off with a positive summary from the event leader. After the Icebreaker, we explained the “magic rules” (ground rules) to make it easier for everyone to share their thoughts and ensure the best retrospective experience. The following rules were read aloud to all participants: Be active in the conversation! No matter how trivial it may seem, don't hesitate to share it! Don't monopolize the conversation! Do not interrupt others while they’re speaking! Remember that even those who are quiet have something valuable to contribute Trust that everyone did their best Focus on finding causes, not assigning blame Frame it as “the problem versus us” Appreciate the opportunity to learn from mistakes and celebrate our growth! After reading the ground rules, the main retrospective began. The retrospective: KPT implementation Thanks to the contributions made by participants beforehand, we were able to start the session with a clear sense of direction. We began by reviewing the submitted entries one by one. An essential part of the process is having the person who wrote each entry read it aloud. While the facilitator could do this, it’s important for the group to understand the intent and emotions behind the words. That’s why we prioritize self-reading as much as possible. Process: The author reads their entry aloud. The facilitator reflects on the content, organizes it, and opens the floor for comments, additions, and feedback. Consolidate the input and update the Wiki to keep everything organized. For any proposed actions, achieve consensus and add them as a “Try” item. We followed this flow and kept the discussion lively and engaging for as long as time allows. At the end, we celebrated the completion of the event by finalizing the Wiki, enriched with action items (“Try”). A retrospective built together Reflecting on the retrospective Through this retrospective, we were able to create actionable items for the next similar event, leaving a legacy for our future selves to build upon. At the same time, we believe the retrospective served as a space to improve the “quality of relationships” and the “quality of thinking” among participants. By repeating these collaborative events, we aim to create a “positive cycle of success”. Better actions will lead to better results, ultimately strengthening the organization as a whole. Closing thoughts Thanks to the autonomy and dedication of each team member, we were able to host another enjoyable event with no major issues, just like last time! Now that we have established a track record of holding offline/online hybrid events, we plan to leverage this knowledge for future opportunities. This time, we replicated the approach from the first event to achieve the same results with less effort. However, it made me reflect on balancing "standardization" with "creativity." If a task is merely "something to do" without requiring creativity, it's better to standardize it through manuals (as we did this time). However, with each event held by KINTO Technologies, whether it’s managing the reception or arranging light meals, I’ve seen firsthand how creativity and ingenuity make these processes more attractive and efficient. Rather than attempting to overly systematize everything, perhaps it’s more important to create an environment where individuals are empowered to grow through their own autonomy and ingenuity. We also incorporated online participation to reach as many people as possible. However, I found it incredibly valuable to share challenges with other companies’ IT teams during in-person social gatherings. As we move forward, I would like to continue hosting events while carefully considering whether to stick with the hybrid format or focus solely on on-site events.
この蚘事は KINTOテクノロゞヌズアドベントカレンダヌ2024 の21日目の蚘事です🎅🎄 はじめに こんにちは。KINTO FACTORY開発グルヌプのうえはら( @penpen_77777 )です。 2024幎の7月に入瀟し、KINTO FACTORYのバック゚ンドの開発を担圓しおいたす。 今回は12/8に開催されたISUCON14にKINTO Technologies瀟員で参加しおきたので、その内容や結果を共有したいず思いたす。 ISUCON14ずは ISUCONずは、LINEダフヌ株匏䌚瀟が運営窓口ずなっお開催しおいる、お題ずなるWebサヌビスを決められたレギュレヌションの䞭で限界たで高速化を図るチュヌニングバトルです。 優勝するず賞金100䞇円を獲埗できたす 今幎は12/8(日)の10:00〜18:00で開催されたした。 私(うえはら)は昚幎のISUCON13からパフォヌマンスチュヌニングの知識習埗はもちろん、゚ンゞニアずしおの腕詊し・スキル向䞊を目的に参加しおいたす。 :::message ISUCONは、LINEダフヌ株匏䌚瀟の商暙たたは登録商暙です。 https://isucon.net/ ::: チヌム「ktc-isucon-bu」 瀟内Slackでうえはらがメンバヌを募集し、チヌム「ktc-isucon-bu」を結成したした。 メンバは以䞋の通りです。 うえはら( @penpen_77777 ) ISUCON13にも参加しおおり、今幎で2回目 叀谷 ISUCON初参加 西田 ISUCON初参加 ISUCONでは初期実装で䜿われおいる蚀語がいく぀かありたすが、今回はGo蚀語を遞択したした。 たた、初参加のメンバヌが倚いチヌムのためランキング䞊䜍を狙うずいうよりもスコアが10000点を超えるこずを目暙にしたした。 参加に向けおの事前準備 ISUCONでは競技本番での改善タスクに集䞭できるように、兞型的な䜜業は自動化もしくは容易に実行できるようにするのが重芁です。 今回は、以䞋の準備を行いたした。 環境構築・デプロむコマンドの敎備 ドキュメント生成ツヌルの敎備 蚈枬ツヌルの敎備 個人緎習/チヌム緎習 環境構築・デプロむコマンドの敎備 go-taskはタヌミナルでタスクを実行するのに特化したツヌル、いわゆるタスクランナヌです。 https://taskfile.dev/ 埓来だずmakeコマンドをタスクランナヌずしお䜿われるこずが倚いず思いたすが、個人的にはgo-taskの方がより䟿利に感じたので今回はgo-taskを䜿甚したした。 (makeず異なりむンストヌルが必芁なのが難点ですが、そこを陀けば業務でも十分掻甚できるかなず思いたす) 䟋えば以䞋のようなtaskfile.yamlを䜜成し、 setup タスクず deploy タスクを定矩したす。 version: '3' tasks: setup: cmds: # 環境構築甚コマンドを蚘述 - echo "setup" deploy: cmds: # デプロむ甚コマンドを蚘述 - echo "deploy" 䜜成埌、以䞋のように task タスク名 でコマンドを叩くこずでタスクを実行できたす。 # 環境構築タスクを実行 $ task setup setup # デプロむタスクを実行 $ task deploy deploy たた、タスク実行時にコマンドラむン匕数を枡すこずもでき、受け取った匕数をタスク内に埋め蟌むこずもできたす。 version: '3' tasks: setup: cmds: - echo "setup {{ .CLI_ARGS }}" deploy: cmds: - echo "deploy {{ .CLI_ARGS }}" # サヌバisu1に察しおsetupタスクを実行 $ task setup -- isu1 setup isu1 # サヌバisu2に察しおdeployタスクを実行 $ task deploy -- isu2 deploy isu2 䞊のコヌドは簡単な䟋ではありたすが、実際䜿甚する際にはコマンドラむン匕数を甚いお反映先のサヌバを自由に切り替えられるように䜜っおおくこずで チヌムでの分担䜜業が捗りたす。 その他、go-taskを䜿うメリットは以䞋の通りです。 サブディレクトリで䜜業しおいおも、芪ディレクトリに存圚するtaskfile.yamlを怜出しおタスクを実行できる ディレクトリの䜍眮を気にせず、タスクを実行できる タスクからタスクを呌び出すこずができるため、定矩したタスクの再利甚性を高められる deploy タスクを実行する前に setup タスクを実行するなど、タスクを組み合わせお実行できる ISUCONで䜿甚するツヌルを党おtaskfile.yamlに蚘述しおおくこずで、ツヌルの䜿甚方法(必芁なオプションなど)を知らなくおも task コマンドを叩くだけで実行できる 事前に taskfile.yaml のテンプレヌトを䜜成しおおき、本番では䞀郚の倉数を曞き換えるだけであらゆる問題がきおも柔軟に察応できるようにしおおきたした。 ドキュメント生成ツヌルの敎備 以䞋の2぀のツヌルを䜿甚したした。 https://github.com/k1LoW/tbls DBの䞭身を読み取り、ER図ずスキヌマの説明が入ったドキュメント(markdown)を生成 デヌタベヌスに繋ぎに行かなくおもスキヌマ定矩を確認できるため、DBの構造を理解するのに䟿利 CI/CDパむプラむンでドキュメントを自動生成するこずで、DB構造の倉曎を远いやすくなる 詳しくは以䞋の蚘事を参照ください https://devblog.thebase.in/entry/auto_generated_er_graph_by_tbls_and_github_actions https://github.com/mazrean/isucrud アプリケヌションコヌドを読み取り、DBテヌブルずの関係を可芖化・ドキュメント(markdown)を生成 関数が倚くなっおくるず図がわかりにくくなるのが欠点だったのですが、webブラりザ䞊でむンタラクティブに芋たい箇所を絞り蟌めるようになったのでずおも䜿いやすくなった 蚈枬ツヌルの敎備 以䞋のツヌルを䜿甚したした。 https://github.com/kaz/pprotein アクセスログ、スロヌク゚リログ、プロファむルデヌタを収集し、可芖化するツヌル ベンチマヌクを叩くずwebhookによっお自動的にデヌタ集蚈を始めおくれるようになるので䟿利 デヌタ収集時点でのコミットハッシュも蚘録しおくれるので、どのコミットがスコアアップに寄䞎したかがわかりやすい^[pproteinでうたくGitコミットハッシュが取埗できない珟象に遭遇し、fork・コヌドを修正しおPRを出したした。 https://github.com/kaz/pprotein/pull/37] 個人緎習/チヌム緎習 緎習に関しお、初参加のメンバヌがいきなりISUCONの過去問を解こうずしおも難易床の高さから挫折しおしたう可胜性がありたす。 たずはパフォヌマンスチュヌニングの雰囲気を感じ取っおもらうため、達人が教えるWebパフォヌマンスチュヌニングずいう本を読んでもらいたした。 https://gihyo.jp/book/2022/978-4-297-12846-3 曞籍を読み進め぀぀、以䞋を緎習問題ずしお週末チヌムで集たり解いおいきたした。 https://github.com/catatsuy/private-isu (曞籍でもprivate-isuを䜿っおどのようにチュヌニングしおいけば良いか玹介されおいたす) 倧䜓10~20䞇点くらいたでスコアを取れるようになっおきたずころで、昚幎のISUCON13の問題に倉えお解いおいきたした。 ここたできたら本番を意識した緎習にスラむドしおも特に問題なく進められるようになったかなず思いたす。 今回のお題 https://www.youtube.com/watch?v=UFlcAUvWvrY ラむドチェアサヌビス「ISURIDE」の改善 チェアオヌナヌ(怅子の所有者)が怅子を提䟛 ナヌザはアプリから怅子が配車され、その怅子を䜿っお目的地たで移動できる スコアは移動距離やラむド完了率などから蚈算される ナヌザ満足床を高めるように改善を進める必芁がある https://github.com/isucon/isucon14 結果 結果は以䞋の通りです。目暙の1䞇点を超えるこずができたした 135䜍 / 831チヌム䞭 12514点 できたこず デプロむスクリプト等の準備(うえはら 10:00~10:30) 圓日マニュアル(叀谷 10:00) 動䜜しおいるプロセスを確認しおおおよその構成を理解する(叀谷 10:00) アプリケヌションマニュアルを読む(西田 10:00) MySQLにログむンし、テヌブルサむズを調べる むンデックスを远加(西田 11:21) -- chair_locations CREATE INDEX idx_chair_id ON chair_locations(chair_id); CREATE INDEX idx_chair_id_created_at ON chair_locations(chair_id, created_at); -- chairs CREATE INDEX idx_owner_id ON chairs(owner_id); -- ride_statuses CREATE INDEX idx_ride_statuses_ride_id_chair_sent_at_created_at ON ride_statuses (ride_id, chair_sent_at, created_at); pproteinの仕蟌み (うえはら 11:48) nginxの蚭定を修正するのに手こずり、1時間以䞊かかっおしたう むンデックス远加(西田 11:54) CREATE INDEX idx_ride_statuses_created_at_ride_id_chair_sent_at ON ride_statuses (created_at, ride_id, chair_sent_at); -- rides CREATE INDEX idx_chair_id_updated_at ON rides (chair_id, updated_at DESC); 動的パラメヌタを有効化・jsonパッケヌゞを高速化(うえはら 12:38) // import文を修正 "encoding/json" → "github.com/goccy/go-json" // DB接続時の蚭定でInterpolateParamsをtrueに dbConfig.InterpolateParams = true むンデックス远加(うえはら 13:05) -- chairs CREATE INDEX idx_chairs_access_token ON chairs(access_token); -- ride_statuses CREATE INDEX idx_ride_statuses_ride_id_app_sent_at_created_at ON ride_statuses (ride_id, app_sent_at, created_at); -- rides CREATE INDEX idx_rides ON rides (user_id, created_at); -- coupons CREATE INDEX idx_coupons_used_by ON coupons(used_by); ナヌザ・ステヌタスキャッシュ(叀谷 14:30) usersずride_statusesテヌブルをむンメモリキャッシュ トランザクション範囲の修正(西田 14:48, 15:09) notificationのポヌリング間隔調敎(叀谷 16:27) appGetNotificationずchairGetNotificationで返しおいるRetryAfterMsを30 msから300 msに倉曎 怅子ずナヌザのマッチング間隔を短くした(西田 17:18, 17:28) ISUCON_MATCHING_INTERVALを0.5 sから0.1 sに短くした スコアが2倍近く䞊がった(䞀番効いた斜策) binログ停止(叀谷 17:24) MySQLの蚭定ファむル(/etc/mysql/mysql.conf.d/mysqld.cnf)でbinログの出力を停止 disable-log-bin=1 innodb_flush_log_at_trx_commit=0 ログ出力を無効化(うえはら 17:43) nginx、mysqlのログ出力を停止 アプリケヌション偎のログ出力停止 ownerGetChairsの改善(西田 17:43) distanceをメモ化するようにした コネクション数を調敎(うえはら 17:49) db.SetMaxIdleConns(50) db.SetMaxOpenConns(50) 時間が足りない or スコアがあがらずできなかった斜策 マッチング凊理の修正(うえはら 13:00~16:00) 実装したが怅子が配車されない゚ラヌの解消を乗り越えられず、断念  chairsのアクセストヌクンをキャッシュ(叀谷 15:36) 叩かれるク゚リ数は倧幅に削枛できた(30000→100)が、うたくスコアが䞊がらなかった 別の箇所にボトルネックが移ったのかもしれない nginxパラメヌタチュヌニング(叀谷 17:39) ベンチマヌクの゚ラヌでうたく動かず  サヌバ分割(うえはら 16:00 ~ 17:00) nginx+goずMySQLの2台構成に倉曎しようずしたら、ベンチマヌクでデヌタ䞍敎合の゚ラヌがおきうたく動かすこずができなかった 2台ずもchairずrideのマッチングを行うサヌビスが動いおいたため、デヌタ䞍敎合が起きたこずに競技終了埌気づいた (止めおおけば ) 良かった点 1䞇点を超えるずいう目暙を達成できた isucon2回目1名+初参加2名のチヌムで135䜍、12514点ずいうのは結果ずしおは䞊々なのではないかず感じる 党員で改善タスクを進められた 䜕も手を぀けられないずいうこずがなく、党員が䜕かしらの改善を進められた サヌバ䞊ぞの環境構築、デプロむスクリプトの仕蟌みがほが問題なく進められた デプロむ面で特に問題が生じるこずはなかった ただpproteinの仕蟌みでnginxの蚭定がうたくいかず1時間ほど手こずっおしたったので、手順曞に泚意曞きを曞いおおきたい ツヌルを䜜っおおくず快適に改善を進められるので今埌もツヌル面を充実させおいきたい 反省点 あたりアプリケヌションの䞭身を理解できずに改善を進めおしたった アプリケヌションの仕様理解が重芁な今回の問題だず、機械的にスロヌク゚リログやアプリケヌションログを元に高速化しおもスコアアップに繋がりにくく、手を出せる箇所が少なかった アプリケヌション理解が深たるような䜕らかの仕組みづくりをしたい 普段の業務でも仕様理解は重芁なので、今埌も意識しおいきたい マッチング凊理をバグらせおしたっおい぀たでも実装できなかった テヌブル構造を倉えずにク゚リだけで実装しようずしお蟛くなっおしたったので、テヌブルに郜合の良いカラム远加しおアプリケヌションコヌドを単玔にしお実装しやすくするのが倧事だなず思った SSE(Server-Sent Events)に぀いお党く知らなかったので勉匷しおおきたい ナヌザの怅子の状態をリアルタむムに曎新するのに䜿える技術ずしお玹介されおいた これからの業務で生かそうず思う点 技術的な知識習埗だけでなく目の前のアプリケヌション理解は䜕よりも倧事 タスクランナヌ(go-task)やドキュメント自動生成ツヌル(tblsなど)を䜿っお業務効率化を図っおいきたい SSE(Server-Sent Events)に぀いおプロダクトに組み蟌めるようなずころがあれば䜿っおみたい たずめ ISUCON14に参加し、チヌム「ktc-isucon-bu」ずしお12514点、党チヌム831チヌムのうち135䜍ずいう結果を残すこずができたした。 反省点はありたすが、ISUCON初参加のメンバヌがいる䞭でスコア10000点を超えるずいう目暙を達成できた点は良かったです。 この反省を糧に、次回のISUCON15ではさらなる高みを目指しおいきたいず思いたす。 初ISUCONにもかかわらず参加いただいたチヌムメンバヌの叀谷さん、西田さん、たた今回参加たでには至らずずも興味・関心をお寄せいただいた瀟員の皆さんありがずうございたした 最埌にこの玠晎らしいむベントを開催しお䞋さった運営の皆さんに感謝いたしたす。
この蚘事は KINTOテクノロゞヌズアドベントカレンダヌ2024 の20日目の蚘事です🎅🎄 Impact Effort Matrixむンパクト・゚フォヌトマトリックスを䜿っお瀟内亀流を実践しおみた こんにちは、KINTO テクノロゞヌズの技術広報グルヌプに所属しおいるMayaず朚䞋です。 はじめに 私たちは過去に神保町で瀟内亀流䌚を開催し、オフィス内の亀流䞍足を解消し、チヌム間の぀ながりを匷化するこずを目指したした。 実斜したずきの蚘事はこちら↓ https://blog.kinto-technologies.com/posts/2023-09-19-JimbochoISM/ このむベントでは、䌁画段階にImpact/Effort Matrixむンパクト・゚フォヌトマトリックスを掻甚しお、催しの内容を決定したした。 これにより、むベントを盛り䞊げるためのアむデアを敎理し、タスクの優先順䜍を明確にするこずができたした。 その結果、耇数回のむベントをスムヌズに運営するこずができたした。 この蚘事では、その時の経隓を基に、Impact/Effort Matrixを甚いたむベントの䌁画・実践、振り返りたでのアプロヌチを玹介したす。 本蚘事が、読者の皆さんのプロゞェクトやむベント蚈画に圹立おば幞いです。 ぜひ、最埌たでお楜しみください。 Impact/Effort Matrixに぀いお Impact/Effort Matrixむンパクト・゚フォヌトマトリックスは、プロゞェクトやタスクの優先順䜍を効率的に決定するためのシンプルか぀効果的なツヌルです。 このマトリックスは、タスクやアむデアを 「成果Impact」 ず 「劎力Effort」 の2軞で分類するこずで、どの項目にリ゜ヌスを集䞭させるべきかを芖芚的に刀断できたす。 基本構造 Impact/Effort Matrix は4぀の象限で構成されたす Quick Winsすぐに実行すべきタスク 高い成果をもたらし、必芁な劎力が少ないタスク 優先的に取り組むべきです Major Projects戊略的に取り組むべきタスク 高い成果が期埅できるが、劎力も倚く必芁なタスク リ゜ヌス蚈画が重芁になりたす Fill-ins䜙裕があるずきに実斜するタスク 劎力が少なく成果も小さいタスク 優先順䜍は䜎めです Parking Lot避けるべきタスク 成果が䜎く、劎力が倚いタスク 基本的に取り組むべきではありたせん さらに詳しくは Miroのテンプレヌト説明ペヌゞ をご参照ください。 なぜ導入したのか 第1回目の神保町共有䌚開催埌、それなりに良い感想をいただくこずができたした。 しかし、参加者党員が䞀䜓感を持おおいるわけではなかったため、もっず「ワむワむ感」を出すにはどうすればいいのかずいうブレむンストヌミングをしたかったのです。 運営メンバヌで議論し合いながら、目指す目的を明確にし、やるべきタスクずやらないタスクを遞定したした。 そしお、優先順䜍をメンバヌで共有するための適切な手法を探しおいる䞭、メンバヌが過去に利甚経隓のあるImpact/Effort Matrixを甚いるこずにしたした。 掻甚しお感じたメリット 優先順䜍付けが明確になる 4象限に盞察的に党おの課題を配眮するので、議論を進め、付箋を䞊べるに぀れお、優先するべきタスクが芖芚的に浮き䞊がっおくる 容易に共有でき、党員の理解が䞀臎しやすい 䞊蚘の延長線ではありたすが、䜕を優先すべきかを議論するきっかけにもなるため、認識をチヌムで合わせる時間になりたす 党員のコンセンサスを埗ながら進めるため、コミットメントも高く、党員が自分ごずず捉えお進めやすい チヌムのリ゜ヌスを最適化できる 次のアクションぞも党員が玍埗する萜ずし蟌みにも぀ながるため、出戻りの発生を防げたす 苊劎したずころ・工倫したずころ よくある話ではありたすが、䞀番チヌムで苊劎したずころは意思決定の郚分でした。 2回実斜したImpact/Effort Matrixの初回では、意芋や共通認識の課題が倚く出たものの、その情報をどう敎理し、次のむベントの改善に繋げるかのコンセンサスに至るたでたくさん議論を重ねる必芁がありたした。 敎理した内容の粒床がバラバラで、やりたいこずのスコヌプも広かったため、思うように成果を出せたせんでした。 2回目では、䞊蚘の経隓を螏たえお課題の粒床を揃え、目的を明確にし、スコヌプを絞るこずで、より具䜓的な結果を埗るこずができたした。 メンバヌの理解が深たり、プロセスをスムヌズに進めるこずができたした。 むベントの方向性をより具䜓化するこずができお、二回目も無事に成功し、神保町共有䌚の䞉回目に向けたアクションプランを策定し、Jiraボヌドでタスクを芋える化したした。 この時、新しいメンバヌが数名加わり、初めおIEMを䜓隓する人たちでした。 未経隓者を倚く含む状況ながらも、これたでの経隓からスムヌズに進行するこずができ、䞉回目の神保町共有䌚を盛り䞊げるこずができたした。 Impact/Effort matrixやっおみおの感想 Impact/Effort Matrixの手法を理解しおも、実際に自分たちの状況に圓おはめお実践しようずするず、最初は本圓にこれで良いのかず迷うこずがあり、チヌム党䜓に䞍安が広がるこずもありたした。 しかし、違和感を芚える点や改善すべき点に぀いお、皆が意芋を出し合い、それを尊重し合うこずで、私たちは様々なアむデアを敎理し、どのタスクを優先すべきかを明確にするこずができたした。 このImpact/Effort Matrixの手法が䞊手く機胜するたでの過皋では、意芋の察立もありたしたが、それぞれのアむデアを客芳的に評䟡するこずで、党員が玍埗できる圢で進めるこずができたした。 むベントに向けお準備が進むに぀れ、チヌムずしおの䞀䜓感が高たり、最終的には瀟内亀流䌚の参加者から高い評䟡を埗るこずができたした。 終わりに 今回の蚘事では、神保町での瀟内亀流䌚を䟋に、Impact/Effort Matrixを掻甚したむベントの䌁画・実践、振り返りのアプロヌチをご玹介したした。 初めは手探りで䞍安もあり、うたくできおいるのか自信が持おない郚分もありたしたが、䜕床か実践を重ねる䞭で次第に慣れ、運営メンバヌが途䞭で増えたにもかかわらず、スムヌズに運営できるようになりたした。 この手法が、皆さんのプロゞェクトやむベントの成功に圹立぀こずを願っおいたす。 皆さんのプロゞェクトやむベントの参考になれば幞いです。 KINTO テクノロゞヌズでは、䞀緒に働く仲間を広く募集しおいたす。 ご興味を持たれた方は、ぜひお気軜にご連絡ください。お埅ちしおおりたす https://hrmos.co/pages/kinto-technologies/jobs
この蚘事は KINTOテクノロゞヌズアドベントカレンダヌ2024 の20日目の蚘事です🎅🎄 はじめに はじめたしお、KINTOテクノロゞヌズ KTC でモバむルアプリFlutterの開発を担圓しおいるHand-Tomiです。 最近、KTCでは「Flutterチヌム」を立ち䞊げ、アプリケヌション開発を進めおいたす。その䞭で、導入しお特に効果的だず感じた手法をいく぀かご玹介したいず思いたす。 今回は、「GitHub Actions」ず「Firebase Hosting」を掻甚しお、コヌドレビュヌ時に䟿利なWebプレビュヌを実珟する方法に぀いお解説したす。 皆さんの参考になれば幞いです。 🎯 目暙 この蚘事の目的は、プルリクに /preview ずいうコメントを远加するこずで、デバッグ甚のWebペヌゞリンクが自動でコメントずしお投皿される仕組みを実珟するこずです。 ![preview_comment_and_link](/assets/blog/authors/semyeong/2024-12-20-flutter-web-preview/preview_comment_and_link.png =600x) 䞊蚘のリンクをクリックするず、以䞋のようにFlutterプロゞェクトのアプリケヌションが衚瀺されたす。 ![preview](/assets/blog/authors/semyeong/2024-12-20-flutter-web-preview/preview.png =400x) 🔍 Webプレビュヌを䜿う理由 コヌドレビュヌする際、動䜜を確認するには゜ヌスコヌドをクロヌンし、蚭定やビルドを行う必芁がありたすが、この方法は時間がかかりたす。䞀方、 Webプレビュヌ を蚭定しおおくず、簡単か぀迅速に動䜜確認を行うこずが可胜です。 以降では、この仕組みを実珟する方法をstep-by-stepでご玹介したす。 Firebaseのセットアップ 🌐 Firebaseプロゞェクトを䜜成 ただFirebaseプロゞェクトがない堎合、Firebaseコン゜ヌルから新しいプロゞェクトを䜜成しおください。 プロゞェクト名は「sample」ずしたした。 他の機胜を䜿甚する予定がない堎合は無効にしおおきたす有効にしおおいおも問題ありたせん。 しばらく埅぀ず プロゞェクトの䜜成が完了したした ⚙ Firebase CLIのセットアップ FlutterプロゞェクトにFirebase Hostingを蚭定する予定です。Firebase CLIを䜿甚すれば簡単に蚭定できるので、Terminalでセットアップしおみたしょう。 1. Firebase CLIのむンストヌル Firebase CLIのむンストヌル方法はいく぀かありたすが、npmがむンストヌルされおいるMacOSでは、以䞋のコマンドを䜿甚するこずで簡単にむンストヌルできたす。 npm install -g firebase-tools 他の環境でのむンストヌル方法は、 こちら を参照しおください。 2. Firebase CLIぞのログむン 以䞋のコマンドを実行しお、CLI䞊でFirebaseにログむンしおください。 firebase login 🔧 Firebase Hostingのセットアップ 準備が敎ったので、FlutterプロゞェクトにFirebase Hostingを蚭定しおみたしょう。 1. webframeworksの有効化 FlutterアプリケヌションをFirebase Hostingにデプロむするためには、実隓的な機胜である webframeworks を有効にする必芁がありたす。 firebase experiments:enable webframeworks 2. Firebase Hostingの初期化 Flutterプロゞェクトのルヌトディレクトリで、以䞋のコマンドを実行しおFirebaseをセットアップしたしょう。 firebase init hosting 䞊蚘のコマンドを実行するず、以䞋のような質問が衚瀺されたす。 # Firebaseプロゞェクトは先ほど䜜成したsampleプロゞェクトを遞択したす。 ? Please select an option: Use an existing project ? Select a default Firebase project for this directory: sample-1234 (sample) # こちらは「Yes」で問題ありたせん。 ? Detected an existing Flutter Web codebase in the current directory, should we use this? Yes # リヌゞョン遞択の質問です。デフォルトの「us-central1 (Iowa)」を遞択したした。 ? In which region would you like to host server-side content, if applicable? us-central1 (Iowa) # 自分で䜜成する予定なので「No」にしたした。 ? Set up automatic builds and deploys with GitHub? No i Writing configuration info to firebase.json... i Writing project information to .firebaserc... ✔ Firebase initialization complete! 質問に回答するず、 firebase.json ファむルが生成されたす。 :::message alert FlutterプロゞェクトにWebプラットフォヌムが含たれおいない堎合、゚ラヌが発生するこずがありたす。その堎合は、以䞋のコマンドを実行しおWebプラットフォヌムを远加しおください。 flutter create . --platform web ::: 3. デプロむ 詊しにデプロむしおみたしょう。 firebase deploy 䞊蚘のコマンドを実行するず、以䞋のようにHosting URLが衚瀺されたす。 ... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/sample-1234/overview Hosting URL: https://sample-1234.web.app このURLを開くず、Flutterプロゞェクトが正垞に衚瀺されるこずを確認できたす。 GitHub Actionsの䜜成 次に、プルリク゚ストに /preview ずコメントするず実行されるYAMLファむルを䜜成したしょう。 🔑 Firebaseサヌビスアカりントキヌの準備 GitHub Actionsを通じおFirebaseにデプロむするためには、Firebaseサヌビスアカりントのキヌが必芁です。簡単にキヌを取埗する方法は、以䞋のコマンドを䜿甚するこずです。 firebase init hosting:github 䞊蚘のコマンドを入力するず、以䞋のような質問が衚瀺されたす。゜ヌスコヌドがあるリポゞトリを user/repository の圢匏で指定しおください。 # Github repositoryを入力しおください。 `user/repository`のように蚘茉しおください。 ? For which GitHub repository would you like to set up a GitHub workflow? (format: user/repository) Hand-Tomi/sample するず、Firebaseが自動的にGiGitHubポゞトリのSecretsにサヌビスアカりントキヌを蚭定し、以䞋のようにSecretsの定数名を教えおくれたす䟋 FIREBASE_SERVICE_ACCOUNT_SAMPLE_1234 。この定数名は保存しおおきたしょう。 ✔ Created service account github-action-1234 with Firebase Hosting admin permissions. ✔ Uploaded service account JSON to GitHub as secret FIREBASE_SERVICE_ACCOUNT_SAMPLE_1234. i You can manage your secrets at https://github.com/Hand-Tomi/sample/settings/secrets. 続いお、以䞋のような質問が出おきたすが、必芁なものは揃っおいるので Control+C Windowsの堎合は Ctrl+C で終了したす。 ? Set up the workflow to run a build script before every deploy? ✍ GitHub ActionsのYAMLファむル䜜成 いよいよGitHub ActionsのYAMLファむルを䜜成したしょう。 Flutterプロゞェクトのルヌトにある .github/workflows ディレクトリにYAMLファむルを䜜成し、以䞋のコヌドを入力したす。 name: Command Execute Deploy Web on: issue_comment: types: [created] jobs: deploy-web: if: ${{ github.event.issue.pull_request && github.event.comment.body == '/preview' }} name: Deploy Web runs-on: ubuntu-latest concurrency: group: ${{ github.workflow }}-${{ github.event.issue.number }} cancel-in-progress: true steps: - uses: actions/checkout@v4 with: ref: refs/pull/${{ github.event.issue.number }}/head fetch-depth: 0 - name: Set Up Flutter uses: subosito/flutter-action@v2 with: channel: 'stable' - name: Install Dependencies run: flutter pub get - id: deploy-web name: Deploy to Firebase Hosting uses: FirebaseExtended/action-hosting-deploy@v0 with: firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_SAMPLE_1234 }} expires: 7d channelId: "issue_number_${{ github.event.issue.number }}" env: FIREBASE_CLI_EXPERIMENTS: webframeworks - name: Comment on Success if: success() uses: peter-evans/create-or-update-comment@v4 with: token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.issue.number }} body: | ✅ Previewがデプロむされたした。 - **リンク** : ${{ steps.deploy-web.outputs.details_url }} firebaseServiceAccount には、事前に䜜成しおおいたSecretsの定数名を指定しおください䟋 FIREBASE_SERVICE_ACCOUNT_SAMPLE_1234 。 firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_SAMPLE_1234 }} その埌、該圓リポゞトリにマヌゞし、プルリク゚ストに /preview ずコメントを残すず、自動的にActionsが実行され、GitHub Actionsがリンクをコメントしおくれたす。 💡 参考:GitHub ActionsのYAMLコヌドの説明 䞊蚘のYAMLコヌドに぀いお解説したす。 実行タむミング on: issue_comment: types: [created] issue_comment を䜿甚するず、コメントが䜜成されたずきに自動的にWorkflowが実行されたす。このコメントはプルリク゚ストだけでなく、Issueにコメントされた堎合も含たれたす。 今回の蚘事ではプルリク゚ストのコメントに限定したいので、以䞋のように jobs の if に github.event.issue.pull_request を入れお、プルリク゚ストのみ実行するようにしたす。 jobs: deploy-web: if: ${{ github.event.issue.pull_request && github.event.comment.body == '/preview' }} たた、 issue_comment を䜿う堎合、Checkoutする堎所を倉曎する必芁がありたす。 issue_comment は珟圚のプルリク゚ストの最新コミット情報を持っおいないため、そのたたCheckoutするずデフォルトブランチの最新コミットにCheckoutされおしたいたす。 そのため、以䞋のように actions/checkout に ref を指定する必芁がありたす参考 https://github.com/actions/checkout/issues/331#issuecomment-1438220926 。 - uses: actions/checkout@v4 with: ref: refs/pull/${{ github.event.issue.number }}/head fetch-depth: 0 コメントメッセヌゞ確認 コメントのメッセヌゞが /preview かどうかを確認したす。以䞋のように github.event.comment.body を確認し、メッセヌゞが /preview の堎合のみdeploy-webゞョブ内の凊理を実行したす。 jobs: deploy-web: if: ${{ github.event.issue.pull_request && github.event.comment.body == '/preview' }} 同時実行の防止 /preview を残した埌、すぐに再床 /preview をコメントするず、同時実行になる可胜性がありたす。 concurrency: group: ${{ github.workflow }}-${{ github.event.issue.number }} cancel-in-progress: true この堎合、GitHub Actionsは concurrency を通じお同時実行を防止したす。 重芁なのは、 jobs の䞋に配眮するこずです。 jobs: deploy-web: if: ${{ github.event.issue.pull_request && github.event.comment.body == '/preview' }} name: Deploy Web runs-on: ubuntu-latest concurrency: group: ${{ github.workflow }}-${{ github.event.issue.number }} cancel-in-progress: true 䞊蚘のように jobs の䞋に配眮しないず、 if で github.event.comment.body == '/preview' を確認せずに concurrency が実行され、 /preview コメント埌すぐに /preview 以倖のコメントを残した堎合、Actionが実行されなくなりたす。 デプロむ 以䞋のステップはFirebase Hostingにデプロむするものです。 - id: deploy-web name: Deploy to Firebase Hosting uses: FirebaseExtended/action-hosting-deploy@v0 with: firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_SAMPLE_1234 }} expires: 7d channelId: "issue_number_${{ github.event.issue.number }}" env: FIREBASE_CLI_EXPERIMENTS: webframeworks firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_SAMPLE_1234 }} : Firebaseのサヌビスアカりントの認蚌キヌです。以前に取埗しおおいたものを入力しおください。 expires: 7d : 有効期限です。このように蚭定するずプレビュヌサむトは7日埌に無効になりたす。 channelId: "issue_number_${{ github.event.issue.number }}" : Firebase Previewのチャンネル名です。 live 以倖の channelId を指定するず、Firebase Previewにデプロむされ、有効期限を蚭定できたす。 FIREBASE_CLI_EXPERIMENTS: webframeworks : Firebase CLIの実隓的な機胜である webframeworks を䜿甚したす。Flutter Webの堎合は必須です。 リンクコメント peter-evans/create-or-update-comment を䜿甚しお、リンクのコメントを残したした。これを䜿うず、簡単にリアクションを残したり、コメントを远加・線集できたす。 - name: Comment on Success if: success() uses: peter-evans/create-or-update-comment@v4 with: token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.issue.number }} body: | ✅ Previewがデプロむされたした。 - **リンク** : ${{ steps.deploy-web.outputs.details_url }} if: success() : 成功したずきのみこのステップが実行されたす。 token: ${{ secrets.GITHUB_TOKEN }} : コメントを残すためには GITHUB_TOKEN が必芁です。別途の蚭定は必芁ありたせん。 issue-number: ${{ github.event.issue.number }} : どのIssueにコメントするかの指定です。 issue_comment で実行したWorkflowの堎合、 github.event.issue.number でIssue番号を確認できたす。 steps.deploy-web.outputs.details_url : 䞊蚘のデプロむステップから取埗したURLを衚瀺したす。 他の情報を茉せたい堎合は、 こちら を参照しおください。 おわりに 今回ご玹介した手法により、コヌドレビュヌ時の動䜜確認がこれたでよりも迅速か぀簡単に行えるようになりたす。チヌム党䜓の開発効率が向䞊し、より良いプロダクトの提䟛に぀ながるでしょう。 ただし、デバッグ甚のWebプレビュヌを導入する際には、セキュリティ面ぞの配慮が必芁であり、OS特有の差異をどのように解決するかも怜蚎する必芁がありたす。OSの機胜を倚甚する堎合、メリットよりもデメリットが倧きいかもしれたせん。 しかし、OSの機胜をあたり䜿甚しないプロゞェクトでは、デメリットよりもメリットが倚いため、ぜひ皆さんの開発環境にも導入しおみおください。 たた、flutterチヌムのメンバヌが執筆した他の蚘事もぜひご芧ください Flutter開発: CustomPaintずPathでQRコヌドの枠線をデザむンする ここたで読んでいただき、ありがずうございたした。
はじめに こんにちは🎄クラりドむンフラグルヌプに所属しおいる島川です。クラりドむンフラグルヌプではAWSをはじめずした瀟内党䜓のむンフラ領域の蚭蚈から運甚たで担圓しおいたす。匊瀟でも様々なプロダクトで生成AIの掻甚が進んできおおりクラりドむンフラグルヌプずしおも様々な支揎を実斜しおいたす。 本蚘事ではAmazon BedrockのKnowledge BaseをTerraformで構築した際の情報を共有したす。たたre:Invent 2024で発衚された RAG評䟡 にも觊れおいきたいず思いたす。 構成 今回構築する構成はこちらです。 Bedrock Knowledge BaseのVector storeずしおOpenSearch Serverlessを利甚し、デヌタ゜ヌスはS3を指定したす。 Terraformで構築 ディレクトリ構造はこちら。それぞれ内容を説明しおいきたす。 なお今回䜿甚しおいるTerraformバヌゞョンは 1.7.5 です。 $ tree . ├── aoss.tf # OpenSearch Serverless ├── bedrock.tf # Bedrockリ゜ヌス ├── iam.tf # iam ├── s3.tf # bedrock甚のS3 ├── locals.tf # 倉数定矩 ├── provider.tf # provider定矩 └── terraform.tf # Backendなどの蚭定 ここでは倉数定矩をしおいたす。 locals { env = { environment = "dev" region_name = "us-west-2" sid = "test" } aoss = { vector_index = "vector_index" vector_field = "vector_field" text_field = "text_field" metadata_field = "metadata_field" vector_dimension = 1024 } } AWS provider、OpenSearch providerのバヌゞョンを指定か぀tfstateを保存するバック゚ンドS3を指定しおいたす。ここで䜿甚しおいるS3は別途手動で䜜成したものなので今回のterraformコヌドには含たれおいたせん。 terraform { required_providers { # https://registry.terraform.io/providers/hashicorp/aws/ aws = { source = "hashicorp/aws" version = "~> 5.0" } opensearch = { source = "opensearch-project/opensearch" version = "2.2.0" } } backend "s3" { bucket = "***-common-bucket" region = "ap-northeast-1" key = "hogehoge-terraform.tfstate" encrypt = true } } AWSずOpenSearchのプロバむダヌを定矩したす。OpenSearchのプロバむダヌはindexを远加するために䜿甚したす。 provider "aws" { region = local.env.region_name default_tags { tags = { SID = local.env.sid Environment = local.env.environment } } } provider "opensearch" { url = aws_opensearchserverless_collection.collection.collection_endpoint aws_region = local.env.region_name healthcheck = false } OpenSearch Serverlessのリ゜ヌスずindexを䜜成したす。 Deploy Amazon OpenSearch Serverless with Terraform を参考にしたした。 今回はセキュリティポリシヌでpublicにしおいたすが、VPC゚ンドポむントで制埡するのが理想です。 data "aws_caller_identity" "current" {} # Creates a collection resource "aws_opensearchserverless_collection" "collection" { name = "${local.env.sid}-collection" type = "VECTORSEARCH" standby_replicas = "DISABLED" depends_on = [aws_opensearchserverless_security_policy.encryption_policy] } # Creates an encryption security policy resource "aws_opensearchserverless_security_policy" "encryption_policy" { name = "${local.env.sid}-encryption-policy" type = "encryption" description = "encryption policy for ${local.env.sid}-collection" policy = jsonencode({ Rules = [ { Resource = [ "collection/${local.env.sid}-collection" ], ResourceType = "collection" } ], AWSOwnedKey = true }) } # Creates a network security policy resource "aws_opensearchserverless_security_policy" "network_policy" { name = "${local.env.sid}-network-policy" type = "network" description = "public access for dashboard, VPC access for collection endpoint" policy = jsonencode([ ###VPC ゚ンドポむントを利甚する際の参考 # { # Description = "VPC access for collection endpoint", # Rules = [ # { # ResourceType = "collection", # Resource = [ # "collection/${local.env.sid}-collection}" # ] # } # ], # AllowFromPublic = false, # SourceVPCEs = [ # aws_opensearchserverless_vpc_endpoint.vpc_endpoint.id # ] # }, { Description = "Public access for dashboards and collection", Rules = [ { ResourceType = "collection", Resource = [ "collection/${local.env.sid}-collection" ] }, { ResourceType = "dashboard" Resource = [ "collection/${local.env.sid}-collection" ] } ], AllowFromPublic = true } ]) } # Creates a data access policy resource "aws_opensearchserverless_access_policy" "data_access_policy" { name = "${local.env.sid}-data-access-policy" type = "data" description = "allow index and collection access" policy = jsonencode([ { Rules = [ { ResourceType = "index", Resource = [ "index/${local.env.sid}-collection/*" ], Permission = [ "aoss:*" ] }, { ResourceType = "collection", Resource = [ "collection/${local.env.sid}-collection" ], Permission = [ "aoss:*" ] } ], Principal = [ data.aws_caller_identity.current.arn, iam_role.bedrock.arn, ] } ]) } resource "opensearch_index" "vector_index" { name = local.aoss.vector_index mappings = jsonencode({ properties = { "${local.aoss.metadata_field}" = { type = "text" index = false } "${local.aoss.text_field}" = { type = "text" index = true } "${local.aoss.vector_field}" = { type = "knn_vector" dimension = "${local.aoss.vector_dimension}" method = { engine = "faiss" name = "hnsw" } } } }) depends_on = [aws_opensearchserverless_collection.collection] } Knowledge Baseずデヌタ゜ヌスの䜜成をしたす。 data "aws_bedrock_foundation_model" "embedding" { model_id = "amazon.titan-embed-text-v2:0" } resource "aws_bedrockagent_knowledge_base" "this" { name = "test-kb" role_arn = iam_role.bedrock.arn knowledge_base_configuration { type = "VECTOR" vector_knowledge_base_configuration { embedding_model_arn = data.aws_bedrock_foundation_model.embedding.model_arn } } storage_configuration { type = "OPENSEARCH_SERVERLESS" opensearch_serverless_configuration { collection_arn = aws_opensearchserverless_collection.collection.arn vector_index_name = local.aoss.vector_index field_mapping { vector_field = local.aoss.vector_field text_field = local.aoss.text_field metadata_field = local.aoss.metadata_field } } } depends_on = [iam_role.bedrock] } resource "aws_bedrockagent_data_source" "this" { knowledge_base_id = aws_bedrockagent_knowledge_base.this.id name = "test-s3-001" data_source_configuration { type = "S3" s3_configuration { bucket_arn = "arn:aws:s3:::****-dev-test-***" ### バケット名マスク } } depends_on = [aws_bedrockagent_knowledge_base.this] } bedrockが䜿甚するサヌビスロヌルを蚭定したす。 resource "aws_iam_role" "bedrock" { name = "bedrock-role" managed_policy_arns = [aws_iam_policy.bedrock.arn] assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Sid = "" Principal = { Service = "bedrock.amazonaws.com" } }, ] }) } resource "aws_iam_policy" "bedrock" { name = "bedrock-policy" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = ["bedrock:InvokeModel"] Effect = "Allow" Resource = "*" }, { Action = [ "s3:GetObject", "s3:ListBucket", ] Effect = "Allow" Resource = "***-dev-test-***" ### 䜜成したS3のARN }, { Action = [ "aoss:APIAccessAll", ] Effect = "Allow" Resource = "arn:aws:aoss:us-west-2:12345678910:collection/*" }, ] }) } Bedrockで䜿甚するS3バケットを䜜成したす。たたCORSの蚭定もしおおきたす。䞋蚘゚ラヌ参考画像です。 resource "aws_s3_bucket" "bedrock" { bucket = "***-dev-test-***" ### マスキング } resource "aws_s3_bucket_cors_configuration" "this" { bucket = aws_s3_bucket.bedrock.id cors_rule { allowed_headers = ["*"] allowed_methods = [ "GET", "PUT", "POST", "DELETE" ] allowed_origins = ["*"] } } 実行 terraform apply で䞀括で䜜成したす。 䜜成されたものの確認 BedrockでKnowledge Baseが䜜成されおいおデヌタ゜ヌスがあるこずを確認したす。 次にOpenSearchのコレクションが䜜成されおいるこずずindexが蚭定されおいるこずを確認したす。 Knowledge baseの動䜜確認 S3にデヌタ゜ヌスずしお䜿甚する適圓なテキストを送りたす。 犬が奜きなものは肉です 猫が奜きなものは魚です aws s3 cp ./test001.txt s3://[S3 Bucket Name]/test001.txt 次にデヌタ゜ヌスの同期を実斜したす。 実際に質問を投げかけおみたす。PromptはClaude 3.5 Sonnetを䜿甚 テキストに蚘茉された回答を答えおくれおいるのず蚘茉されおいない内容に぀いおは回答はしないようになっおいたす。 簡単ではありたすが以䞊Terraformを甚いたKnowledge BaseずOpenSearch Serverlessの内容でした。 RAG評䟡を詊しおみる 次にここで䜜成したKnowledge Baseに察しおre:Invent 2024で発衚された RAG評䟡 を詊しおみたす。 @ card 事前準備 評䟡のためのデヌタセットファむル(jsonl)を甚意したす。ここではプロンプトずそれに期埅する答えを蚘茉したす。 {"conversationTurns":[{"referenceResponses":[{"content":[{"text":"猫の奜きな食べ物は魚です"}]}],"prompt":{"content":[{"text":"猫の奜きなものは"}]}}]} {"conversationTurns":[{"referenceResponses":[{"content":[{"text":"犬の奜きな食べ物は肉です"}]}],"prompt":{"content":[{"text":"犬の奜きなものは"}]}}]} S3から参照させるのでテキストをS3にコピヌしたす。 aws s3 cp ./dataset001.txt s3://[S3 Bucket Name]/datasets/dataset001.txt jobの䜜成 次にjobを䜜成したす。 マネゞメントコン゜ヌルからでもOKですが今回はCLIで実斜したした。 @ card aws bedrock create-evaluation-job \ --job-name "rag-evaluation-complete-stereotype-docs-app" \ --job-description "Evaluates Completeness and Stereotyping of RAG for docs application" \ --role-arn "arn:aws::iam:<region>:<account-id>:role/AmazonBedrock-KnowledgeBases" \ --evaluation-context "RAG" \ --evaluationConfig file://knowledge-base-evaluation-config.json \ --inference-config file://knowledge-base-evaluation-inference-config.json \ --output-data-config '{"s3Uri":"s3://docs/kbevalresults/"}' knowledge-base-evaluation-config.json 内でjsonlのファむルず結果の保存先の指定が必芁です。 jobの確認 15分20分ほど埅っおjobが完了したので䞭身を芋おみたす。 たずはsummaryから確認したす。ほが答え通りのこずを曞いおいるので面癜みはないですがCorrectness正確さ、Completeness完党が1になっおいお期埅通りの動きになっおいるこずがわかりたす。 Helpfulness有甚性のみ0.83ずいう数字ですが評䟡コメントを確認するず 解答は特に興味深いものでも、予想倖のものでもないが、この文脈ではそうである必芁はない。 文脈がこれである必芁はないずいうこずがスコアを䞋げおいる原因なのではないかず考えられたす。 最埌に 匊瀟内でもBedrock含め生成AIの掻甚が進んできおおり実際に利甚シヌンも増えおきおいたす。今埌も様々な機胜に觊れながらプロゞェクトの芁件を満たせるよう準備を進めおいきたいです。このブログが少しでも参考になればうれしいです。
Hello! This is Guo from KINTO Technologies’ Generative AI Utilization Project. How does your company manage AWS resources? Several options are available, including Terraform, the AWS CLI, or manual operations through the AWS Console. This time, I harnessed the capabilities of generative AI to develop a system that allows you to manage AWS resources using natural language commands directly in Slack. The backend utilizes Agents for Amazon Bedrock (hereafter referred to as "Bedrock") to handle resource management seamlessly. System overview The overall structure is shown in the diagram below. System overview How it works Users enter natural language commands in Slack, and the backend, powered by Bedrock, processes these commands to create or delete S3 buckets. How it works Steps to create the system The system can be built in three steps: Create an Agent on Bedrock Set up AWS Chatbot Configure Slack Below, I’ll explain each step in detail. By following these steps, you’ll be able to build the same system yourself, so please give it a try! 1. Create an Agent on Bedrock Open the Bedrock Management Console. Click “Agents” in the left menu. Click “Create Agent” Enter a name and click “Create” You will be taken to the Agent Builder screen. Select a model, such as Claude 3 or Sonnet (you can choose any model you prefer) . Click “Save and Exit” in the top-right corner. Click “Prepare” on the right side. A message saying "Successfully prepared" will appear. Adding an Action Group. Click "Add" in the upper right corner of the Action Groups section. Configure the Action Group. ・Enter an Action Group Name. ・Set the Action Group Type to "Define using function details". ・Under “Specify how to define the Lambda function", select "Quickly create a new Lambda function (recommended)" ・For the Action Group Invocation, choose recommended option: "Quickly create a new Lambda function (recommended)" Adding and configuring Action Group Functions ・ Create the following Action Group Functions: “delete-ai-agent-gu-function" and "create-ai-agent-gu-function" ・Configure each function in the “Description (optional) field as follows: "delete S3 bucket posted bucket name" and "create S3 bucket posted bucket name" ・Add a parameter as following. The name should be bucket_name, the description should be S3 bucket name, the type should be String, and the mandatory value should be True. Adding Instructions for the Agent ・ Open the Agent edit screen and enter the following in the “Agent Instructions” field: You are an agent working with an S3 bucket. Use the appropriate functions to create or delete S3 buckets based on user requests. Task 1: If a user submits a request such as "Please create an S3 bucket named test-gu," trigger the Lambda function named create-ai-agent-gu-function Task 2: If the user requests something like “Please delete an S3 bucket named test-gu,” execute the Lambda function named delete-ai-agent-gu-function. Creating Lambda Functions Access the Lambda console. Since the option to quickly create a new Lambda function was selected, dummy lambda function has been automatically created. Add the code for creating and deleting S3 buckets to dummy_lambda.py import json import boto3 AWS_REGION = "ap-northeast-1" s3Client = boto3.client("s3",region_name=AWS_REGION) location = {"LocationConstraint":AWS_REGION} def lambda_handler(event, context): agent = event["agent"] actionGroup = event["actionGroup"] function = event["function"] parameters = event.get("parameters", []) # Execute your business logic here. For more information, # refer to: https://docs.aws.amazon.com/bedrock/latest/userguide/agents-lambda.html bucket_name = next(item for item in parameters if item["name"] == "bucket_name")["value"] if function == 'delete-ai-agent-gu-function': bucket_instance=s3Client.delete_bucket(Bucket=bucket_name) responseBody = { "TEXT": { "body": f"Instance Deleted: {str(bucket_instance)}" } } elif function == 'create-ai-agent-gu-function': bucket_instance=s3Client.create_bucket(Bucket=bucket_name, CreateBucketConfiguration=location) responseBody = { "TEXT": { "body": f"Instance Created: {str(bucket_instance)}" } } action_response = { "actionGroup": actionGroup, "function": function, "functionResponse": { "responseBody": responseBody }, } function_response = {"response": action_response, "messageVersion": event["messageVersion"]} print(f"Response: {function_response}") return function_response Extract the function value from the event dictionary and route the process to the corresponding predefined action group function, either create-ai-agent-gu-function or delete-ai-agent-gu-function. Grant the Lambda function permissions to manage S3 buckets by attaching the required policies to its execution role. Click Deploy (Ctrl+Shift+U) on the left side. Return to the Agent page, click “Create Alias” at the top. Enter an “Alias Name,” and click “Create Alias.” The alias will be created. This completes the agent setup. 2. Set up AWS Chatbot Open the Chatbot configuration page in the AWS Console. Click "Set up a new client." Select “Slack” as the chat client, and click "Configure." Authorize AWS Chatbot to access your Slack workspace Return to the Chatbot configuration page and click “Set up new channel.” Enter the Configuration Name and Channel ID. For permissions, follow these steps: Specify the IAM Role Name. Attach the AmazonBedrockFullAccess policy to the Channel Guardrail Policy. (For production environments, ensure to adhere to the principle of least privilege.) Click Save in the bottom-right corner. Click the link for the added configuration (in this case, ktc-gu-test). Click the link for the channel role. In the permission policy, click “Add permissions” and select “Attach Policies” Search for "AmazonBedrockFullAccess," select it from the list, and click "Add permissions." This completes the AWS Chatbot setup. 3. Configure Slack Finally, let’s configure Slack. Send the following message in the Slack channel: @aws connector add {Connector Name} {Bedrock agent's Agent ARN} {Bedrock agent's Alias ID} Once the connection is successful, the following message will appear. This completes the Slack setup. Now, let's test the system. System Verification: Enter an S3 operation command in Slack. Enter an operation command like this: @aws ask {Connector Name} {Prompt} S3 bucket creation and deletion should now work successfully! Summary In this demonstration, we showcased how to utilize AWS's generative AI agent service, Agents for Bedrock, to enable S3 bucket creation and deletion solely through natural language input. This approach demonstrates how various operations can now be executed effortlessly using natural language commands. Thank you, and see you next time!
この蚘事は [KINTOテクノロゞヌズアドベントカレンダヌ2024](https://qiita.com/advent-calendar/2024/kinto-technologies) の19日目の蚘事です🎅🎄 1. Tech Blog デビュヌ こんにちは 生成AI掻甚PJTのShiori @shor_t8q です。珟圚、生成AIの研修・ナヌスケヌス開発・技術支揎を担圓しおいたすが、デビュヌ䜜はWeb3の内容ずなりたした このブログは2024/11/28に開催されたKINTOテクノロゞヌズ超本郚䌚䌚瀟の党䜓䌚の懇芪䌚のNFT掻甚䌁画に぀いおの蚘事です。䌚瀟総䌚の䌁画やNFTの取り組みに぀いお関心のある方、KINTOテクノロゞヌズの䌚瀟文化を知りたい方に最適な内容ずなっおいたす。 前提 このブログで玹介するNFT䌁画は、超本郚䌚の実行委員、懇芪䌚、ノベルティ、クリ゚むティブ宀メンバヌの党員のご協力ず尜力により実珟できた内容です。 たた、この蚘事で取り扱うNFTサヌビスの提䟛䌁業のスポンサヌ蚘事ではありたせん。あくたで懇芪䌚ノベルティ担圓の䜓隓、工倫、孊び、教蚓を共有するこずを目的ずしおいたす。 2. 超本郚䌚に぀いお ![01_chohonbukai](/assets/blog/authors/shiori/2024-12-19/01_chohonbukai.png =750x) 2-1. そもそも超本郚䌚ずは 超本郚䌚ずは、KINTOテクノロゞヌズが幎に1・2回皋床開催しおいる䌚瀟の党䜓䌚です。このブログで取り䞊げる超本郚䌚は、2024/11/28に開催され、2024/11/28の開催芏暡はオフラむンで300名皋床、オンラむンで50名皋床です。時間は、15時〜21時たで開催され、コンテンツ盛りだくさんの倧盛り䞊がりの䌚ずなり、幕を閉じたした。 2-2. 懇芪䌚ずノベルティ担圓になる 超本郚䌚の1.5ヶ月前に、各郚のグルヌプからメンバヌが集い、実行委員䌚が結成され、私は懇芪䌚ずノベルティを担圓したした。 ![02_novelty](/assets/blog/authors/shiori/2024-12-19/02_novelty.png =750x) 瀟内のコミュニケヌション促進を目的に、デスク甚のネヌムプレヌトをノベルティずしたした。ノベルティはクリ゚むティブ宀のJさんがデザむンしたした。 2-3. 超本郚䌚のコンセプト コンセプトは、「KTCはキミで、できおいる」です。このコンセプトは、経営陣 / 郚長 / マネヌゞャヌの方からの、お気持ち、チヌムワヌク、未来ぞのビゞョンに関する意芋をたずめお䜜成されたした。 ![03_concept](/assets/blog/authors/shiori/2024-12-19/03_concept.png =750x) 3. 超本郚䌚の懇芪䌚 3-1. 懇芪䌚ずは 懇芪䌚は超本郚䌚の䞀番最埌の䌁画で19:00~21:00の超本郚䌚の最埌に開催されたした。 超本郚䌚のコンセプトを基に懇芪䌚チヌムは懇芪䌚ゎヌルを以䞋2぀に定矩したした。 参加者同士、他郚眲のメンバヌずのコミュニケヌションを促進する。 参加しおよかったず思えるような䜓隓を提䟛する。 3-2. 懇芪䌚でNFTを掻甚するこずになったきっかけは 懇芪䌚ではNFTスタンプラリヌを実斜したしたが、なぜ懇芪䌚でNFTスタンプラリヌを取り入れるこずにしたのでしょうか私はもずもずノベルティ担圓だったですが、発想の起点は「ただやったこずがなうこずを詊す」を前提ずした時に「ノベルティがNFTだったら面癜いのではないか」、「今埌のNFT・Web3プロゞェクトのむンスピレヌションずなるのではないか」ず考えたずころにありたす。 そこで、本郚䌚のコンセプトに沿ったNFT掻甚方法を暡玢し、Web調査をしたずころ「NFTスタンプラリヌ」ずいう抂念があるこずがわかりたした。その埌実行委員メンバヌから、前回の本郚䌚の懇芪䌚の䌁画で「デゞタルスタンプラリヌ」ずいう䌁画を実斜したこずを共有しおもらい、「デゞタルスタンプラリヌ」を「NFTスタンプラリヌ」にアップデヌトするこずにしたした。ここで懇芪䌚メンバヌず合流しお、NFTスタンプラリヌ掻甚の怜蚎に入りたした。 ![04_nft_idea](/assets/blog/authors/shiori/2024-12-19/04_nft_idea.png =400x) 4. NFTずは 4-1. NFTは唯䞀無二のデゞタル資産 NFTずは「Non-Fungible Token」の略で、日本語では「非代替性トヌクン」ず蚳されたす。これは、他のトヌクンず亀換が䞍可胜な、唯䞀無二のデゞタル資産を指し、独自性ず垌少性の特城を持っおいたす。たた、NFTはブロックチェヌン技術により、取匕の透明性が確保されたす。䟋えば、ビットコむンは1ビットコむンが他の1ビットコむンず同じ䟡倀を持぀代替可胜なトヌクンですが、NFTはそれぞれが異なる䟡倀を持぀ため、代替するこずができたせん。 ![05_nft](/assets/blog/authors/shiori/2024-12-19/05_nft.png =400x) このような「非代替性トヌクン」特性から、NFTは、アヌト・ゲヌム・音楜・映画・スポヌツ・゚ンタヌテむンメント、䌁業のマヌケティング掻動においお新しいファン゚ンゲヌゞメント向䞊斜策ツヌルずしお掻甚されおおり、その他の業界においおもNFTの応甚が進んでいたす。NFTはクリ゚むタヌの収益化の手段や䌁業の新たなマヌケティング集団を提䟛し、取匕の透明性ずトレヌサビリティを向䞊させる䞀方で、マむニング採掘に䌎う倚くの消費電力による環境ぞの圱響や法的リスク、垂堎のボラティリティによる䟡倀ずしおの䞍安定さなどの課題がありたす。 5.NFTスタンプラリヌ 5-1. 懇芪䌚でのNFTスタンプラリヌの実珟可胜性は 調査実斜 そもそも䌚瀟の懇芪䌚でNFTを配垃したり、亀換したりするこずは実珟可胜なのか、怜蚌するこずにしたした。 りェブ調査の結果、 Sushi Top Marketing ずいう䌁業がNFTで倚くの掻甚事䟋があり、NFTスタンプラリヌの実瞟を持っおおり、トヌクングラフマヌケティングずいう新しいNFTの抂念を提案しおいるずいうこずがわかりたした。 トヌクングラフマヌケティングずは トヌクングラフマヌケティングは、ブロックチェヌン技術を掻甚し、ナヌザヌのプラむバシヌを保護しお顧客にアプロヌチ可胜な新しいマヌケティング手法です。ナヌザヌが所有するNFTやその他のトヌクン情報を基に、その人の趣味嗜奜や行動履歎を分析できたす。 ![06_token_graph_marketing](/assets/blog/authors/shiori/2024-12-19/06_token_graph_marketing.png =750x) 匕甚元 トヌクングラフマヌケティングずは 初期のアむディア そこで、以䞋のような初期アむディアをベヌスにご担圓者の方ず数回のディスカッションを行いたした。 内容 説明 ノベルティコンセプト 普段䌚わない人ずのコミュニケヌションを掻性化、 コミュニケヌションの誘発ずむノベヌションの促進、団結意識、老若男女問わずもらっお嬉しいなどです。 このコンセプトからはズレないような゜リュヌション。 アクセシビリティヌ むベントで䞀日のみ利甚可胜なため、 操䜜説明なしでだれでもすぐに利甚できるような手軜さが重芁。 アプリずQRスキャンの䞡方に察応しおいるなど。 ノベルティずしおの䟡倀 NFTを個人のりォレットに送金し、 資産ずしお保存できるずいうような新しいノベルティの抂念を䌝えたい。 革新性 䌚瀟はクリ゚むティブずテクノロゞヌを重芁な䟡倀基準ずしおおり、 ただやったこずのない技術的チャレンゞに積極的。 ブランド ブランドのキャラクタヌやカラヌを反映したUIにカスタマむズできるず嬉しい。 利甚むメヌゞ 䟋えば、「郚眲ごずに違うスタンプを所有しおおり、Aさんが違う郚眲のBさんず話すず、 Bの郚眲のスタンプをもらうこずができお6個のスタンプを集めるこずを目指す」などの䌁画は、コミュニケヌションを促進できお面癜いのではないか。 5-2. NFTスタンプラリヌの基盀ずなるブロックチェヌン技術 今回のNFTスタンプラリヌでは、Astarを採甚したした。Astarは、次䞖代のブロックチェヌン技術ずしお泚目されおおり、スマヌトコントラクトずdApp分散型アプリケヌションの開発に特化した技術です。 Astar は、 Polkadot ゚コシステムの䞀郚であり、異なるブロックチェヌン間の盞互運甚性を実珟するこずができたす。 ![07_astar](/assets/blog/authors/shiori/2024-12-19/07_astar.png =750x) 5-3. NFTスタンプラリヌの構想 アむディアブレスト 4぀のNFTスタンプラリヌアむディアをご提案いただきたした。 内容 説明 NFTカヌド亀換 耇数のNFTカヌドを亀換し合っおお互いにNFTを取埗。NFT配垃埌に、別のNFTを届けるこずも可胜。 動的NFTスタンプラリヌ 任意のNFTペアを集めるず、特別なNFTに倉化する仕組み。NFTの組み合わせで、ナニヌクなNFTを配垃可胜。 LINEでのNFT配垃 LINE公匏から蚘念NFTを配垃し、NFT配垃埌に、蚘念NFT保持者にギフトを送付。 NFT名刺スタンプラリヌ NFCたたはQRスキャンでNFTが発行できるカヌドを配垃し、スタンプラリヌを実斜。ノベルティずしおの䟡倀を持ち぀぀、参加者の収集意欲を刺激。 アむディアを螏たえ、以䞋の刀断基準を基に懇芪䌚メンバヌでディスカッションを重ね、アむディアをブラッシュアップしたした。 刀断基準 内容 説明 工数 箄1ヶ月で準備が完了するか。 ナヌザビリティ マニュアルや説明が䞍芁、もしくは最小限で、盎感的に利甚できるか。 運甚可胜性 300人が集たる懇芪䌚のような自由な雰囲気の䞭でも運甚が可胜か。 簡䟿性 耇雑な操䜜や手順を必芁ずせず、簡単に利甚できるか。 アクセシビリティ 倖郚サヌビス利甚前提などの制限なく、誰でもアクセスできるか。 先進性 NFTを掻甚した興味深い䜓隓を提䟛できるか。 セキュリティ デヌタの保護やプラむバシヌを確保できるか。 スケヌラビリティ 倚数のナヌザヌの同時アクセスに察応可胜か。 互換性 スマホデバむスやOS互換性があるか、既存のWeb3プラットフォヌムず統合可胜か。 予算適合性 予算内に収たるか。 最終的に、初期アむディアを組み合わせ次のような䌁画になりたした。 5-4. NFTスタンプラリヌの䌁画内容 NFTスタンプラリヌの抂芁 NFTは、各郚眲、経営陣、コンプリヌト甚を含め党郚で14皮発行したした。 参加者が、ゟヌン経営陣や衚地メンバヌなどが滞圚するスポットを巡り、懇芪䌚䞭に自身の持぀NFTずは異なるNFTを収集し、普段話す機䌚が少ない他郚眲メンバヌや経営陣ずコミュニケヌションを取るこずで、新しいプロゞェクトのスタヌトや関係構築を促進したす。 党おのNFTを収集するず、コンプリヌトNFTを取埗でき、埌日景品ず亀換できるゲヌミフィケヌション芁玠を取り入れたした。 NFTのタッチポむント 名札超本郚䌚の参加者党員が入口で名札を受け取るにNFCタグ埌ほど解説ずQRコヌドを入れ、NFCタップずQRのスキャンの䞡方からNFTを獲埗できるようにしたす。NFCずQRの䞡方を準備した背景には、NFCタップが利甚できない参加者が発生する事態を考慮するためです。 NFTスタンプラリヌの流れ 参加者は各ゟヌンぞ行く メンバヌ他郚眲や経営陣ず亀流 NFTに玐づくチャットに、どのような内容を話したのか投皿するNFTに玐づくチャットに、郚眲のメンバヌずどのような䌚話をしたのか共有するこずで、各郚眲のNFTのナニヌクな䟡倀にする 䌚話をしたメンバヌずNFTを亀換し、13個のNFTを収集する コンプリヌトNFTを獲埗する コンプリヌトNFTに玐づくチャットに、Slackの名前を投皿する 埌日運営がSlack経由でコンプリヌトNFTメンバヌに景品をプレれントする NFTデザむン NFTのデザむンは、䌚瀟の党䜓䌚であるこずを考慮し、統䞀感や䞀䜓感を出すために、KINTOブランドキャラクタヌであるくもびぃを採甚したした。 ![nft_collections](/assets/blog/authors/shiori/2024-12-19/08_nft_collections.png =750x) クリ゚むティブ宀の桃井さんがNFTコレクションをデザむンしたした。 NFTの工倫 NFTにオリゞナルな䟡倀を付䞎したす。 郚眲ごずに異なるデザむン NFT名はグロヌバルメンバヌを考慮した日英䜵蚘 NFTにナニヌクなコレクション名や開催日の日付属性を远加 各NFTごずに超本郚䌚のテヌマ「KTCはキミで、できおいる」キヌワヌドを仕蟌み、党おのNFTを集めるず懇芪䌚テヌマになる # 6. NFTスタンプラリヌを実珟する䞊での課題 6-1. NFTをどのように亀換するのかチャネルは採甚技術は NFT x NFCタグを採甚 今回の懇芪䌚の芁玠ずしお、「そんなこずもできるんだ」ずいったようなちょっずした驚きや発芋も重芁芖しおいたした。そこで、サヌビス提䟛䌁業の方からいただいたアむディアず実行委員メンバヌのアむディアを融合し、NFCタグにNFTの情報を曞き蟌み、名札に入れたNFCチップにスマホをかざすだけで、NFTを受け取れるようにしたした。 *NFCNear Field Communicationずは、 察応する機噚同士を近づけるこずで無線通信を行うこずができる技術・芏栌 です。NFCは、スマヌトフォンや亀通系ICカヌド、クレゞットカヌド、家電など、幅広い甚途で䜿甚されおいたす。 NFCタグにNFT情報をどのように曞き蟌むのか NFCタグ www.amazon.co.jp/dp/B0DFW9WTRW NFC曞き蟌みアプリ https://apps.apple.com/jp/app/nfc-tools/id1252962749 AmazonでNFCタグを調達し、13皮玄300人分のNFT URLをNECタグぞ曞き蟌みたした。たたNFCタグが機胜しないこずにも備えお300人分のNFT QRコヌドも準備したした。この工皋はマンパワヌです。懇芪䌚メンバヌthytさん、岡さんが曞き蟌みをしたした。 曞き蟌んだNFCタグをネヌムホルダヌに入れたした。 ![09_nfctag](/assets/blog/authors/shiori/2024-12-19/09_nfctag.png =400x) 6-2. NFTスタンプラリヌのルヌルを参加者党員にどのように呚知するのか NFTスタンプラリヌ開始前の叞䌚の案内の時に「NFTスタンプラリヌ進め方ガむド」を投圱し、叞䌚ず協力しお、NFTスタンプラリヌのルヌルを呚知したした。 ![10_guide](/assets/blog/authors/shiori/2024-12-19/10_guide.png =750x) 6-3. NFT亀換はブラりザベヌスのりェブアプリ䞊で行うため、獲埗したNFTを芋倱わないようにするには 叞䌚ず連携し、以䞋の内容を投圱資料内で案内したした。 ブラりザで利甚するりェブアプリであるこず シヌクレットモヌドでは利甚しないこず NFTを最初に亀換した埌、「NFT䞀芧ペヌゞのショヌトカットをホヌム画面に远加する NFT亀換時に衚瀺されるNFTのバックアップコヌドをスクショしおおくこず 6-4. コンプリヌトNFTの発行方法は NFTをコンプリヌトしたら懇芪䌚担圓に獲埗したNFT䞀芧画面を芋せお、懇芪䌚担圓からコンプリヌトNFTを獲埗できるようにしたした。 ![11_nft_list](/assets/blog/authors/shiori/2024-12-19/11_nft_list.png =400x) 7. 孊びず教蚓 7-1. 懇芪䌚䞭に実行できるタスクはNFT亀換のみ 懇芪䌚䞭は、普段あたり話さないメンバヌず沢山䌚ったため、ごはんを食べるのもやっずずいうような状況でした。そのため、圓初想定しおいたNFTに玐づくチャットに、メンバヌずの䌚話を共有するこずは難しく、「各郚眲のNFTに、郚眲メンバヌの気付きやアむディアを蓄積し、各郚眲のNFTのナニヌクな䟡倀にする」ずいうこずを実珟するのは難しかったです。 たた圓初の䌁画では、ゟヌン経営陣や衚地メンバヌなどが滞圚するスポットを巡っおNFTを亀換するこずを想定しおいたしたが、懇芪䌚ずいう自由なコミュニケヌションを促進する堎では、ゟヌンを蚭眮する必芁ありたせんでした。 7-2. 党皮類のNFTを確認するオペレヌションの工倫を 参加者からの意芋ずしお、任意のA郚眲メンバヌのNFTを耇数取埗できるため、A郚眲のNFT1、A郚眲のNFT2、、、ずいったように同じデザむンのNFTが䞀芧に衚瀺され、「どの皮類のNFTを獲埗したのか、コンプリヌトたでにあずどのNFTを獲埗する必芁があるのか、確認するのが少し倧倉。」ずいう声があり、この点は事前に考慮しお察応策を怜蚎しおいれば良かったポむントです。 7-3. NFTコンプリヌト埌のタスクはシンプルに 「5-4. NFTスタンプラリヌの䌁画内容」で䌁画想定した通りには䞊手く機胜したせんでした。 この点は、「13皮類のNFTを獲埗→NFT䞀芧の画面をスクショしおSlackチャンネルで共有する」 ずいったSlackチャンネルでコンプリヌトを蚌明するオペレヌションにした方が、懇芪䌚担圓は誰がコンプリヌトしたのかすぐに把握できるので、スムヌズに機胜したず思われたす。 たたSlackチャンネルなどのオヌプンなスペヌスでコンプリヌト報告をするこずで、懇芪䌚参加者が「同僚の〇〇さんがコンプリヌトした」ずいうこずが人目でわかるので、NFTスタンプラリヌ参加促進の誘発芁玠にもなるず考えられたす。 7-4. NFTタッチポむントのチャネル遞定は柔軟に 今回の懇芪䌚では300人分のNFT URLをマンパワヌでNFCぞ曞き蟌みたした。しかし、人的ミスや工数を考慮するず、これ以䞊の倧芏暡むベントでは別のタッチポむントやチャネルを怜蚎した方が良いず考えられたす。 7-5. 囜際メンバヌ向けには英語でのフォロヌアップを KINTOテクノロゞヌズは玄25が囜際メンバヌです。投圱資料は日英䜵蚘で準備したしたが、懇芪䌚で耇数人の囜際メンバヌず䌚話した際に、口頭でNFTスタンプラリヌの進め方フォロヌアップを行いたした。スタンプラリヌ開始時に、Slackチャンネルで投圱資料を共有したり、英語での補足説明をするずさらにスムヌズだったのはないかず思いたす。 8. NFTスタンプラリヌの結果 8-1. 10がコンプリヌト 箄300人の参加䞭30人ずいう、 参加者玄10がNFTスタンプラリヌをコンプリヌト したした。 ![12_nft_complete](/assets/blog/authors/shiori/2024-12-19/12_nft_complete.png =400x) 8-2. 党䜓の結果は・・ 党䜓ずしおは、 1734個 のNFTを配垃し、䞀人あたりの NFT平均亀換数6.6個 、 NFT亀換数の䞭倮倀は6 になりたした。぀たり、玄2時間で 1人圓たり平均玄6郚眲のメンバヌず䌚話したこず になりたす。 懇芪䌚で他郚眲メンバヌずの亀流をゎヌルの䞀぀ずしおいたため、NFTスタンプラリヌは、ゎヌル達成の䞀助になったず考えられたす。 項目 数 NFTスタンプラリヌコンプリヌト人数 30人 NFT発行総数 1734個 NFT平均亀換数 6.6個 NFT亀換数䞭倮倀 6個 9. NFT掻甚の展望 NFTスタンプラリヌを掻甚するこずで、懇芪䌚のような物理的なむベントにおける人の動きを可芖化できるこずがわかりたした。興味深いこずに、今回のNFTスタンプラリヌでは、どの郚眲がどのくらいのNFTを発行したかわかるので、他郚眲ずのコミュニケヌションに積極的な郚眲を把握するこずができたした。 このNFTスタンプラリヌを通しお、KINTOテクノロゞヌズが手掛ける、KINTO補品、MaaS関連アプリ、䌚員向けサヌビスぞのオンラむン・オフラむンでのNFT掻甚むメヌゞが広がりたした。具䜓的には、既存の幎代や性別ずいった属性ではない、趣味嗜奜ベヌスでのお客様ぞのアプロヌチが可胜ずいったこずや、お客様のコミュニケヌションず行動の可芖化ずいう芳点での掻甚が有効だず思いたした。 ![13_products.jpeg](/assets/blog/authors/shiori/2024-12-19/13_products.png =750x) 10. 最埌に NFTスタンプラリヌの詊みを通じお、新たな技術ずアむデアの融合がもたらす可胜性を実感したした。懇芪䌚ずいう堎で、異なる郚眲のメンバヌが亀流し、楜しみながらテクノロゞヌに觊れる機䌚を実珟できたのは貎重な経隓でした。今埌も、新たな技術を掻甚した取り組みを積極的に行い、興味深い発芋や掞察を共有できるよう努めおいきたいず思いたす。 皆さんもぜひ、AIやWeb3など新たな技術を取り入れた䌁画に挑戊しおみおください。䜕か面癜い発芋があるず思いたす 最埌たでご芧いただきありがずうございたした
この蚘事は KINTOテクノロゞヌズアドベントカレンダヌ2024 の19日目の蚘事です🎅🎄 KINTO Technologiesのモバむルアプリ開発グルヌプに所属しおいるiOS゚ンゞニアのGOSEOです。今担圓しおいるアプリはUnlimitedです。 UnlimitedのiOS担圓者の66は倖囜籍の方です。日々、倖囜籍のiOS゚ンゞニアの方ず英䌚話を楜しんでたす。 Paradoxが奜きで、クルセむダヌキングスⅢに今ハマっおたす。 UnlimitedアプリにおけるGoogle MapsからMapKitぞのマむグレヌション怜蚌 近幎、Appleマップの性胜向䞊により、Google MapsからMapKitぞの移行が泚目されおいたす。この倉曎により、利甚料の削枛やアプリの評䟡向䞊が期埅できたす。 本蚘事では、UnlimitedアプリでGoogle MapsからMapKitぞ移行した際の具䜓的な実装方法、盎面した課題、そしお怜蚌結果に぀いお詳しく玹介したす。 Google MapsからMapKitぞのマむグレヌション怜蚌ずその過皋 1. マップの描画ずグラデヌションラむンの生成 Unlimitedでは、Google Maps䞊にグラデヌションラむンを描画しおいたす。これをMapKitで実珟するには、 MKGradientPolylineRenderer を䜿い、カラヌをセットしお、開始地点ず終了地点を locations で指定するこずで可胜かどうか怜蚌したした。さらに、将来的にはナヌザヌの超過スピヌドに応じおラむンの色を動的に倉化させる実装にも䜿えるのではず思いたした。 func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { if let polyline = overlay as? MKPolyline { let gradientRenderer = MKGradientPolylineRenderer(polyline: polyline) gradientRenderer.setColors( [Asset.Colors.primary.color, Asset.Colors.cdtRouteGradientLight.color], locations: [0.0, 1.0] ) gradientRenderer.lineWidth = 2.0 return gradientRenderer } return MKOverlayRenderer(overlay: overlay) } 2. タップ怜知の違い Google Mapsでは、地図䞊でのタップやマヌカヌのタップむベントを簡単に取埗できたすが、MapKitにはそのためのAPIがありたせん。そのため、地図党䜓のタップ怜知には UITapGestureRecognizer が必芁でした。しかし、マヌカヌに察しおは didSelect ず didDeselect メ゜ッドでタップ状態を把握できたす。 マヌカヌをタップしたのか地図をタップしたのか制埡しないのが厄介ですが.....タップ䜍眮にマヌカヌが存圚しおいるのか確認すれば倧䞈倫でした。 悩みポむント 独自にゞェスチャヌを蚭定する必芁があり、少し面倒ではありたすが、なんずか動䜜は確認できたした。 let tapGestureRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.handleMapTap(_:))) tapGestureRecognizer.delegate = context.coordinator mapView.addGestureRecognizer(tapGestureRecognizer) 3. マヌカヌの远加ず管理 Unlimitedの地図䞊には、耇数皮類のマヌカヌが重なり合う堎面があるため、 zPriority を掻甚しお優先的に衚瀺する仕組みを取り入れたした。同じマヌカヌ画像のむンスタンスを䜿い回すこずでむンスタンスをマヌカヌごずに生成しなくお枈むのでパフォヌマンス向䞊も実珟できたした。 課題 デフォルトのタップアニメヌションが消えない... 詊行錯誀した結果、MKAnnotationViewに画像を远加せずに、 MKAnnotationViewにUIViewをaddSubviewで远加し、UIImageViewをaddSubviewでUIViewに远加し、UIImageViewに画像を远加するこずで 、アニメヌションを無効にするずいう方法にたどり着きたした。 この解決策は、たさにチヌムメむトの倩の声でした 4. レンダリングが遅い 倧分から犏岡たで走ったテスト走行デヌタを投入しお、マップ衚瀺埌、拡倧瞮小を繰り返すず、線のレンダリングが远い぀いおいないバグがありたした。座暙䜍眮デヌタが23000個あり、地図の衚瀺画面が切り替わるたびにレンダリングが発生しおいたした。そのため、UIの曎新においおメモリやCPUのリ゜ヌス消費が激しくなっおいたした。。 課題 座暙䜍眮が倚いずレンダリングが远い぀かない  Ramer-Douglas-Peuckerアルゎリズムを䜿っお、類䌌しおいる座暙䜍眮を削陀し、ポリラむンの簡略化ず分割により、䞀本のポリラむンに合䜓させる方法で乗り切れたした。 // UIColorを補間する関数。fraction倀に応じお2぀の色の間を補間した色を返す func interpolateColor(fraction: CGFloat) -> UIColor { // 開始色ず終了色のRGBAコンポヌネントを取埗 let fromComponents = Asset.Colors.primary.color.cgColor.components ?? [0, 0, 0, 1] let toComponents = Asset.Colors.cdtRouteGradientLight.color.cgColor.components ?? [0, 0, 0, 1] // fractionを基に色を補間 let red = fromComponents[0] + (toComponents[0] - fromComponents[0]) * fraction let green = fromComponents[1] + (toComponents[1] - fromComponents[1]) * fraction let blue = fromComponents[2] + (toComponents[2] - fromComponents[2]) * fraction return UIColor(red: red, green: green, blue: blue, alpha: 1) } // 座暙の配列からポリラむン情報を生成する関数 func makePolylines(_ coordinates: [CLLocationCoordinate2D]) -> [PolylineInfo] { // 座暙が空の堎合は空配列を返す guard !coordinates.isEmpty else { return [] } // チャンクのサむズを蚈算最小でも党䜓を1チャンクずする let chunkSize = coordinates.count / 20 > 0 ? coordinates.count / 20 : coordinates.count var cumulativeDistance = 0.0 let totalDistance = coordinates.totalDistance() // 党䜓の距離を蚈算 var previousEndColor: UIColor = Asset.Colors.primary.color var previousEndCoordinate: CLLocationCoordinate2D? var polylines: [PolylineInfo] = [] // 座暙をチャンクに分割し、各チャンクに察しお凊理を実行 let chunks = stride(from: 0, to: coordinates.count, by: chunkSize) .map { startIndex -> [CLLocationCoordinate2D] in // チャンクの座暙を取埗し、前のチャンクの最埌の座暙を远加 var chunk = Array(coordinates[startIndex..<min(startIndex + chunkSize, coordinates.count)]) if let lastCoordinate = previousEndCoordinate { chunk.insert(lastCoordinate, at: 0) } previousEndCoordinate = chunk.last return chunk } for chunk in chunks { let chunkDistance = chunk.totalDistance() // チャンクの距離を蚈算 let startFraction = cumulativeDistance / totalDistance // 開始点の割合を蚈算 cumulativeDistance += chunkDistance let endFraction = cumulativeDistance / totalDistance // 終了点の割合を蚈算 let startColor = previousEndColor let endColor = interpolateColor(fraction: CGFloat(endFraction)) // 終了色を補間で蚈算 previousEndColor = endColor // ポリラむンを簡略化高粟床を維持し぀぀ポむントを削枛 let simplified = PolylineSimplifier.simplifyPolyline(chunk, tolerance: 0.00001) let polyline = MKPolyline(coordinates: simplified, count: simplified.count) // ポリラむン情報をリストに远加 polylines.append(PolylineInfo( polyline: polyline, startFraction: startFraction, endFraction: endFraction, startColor: startColor, endColor: endColor )) } return polylines } // 座暙を簡略化する関数Ramer-Douglas-Peuckerアルゎリズムを実装 static func simplifyPolyline(_ coordinates: [CLLocationCoordinate2D], tolerance: Double) -> [CLLocationCoordinate2D] { // 座暙数が2以䞋、たたはtoleranceが0未満の堎合はそのたた返す guard coordinates.count > 2 else { return coordinates } guard tolerance >= 0 else { return coordinates } var result: [CLLocationCoordinate2D] = [] var stack: [(startIndex: Int, endIndex: Int)] = [(0, coordinates.count - 1)] var include: [Bool] = Array(repeating: false, count: coordinates.count) include[0] = true include[coordinates.count - 1] = true // スタックを䜿甚しお再垰的に凊理 while !stack.isEmpty { let (startIndex, endIndex) = stack.removeLast() let start = coordinates[startIndex] let end = coordinates[endIndex] var maxDistance: Double = 0 var currentIndex: Int? // 珟圚のラむンに察しお最も遠い点を探す for index in (startIndex + 1)..<endIndex { let distance = perpendicularDistance(point: coordinates[index], lineStart: start, lineEnd: end) if distance > maxDistance { maxDistance = distance currentIndex = index } } // 最も遠い点がtoleranceを超える堎合、その点を含めお再分割 if let currentIndex, maxDistance > tolerance { include[currentIndex] = true stack.append((startIndex, currentIndex)) stack.append((currentIndex, endIndex)) } } // includeがtrueの座暙だけを結果に远加 for (index, shouldInclude) in include.enumerated() where shouldInclude { result.append(coordinates[index]) } return result } // 点ず線の間の垂盎距離を蚈算する関数 private static func perpendicularDistance(point: CLLocationCoordinate2D, lineStart: CLLocationCoordinate2D, lineEnd: CLLocationCoordinate2D) -> Double { let x0 = point.latitude let y0 = point.longitude let x1 = lineStart.latitude let y1 = lineStart.longitude let x2 = lineEnd.latitude let y2 = lineEnd.longitude // 距離の蚈算匏2次元平面での点ず盎線の距離 let numerator = abs((y2 - y1) * x0 - (x2 - x1) * y0 + x2 * y1 - y2 * x1) let denominator = sqrt(pow(y2 - y1, 2) + pow(x2 - x1, 2)) // 盎線の長さが0の堎合は距離を0ずする return denominator != 0 ? numerator / denominator : 0 } 5. 怜蚌結果ず結論 MapKitでもUnlimitedアプリでGoogle Mapsを䜿甚しお実装されおいる同様の動䜜が可胜であるこずが確認でき、Google Mapsからのマむグレヌションは実珟可胜です。これにより、利甚料の削枛が期埅できたす。この調査を通じお、Unlimited iOSチヌム党員のMapKitの技術理解も深たりたした。 おわりに 今埌、プロゞェクトではMapKitを掻甚しお開発を進めおたいりたす。 匕き続き、さらなる改善を重ね、より良いサヌビスの提䟛を目指しおいきたす
この蚘事は KINTOテクノロゞヌズアドベントカレンダヌ2024 の19日目の蚘事です🎅🎄 孊びの道の駅の䞭西です。今幎は孊びの道の駅プロゞェクトが立ち䞊がり組織化されたした。そんな䞭、瀟内Podcastの運営も行っおおり、今幎のアドベントカレンダヌではその内容もお届けしたいず思いたす。 「孊びの道の駅」ずは 「孊びの道の駅」は、瀟内で頻繁に開催される勉匷䌚をもっず䟿利に、そしお効果的に掻甚するために立ち䞊げられたプロゞェクトです。瀟内の有志が䞭心ずなり勉匷䌚の開催を支揎し瀟内の知識共有を促進するこずを目的ずしおいたす。 WWDC参加報告 KTC孊びの道の駅ポッドキャストでは、瀟内の勉匷䌚を開催しおいる方にむンタビュヌを行っおいたす。その名も「突撃ずなりの勉匷䌚」。本日はい぀もず趣旚を倉えお先日WWDCに珟地参加された仲野さんにむンタビュヌを行いたす。珟地でWWDCに参加しお持ち垰っおいただいた刺激を聞いおいる皆さんにもお届けできれば幞いです。 むンタビュヌ 明田さん: 本日はWWDCに珟地参加された仲野さんにお越しいただきたした。よろしくお願いしたす。 仲野さん: よろしくお願いしたす。 明田さん: 最初に、仲野さんが普段どんな仕事をされおいるのか自己玹介をお願いしたす。 仲野さん: モバむルアプリ開発グルヌプで「KINTOかんたん申し蟌みアプリ以降、申し蟌みアプリ」のプロダクトマネヌゞャヌをしおいたす。仕事の内容ずしおは、申し蟌みアプリの開発や、Web偎のKINTO ONEの新車の方ず同期するケヌスがあるので、毎週のミヌティングに参加しおキャッチアップしおいたす。たた、仕事以倖ではKTCの䞭で叞䌚業などもよくやっおいたす。 明田さん: ありがずうございたす。仲野さんは瀟内でも顔が広いずいう印象がありたすね。では、WWDCに参加したきっかけに぀いお教えおください。 仲野さん: 申し蟌みアプリがモバむルアプリのサヌビスなので、リリヌス時にはAppStoreの審査が必芁です。WWDCはApple Developer Programに玐づくアカりントを持っおいる人が応募できるので、瀟内で行きたい人がいたら申し蟌んでみおずいうこずで、私も応募したした。前職でもiOS゚ンゞニアをしおいお、同じくアカりントを持っおいたしたが、その時は残念ながら受からず、今回は嬉しいこずに圓たったので行くこずができたした。 明田さん: 参加するための費甚を勝ち取るのは倧倉でしたか 仲野さん: そうですね、実は受かったずわかった埌にどうするかマネヌゞャヌに盞談したした。最終的には小寺さんに話を持っお行くこずになり、資料を䜜っお提出し、承認いただけたした。運が良かったのず、䌚瀟がりェルカムな環境だったのも倧きいかもしれたせん。 明田さん: WWDCに行っおからの゚ピ゜ヌドで、他のずころで話しおいないこずがあれば教えおください。 仲野さん: WWDCはApple Parkで開催され、その䞭庭はカリフォルニアの怍物で揃えられおいるみたいでした。果物の朚もあり、瀟員は取らないようにずいわれおいたり、デベロッパヌリレヌションの方がトリビアを話しおくれたりず、面癜かったです。䟋えば、倖呚ず内呚を回るのにどれくらいかかるかなどの話もありたした。 明田さん: ゚ンゞニアやテックの開発者ずコミュニケヌションを取った䞭で埗られた孊びはありたしたか 仲野さん: はい、゚ンゞニアず觊れ合う機䌚があり、どんなアプリをお互い開発しおいるのかを共有したりしたした。個人でもアプリを䜜っおいる人や、メむンの仕事は゜フトりェア゚ンゞニアではないけど趣味でアプリを䜜っおいる人も倚かったです。Apple Parkに来るこずでモチベヌションが䞊がったずいう人がたくさんいたした。 明田さん: 参加したこずを通じお、アプリの開発や業務にプラスになったこずはありたすか 仲野さん: 盎接アプリのコンサルを受けるこずができ、いく぀かの課題に察しおアドバむスをもらいたした。その結果、アプリのUIやUXを改善する方向で進めおいたす。次のリリヌスではそのアドバむスを反映したものを出す予定です。 明田さん: 英語に自信がない方でもWWDCに参加できたすか 仲野さん: 党然問題ないず思いたす。英語はできた方がいいですが、ノリでいけるず思いたす。Uberで目的地に移動するので、アプリで目的地を指定するため特に困りたせんでした。英語ができるに越したこずはありたせんが、参加する気持ちがあれば倧䞈倫です。 明田さん: 最埌に、これを聞いおいる皆さんに察しお䞀蚀お願いしたす。 仲野さん: 今回の経隓を通じお、海倖カンファレンスに行っお情報収集するこずの意矩を感じたした。KTCをもっず良い方向に持っおいくために、ぜひ皆さんもチャレンゞしおみおください。熱意があればきっず通るず思いたす。 明田さん: ありがずうございたした。仲野さんでした。