TECH PLAY

KINTOテクノロジーズ

KINTOテクノロジーズ の技術ブログ

969

Introduction Hello! I'm Yao Xie from the Mobile Application Development Group at KINTO Technologies, where I develop the Android app of KINTO Kantan Moushikomi (KINTO Easy Application) . In this article, I’ll be sharing some thoughts on how to implement a hybrid model that takes advantage of both Compose Multiplatform and native UI frameworks. Developing mobile apps often means juggling limited budgets, varied team sizes, and tight timelines: all while ensuring long-term maintainability and a consistent user experience. A hybrid architecture built on Kotlin Multiplatform (KMP), which now includes Compose Multiplatform as a core UI framework, combined with native frameworks such as SwiftUI (iOS) and Jetpack Compose (Android), offers the flexibility to meet these challenges. Whether you’re launching an MVP on a shoestring budget or scaling up for a fully polished app, this approach adapts to your constraints and preserves code quality over time. A Flexible and Maintainable Approach for Diverse Constraints Rapid Development with Consistency For projects constrained by limited budget, small teams, or short deadlines, the benefits I perceive are the following: Shared Business Logic: by writing your core functionality (networking, data models, business rules) once in a KMP module, will ensure consistent behavior across Android and iOS while reducing duplication and ease future maintenance. Shared UI with Compose Multiplatform: Compose Multiplatform is part of the Kotlin Multiplatform ecosystem, which means it naturally builds on shared Kotlin code to build UI components. Develop most of your UI as shared composable components. Android benefits directly via Jetpack Compose, and iOS can embed these components using helpers like ComposeUIViewController. This uniform approach guarantees that both platforms adhere to the same design and behavior guidelines, simplifying long-term support. This strategy minimizes development time while maintaining consistency—a key factor for high-quality user experiences and future-proof code. "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." Scaling Up with Native Enhancements As your project secures more funding, personnel, or additional time: Incremental Native Integration: With a solid shared foundation, you can gradually replace or enhance key screens using native UI elements. For example, you can enhance critical iOS screens with SwiftUI to better align with platform-specific design standards. Expect/Actual Mechanism: Kotlin’s expect/actual pattern lets you define a generic shared component (like a platform-specific button) and then provide native implementations. This enables you to start with a shared UI and later invest in polished native refinements where they matter most. Adapting to Different Team Sizes and Project Timelines The hybrid approach is designed to flex as your project evolves: For Lean Teams and Tight Schedules: Focus on maximum code reuse. A small team can build and maintain the shared business logic and UI, ensuring consistency while speeding up time-to-market. For Larger Teams or Extended Deadlines: As your team grows or deadlines relax, allocate additional resources toward developing native components to enhance user experience. This phased strategy minimizes risk and ensures that the core logic remains stable and maintainable over time. I find that by keeping the shared logic and UI consistent across platforms, you reduce complexity and technical debt, making projects easier to maintain and evolve. Code Snippets Illustrating the Kotlin Multiplatform Hybrid Mode Shared Business Logic This shared module guarantees that both Android and iOS apps use the same core logic, ensuring consistency and reducing maintenance overhead. // Api interface Api { suspend fun getUserProfile(): User } class ApiImpl(private val client: HttpClient) : Api { override suspend fun getUserProfile(): User { return client.get { url { protocol = URLProtocol.HTTPS host = "yourdomain.com" path("yourpath") } }.safeBody() } } // Repository interface UserRepository { suspend fun getUserProfile(): Flow<User> } class UserRepositoryImpl(private val api: Api) : UserRepository { override suspend fun getUserProfile(): Flow<User> { return flowOf(api.getUserProfile()) } } // ViewModel class ProfileViewModel( private val repository: UserRepository, ) : ViewModel() { private val _uiState = MutableStateFlow(ProfileUiState()) val uiState: StateFlow<ProfileUiState> = _uiState.asStateFlow() @OptIn(ExperimentalCoroutinesApi::class) fun onAction(action: ProfileScreenAction) { when (action) { is ProfileScreenAction.OnInit -> { viewModelScope.launch { // Set loading state to true _uiState.update { it.copy(isLoading = true) } // Retrieve authorization info and then fetch user profile data repository.getAuthorizationInfo() .flatMapLatest { authInfo -> // If authInfo exists, call getUserProfile() to get user data; otherwise, emit null if (authInfo != null) { repository.getUserProfile() } else { flowOf(null) } } // Catch any exceptions in the Flow chain .catch { e -> e.printStackTrace() } // Collect the user profile data and update the UI state .collect { userProfile -> _uiState.update { state -> state.copy( isLoading = false, data = userProfile, errorMessage = if (userProfile == null) "User profile data is null" else null ) } } } } } } } Shared UI with Compose Multiplatform Compose Multiplatform—being an integrated part of Kotlin Multiplatform—allows you to create UI components in shared Kotlin code: @Composable fun ProfileScreen( viewModel: ProfileViewModel = koinViewModel() ) { val uiState = viewModel.uiState.collectAsState().value LaunchedEffect(Unit) { viewModel.onAction(ProfileScreenAction.OnInit) } Column( modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) .background(White) .padding(16.dp) ) { // Profile header with image and user details Row( modifier = Modifier .fillMaxWidth() .background(White, shape = RoundedCornerShape(16.dp)) .padding(16.dp), verticalAlignment = Alignment.CenterVertically ) { AsyncImage( model = uiState.data.profileImage, contentDescription = "Profile Image", modifier = Modifier .size(64.dp) .clip(CircleShape) ) Spacer(modifier = Modifier.width(16.dp)) Column { Text( text = uiState.data.userName, fontSize = 16.sp, color = Color.Black ) Text( text = uiState.data.email, fontSize = 14.sp, color = Color.Blue.copy(alpha = 0.6f) ) } } Spacer(modifier = Modifier.height(16.dp)) MenuLabel(label = "Account Settings") .... } } Lean Approach: I find using this composable directly on both platforms convenient for a consistent look and behavior. Scaled Approach: Enhance the UI with native components as needed without altering the underlying business logic. Native UI via Expect/Actual Define an expected component: @Composable expect fun PlatformButton( modifier: Modifier = Modifier, label: String, onClick: () -> Unit ) Android Implementation (androidMain): @Composable actual fun PlatformButton( modifier: Modifier, label: String, onClick: () -> Unit ) { Button( onClick = onClick, modifier = modifier ) { Text(text = label) } } iOS Implementation (iosMain): @Composable actual fun PlatformButton( modifier: Modifier, label: String, onClick: () -> Unit ) { UIKitView( modifier = modifier, factory = { // Create a native UIButton instance. val button = UIButton.buttonWithType(buttonType = 0) button.setTitle(label, forState = UIControlStateNormal) // Style the button ... // Create a target object to handle button clicks. val target = object : NSObject() { @ObjCAction fun onButtonClicked() { onClick() } } // Add the target with an action selector. button.addTarget( target = target, action = NSSelectorFromString("onButtonClicked"), forControlEvents = UIControlEventTouchUpInside ) button } ) } Blended UI: A Key Advantage Over Flutter Unlike Flutter, Compose Multiplatform supports blending shared UI and native components seamlessly on a single screen. In many scenarios, you may not need a complete switch from shared UI to native UI—rather, you can blend them on a single screen. This approach allows you to tap into the strengths of both Compose Multiplatform and native frameworks without fully committing to one for an entire screen. For example, you might want to display a shared composable header alongside a native SwiftUI list on iOS. Here’s how you can achieve a blended UI: Embedding Shared Composables in a Native Layout: One of Compose Multiplatform’s strengths is the ability to seamlessly embed shared Compose UI components into native SwiftUI layouts. Developers can gradually adopt shared components without rewriting entire screens, a flexibility that's difficult to achieve with Flutter’s overlay approach. For example, you can use SwiftUI as a container to host Compose Multiplatform’s shared UI wrapped in a UIViewController: import SwiftUI import shared // Import the shared KMP framework struct ComposeContainerView: UIViewControllerRepresentable { let user: User func makeUIViewController(context: Context) -> UIViewController { // Use the Compose wrapper to create the UIViewController return AppComposeUI().createProfileVC(user) } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { } } struct ContentView: View { let user: User var body: some View { VStack { Text("Native SwiftUI Header") .font(.headline) .padding() // Embed the Compose UI inside SwiftUI. ComposeContainerView(user: user) .frame(height: 250) List { Text("Native SwiftUI Item 1") Text("Native SwiftUI Item 2") } } } } Embedding Native iOS UI into Compose Multiplatform Screens Compose Multiplatform also enables embedding native iOS views (e.g., SwiftUI or UIKit) within shared Compose screens—another capability not easily achieved by Flutter. Define a SwiftUI view to embed: import SwiftUI struct MySwiftUIView: View { let user: User var body: some View { VStack { Text("Native SwiftUI Content") .font(.body) Text("Welcome, \(user.firstName)") } .padding() .background(Color.gray.opacity(0.2)) .cornerRadius(8) } } Then integrate this native view into your shared Compose UI using UIKitView: @Composable fun ComposeWithNativeUI(user: User) { Column { // Shared Compose UI header. ProfileHeader(user = user) Spacer(modifier = Modifier.height(16.dp)) // Embed a native iOS view using UIKitView. UIKitView(factory = { // Create a UIHostingController with a SwiftUI view. val hostingController = UIHostingController(rootView = MySwiftUIView(user = user)) hostingController.view }, modifier = Modifier.fillMaxWidth().height(100.dp)) } } This bidirectional inline integration sets Compose Multiplatform apart from Flutter, enabling teams to incrementally adopt shared UI components while maintaining native look and feel. It offers developers greater flexibility and reduces the risk of large-scale rewrites, combining the efficiency of shared code with the richness and quality of native UI. Compose Multiplatform provides a significant advantage over Flutter by enabling more flexible, fine-grained integration between shared UI and native platform UI. Unlike Flutter, which typically renders shared UI components through an overlay mechanism, Compose Multiplatform uses an inline rendering approach, allowing shared and native UI elements to blend naturally together. Pros Best Practices for Flexibility, Maintainability, and Scalability Embrace Rapid Prototyping: I’ve learned the hard way that spending weeks perfecting pixel details before users even touch the app is risky. These days our team spins up a shared‑UI prototype in a week or two, pushes it into stakeholders’ hands, and soaks up feedback early. When we’re confident the idea sticks, we layer on native flourishes—animations, platform‑specific gestures—without throwing away what we built. Plan Incremental Development: Our rule of thumb: launch small, refactor later. We start with a KMP module for core logic and a single shared Compose screen. Once that slice proves itself, we peel off the next screen—or replace a shared widget with a SwiftUI or Jetpack Compose version—one commit at a time. The gradual approach keeps velocity up and rewrites down. Balance Resources, Quality, and Scalability: When it was just two of us, 90 percent of the UI lived in shared code because that’s what we could afford. As head‑count and design ambitions grew, we shifted the critical flows to native, leaving the rest untouched. That staged migration kept the backlog realistic and let us dial quality up without derailing releases. Maintain Consistency: Centralizing business logic in one Kotlin module has saved us countless merge headaches. A single bug fix lands once and rolls out everywhere—no more “iOS fixed, Android still broken” stand‑ups. It’s not flashy, but this shared core is what lets the team sleep at night when deadlines loom. Ensure Elasticity: In my experience leading mixed‑platform projects, the teams that thrive are the ones that treat architecture like a living organism, not a static blueprint. We design every layer so it can flex when budgets tighten, timelines shift, or a surprise hire brings new skills. Because Compose Multiplatform lets us blend shared and native UI on demand, we can pivot from “MVP mode” to “native‑polish mode” in days, not months. That elasticity has repeatedly saved us when product strategy—or the market itself—changed overnight. Conclusion This elastic hybrid architecture, built on Kotlin Multiplatform and Compose Multiplatform alongside native UI frameworks, offers unparalleled flexibility. It allows you to adjust your development strategy based on budget, team size, and timeline constraints while maintaining consistency and long-term maintainability. For lean projects, maximize code reuse to launch quickly; as resources expand, incrementally enhance critical screens with native UI elements without rewriting your core logic. Embrace this flexible, incremental model to reduce duplication, streamline maintenance, and deliver a consistent, high-quality user experience that scales as your project evolves.
アバター
About KTC's Engineering Office In January 2025, KINTO Technologies (KTC) established a new organization: the Engineering Office. This article introduces what the Engineering Office is working on, while also helping raise awareness of its purpose within the company. What We’re Aiming For Our primary goal is to "strengthen KINTO Technologies' capabilities as an engineering organization." To achieve this over the medium to long term, we’re actively working to foster new capabilities and shape a supportive, evolving engineering culture. As a team reporting directly to the Vice President , we stay closely aligned with key management issues. Together, we formulate hypotheses about what initiatives KTC truly needs, and each of us leverages our own experiences and expertise to lead cross-functional efforts across the company . Our Mindset It’s easy to look at other teams and wish for what they have. But if we want to unlock new possibilities, we also need to take a closer look at the strengths we’ve already built and make the most of them. Real progress begins when we start asking ourselves questions like, "What if we added this, tweaked that, or took something away? Could we become even stronger?" It is important to correctly understand the current situation and take action based on that context. KTC already has a workforce of over 350 people. Because our existing operations and organizational structures are well established, bringing about change is not easy. Precisely because we are in an uncertain and ambiguous situation where no one knows the right answer for us, we must remain persistent. Instead of rushing to conclusions, we should focus on identifying what is truly necessary. What Not to Do We don’t plan to directly handle the following areas: Planning, promotion and execution of business strategies and development projects Project and program management for development work Recruitment, PR, internal communications, and company culture initiatives While the Engineering Office works to strengthen KTC’s engineering capabilities through planning and promotion, we do not take on responsibilities such as hiring, training, evaluation, or public relations, which are roles that similar departments at other companies may often manage. At present, as we move projects forward, we’re collaborating with the respective dedicated teams at key points when needed. Activity Example 1: Planning to Accelerate Key Initiatives While KTC is steadily bringing together talented individuals, we believe that achieving even greater outcomes as an in-house development team requires further organizational and team maturity. Through ongoing discussions with the Vice President, I was involved in shaping and articulating the key focus themes for 2025. Since AI First already has a dedicated project team, the Engineering Office is focusing on the remaining three themes: Release First User First Organizational Intensity We’re planning initiatives to support internal volunteer efforts and cross-team projects, based on two key pillars: 1. Improving IT literacy across the organization and 2. Creating real examples and encouraging behavioral change . Activity Example 2: Supporting Development Team Process and Communication Y.Naito-san is leveraging her expertise and experience in SPI ( Software Process Improvement ) to support in-house development teams. Specifically, our efforts include facilitating team retrospectives, assisting in the operation of development tools such as JIRA and Findy Team+, organizing study sessions to share knowledge needed for process improvement, and providing mentoring. The initiative aims to improve communication, tools, processes, and empowerment, enabling teams to achieve results that no individual member could accomplish alone. We’re also working to uncover know-how and best practices developed by individuals or specific teams, and to share them across the organization to broaden and deepen collective knowledge, ultimately driving efforts to enhance the company’s overall technical capabilities. Activity Example 3: Creating an Environment Where Individual Growth and Contribution Go Hand in Hand Our Vice President made the following request, in line with our identity as a technology company: "We want to ensure that engineers, designers, and other professionals working as specialists are able to contribute to the company and that their contributions are properly recognized." We’ve only just started the discussion, so nothing is set in stone yet. However, we’ve begun working with HR and are starting conversations with department heads to explore how we can turn this into reality. To continue being a company that contributes through its software development and technical capabilities, we believe it’s essential to build an environment where members can continue growing. This includes initiatives like developing career paths and increasing opportunities for professional challenges. Let's Make Our Work More Interesting! (Hiring Info) We haven't formalized our operations just yet, so we're not officially advertising job openings. But if you’re the kind of person who’s excited to shape your own mission based on your own themes and beliefs. we think you’ll really enjoy being here. Let's make our work more exciting and meaningful, with our own hands! 💪 Requirements Someone who can move independently and take initiative in a high-autonomy environment Someone who can navigate uncertainty and keep moving forward through trial and error Someone who can stay patient and persistent in the face of ambiguity, without rushing to conclusions Someone who can inspire change and bring others along for the ride If you are interested, please feel free to reach out via Open Positions page. If you know someone on the team, you can also message us directly via DM! (・∋・)ノシ https://hrmos.co/pages/kinto-technologies/jobs/0000127 KINTO Technologies is also looking for people to join us across a variety of teams and roles. For more information, please see the recruitment information .
アバター
こんにちは こんにちは、2025年2月入社の hayashi-d1125 です! 本記事では、2025年2月入社のみなさまに、入社直後の感想をお伺いし、まとめてみました。 KINTOテクノロジーズ(以下、KTC)に興味のある方、そして、今回参加下さったメンバーへの振り返りとして有益なコンテンツになればいいなと思います! 佐竹 康晴 自己紹介 新サービス開発部 プロジェクト推進Gの佐竹です。 社内で新たに企画するプロダクトやプロジェクトのPdM/PMを担当しています。 所属チームの体制は? プロジェクト推進G全体で15名、私が所属するPMのチームは6名の体制になります。 KTCへ入社したときの第一印象?ギャップはあった? トヨタグループの内製会社として、社内組織や体制が高度に組み上げられており、想像以上の内製組織でびっくりしました。 現場の雰囲気はどんな感じ? 不明なことに対して情報やアドバイスをもらえるなど、チーム内での相互フォロー関係ができており、出社時にはランチ、業務後や週末には飲み会や一緒に出かけるなど、部署の垣根を越えた交流も盛んで、活気があります。 ブログを書くことになってどう思った? 入社前に読んでいたテックブログにこんな早々にブログ投稿することになるとは思ってもみませんでした。 大変光栄ですし、色々なことを発信していくことは好きですので、今後も機会があれば積極的に投稿させていただきたいと思います。 工藤 啓さん → 佐竹 康晴さんへの質問 他部署のメンバーとの関わりなどどのようにされていますか? Bear BashやKTC内の部活など他部署メンバーと交流できる機会に積極参加して繋がりを広げています。 特にBear Bashでは会場BGMとしてDJを披露したおかげで、多数の方と交流することができました! 脇坂 友里絵 自己紹介 開発支援部 企画管理Gで請求や予算など、KTCのお金に携わるバックオフィス業務を主に行っています。 所属チームの体制は? 6名体制で分担しながら業務を行っています。 KTCへ入社したときの第一印象?ギャップはあった? 思っていたよりも意思決定から行動までのスピードが早く驚きました! 現場の雰囲気はどんな感じ? 現場の雰囲気としてはとても協力的だと思います。 各拠点にチームメンバーがいるのでリモートでのやり取りが多いのですが、定期ミーティングを行うなど業務がスムーズに進むようにコミュニケーションを増やしています。 ブログを書くことになってどう思った? 文章を書くことに対して苦手意識はあるのですが、いい機会だな!と前向きに捉えています。 佐竹 康晴さん → 脇坂 友里絵さんへの質問 入社してみて、今まで勤務されていた会社とは異なっていたのはどんなところでしょうか? 会社として勉強会やセミナーなど、学ぶことに対しての投資は惜しみなくされているのかなと思っています。 楊 小龍 自己紹介 業務システム開発部Salesforce開発Gの楊です。 Kinto Factory保守開発を担当しています。 所属チームの体制は? 自分を含めて全 6 名のグループです。 KTCへ入社したときの第一印象?ギャップはあった? 「自由」だと感じます。 服装も、出社時間も 現場の雰囲気はどんな感じ? チーム全員が優しく、わからないことがあったら聞きやすいです。 ブログを書くことになってどう思った? 感想類の文書を書くことが苦手と思います。。。 脇坂 友里絵さん → 楊 小龍さんへの質問 入社後、一番困ったことを教えてください! MTG、しゃべりで、時々わからない言葉があります。 今も日本語を頑張って勉強しています! 林田 洋平 自己紹介 プラットフォームグループ/プラットフォームエンジニアリングチームの林田です。 KTC の開発チームのために各種ツールの開発・提供・メンテナンス等を行っております。 普段は Osaka Tech Lab で働いております。 所属チームの体制は? Osaka Tech Lab に3名。 神保町オフィスに6名の体制で仕事をしております。 拠点が離れているのでやりとりは Slack や Teams 等のコミュニケーションツールを使って行っております。 KTCへ入社したときの第一印象?ギャップはあった? 創業して僅か約4年の会社とは思えないほどに色んな制度やフローが整っている会社だと思いました。 一方で自チームに関しては、まだ未整備な部分も多くこれからチームビルディングに関われる機会も多そうで楽しみに思いました。 現場の雰囲気はどんな感じ? 私が勤務している Osaka Tech Lab はもともと1名だったのですが、私が入社した時点でやっと3名になりました。 雰囲気としては拠点が離れているぶん、まだ神保町オフィスのトレンドに付いて行けていない印象があるので、コミュニケーション面で課題を感じました。 ブログを書くことになってどう思った? 前職でも書いていたので特に苦手意識や違和感はありませんでした。 しかしネタ探しは会社が変わっても変わらず大変なので(笑)日頃から新しい技術に積極的に触れるようにしてネタに困らないようにしなければと思っております。 楊 小龍さん → 林田 洋平さんへの質問 休みの日どう過ごしますか? 妻と子の5人家族なのでもっぱら家族サービスに精を出しております。 先週は家族5人で車で愛知県の中部国際空港セントレアに遊びに行って来ました。 兒玉 桜 自己紹介 データ分析部 分析プロデュースG でデータ分析をしています。 所属チームの体制は? 上長+先輩4名+自分 KTCへ入社したときの第一印象?ギャップはあった? 入社オリエンテーションが手厚くて驚きました。 それ以外は事前にお聞きしていた通り適度(?) に自由な印象を受けているので、ギャップはありませんでした。 現場の雰囲気はどんな感じ? みんな穏やかで優しい。 しかし仕事はプロフェッショナルという謎のギャップにやられています。 (プロフェッショナル=怖いという先入観あり) ブログを書くことになってどう思った? 話をお聞きしたときは、正直「めんどうだな」と思いました。 が、実際に記事を書いていると自分の現在地の再確認にもなりやって良かったなと感じました。 何事も挑戦する事が大事だなと思いました。 林田 洋平さん → 兒玉 桜さんへの質問 データ分析のお仕事をしようと思ったきっかけは? アウトソーシング業界にいたある時、急遽欠員が出たクライアント先の穴埋めとしてたまたま配属されたのがアクセス解析チームでした。 そんな仕事がある事すら知らなかった未経験状態で始まったのですが、業務にあたるうちに深めたくなってしまい現在に至ります。 小川 就也 自己紹介 業務システム開発部 Salesforce開発G 小川です。 Factory BOシステムの保守を担当しています。 所属チームの体制は? マネージャー1名メンバー5名でSalesforceの運用保守、データ連携、Salesforceが関連するプロジェクト対応を行っています。 KTCへ入社したときの第一印象?ギャップはあった? 技術者集団=ある程度の技術力や知識が無いと質問や相談しにくいのでは?と思っていましたが、気軽に質問/相談できる雰囲気でした。 レスポンスもとても早く、親身に対応してくださる方が多いです。 現場の雰囲気はどんな感じ? 入社したときの第一印象、ギャップにも書きましたが、とても気軽に質問/相談ができる雰囲気です。 ブログを書くことになってどう思った? 今までブログを書くことをやったことが無かったので、機会をいただけたことに感謝しています。 兒玉 桜さん → 小川 就也さんへの質問 仕事の合間や休憩時間、どのようにリフレッシュしていますか? 在宅勤務時は昼休憩に30分程ランニングしてます。 ランニング中は考えている余裕が無くなるので強制的に無心になれます。 出社時はまだ模索中です。 安田 早希 自己紹介 プラットフォーム開発部 Cloud InfrastructureGに所属となりました、やっさんです。 部署名の通り、サービス基盤のクラウドインフラの部分を担当しております。 所属チームの体制は? クラウドインフラGとしては9名体制ですが、さらに細かくチームが分かれております。 KTCへ入社したときの第一印象?ギャップはあった? ルールとか非常に硬いイメージを持って入社したのですが、実際は上下関係なく接しやすく、チャットでもスタンプが飛び交うような和気あいあいとしていたことが、ギャップでしたね。 現場の雰囲気はどんな感じ? 前職では、「静かに、音を立てない」といった雰囲気だったこともあり、なかなか業務のことを相談しずらかったのですが、今はすぐに相談できる状況ですし、チーム仲がよいので出社メンバーで必ず、ランチを食べに行っています♪ ブログを書くことになってどう思った? 入社前に見ていたので、自分も書くことになったのか~と、感慨深いです 小川 就也さん → 安田 早希さんへの質問 神保町オフィス周辺でおすすめの飲食店はありますか? 先日行った、「森のブッチャーズ」というお店がおすすめです。 ランチメニューで、ビーフやポークのステーキが食べ応えあってよかったです。 11時半ごろに行って30分待ちましたが、並ぶ価値がありました! 工藤 啓 自己紹介 モビリティプロダクト開発部エンゲージG配属になりました工藤です。 販売店様内の業務DX化支援を行います。 所属チームの体制は? チームはMgr含め3名ですが、部内の開発担当チームやKINTO営業部とも協業しながら販売店様に入り込みDXニーズを聞き出していきます。 KTCへ入社したときの第一印象?ギャップはあった? エンジニアが周りにたくさんいるなーという印象。 これまでエンジニアとがっつり仕事をしたことがなかったので皆さんのモニター画面がコードばかりなのが新鮮でした。 現場の雰囲気はどんな感じ? 現場に訪問することが多く、社内にいないことが多いのですが、全員販売店様ファーストで提案を考えていることに刺激を受けます。 ブログを書くことになってどう思った? 会社のブログに携わることがこれまでなかったのでこの内容が発信されると思うと、本当に大丈夫かなと心配になります。 安田 早希さん → 工藤 啓さんへの質問 エンゲージメントを高めるために生成AIを使うとしたら、どのようなものがあると思いますか? お客様への代替車種提案業務など既に、生成AIを活用したプロダクトがあります。 他にも社内問合せ業務の効率化に活用するなど、販売店様への業務DXにおいて活用のシーンはかなり多いと思います。 さいごに みなさま、入社後の感想を教えてくださり、ありがとうございました! KINTO テクノロジーズでは日々、新たなメンバーが増えています! 今後もいろんな部署のいろんな方々の入社エントリが増えていきますので、楽しみにしていただけましたら幸いです。 そして、KINTO テクノロジーズでは、まだまださまざまな部署・職種で一緒に働ける仲間を募集しています! 詳しくは こちら からご確認ください!
アバター
Introduction Hello, I'm Mizuki, and I joined the company in September! In this article, I interviewed the members who joined in August and September 2024 and gathered their first impressions after joining KINTO Technologies. I hope this article will be helpful for those interested in KINTO Technologies and serve as a nice reflection for the members featured here! K.W Self-Introduction I am a PdM (Product Manager) on the JP Membership Platform Team, which is part of the Common Service Development Group in the Group Core Systems Division. I started my career as a PdM at a major web services company straight out of university. KINTO Technologies (KTC) is my second company. How is your team structured? The JP Membership Platform team develops membership-related features for KINTO's web services and mobile apps in Japan. Our team consists of eight members: one team leader, one PdM, six software engineers (including team members from partner companies). What was your first impression of KTC when you joined it? Were there any surprises? Since KTC is made up entirely of mid-career professionals and new members join almost every month, I immediately felt a welcoming atmosphere for newcomers. As for any surprises, this was my first time changing jobs, so I was honestly a bit nervous about whether I could contribute. But thanks to the support of my teammates, I feel like I’ve blended in better than I expected. What’s the atmosphere like on the team? KTC is still a relatively new company, so we’re in the process of establishing rules and structures. That said, I’ve found that each member is proactive and that there’s a culture of actively adopting new development methods and initiatives. How did you feel about writing a blog post? I haven’t had many chances to share things through blogs, so I took my time writing this one while looking at past onboarding posts for inspiration. Question from MK-san: Any recommended items you use in the office? It’s actually something I use at home rather than at the office, but I highly recommend a height-adjustable desk. Here’s the one I use. https://www.amazon.co.jp/dp/B08CXSV3RX Shiori ![](/assets/blog/authors/mizuki/20250123/suda.png =250x) Self-Introduction I work as a Generative AI Engineer in the IT/IS Division on the Generative AI Development Project. My main responsibility is promoting the use of generative AI. This includes conducting internal training sessions, developing use cases, and providing technical support for generative AI. How is your team structured? Our team consists of five members, including myself: three based in Nagoya, one in Jimbocho, and me in Muromachi. What was your first impression of KTC when you joined it? Were there any surprises? I was impressed by the well-established environment for keeping up with technology and sharing knowledge — there are monthly themed study sessions, regular Toyota Group tech meetups, internal training opportunities, and access to external seminars. The company is also proactive in sharing its work through the tech blog and presentations. Just four months after I joined, I had the opportunity to speak at an external seminar about how we’re using generative AI internally. I also learned the term "menchaku" after joining the company. This is a Toyota word that refers to "communicating in person." I felt that this culture of balancing in-person and online communication helps reduce misunderstandings and promotes faster decision-making and value creation. As Toyota’s in-house development organization, we handle much more than just mobility products like KINTO. Our work also includes finance, MaaS, technical support for vehicle systems, dealership digital transformation, and generative AI. This broad scope gives us many opportunities to expand our knowledge across different fields. I also feel that decision-making here is quite democratic. For example, our office drink flavors are rotated seasonally — spring/summer and fall/winter— and each time, a “Flavor Preference Survey” is conducted. The current fall/winter flavors were chosen based on the survey results, which really impressed me! What’s the atmosphere like on the team? Whether it’s on Slack or in person, when someone runs into a problem, others always step in with thoughtful support. It’s a really warm and welcoming environment. It's also easy to invite people to lunch, and I’ve had the chance to connect with team members outside of my division, which has been a lot of fun. How did you feel about writing a blog post? ✌️😆✌️ Question from K.W: Do you have a personal motto? I'm not sure if I’d call them mottos, but I do have two personal themes I’m focusing on for 2024 and 2025: "Pivot" and "Act now." In the field of generative AI, technology and information are updated incredibly fast. Major tech announcements happen frequently, and it’s not uncommon for a worldview that felt new yesterday to become the norm today. In such an environment, it’s important to quickly test ideas, measure their impact, adjust course, and put them into action — all in fast cycles, even when the outcome is uncertain. That's why I try to minimize the time between “having an idea” and “taking action,” whether it’s for work or daily life. Yukki~ ![](/assets/blog/authors/mizuki/20250123/yukki-.jpeg =250x) Self-Introduction Nice to meet you, I'm Yukki. I belong to the Corporate IT Group in the IT/IS Division. My role involves identifying and resolving issues across a wide range of areas, including internal information systems, network infrastructure, and security. How is your team structured? I’m part of the Boost team, which currently has two members. Our team supports the Corporate IT Group by tackling challenges and providing behind-the-scenes support. Each of us focuses on problem-solving in our respective areas of expertise. Currently, I’m involved in infrastructure design related to the renewal of various KINTO systems. I’m working on improvement initiatives while keeping the concept of Shu-Ha-Ri in mind. *Shu-ha-ri is a process of learning: first following the established way (Shu), then breaking it (Ha), and finally creating a new approach (Ri). What was your first impression of KTC when you joined it? Were there any surprises? Before joining, I assumed that, as a subsidiary of a large company, there would be some limitations — even though KTC moves at a startup-like pace. But after joining, I was surprised at how much freedom and autonomy the company offers. It feels fast-paced and venture-like. At the same time, the areas that require governance are well managed, and I think the balance between agility and stability is well maintained. Regarding remote work, the basic guideline is to come into the office twice a week, but I really appreciate the flexibility KTC provides in accommodating family needs and personal circumstances. What’s the atmosphere like on the team? There were more people working remotely than I expected. I was surprised to sometimes be the only one in my seating row. With so many people taking advantage of remote work, I found the environment to be very remote-friendly. That said, the office is well-equipped with video conferencing systems and communication tools like Slack, so it’s easy to talk to people, and I feel reassured by the setup. It’s also been a huge help that my manager is always available when I need to talk. Although it’s a group-wide initiative, we also have a 30-minute casual chat session once a week, which is great. It gives us a chance to connect with colleagues from Tokyo, Nagoya, and Osaka despite the physical distance. How did you feel about writing a blog post? Even though I joined the company at the same time as others, the physical distance made it hard to talk or interact much. Writing this blog gave me a great chance to connect with other new joiners from different locations. Before joining KTC, my previous role didn’t involve much outward communication. I hope to gradually take more opportunities to share and communicate externally. Question from Shiori-san: I heard that photography is your hobby. Do you have any tips for improving photography skills? I’m still learning myself, but lately I’ve been paying more attention to the balance between the background, middle ground, and foreground, as well as how elements are arranged within the frame. I also try to go out and find new subjects each season to increase my shooting opportunities. Mizuki Self-Introduction I’m part of the Talent Acquisition Team in the Human Resources Group, within the Development Support Division. We handle engineer recruitment and also organize hiring events in Osaka! How is your team structured? There are six members on the Talent Acquisition team. What was your first impression of KTC when you joined it? Were there any surprises? There wasn't really any gap. Since I had previously worked as a recruitment agent supporting KTC, I already had a good understanding of the company’s atmosphere and culture! However, I was pleasantly surprised by how much trust and autonomy each employee is given. What’s the atmosphere like on the team? I feel that our team truly lives out the value of "respect for all," which is something we hold dear as an HR team. Until December, I was working at Osaka Tech Lab, and I was honestly amazed at how warm and homey the atmosphere was. I really hope that Osaka Tech Lab can continue to keep that great vibe. How did you feel about writing a blog post? Since I’m based in a different location, I only had a brief chance to meet most of the other new joiners during orientation. So writing this blog felt like a great opportunity to get to know everyone's hobbies and roles. Question from Yukki~-san: What’s your most recommended tsukemen spot? I listed my favorites by location! Please check them out if you get the chance! Tokyo: Dogenzaka Mammoth (Shibuya) https://tabelog.com/tokyo/A1303/A130301/13122700/ Osaka: Miyata Menji (Shinsaibashi) https://miyata-menji.com Nagoya: Hanzo (Fujigaoka) https://www.menya-hanzo.com/hanzo.html R.K Self-Introduction I belong to the Marketing Product Group within the Mobility Product Development Division. I’m currently the PdM for "Prism Japan," a travel app and website. My first company was in the human resources industry, where I worked on app and website growth. KTC is my second company. How is your team structured? Our team consists of one team leader/engineer, two engineers, one marketer, one writer, and one PdM. What was your first impression of KTC when you joined it? Were there any surprises? I had heard that the team was very friendly, and when I actually joined, it turned out to be exactly that. Since this was my first job change, I was honestly a bit anxious about whether I could be of any help. But thanks to the strong support from my teammates, I’ve been able to keep going and do my best! What’s the atmosphere like on the team? Since we're working on a product in its growth phase, everyone naturally goes beyond their job descriptions, contributing in various ways within a cheerful and collaborative atmosphere. How did you feel about writing a blog post? I haven't had many chances to write blog posts, so I referred to everyone else's comments for inspiration! Question from Mizuki-san: Where is the best place you’ve ever visited overseas? Aside from the more common destinations, I really enjoyed New Zealand! I took a road trip around the South Island, visiting lots of different spots. The nature was rich and breathtaking, the food was great, the towns were clean and beautiful, and time just felt slower in the best way. It was a trip that exceeded all my expectations, and I’d love to go back someday! Chen Self-Introduction I’m originally from Xiamen, China, and worked as an engineer in the Internet industry there for about 10 years. KTC is the first Japanese company I’ve worked for. I am currently part of the Platform Development Division, in the DBRE team, where I develop database-related operational tools. My MBTI type is INFP. My hobby is trying out new things. In just three months, I've been to almost every restaurant in the Jimbocho (half of them are curry spots, though). I enjoy visiting art museums in Tokyo, especially the contemporary art ones — part of the fun is not always understanding them. I have a weakness for new product releases. How is your team structured? There are five of us working in the Jimbocho office, and we recently merged with the SRE team, so we now have a total of seven members. What was your first impression of KTC when you joined it? Were there any surprises? My first impression was that the office wasn't flashy, but it didn't feel like a traditional Japanese company either — it actually had a bit of a global/foreign-company vibe. During orientation, there was a lot of information about the internal tools and initial setup, and even with my IT background, it took some time to get used to everything. Since there aren’t many people in the Jimbocho office, it’s a quiet space where I can really focus. I was glad to hear that many people work from home — something that’s still relatively rare in China. What’s the atmosphere like on the team? Our team members are very kind and hardworking. It’s rare to see such detailed support for internal clients (like product teams) and fellow teammates — but that’s exactly what I’ve found at DBRE. During onboarding, I was never ignored for not knowing something — I was always encouraged to ask questions anytime. Also, no one ever put me through the usual “let’s see what you can do” period as a new hire. We always discuss tasks together before starting development. At first, I was surprised by this team-based approach, since I was used to solving things on my own. But once I got used to the pace, I found it really comfortable. There is a lot to learn from how others approach problem-solving, and when everyone’s aligned, it really boosts your confidence in taking on challenges. How did you feel about writing a blog post? I want to improve how I express and share what I know, so I’m going to keep challenging myself to write more. After reading the tech blogs written by my teammates, I realized that what I’ve been missing is the ability to organize and present information clearly. Question from R.K-san: You've been to almost every restaurant in the Jimbocho — what's your favorite lunch spot? Thank you for the question! For reference, I personally love Southeast Asian food — sour, sweet, and full of variety. [Thai food] The best spot is Bangkok Cosmo Shokudo. Even at night, the prices are reasonable and the portions are generous. You can't go wrong with any item on the menu. [Ramen] To be honest, I don't have the patience to wait three hours at Ramen Jiro...😅 So instead, I recommend Yojinbo. I personally like it better than Butayama. Also, "Ebimaru Ramen" is a must-try. The flavor of the soup is really amazing. [Korean food] I went to Keijoen without realizing it had been featured on the TV show "Solitary Gourmet." Their kontan soup set meal is delicious and well-priced. [Indian food] Namaste India (on the first floor) is plenty good in my opinion — though to be honest, I don’t really notice much difference between most Indian places...😂 That said, I recently found a place called Gurgaon in Ginza, and their cheese kulcha was so good, it’s worth the trip. [Curry] Here are my top 3 curry picks: Panch Mahal — their lassi is excellent Takeuchi Jimbocho Main Branch — be warned: some dishes are quite spicy Chantoya Coconut Curry — the coconut-based soup curry leaves a lasting impression T.A. ![](/assets/blog/authors/mizuki/20250123/ki2.jpeg =250x) Self-Introduction I’m in Information Security and belong to the Security and Privacy Group in the IT & Information Security Division. My hobby is doing solo activities. How is your team structured? There are three of us, including the team leader and a contractor. It's currently our busiest season, so I'm feeling the pressure! What was your first impression of KTC when you joined it? Were there any surprises? I felt that KTC was a flexible and fast-paced company. There are many people from different nationalities and backgrounds, so I learn a lot just from casual conversations. What’s the atmosphere like on the team? There’s a strong sense of continuous improvement. It really feels like something gets upgraded every week, which keeps my curiosity sparked. We often focus on how to do things more efficiently, so I feel like I'm constantly sharpening my own skills as well. How did you feel about writing a blog post? I just hope I don’t make any typos... Question from Chen-san: What exactly do you mean by "solo activities”? I often go drinking alone, watch movies alone, or go solo camping. Recently, I even went to a Christmas market by myself. The illuminations were beautiful. MK Self-Introduction I’m a front-end engineer in the Digital Transformation Development Group of the Mobility Product Development Division. I develop products that support the digital transformation of dealership operations. My career path so far has been: sales → admin → front-end engineer. Also... I love prosciutto. How is your team structured? We’re a team of nine, working on multiple products. All of our engineers are skilled in a wide range of technologies, so we switch between coding and planning depending on the project, without being limited to any specific domain. What was your first impression of KTC when you joined it? Were there any surprises? To be honest, I thought it might be a bit strict before I joined... But once I got here, I found that it’s actually a very flexible company. It feels like the best of both worlds — the stability of Toyota with the agility of a young company. What’s the atmosphere like on the team? There’s a real passion for technology. There’s a real passion for the product, too. Communication is lively, and there’s great energy all around. How did you feel about writing a blog post? I thought it would be a great way for people outside the company to hear directly from those of us actually working on development. I'm also excited to read what everyone else thinks about the company! Question from T.A.-san: Were there any superstitions or lies you believed (or were fooled by) as a child? I used to believe the purple part of a pigeon's neck was poisonous. Finally Thank you to everyone for sharing your impressions after joining the company! At KINTO Technologies, new members are joining the company almost every day! We'll be posting more new-joiner stories from across divisions, so stay tuned! And yes — we're still hiring! KINTO Technologies is looking for new teammates to join us across a variety of divisions and roles. For more details, check it out here !
アバター
📱 Appium Meetup Tokyo #2 開催決定!大好評のモバイルテスト自動化イベントがさらに進化して帰ってくる! 技術広報Gの中西です。前回大きな盛り上がりを見せた「Appium Meetup Tokyo」の第2回目が、2025年5月28日(水)にKINTOテクノロジーズの室町オフィスで開催されます。前回はAppiumの実践的な活用事例やパフォーマンス改善の劇的な成功例が紹介され、多くの参加者から高い評価をいただきました。 🎯 今回の注目ポイント 今回のイベントでは、モバイルアプリのE2Eテストや自動化を一段階引き上げるためのノウハウや最先端技術を、現場で活躍するエンジニアたちが余すことなくお伝えします。 Appiumテストの失敗原因調査のコツと実践 (MagicPod 脇坂 雅幸 氏) モバイルE2Eテストにおける失敗原因を迅速に特定・解決するためのデバッグ手法を具体的に解説!Appium Inspectorの活用法やWebDriverAgentに関連するトラブルシューティングの実例を共有します。 モバイルアプリのVRT環境構築に向けた取り組み (カシオ計算機 髙橋 秀徳 氏) Flutter製アプリ「CASIO WATCHES」でのAppiumを活用したビジュアルリグレッションテスト(VRT)自動化事例を紹介!スクラム開発の現場での課題解決と効率化への実践的なアプローチを詳しく解説します。 手動リンクチェック撲滅!Appiumで実現するネイティブアプリURL完全自動化 (KINTOテクノロジーズ 岡 郁弥、パンヌウェイ) Webでは簡単にできるリンク先チェックの自動化ですが、ネイティブアプリでは技術的な制約から実現が難しいとされてきました。その課題をクリアし、ネイティブアプリでもリンクチェックを完全自動化するための具体的なノウハウと工夫を共有します。 Appiumで安定したスクロール量を実現するちょっとした小技 (Autify 武藤 大樹 氏) 実務で即活用できるノウハウ満載!小さな工夫で大きな改善をもたらすテクニックをご紹介します。 🕒 タイムスケジュール 時間 セッション内容 18:30 開場 19:00 イベント開始 19:05 Appiumテストの失敗原因調査のコツと実践 19:45 モバイルアプリのVRT環境構築に向けた取り組み 20:05 休憩 20:15 手動リンクチェック撲滅!Appiumで実現するネイティブアプリURL完全自動化 20:35 Appiumで安定したスクロール量を実現するちょっとした小技 20:55 懇親会(現地参加のみ) 21:30 撤収 🏢 開催概要 日時 :2025年5月28日(水)19:00~21:30(18:30開場) 会場 :KINTOテクノロジーズ 室町オフィス(東京都中央区日本橋室町2-3-1 室町古河三井ビルディング16階) 参加費 :無料 定員 :現地参加20名、オンライン参加50名(Zoomウェビナー) 🌟 お申し込み方法 参加希望の方は、 イベントページ よりお早めにお申し込みください。ご登録はお早めに! 💬 こんな方に特におすすめです モバイルアプリのテスト自動化を次のレベルに引き上げたい方 Appiumの導入・活用に興味があり、具体的な成功事例を知りたい方 最新の自動化技術を学び、QA業務の負担を劇的に軽減したい方 🚀 モバイルテストの未来を一緒に創ろう! 前回の参加者アンケートでもAppiumの実践的な活用方法やノウハウに関する関心が非常に高く、コミュニティの交流も活発でした。今回も充実した内容とともに、新たな交流の機会をご用意しております。皆さんとお会いできるのを楽しみにしています! 参加を検討している方へ モバイルアプリの自動テストをこれから本格的に導入したい方 Appiumに興味があるが具体的な事例やノウハウが欲しい方 CI/CDと組み合わせた運用に関心があるエンジニアやQA担当の方 他社事例を参考に自社のテスト文化を改善したい方 上記に当てはまる方は、ぜひAppium Meetup Tokyoで最新の知見を共有し合いましょう。今後の告知や詳細情報は @AutifyJapan や @KintoTech_Dev でさせて頂きます。ご質問やご要望などがございましたら、お気軽にお寄せください。 Appium Meetup Tokyoでお会いできることを心より楽しみにしています。
アバター
はじめに こんにちは! KINTOテクノロジーズでWebエンジニアをしている亀山です。 現在はマーケティングプロダクト開発グループという部署に所属しています。 今回はサーバレス構築についてお話しします。 ECSなどのコンテナが常時起動しているアプリケーションは、稼働している間、たとえリクエストが来なくても起動している時間分のリソース(CPUやメモリ)に対して課金が発生します。そのため、PoC開発や極端にリクエストが少ないプロダクトにおいては特に「 使っていないのにお金がかかる 」状態になりがちです。 そのようなプロダクトに対しては、使っている間だけサーバーが立ち上がり、一定時間処理が行われないと自動で停止するような従量課金型のサーバレスアーキテクチャによってランニングコストを大幅に抑えることが可能になります。 そこで私たちは下記の要点でLambdaアプリケーションを構築しました。 AWSのAPI Gateway + Lambdaでサーバレス開発 TypeScript + Expressでシンプルかつ汎用的なAPI開発 サーバレスについて AWSのサーバレス構成として広く用いられているLambdaを採用しましたLambdaはサーバレスアーキテクチャであるため、先にも述べましたが、サーバーの起動・停止やスケーリングを自動で行ってくれ、使った分だけ課金される従量課金制でコストを最小限に抑えられます。 一方でこのようなサーバレスAPIのデメリットとしては、 コールドスタートによる応答遅延 が発生する点があります。特にリクエスト数の少ない環境や、一定時間アクセスがないときにLambdaがスリープ状態になり、再度リクエストが来た際にコンテナの起動時間(実測値として応答時間約1秒)がかかるという特性があります。 まとめると、 とにかくサクッとプロトタイプを構築したいであったり、応答遅延を許容できるようなユーザー(例えば社内メンバー)向けのツールを構築したいという方には特におすすめな インフラ構成になります。 Lambdaでどれくらい費用が安くなるのか? 常時実行コンテナのFargateと今回使用するサーバレス型のLambdaで料金比較をしてみます。 Fargate AWS Fargateの料金について 0.5 vCPU でメモリ2GBを想定して1時間あたりの1タスク稼働費用は vCPU料金: 0.5 vCPU * $0.04048 / vCPU-時間 = $0.02024 / 時間 メモリ料金: 2GB * $0.004445 / GB-時間 = $0.00889 / 時間 という計算から1時間あたり合計費用は $0.02024 + $0.00889 = $0.02913 となり、 そのため1ヶ月720時間稼働するとすると$0.02913 * 720時間 = $20.9736 が1タスク月当たりかかります。(ただし、夜間停止やvCPUスペックダウンによって節約すること可能) これは1環境あたりの費用なので本番環境、開発環境など複数の環境が必要であればその数だけ掛け算されます。 Lambda AWS Lambdaの料金について 一方でLambdaはリクエスト件数とリクエストによって一時的に起動するコンテナの計算時間(コンピューティング時間)によって計算されます。 GB-秒あたり0.00001667 USD 1,000,000 件のリクエストあたり0.20 USD Fargateと同様の2GBで、1リクエストあたり0.5秒の計算時間、さらに1ヶ月あたり10万件のリクエストであると想定すると月当たりの合計費用は$0.02 (リクエスト費用) + $1.6667 (計算費用) = 約 $1.69 が月当たりかかります。 さらに良いことに、環境を増やしたり、1環境あたりのLambda数を増やしたとしても、合計リクエスト数が同じであれば上記と同じ金額になります。 これらの計算シミュレーションからLambdaのコスト面での優位性がわかると思います。 特に売上の出ないかつトラフィックの少ない社内向けツールであったり、PoCのプロダクトであればこのような費用削減は特にメリットが大きくコスト面でのハードルを下げてくれることが期待できます。 Expressについて サーバサイドJSのフレームワークとしてExpressを採用しました。 ルーティングやミドルウェアの概念が直感的に理解できるように設計されており、初めて Node.js でサーバサイド開発を行う開発者にとっても扱いやすい構成となっています。小規模なAPIから中〜大規模なアプリケーションまで、スムーズに拡張できる設計が可能です。また、ルーティングの記述も簡潔です。 app.get('/users/:id', (req, res) => { res.send(`User: ${req.params.id}`); }); ログ出力には morgan、認証処理には passport、入力バリデーションには express-validator など、用途に応じて豊富なミドルウェアのライブラリを簡単に組み込むことができます。これにより、アプリケーションの機能追加や保守が容易になります。 AWS公式で配布されているLambdaライブラリを用いてエンドポイントを構築することも可能ですが、汎用ライブラリであるExpressを用いて構築しておけばアプリケーションの規模が拡大したタイミングでECSやApp Runnerに転用する際にエンドポイント以降のコードを転用することもLamda特化のライブラリを使用するより容易になります。 開発方針 本記事では、 1つのLambda関数に複数の API エンドポイントをまとめて搭載する構成 を採用しています。 これは、Lambdaの特性である「ホットスタート」を活用するためです。 Lambda関数は一度起動されると、一定時間はメモリ上に残り続ける「ホットスタート」の状態になります。そのため、1つのAPIがリクエストされて Lambdaが起動されたあとは、同じ関数内の他のAPIに対するリクエストも高速に処理できるようになります。 この性質を活かすことで、操作時のパフォーマンスの向上が期待できます。 ただし、Lambdaにはデプロイ可能なパッケージサイズに制限(zip圧縮時で50MB以内かつ展開後で250MB以内)があるため、アプリケーション内すべてのAPIを1つの関数に詰め込むと最終的にこの上限に到達するため、現実的ではありません。 そのため、 画面単位や機能単位で関連のあるAPIを同一の Lambda関数にまとめる構成 とし、最終的には1つのリポジトリで複数の Lambda関数を管理していくmonorepo構成を前提で進めていきます。 また本記事ではSAMによるローカル実行できるようにするまでをゴールとし、AWSコンソールの設定やデプロイ以降のお話は割愛させていただきます。 環境構築(コーディングまでの準備) 本記事では複数の Lambda関数や共有コードを管理しやすいpnpmにAWS SAM を組み合わせた環境構築方法を説明します。 プロジェクト全体を pnpm のワークスペースとして管理し、各 Lambda関数や共通ライブラリを独立したワークスペースとして扱います。デプロイツールにはAWS SAM(Serverless Application Model)を利用します。 主に以下のツールが必要になります。 Node.js pnpm AWS CLI AWS SAM CLI Git (バージョン管理) Gitのインストールは割愛します。 必要なツールのインストール Node.js これまでと同様に Node.js が必要です。公式サイトから LTS 版をインストールしてください。 Node.js公式サイト インストール後、以下のコマンドでバージョンが表示されることを確認します。 node -v npm -v # pnpmをインストールするために使用する pnpm 依存ライブラリの管理には pnpm を使用します。pnpm は特に複数のモジュール(Lambda function)を1つのリポジトリで管理するようなmonorepo構成での依存解決やディスク使用効率に優れています。 以下の方法でインストールします。 npm install -g pnpm または、curl などを使用する方法は pnpm の公式サイトを参照してください。 pnpm インストールガイド インストール後、以下のコマンドでバージョンを確認します。 pnpm -v AWS CLI これまでと同様に AWS との連携に必要です。インストールおよび aws configure による認証情報の設定を行ってください。 AWS CLIインストールガイド AWS SAM CLI 今回はデプロイツールとして AWS SAM (Serverless Application Model) を使用します。AWS SAM はサーバーレスアプリケーションのための IaC (Infrastructure as Code) フレームワークであり、SAM CLI はローカルでのビルド、テスト、デプロイをサポートします。 以下の公式サイトを参考に、お使いのOSに合わせた方法でインストールしてください。 AWS SAM CLIインストールガイド インストール後、以下のコマンドでバージョンを確認します。 sam --version プロジェクト構造とワークスペース設定 プロジェクトのルートディレクトリには、monorepo全体の設定ファイルや、開発時に共通で使うツール(例: esbuild)の依存関係を定義する package.json を置きます。各 Lambda関数や共通ライブラリは、例えば functions ディレクトリの中にそれぞれ独立したサブディレクトリとして作成し、これらをpnpmのワークスペースとして定義します。 提供いただいた構造を参考に、基本的な構造と設定ファイルを説明します。 sample-app/ # (ルートディレクトリ) ├── functions/ │ ├── common/ # 共通コード用ワークスペース │ │ ├── package.json │ │ ├── src/ │ │ └── tsconfig.json │ ├── function-1/ # Lambda関数1用ワークスペース │ │ ├── package.json │ │ ├── src/ # Expressアプリやハンドラコード │ │ └── tsconfig.json │ └── function-2/ # Lambda関数2用ワークスペース │ ├── package.json │ ├── src/ │ └── tsconfig.json ├── node_modules/ # pnpmによって管理される依存ライブラリ ├── package.json # ルートのpackage.json ├── pnpm-lock.yaml # ルートのロックファイル ├── pnpm-workspace.yaml # ワークスペース定義ファイル ├── samconfig.toml # SAM デプロイ設定ファイル (初回デプロイで生成) └── template.yaml # AWS SAM テンプレートファイル ルートのpackage.json リポジトリ全体で共有するスクリプトや開発ツール(esbuild など)を定義します。 package.json { "name": "sample-lambda-app-root", // プロジェクト全体を表す名前 "version": "1.0.0", "description": "Serverless Express Monorepo with SAM and pnpm", "main": "index.js", "private": true, // ルートパッケージは公開しない設定 "workspaces": [ "functions/*" // ワークスペースとなるディレクトリを指定 ], "scripts": { "build": "pnpm -r build", // 全ワークスペースの build スクリプトを実行 "sam:build": "sam build", // SAMでのビルド (後述) "sam:local": "sam local start-api", // SAMでのローカル実行 (後述) "sam:deploy": "sam deploy" // SAMでのデプロイ (後述) }, "devDependencies": { "esbuild": "^0.25.3" // 各ワークスペースのビルドで使う esbuild をルートで管理 // 他、monorepo全体で使う開発ツールがあればここに追加 }, "keywords": [], "author": "", "license": "ISC" } pnpm-workspace.yaml どのディレクトリをワークスペースとして扱うかを定義します。 pnpm-workspace.yaml packages: - 'functions/*' # `functions` ディレクトリ内の全てのサブディレクトリをワークスペースとする # - 'packages/*' # 別のワークスペースグループがあれば追加 依存ライブラリ管理 (pnpm ワークスペース) 各Lambda関数や共通ライブラリに必要な依存ライブラリは、それぞれのワークスペース内の package.json に記述します。 例: functions/function-1/package.json { "name": "function-1", // ワークスペースの名前 "version": "1.0.0", "description": "Lambda Function 1 with Express", "scripts": { "build": "esbuild src/app.ts --bundle --minify --sourcemap --platform=node --outfile=dist/app.js", // esbuildでビルド "start:dev": "nodemon --watch src -e ts --exec \"node dist/app.js\"", // ローカルテスト用のスクリプト (SAM Localとは別に用意しても良い) "tsc": "tsc" // 型チェック用 }, "dependencies": { "@codegenie/serverless-express": "^4.16.0", // Lambdaアダプター "express": "^5.1.0", "@sample-lambda-app/common": "workspace:*" // 共通ライブラリへの依存 }, "devDependencies": { "@types/aws-lambda": "^8.10.138", // Lambdaの型定義 "@types/express": "^4.17.21", "nodemon": "^3.1.0", "typescript": "^5.4.5" // esbuild はルートの devDependencies にあるのでここでは不要 }, "keywords": [], "author": "", "license": "ISC" } @sample-lambda-app/common : functions/common ワークスペースを指します。 "workspace:*" とすることで、ローカルの common ワークスペースを参照するようになります。 common ワークスペース側の package.json で "name": "@sample-lambda-app/common" , と定義している必要があります。 scripts.build : esbuild を使用して、TypeScript コードと依存ライブラリをまとめて1つの JavaScript ファイル (dist/app.js) にバンドルする例です。Lambdaにデプロイするパッケージサイズを削減するために重要なステップです。 依存ライブラリのインストールは、プロジェクトのルートディレクトリで 一度だけ pnpm install を実行します。pnpmが pnpm-workspace.yaml を見て、各ワークスペースの package.json に記述された依存関係を解決し、効率的に node_modules を構成します。 pnpm install 特定のワークスペースにライブラリを追加したい場合は、ルートから以下のコマンドを実行します。 pnpm add <package-name> -w <workspace-name> # 例: pnpm add axios -w functions/function-1 pnpm add -D <dev-package-name> -w <workspace-name> # 開発依存の場合 実際にサンプルコードを書いてみる 先ほど説明したディレクトリ構成は、複数function構成になるように function-1 と function-2 の2つのfunctionモジュールを用意し、それらのfunctionが共用部品として利用できるために common というモジュールを用意しています。 具体的にコードを書いていきます。 commonのコード まず共通部品であるcommonにサンプルとしてミドルウェア関数を1つ書いてみます。 functions/common/src/middlewares/hello.ts import { Request, Response, NextFunction } from 'express'; /** * サンプル共通ミドルウェア * リクエストログを出力し、カスタムヘッダーを追加します。 */ export const helloMiddleware = (req: Request, res: Response, next: NextFunction) => { console.log(`[Common Middleware] Received request: ${req.method} ${req.path}`); // レスポンスにカスタムヘッダーを追加 res.setHeader('X-Sample-Common-Middleware', 'Applied'); // 次のミドルウェアまたはルートハンドラに進む next(); }; 続いて、middlewares/内のエクスポートを追加します。 functions/common/src/middlewares/index.ts export * from './hello'; // middlewares内に他のミドルウェアがあればここに追加していく さらにワークスペースのトップレベルのsrc/でもエクスポートしてあげる必要があります。 functions/common/src/index.ts export * from './middlewares'; // middlewaresのような共通処理が他にあればここに追加していく(utilsとか) funciton-1側のコード 次にfunction-1側のコードを書いていきます。 functions/function-1/src/app.ts import express from 'express'; import serverlessExpress from '@codegenie/serverless-express'; import { helloMiddleware, errorHandler } from '@sample-lambda-app/common'; // 共通ミドルウェア、エラーハンドラをインポート // apiRouter のインポートは不要になりました // import apiRouter from './routes/api'; // import cookieParser from 'cookie-parser'; // 必要に応じてインストール・インポート const app = express(); // express標準ミドルウェアの適用 app.use(express.json()); // JSONボディのパースを有効化 // app.use(cookieParser()); // クッキーパースが必要な場合このように追加する // 共通ミドルウェアの適用 app.use(helloMiddleware); app.get('/hello', (req, res) => { console.log('[Function 1 App] Handling GET /hello'); res.json({ message: 'Hello from Function 1 /hello (Simplified)!' }); }); app.post('/users', (req, res) => { console.log('[Function 1 App] Handling POST /users'); console.log('Request Body:', req.body); // JSONボディをログ出力 res.status(201).json({ received: req.body, status: 'User created (sample)' }); }); // common等にエラーハンドラミドルウェアを作成し、使用する場合は全てのミドルウェアとルート定義の後に配置する。 // app.use(errorHandler); // 本記事では作成していない // ハンドラのエクスポート export const handler = serverlessExpress({ app }); 補足:このあと行うtemplate.yamlでのAPI Gatewayの設定で、/function1 を取り除いたパスが渡されるようになるので、ここに定義するルートは、API Gateway のベースパスからの相対パスになります。 例えば、API Gatewayへのリクエストが /function1/hello なら、ここに定義する /hello にマッチします。 function-2側のコード functions/function-2/src/app.ts import express from 'express'; import serverlessExpress from '@codegenie/serverless-express'; // ★アダプターをインポート★ import { helloMiddleware, errorHandler } from '@sample-lambda-app/common'; // 共通ミドルウェア、エラーハンドラをインポート // ルーターファイルは使用しないためインポート不要 // import apiRouter from './routes/api'; // import cookieParser from 'cookie-parser'; // 必要に応じてインストール・インポート const app = express(); // express標準ミドルウェアの適用 app.use(express.json()); // JSONボディのパースを有効化 // app.use(cookieParser()); // クッキーパースが必要な場合このように追加する // 共通ミドルウェアの適用 app.use(helloMiddleware); // ルートをごとに処理を定義 app.get('/bye', (req, res) => { console.log('[Function 2 App] Handling GET /bye'); res.json({ message: 'Goodbye from Function 2 /bye!' }); }); app.post('/items', (req, res) => { console.log('[Function 2 App] Handling POST /items'); console.log('Request Body:', req.body); // JSONボディをログ出力 res.status(201).json({ received: req.body, status: 'Item created (sample)' }); }); app.get('/status', (req, res) => { console.log('[Function 2 App] Handling GET /status'); res.json({ status: 'OK', function: 'Function 2 is running (Simplified)' }); }); // common等にエラーハンドラミドルウェアを作成し、使用する場合は全てのミドルウェアとルート定義の後に配置する。 // app.use(errorHandler); // 本記事では作成していない // ハンドラのエクスポート export const handler = serverlessExpress({ app }); 今回サンプルなのでルート内の処理を全てアロー関数で書いていますが、実際の開発では処理が複雑になったら別のtsファイルに処理をまとめた方が良いと思います。 また、開発していく中でルートごとに使用するミドルウェアを使い分けたい場面などが出てくると思います。その際はexpressのRouterのライブラリを用いてAPIルーターを作成するとより柔軟に作成できますので調べて試してみてください。(参考: https://expressjs.com/ja/guide/routing.html ) SAMローカル実行するための準備 AWS SAM テンプレート (template.yaml) プロジェクトのルートに template.yaml ファイルを作成し、デプロイするAWSリソースを定義します。Lambda関数、API Gateway、必要な IAMロールなどを記述します。 template.yaml AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: Sample Serverless Application Globals: # Functions 全体に適用する共通設定 (メモリサイズやタイムアウトなど) Function: Timeout: 30 MemorySize: 256 # 適宜調整する Runtime: nodejs20.x Architectures: - x86_64 Environment: Variables: NODE_ENV: production Resources: # function-1 ワークスペースに対応するLambda関数リソース定義 Function1: Type: AWS::Serverless::Function # AWS SAMで定義するサーバーレス関数 Properties: FunctionName: sample-express-function-1 # AWSコンソールに表示されるLambda関数名 (任意) Description: Express App for Function 1 (Simplified) # CodeUri は SAM がコードをパッケージングする際のソースディレクトリを指す。 # ここには、sam build 前のソースコードがあるディレクトリを指定。 CodeUri: functions/function-1/ # Handler は、sam build によって生成された成果物の中でのエントリーポイントを指す。 # esbuild が src/app.ts を dist/handler.js にバンドルし、 # その中で 'export const handler = ...' を CommonJS の 'exports.handler = ...' に変換するため、 # 'ファイル名(拡張子なし).エクスポート名' と記述する。 Handler: handler.handler Events: # API Gateway からのトリガー設定 Function1Api: Type: Api # API Gateway REST APIをトリガーとする Properties: Path: /function1/{proxy+} # 許可するHTTPメソッド (ANYは全てのメソッドを許可) Method: ANY # function-2 ワークスペースに対応するLambda関数リソース定義 Function2: Type: AWS::Serverless::Function Properties: FunctionName: sample-express-function-2 # AWSコンソールに表示されるLambda関数名 (任意) Description: Express App for Function 2 (Simplified) # CodeUri は function-2 ワークスペースのソースディレクトリを指す CodeUri: functions/function-2/ # Handler は function-2 のビルド成果物の中でのエントリーポイントを指す Handler: handler.handler Events: # API Gateway からのトリガー設定 (function-2用) Function2Api: Type: Api Properties: # Function 2 が処理するAPI Gatewayパス Path: /function2/{proxy+} Method: ANY Transform: AWS::Serverless-2016-10-31 : SAM テンプレートであることを示します。 Resources : デプロイする AWS リソースを定義します。 Type:AWS::Serverless::Function : Lambda関数リソースです。 CodeUri : Lambda関数としてデプロイするコードがあるディレクトリを指定します。 functions/function-1/dist のように、各ワークスペースのビルド成果物の場所を指定します。 Handler : Lambda関数が実行されるときに最初に呼び出されるコード内の関数名を指定します。バンドル後のファイル ( dist/app.js ) の中でエクスポートされる関数名になります。 Events : その Lambda関数をトリガーするイベントを設定します。 Type: Api は API Gateway からのHTTPリクエストをトリガーとする設定です。 Path と Method で特定のエンドポイントに紐づけます。 /{proxy+} は、そのパス以下の全てのリクエストをキャッチするための記法です。 ローカルでの開発とテスト (AWS SAM CLI) AWS SAM CLI を使うと、ローカル環境で Lambda関数と API Gateway をエミュレートしてテストできます。 各ワークスペースのビルド : まず、各ワークスペースのソースコードを JavaScript にビルドします。ルートディレクトリで定義したスクリプトを利用できます。 pnpm run build # functions/* 以下のそれぞれの build スクリプトが実行される これにより、例えば functions/function-1/dist/app.js のようなビルド成果物が生成されます。 SAMビルド : 次に、AWS SAM がデプロイ用のパッケージを作成するためのビルドを実行します。 sam build このコマンドは template.yaml を読み込み、 CodeUri: で指定された場所にあるビルド成果物を ( .aws-sam/build ディレクトリ以下に) コピーし、Lambdaが必要とする形式に整えます。 ローカルAPI起動 : SAM CLI が提供するローカル API 機能を使って、API Gatewayをエミュレートし、ローカルで Lambdaコードを実行できるようにします。 sam local start-api コマンド実行後、 http://127.0.0.1:3000 のようなURLでローカルサーバーが起動します。ブラウザやPostman/curl などで、 template.yaml で定義したパス(例: /function1/hello )にアクセスすると、ローカルで Lambda関数が実行されます。 ローカル開発中は、ソースコードを変更したら pnpm run build → sam build → sam local start-api を再実行するか、sam local start-api --watch オプションを使ってコード変更を監視させるなどの方法があります。(--watch オプションはビルドやエミュレーションの再起動を自動で行ってくれますが、実際の環境構成によっては少し工夫が必要な場合もあります) 終わりに 今回はTypeScriptのサーバレスをLambdaとExpressを用いて、ローカル実行するまでの方法ご紹介しました。実際にプロダクトをリリースするにあたり、AWSインフラを構築し、適切な設定をするなどの作業が必要になります。 特にExpressであったりmonorepo構成については初めての試みであったため躓くことがあり、備忘録も兼ねて細かくご説明したため、少々長くなってしまったかもしれません。 同じように困っている人にとって少しでもお役に立てていただければ幸いです。
アバター
Introduction Hello, I'm kh, and I came on board this September! In this article, we asked those who joined the company in August and September 2024 about their impressions immediately after joining the company, and summarized them. I hope this content will be useful for those who are interested in KINTO Technologies, and serve as a reflection for the members who participated in the interview. Naito Self-introduction I work in the Engineering Office. I'm involved in improving processes across different product teams. What is the structure of your team? The Engineering Office was just established in January and consists of two people. What was your first impression of KTC (KINTO Technologies) when you joined? Were there any surprises? Thanks to the interviews and chats I had before joining, there weren't any major surprises. The company has offices in Tokyo, Nagoya, and Osaka, with people frequently coming and going between them. On my very first day, I met several colleagues from the Nagoya office and thought, 'Wow, Nagoya’s actually pretty close! As I started chatting with more people in the company, I realized how embedded "kaizen" is in everyday work. Everyone knows about the Toyota Production System (TPS), which impressed me. What is the atmosphere like on-site? I've been reaching out to various development teams for chats and advice, and everyone has been genuinely kind. I really appreciate how they loop me in and make me feel part of things! How did you feel about writing a blog post? I had been reading tech blogs before I joined the company. So being on the writing side now feels pretty exciting. Question from Mari: Why did you choose this company? Cars are a familiar part of my daily life, so the domain naturally caught my interest. On top of that, I felt like KTC is a company that's going to keep evolving—and I wanted to be part of that journey and enjoy the changes firsthand. R.Y. Self-introduction I'm originally from Hong Kong and moved to Japan in 2023. After graduating, I joined KTC this August, and now I'm part of the Security & Privacy Group. What is the structure of your team? In the Security & Privacy Group, we're divided into teams based on our responsibilities. I'm on the Defense Team, where I mainly handle vulnerability assessments and respond to security consultation tickets. What was your first impression of KTC (KINTO Technologies) when you joined? Were there any surprises? The office is really spacious, with lots of open areas that everyone can use freely. There are also plenty of study sessions and social events, so you get the chance to pick up knowledge beyond your daily work. What is the atmosphere like on-site? Everyone is friendly and easy to talk to. In addition to work, there are all kinds of Slack channels for hobbies and local topics, so it's easy to connect with others who share your interests. How did you feel about writing a blog post? Looking back on everything I've experienced over the past three months—and getting to share it with future team members—makes me genuinely happy. Question from Naito: I'd love to travel to your hometown, Hong Kong. Please let me know if you have any recommendations for sightseeing or food! If you're a Disney fan, Hong Kong Disneyland is a must. The park is compact, so it's easy to explore the whole park in one day. When it comes to food, Hong Kong has tons of delicious local comfort food. Some examples of must-tries: chewy and bouncy curry fish balls, fish-meat shumai, and rich, bold-flavored Hong Kong-style milk tea. Eating on the go is common in Hong Kong, so dive in and enjoy the experience of this culture. (By the way, you can try some popular Hong Kong eats right here in Japan too—check out the Tam Jai Sam Goh Official Website if you're curious.) tHyt Self-introduction Hi, I'm tHyt from the Mobility Product Development Division. While I take on some engineering lead responsibilities, I mainly work as a front-end engineer. What is the structure of your team? Our team has nine members, with specialists across front-end, back-end, and infrastructure. It's a well-rounded crew. What was your first impression of KTC (KINTO Technologies) when you joined? Were there any surprises? Since the company is still relatively young, I expected some areas might be underdeveloped in terms of systems and structure—but to my surprise, everything was impressively well organized. What is the atmosphere like on-site? I'm based at the Osaka Tech Lab, and since the members aren't many, there's always chatter happening across teams. It keeps things interesting. All of my team members except for myself work in the Muromachi office, but we enjoy working together through daily meetings and business trips. How did you feel about writing a blog post? I knew about these new joiner blog posts even before I joined the company, and the day has finally come for me to write one...! That's how I feel. I'm looking forward to using the tech blog to share more than just intros! Question from R.Y.: After joining the company, was there anything you struggled to get used to? How did you overcome it? Hands down, business trips. Since I'm the only one in my team based in Osaka, I travel to Tokyo about once a month to help keep communication flowing. (Huge thanks to the company for supporting that!) Before joining KTC, I had only ever been on one business trip, and I rarely took the Shinkansen—so at first, I was pretty anxious about it all. But now, I've gotten used to it and have no trouble traveling. Remote communication works well, but face-to-face interaction is different. I'd definitely like to keep that going. kh ![](/assets/blog/authors/kh/kh.png =250x) Self-introduction I'm part of the Analysis Group. My work mainly involves building the data infrastructure and collecting the data needed for analysis. What is the structure of your team? There are 10 people including the leader, myself, and folks from partner companies and temporary staff. What was your first impression of KTC (KINTO Technologies) when you joined? Were there any surprises? Since KTC is still a relatively new company, I was expecting a fast-paced, startup-like vibe. But it actually felt more relaxed—in a good way. What is the atmosphere like on-site? We are a group of people with a variety of backgrounds, and everyone brings something different to the table in a friendly vibe. How did you feel about writing a blog post? I’d known KTC was active with tech blog posts, so writing this felt like taking that first step into being part of that culture. Question from tHyt: Got any tips for data analysis? Well, I actually focus more on building the data infrastructure rather than doing the analysis itself, so this might not be the exact answer you were expecting. But no matter how great your data analysis is, it won't be helpful if the data quality is poor. Ensuring data quality at the platform level is, in my view, the essential first step in any successful data analysis. woshahua Self-introduction Hi, my name is Gao. I work in the Woven Payment Solution Development Group! I'm a Chinese-born engineer with a solid Kansai dialect—it's stuck with me completely. My hobbies are basketball, sauna and poker. Recently, I've been working on a personal app that analyzes poker win rates—just for fun! What is the structure of your team? Our team is primarily made up of engineers, and we also work together with engineers from Woven. What I really like is that, no matter which organization we’re part of, everyone's aligned and moving together toward the same goals. What was your first impression of KTC (KINTO Technologies) when you joined? Were there any surprises? Even though KTC's attempt is still relatively new in the automotive field, it struck me as a company actively taking on a wide range of services and development projects. No big surprises, but I was honestly impressed by how much the company encourages technical sharing—and how there are study sessions going on nearly every week. What is the atmosphere like on-site? It's an environment where you're encouraged to explore all sorts of technologies, regardless of your past experience. Whenever I run into a roadblock, someone on the team is always quick to jump in and help. I really appreciate how supportive everyone is. How did you feel about writing a blog post? Both the company and the team are big on promoting tech knowledge, so I'm excited to contribute and share more going forward! Question from kh: I heard that you have a pet. Does living with a pet affect your daily life or work? Yes! I have a guinea pig at home, and just watching it after work is incredibly soothing. Being able to work remotely means I can spend more time with my pet, which I love. I truly think having emotional breathing room at work makes a difference in performance. My guinea pig helps ease the stress and gives me a nice mental reset! Mari Self-introduction I'm a team member of the Development Support Division, Human Resources Group, Talent Acquisition Team. We are recruiting mainly engineers. What is the structure of your team? There are six of us, including myself—and starting in January, we'll all be working from the Muromachi office! What was your first impression of KTC (KINTO Technologies) when you joined? Were there any surprises? The office is lovely! All the engineers are easy to talk to—cheerful, approachable, and just fun to be around. What is the atmosphere like on-site? The atmosphere is joyful and open—everyone's kind, and honest. It's full of people who are not only hardworking but also genuinely considerate of those around them. How did you feel about writing a blog post? I wasn't sure what to write at first, but I ended up going with an honest take on how I’m feeling right now! I also got inspiration from reading everyone's blog posts! Question from woshahua: How do you refresh yourself during work or on your days off? During work, I like to go for short walks to clear my head. On my days off, I try to stay active—going out or hitting the gym whenever I can. C4 ![](/assets/blog/authors/kh/20250123/c4.jpg =250x) Self-introduction I'm am part of KTC, but currently seconded to the KINTO Administration Department, where I mainly handle general office operations. My MBTI type is ISFJ-T, so I think I'm naturally suited for administrative work, though that might just be wishful thinking. What is the structure of your team? There are eight of us working at the Nagoya office, including myself. What was your first impression of KTC (KINTO Technologies) when you joined? Were there any surprises? My first thought was, "Oh, this office is really stylish." It was my first time working in an office, and I imagined it to be more formal, but the atmosphere in the team is relaxed and friendly, and we often go out to eat outside of work, so I think there is a lot of communication. What is the atmosphere like on-site? Not just my team, but everyone around me has been incredibly kind. Even when I ask questions during busy times, no one has ever reacted negatively or made me feel like a bother. We have weekly 1-on-1s and team meetings, which help me stay in the loop about what others are working on—even if I'm not directly involved—and I'm really grateful to have regular chances to talk through any challenges in my own work. How did you feel about writing a blog post? To be honest, I wasn't sure if a story from a non-engineer like me—doing admin and general affairs—would even be useful on a tech blog (laughs). But here I am, giving it a shot. Question from Mari: My MBTI is ESFP! The results were eerily accurate, especially the part about struggling with details. What about you? Was ISFJ-T accurate for you? What parts hit home? Oh, yes. Some parts hit a little too close to home, like "resistant to change," "perfectionist," and "self-critical" (ouch, right? lol). And that mindset of "If it makes someone else happy, I'll put myself second"—yep, that one definitely checks out. So yeah, I'd say the result was pretty spot-on. MBTI is great for self-reflection. I definitely recommend giving it a try!! Mari Self-introduction I'm a UI/UX designer in the Retailer Digital Transformation Planning Team, part of the Mobility Product Development Division's DX Planning Promotion Group. I design products that support the digital transformation of dealership operations. What is the structure of your team? We've got one team lead, three directors, and four designers (including me). What was your first impression of KTC (KINTO Technologies) when you joined? Were there any surprises? Since the parent company is big, I expected a lot of structure—and that's definitely true. But at the same time, the atmosphere is surprisingly free and relaxed. No real surprises after joining. What is the atmosphere like on-site? It's busy and we've got a lot on our plates. But that just makes the work more rewarding. The team's full of energy, and everyone gets along great. Very positive and easygoing environment. How did you feel about writing a blog post? I wasn't sure what to write at first, but ended up just sharing how I genuinely feel! I'm also looking forward to reading everyone else's posts! Question from C4: I heard you have a cat at home! I live with five myself. What's one product your cat absolutely loved? (Snacks, toys—anything!) Five!! Amazing! 🥰 My cat's a bit of a diva—most things get the “how dare you present me this peasant toy” treatment. That said, Churu treats is her one true weakness—especially the premium ones with fancy ingredients. Total game-changer 😂 Also, not sure how she feels about it, but I got a Miruto automatic litter box—makes my life way easier and has been super helpful! Oh, and the cat tower I bought? She's never touched it. After a month of rejection, it sadly became oversized trash… Finally Thanks to everyone who shared their first impressions after joining! There are more and more new members at KINTO Technologies every day! We'll be posting more new-joiner stories from across divisions, so stay tuned! And yes — we're still hiring! KINTO Technologies is looking for new teammates to join us across a variety of departments and roles. For more details, check it out here !
アバター
Hello! I am Wada ( @cognac_n ), a Generative AI Evangelist at KINTO Technologies (KTC), part of the Generative AI Development Project. Trying DeepSeek R1 Using Azure AI Foundry 1. Introduction Recently, large language models (LLMs) have seen significant progress, with numerous companies announcing their own versions. One standout gaining attention is DeepSeek R1 , developed by the Chinese AI company DeepSeek. On January 30, 2025, Microsoft made the DeepSeek R1 model available on Azure AI Foundry and GitHub. In this article, I’ll share a summary of the process I followed to try out DeepSeek R1 using Azure AI Foundry, along with my impressions. 2. What is Azure AI Foundry? Azure AI Foundry is Microsoft's comprehensive platform for AI development . It offers a unified set of tools and services for developers to build, evaluate, and deploy generative AI solutions and custom copilots. Main features Utilizing various AI models: Supports a wide range of cutting-edge and open-source models provided by partner companies, including Microsoft, OpenAI, Hugging Face, Meta, and Mistral. DeepSeek R1 was also provided as part of this initiative. Integrated AI toolchain: An SDK, API, and portal are provided to accelerate the entire development lifecycle, offering a seamless experience from data preprocessing to model inference and continuous monitoring. Responsible AI practices: It has incorporated evaluation features, safety filters, and security controls to provide mechanisms to enhance the reliability and transparency of AI. Scalability for enterprises: It ensures high availability and scalability on Azure's managed infrastructure, supporting enterprise-level monitoring and governance. @ card The Azure AI Foundry portal states that when using models through the model catalog, prompts and outputs are not shared with Microsoft or the model provider. This allows for secure use of a variety of models. Microsoft provides and manages the hosting infrastructure and API endpoints. Models hosted in this "Model as a Service" (MaaS) scenario are subject to Azure data, privacy, and security commitment. Check the details of the Azure compliance certifications applicable to Azure AI Foundry. Microsoft functions as a data processor for prompts and outputs sent and generated by models (MaaS) deployed for pay-as-you-go billing system inference. Microsoft does not share these prompts and outputs with the model provider. Additionally, Microsoft does not use these prompts and outputs to train or improve Microsoft, model provider, or third-party models. @ card 3. Building a DeepSeek R1 Environment on Azure AI Foundry From this point forward, I’ll walk through the steps to actually use DeepSeek R1 on Azure AI Foundry. Please note that the detailed screen transitions and settings are based on the specifications as of January 31, 2025. Since changes to the UI and operations occur frequently, I will quote the official documentation as much as possible. Prerequisite preparations and account settings Preparation of an Azure account Access to Azure AI Foundry @ card Steps for installing DeepSeek R1 Creating a Project: Create a new project on the Azure AI Foundry portal. DeepSeek-R1 is available in the following regions: [eastus2, westus3, northcentralus, eastus, southcentralus, westus]. (As of January 31, 2025) @ card Selecting DeepSeek R1 model: Search for DeepSeek R1 in the "Model Catalog" and transition to the model page. Set deployment name and check the price: Set a deployment name of your choice. Set the content filter to ON/OFF. As of January 31, 2025, DeepSeek-R1 is provided free of charge. The price is expected to change in the future, so be sure to check back regularly for the latest information. DeepSeek R1 is currently available at no cost, though usage is subject to rate limits that may change at any time. Pricing may be updated in the future, and continued use will be subject to the new rates. As the model is in preview, a new deployment may be required to maintain access. 4. Deployment and endpoint creation: An endpoint is automatically generated in the Azure AI Foundry workspace, and a URI and API key for calling the model are issued. 4. A simple demo using DeepSeek R1 Here, I will introduce an example code to try out inference with DeepSeek R1. Install necessary libraries. pip install azure-ai-inference Below is an example code for using the API. Azure AI Foundry also provides code samples, making it very easy to try out. from azure.ai.inference import ChatCompletionsClient from azure.ai.inference.models import SystemMessage, UserMessage from azure.core.credentials import AzureKeyCredential client = ChatCompletionsClient( endpoint="<YOUR_TARGET_URI>", credential=AzureKeyCredential("<YOUR_KEY>"), ) deploy_name = "<YOUR_DEPLOY_NAME>" response = client.complete( messages=[ SystemMessage(content="You are a helpful assistant."), UserMessage( content="Please think about ways to promote the use of generative AI in companies. Answer in Japanese." Switch the legend to Japanese, ), ], max_tokens=2048, model=deploy_name, ) print(response.choices[0].message.content) Example of response <think> The first step is to clearly understand what the problem is. You need to think about how to promote the use of generative AI in the company. Generative AI has a wide range of potential applications, so it's important to first assess and understand your company’s current situation. It's essential to identify which departments could benefit from AI adoption and what potential challenges they may face. For example, marketing, customer support, and business process automation are some potential areas. Next, education and training are important. If employees are not provided with opportunities to learn how to use AI, it will be difficult to actually utilize it. Especially, to alleviate concerns and lack of understanding about AI, it might be a good idea to conduct workshops and training programs. Selecting the right tools is also necessary. It is important to select a generative AI platform or tools that suit your company's needs Depending on the situation, customization may be necessary, and addressing security and data privacy issues is also required. Support from the management is also essential. Without support from management, it will be challenging to secure the necessary budget and resources. Clearly communicating the benefits of AI implementation is essential to gaining management’s understanding and support. Furthermore, making successful cases is effective. If certain departments successfully pilot AI and demonstrate tangible results, it becomes easier to scale adoption across other departments. Sharing the results company-wide and expanding on them can be an effective strategy. It is also important to develop ethical guidelines and policies. Clear rules will need to be established to prevent the misuse of AI and encourage its responsible use. Continuous evaluation and improvement also should not be overlooked. Even after implementing AI, it's crucial to evaluate its effectiveness and make improvements based on feedback to ensure ongoing progress. It seems important to consolidate these points and consider concrete steps to move forward. </think> To promote the utilization of generative AI within a company, it is effective to systematically follow the steps below: --- ### **1. Current situation analysis and goal setting** - **Identifying needs**: Identify the business challenges of each department (planning, sales, development, support, etc.) and clarify the areas where generative AI can provide solutions (document creation, data analysis, customer support, etc.). - **Prioritization**: Prioritize the implementation of use cases with high impact and feasibility (e.g., automatic response to inquiries and automated report generation). --- ### **2. Building a system and changing awareness** - **Launching a promotion team**: Establish a promotion team consisting of representatives from management, the IT department, and each department to collaborate to secure the budget and resources. - **Implementation of educational programs**: - **Basic understanding**: Share the mechanisms, benefits, and ethical risks (e.g., data leakage and bias) of generative AI through training. - **Hands-on training**: Provide hands-on training to promote learning of prompt design and output verification methods. --- ### **3. Tool selection and test operation** - **Choosing the right AI for your company**: - Compare open sources (e.g., Llama 2) and cloud services (ChatGPT Enterprise, Google Vertex AI, etc.). - Select based on security standards (e.g., data encryption and whether the pre-trained model can be customized). - **PoC (Proof of Concept)**: Conduct test operations in a limited scope to verify accuracy and business efficiency improvement. --- ### **4. Establishment of governance** - **Development of usage guidelines**: - Set clear rules to prevent the input of confidential information and implement a system for double-checking output content. - Address legal risks regarding copyright and privacy. - **Monitoring System**: Regularly monitor the output quality and ethical aspects of AI and continuously improve them. --- ### **5. Cultivating a company culture** - **Sharing successful cases**: Boost motivation by sharing success stories from departments that have achieved positive results, through internal presentations or reports. - **Incentive design**: Recognize and reward teams that have improved business efficiency through the use of AI. --- ### **6. Collaboration with external entities and adaptation to evolution** - **Collaboration with vendors and experts:**: Seek support for staying up to date with the latest technological trends and for implementing necessary customizations. - **Continuous AI Updates**: Regularly review AI usage methods in response to advancements in model accuracy and changes in regulations. --- ### **Key points** - **Management commitment**: Demonstrating return on investment (ROI) and securing management support with a long-term perspective is crucial. - **Improvement driven by the field:**: Utilize feedback from employees (i.e., users) to optimize tools and processes. Generative AI is a "tool," and the success or failure of its utilization depends on "how humans use it." In addition to introducing technology, improving digital literacy throughout the organization and ensuring psychological safety are keys. 5. Impressions from actual use Response: It took about 4 minutes for the response this time. It appears that the latency was caused by both the LLM's own inference time and the increased processing time resulting from heavy usage. Output precision: Since it's an inference model designed for "thinking," it provides responses that convey a sense of deep insight, even when handling highly abstract or complex prompts. In API usage, the thinking process is output in a format enclosed by the tag. This is easy to use. Looking at the contents inside the tag reveals a thinking process as if a discussion were taking place among multiple people. Conclusion: Azure AI Foundry provides a convenient way to experiment with the latest models developed by third parties. In the generative AI space, where "trying it out first" is key, this ease of experimentation is extremely valuable. We Are Hiring! KINTO Technologies is looking for passionate individuals to help drive AI adoption in our business. We’re happy to start with a casual interview. If you’re even slightly interested, feel free to reach out via the link below or through X DMs . We look forward to hearing from you! Great place to stay! https://hrmos.co/pages/kinto-technologies/jobs/1955878275904303115 Thank you for reading this far!
アバター
はじめに こんにちは、2025年1月入社の こっしー です! 本記事では、2025年1月入社のみなさまに、入社直後の感想をお伺いし、まとめてみました。 KINTOテクノロジーズ(以下、KTC)に興味のある方、そして、今回参加下さったメンバーへの振り返りとして有益なコンテンツになればいいなと思います! S.H 自己紹介 2025年1月入社のS.Hです。モビリティプロダクト開発部、DX開発GでPjMを担当しています。 これまでは数社のIT会社、制作会社でマーケやPdM、ディレクター、設計開発やPjM等を経験してきました。 所属チームの体制は? 十数名のチームとなり、複数のプロダクトや案件を対応しています。 KTCへ入社したときの第一印象?ギャップはあった? 高い技術力を持ち、社内外の勉強会も多数開催、参加者も多く、大変向上心が高いと感じました。ギャップは第一印象よりさらに想像以上に勉強熱心な方が多いところです。勉強会にオンラインで100名以上集まっているケースもあり圧巻です。 現場の雰囲気はどんな感じ? 気軽に質問したり、相談が出来る雰囲気だと思います。メンターさんだけでなく、困っていたら色々な方がフォローしてくださり働きやすい環境かと思います。 ブログを書くことになってどう思った? 想像もしていなかったので驚きました。 youさん→S.Hさんへの質問 KTCのDX推進に当たって感じる感想を教えていただけますか? グループ会社全体で見ますと、DX推進分野はとてもやれる事が多いと感じています。現場で働く方やその先にいるお客様にとってよい環境やシステムを提供できるよう尽力していきたいと思っております。 呂 文佳(wenjia lu) 自己紹介 プラットフォームのQAを担当しております。 所属チームの体制は? QAが9名、チームメンバーが4名います。 KTCへ入社したときの第一印象?ギャップはあった? 暖かいチームです。 仕事のやりがいがあります。 現場の雰囲気はどんな感じ? みんなコミュニケーションを取り合って仕事を進めている感じです。 ブログを書くことになってどう思った? 何を書けばよいか迷っています。 S.Hさん→呂さんへの質問 KTCで変わってるなーと感じた会社の文化や出来事はありますか? 変わっていると感じたことはありませんよ。 I 自己紹介 2025年1月入社のIです。モビリティプロダクト開発部 DXソリューションGでディレクターを担当しています。これまでは、マーケやPdM、ディレクターを経験してきました。 所属チームの体制は? ディレクターとデザイナーが在籍し、複数のプロダクトを担当しています。 KTCへ入社したときの第一印象?ギャップはあった? 新しい技術もキャッチアップできる環境で、学びが多い環境だと思います。 現場の雰囲気はどんな感じ? 業務のことはもちろん、心理面も気軽に相談できるフォローがあり、働きやすいです。 ブログを書くことになってどう思った? 入社ブログは初めて書くので驚きました。 呂さん→Iさんへの質問 KTCで一番やりたいことを教えていただけますか? ユーザーの課題解決をでき、自社の収益性も高いプロダクトを作れるようになりたいです。 KS 自己紹介 新車サブスク開発G コンテンツ開発TのKSです。 主にKINTO ONE の静的コンテンツのフロントエンドを担当しています。 所属チームの体制は? アシスタントマネージャー1名、リーダー1名、メンバー8名の10名体制です。 KINTO ONEサイトやコーポレートサイトなど複数サイトの開発、保守運用を行っています。 KTCへ入社したときの第一印象?ギャップはあった? 面接時にご説明いただいていましたので、特にキャップはなかったです。 社内でたくさん勉強会が開催されていて、会社全体が技術的モチベーションが高い印象を受けました。 現場の雰囲気はどんな感じ? チーム内はもちろん、他部署のディレクターやデザイナーの方ともコミュニケーションとりやすく、楽しく開発できる環境です。 ブログを書くことになってどう思った? 何度か拝見させていただいたことはありましたが、書く側になるとは思っていませんでした。 Iさん→KSさんへの質問 所属しているチームで一番HOTなプロジェクトはなんですか? KINTO ONEサイトのマイグレーションプロジェクト(Vue.jsからNext.jsへ)です。 自分はデザインシステムやコンポーネントの設計や開発を担当しています。 李 俊起(Joonki Lee) 自己紹介 李俊起(イジュンギ)です。 ”リ”ではなくて”イ”ですので、間違わないでください! プラットフォーム開発部プラットフォームグループで、開発者のための環境構築やツール開発などを行っています。 所属チームの体制は? スクラッチチームとマネージドプラットフォームチームに分かれていて、スクラッチチームは主にスクラッチからツールの開発を行い、マネージドプラットフォームチームはSaaSやManaged Serviceを使って環境構築を行っています。 KTCへ入社したときの第一印象?ギャップはあった? マネージャー層との距離感が近いと思いました。ギャップをそこまでなかったです。 現場の雰囲気はどんな感じ? 普段は静かで各自黙々と自分のタスクをこなしている感じですが、何か議論するときは皆熱くなり盛り上がります。 ブログを書くことになってどう思った? 普段の業務についてもテックブログで公開してみたいと思いました。 KSさん→李さんへの質問 まだ神保町オフィスに行ったことないのですが、オフィスはどんな雰囲気ですかー? 最近のリニューアル工事で開放感があって少しおしゃれになりました。 こっしー ![プロフィール画像 こっしー](/assets/blog/authors/kossy/profile-img.png =250x) 自己紹介 古代(こしろ)です 🙌 プラットフォーム開発部で KINTOサービス やその他のサービス の基盤となるクラウドインフラの構築や保守運用を担当しています! 所属チームの体制は? 部の配下に Platform 、 DBRE 、Cloud Infrastructure 、 QA の4つのグループがあり、サービスの非機能に責務を持つ組織としてさまざまな取り組みをしています。 KTCへ入社したときの第一印象?ギャップはあった? 設立から4年にも関わらず、オンボーディングの仕組みが整っていると感じました。また、運営しているサービスが想像以上に多く、技術的な挑戦も思っていた以上に積極的に行われており、そういった部分が良い意味でギャップとして感じました。 現場の雰囲気はどんな感じ? とても仲が良くて、出社のたびにチームメンバーとご飯に行っています。雑談も多く、なんでも会話できる環境に助けられています。 ブログを書くことになってどう思った? はやくテックブログを書きたいと思っていたので、キッカケ作りにはとても良いなと思いました! 李さん →こっしーさんへの質問 いま一番興味のある技術ワードを教えて下さい! 「プラットフォームデザインパターン」です!Platform Engineeringの文脈において、ユーザーに応じて提供するプラットフォームの特性(Dev Teamに任せる責任範囲の違い)を意識したプラットフォームプロダクトの設計パターンに興味があります! TY 自己紹介 IT/IS部、コーポレートITG所属の山田です。主に従業員マスタ構築や業務効率化・改善に向けたシステム構築に携わってます。 所属チームの体制は? チームはInnovation Drive チームで、メンバーは9名います 自社内だけでなくグループへの支援も行っているのが特徴です。 KTCへ入社したときの第一印象?ギャップはあった? 面接で見聞きした情報とギャップがないよう、オフィス見学もさせていただいたこともあり、ほぼなかったです。 オフィス見学の際には、名古屋にいるマネージャーの方々がわざわざ出張して対面で対応していただけたことも入社の決め手でした。とても嬉しかったです。 現場の雰囲気はどんな感じ? 皆さん建設的な議論ができる方々で、困っていれば手を差し伸べてくれる、とても働きやすい環境だと思います。 ブログを書くことになってどう思った? 期限ギリギリに書き上げている自分を責めつつ、これを見て少しでも興味を持って入社してくれる方がいると嬉しいです! こっしーさん→TYさんへの質問 KTCでチャレンジしてみたい技術やプロジェクトがあれば教えて下さい! 技術的なところだと、データスペースは触ってみたい技術です。あとはプロジェクト化までいかない細かい領域での問題解決が今のところ多いですが、ユーザー(社員)の利便性向上に関してトコトンこだわって取り組んでいきたいです。 瀧川 直樹(Naoki Takigawa) 自己紹介 瀧川です。プラットフォーム開発部スクラッチ開発チームでエンジニアが使うツールの検証や開発をしています。フロントエンド開発をメインで担当しています! 所属チームの体制は? こっしーさんの説明がまとまっていたので、そちらを参考にしてもらえると↓ 部の配下に Platform 、 DBRE 、Cloud Infrastructure 、 QA の4つのグループがあり、サービスの非機能に責務を持つ組織としてさまざまな取り組みをしています。 KTCへ入社したときの第一印象?ギャップはあった? 入社時の面接でできたばかりのチームなので教育体制があまり整っていないかもと聞いていましたが、オンボーディング資料やOJT研修が準備されていて全然そんな事ないやんって思いました。 現場の雰囲気はどんな感じ? なんでも質問しやすい雰囲気です。プラットフォーム開発部のメンバーが東京勤務が多く、月1くらいでお互いの拠点を行き来しています〜。 ブログを書くことになってどう思った? 何こうかな…て思いました。 TYさん→瀧川さんへの質問 今一番興味がある・ハマっている技術領域があれば教えてください! 技術領域はAI…?AIを使った開発の効率化に興味があって、Devin、OpenHands、GithubCopilt✖️MCPなど色んなツールを並行で稼働させて、AI開発部隊を作って開発の効率化を模索しています。レビューが大変…(笑) 喬 禹(Yu Qiao) 自己紹介 喬 a.k.a Alexです!IT/IS部、AIファーストグループで、生成AIエンジニアとして生成AIの事業推進支援やPoCを担当しています! 所属チームの体制は? チームメンバー6名、それぞれ異なる専門スキルを持ち、自身の小分けされた領域で活躍しています。 KTCへ入社したときの第一印象?ギャップはあった? 面接官から感じた風土とほぼ一致していると感じたので、ギャップはありませんでした。瀧川さんの言ったように、教育体制があまり整っていないかもと入社前に聞きましたが思ったより充実で良い意味で裏切られました。 現場の雰囲気はどんな感じ? チャンレンジしたいことを自由にチャレンジできるし、一人で解決できないことがあればいつでも助けを求めることができる環境です。 ブログを書くことになってどう思った? またテックブログを書きたくなってきました! 瀧川さん→Alexさんへの質問 いつも使っている会議の時に付けているヘッドフォンは何というやつですか?おすすめのポイントとかあれば教えて欲しいです! これは前々職でもらったものです。コロナの初期に会社がフルリモートに切り替わったタイミングで、チーム全員にノイズキャンセリング機能が優れたヘッドフォンを購入する必要がありました。その時、上司と一緒にヨドバシカメラに行って選びました。 you ![プロフィール画像 you](/assets/blog/authors/you/tanuki.jpeg =250x) 自己紹介 プラットフォーム開発部・Cloud Infrastructure Gの 劉(you)です!主にAWSを中心に社内のインフラの構築・運用・改善など様々な業務に触り合っています。 所属チームの体制は? Cloud Infrastructure Gは現在、9人体制でマネージャー・各リーダーともフラットに会話して業務をする事ができる環境です。Gの皆さんが意識高く仕事を取り組んでいますので、モチベーションが上がる毎日を過ごしてます。 KTCへ入社したときの第一印象?ギャップはあった? 会社の進化が早すぎると感じました。内部の体制とか業務の進め方とか、私が思った以上に整えていて感心しました。ギャップがあるとしたら、コミュニケーションも取りやすくて技術的なチャレンジが会社全体で起きてる、すごくいい方向でした。 現場の雰囲気はどんな感じ? リスクテイクがすごく忠実していて、業務に関して自由に意見交換ができる素晴らしい環境です! ブログを書くことになってどう思った? 次のテクブログのネタを考えています! Alexさん→youさんへの質問 今後KTCでどんなことに挑戦してみたいですか? KTCの技術と文化を進化して行きたいです。一人で成し遂げられることは本当に少ないと思いますので、私ができることの最大を発揮して影響を与えられるように頑張ります!今は新技術の習得・発信を中心にやりたい所です。 さいごに みなさま、入社後の感想を教えてくださり、ありがとうございました! KINTO テクノロジーズでは日々、新たなメンバーが増えています! 今後もいろんな部署のいろんな方々の入社エントリが増えていきますので、楽しみにしていただけましたら幸いです。 そして、KINTO テクノロジーズでは、まだまださまざまな部署・職種で一緒に働ける仲間を募集しています! 詳しくは こちら からご確認ください!
アバター
Introduction The combination of VSCode and Copilot is an absolute blast. It's so much fun that I almost forget I have a day job. I’m writing this article because I simply have to share how incredibly enjoyable this development experience has been. This article is the entry for day 25 in the KINTO Technologies Advent Calendar 2024 🎅🎄 What I'll Talk About today The AI world has been on fire since last year, and this year was no exception: there's been no shortage of buzz! At KTC, we've been diving headfirst into AI, looking for smart ways to boost our development productivity. In this post, I'll shine a spotlight on what you can actually do when you pair VSCode with Copilot. Now, maybe you're thinking, “AI? Meh. It just spits out vague code and I can write better stuff faster myself.” I get it. That was my take too, until I saw the new Copilot Chat and Edits features unveiled at GitHub Universe. Suddenly, coding with AI started to look… kind of fun? So today, I'll share some tips that have been genuinely useful when teaming up with Copilot Chat/Edits in real-world dev work. https://reg.githubuniverse.com/flow/github/universe24/attendee-portal/page/livestream?tab.day=20241029 Why Flutter? When doing mobile development, it's common to use the standard IDE for each OS, whether it’s iOS or Android. However, since this article focuses on programming with GitHub Copilot, we'll be working under the assumption that development is done using VSCode. With that in mind, Flutter stands out as a major mobile framework that officially supports VSCode. I also got a lot out of attending FlutterKaigi recently, so for this project, I decided to use Flutter for collaborating with AI. I even contributed to the FlutterKaigi app. Just a tiny issue, but still 😀 What can it actually do? Many of the features announced at GitHub Universe are still in preview, so what's available is limited. But even just using the already released Copilot Chat and Edits has made working with AI more enjoyable and clearly improved the developer experience. When you hear “coding with AI,” you might picture building apps without writing any code, or having code generated automatically. And sure, auto-generating code is possible, but that's really just one small part of what AI can do. Also, generating complex, fully functional code with a single prompt? Not exactly easy. Writing the right prompt is half the battle. In this article, we'll share tips for using Copilot Chat/Edits to do everyday coding tasks (like writing test code, formatting and breaking up code, and refactoring) all in collaboration with AI to help improve code quality. Now, here are some tips. Code Summary Copilot Chat makes it easy to generate code summaries. This can speed up code comprehension during onboarding. Add comments BEFORE AFTER If you want to add comments to your code, Copilot Edits can insert them directly into your file. This helps deepen your understanding of the code. Copilot can also update existing comments, making sure they stay accurate. For example, if you add validation to the add method in the class above, you can give an instruction like the one below, and Copilot will update the comment accordingly. BEFORE AFTER Creating Test Code You can add files to reference (besides the current one) above the text input field in Copilot Edits. So, when asking it to write test code, just create a test file, keep it open, and add the target file to the reference list. Copilot will then generate the test code for you. Code Formatting & Splitting When building UIs with declarative languages like Flutter, deeply nested code tends to become a common issue. ::: details Code before formatting class SomethingPage extends StatelessWidget { const SomethingPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Something Page'), ), body: Center( child: Container( padding: const EdgeInsets.all(16.0), color: Colors.blueAccent, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: const EdgeInsets.all(8.0), color: Colors.redAccent, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: const EdgeInsets.all(4.0), color: Colors.greenAccent, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: const EdgeInsets.all(2.0), color: Colors.yellowAccent, child: const Text('Deeply Nested Widget 1'), ), Container( padding: const EdgeInsets.all(2.0), color: Colors.purpleAccent, child: const Text('Deeply Nested Widget 2'), ), ], ), ), ], ), ), ], ), ), ), ); } } ::: Copilot Edits can help with this too. It splits and formats the code into cleaner, more readable chunks. :::details Formatted code class SomethingPage extends StatelessWidget { const SomethingPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Something Page'), ), body: Center( child: Container( padding: const EdgeInsets.all(16.0), color: Colors.blueAccent, child: const NestedContainer(), ), ), ); } } class NestedContainer extends StatelessWidget { const NestedContainer({super.key}); @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: const [ InnerContainer(), ], ); } } class InnerContainer extends StatelessWidget { const InnerContainer({super.key}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(8.0), color: Colors.redAccent, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: const [ DeeplyNestedContainer(), ], ), ); } } class DeeplyNestedContainer extends StatelessWidget { const DeeplyNestedContainer({super.key}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(4.0), color: Colors.greenAccent, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: const [ DeeplyNestedWidget1(), DeeplyNestedWidget2(), ], ), ); } } class DeeplyNestedWidget1 extends StatelessWidget { const DeeplyNestedWidget1({super.key}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(2.0), color: Colors.yellowAccent, child: const Text('Deeply Nested Widget 1'), ); } } class DeeplyNestedWidget2 extends StatelessWidget { const DeeplyNestedWidget2({super.key}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(2.0), color: Colors.purpleAccent, child: const Text('Deeply Nested Widget 2'), ); } } ::: Refactor Even those legacy methods tangled up with complex dependencies, something that you often see in older code, can be refactored using Copilot Edits based on SOLID principles. :::details Classes with methods with complex dependencies class SomethingLogic { Future<void> performComplexOperation() async { // Fetch data from remote server final response = await http.get(Uri.parse('https://example.com/data')); if (response.statusCode != 200) { throw Exception('Failed to load data'); } final data = jsonDecode(response.body); // Save data to local database final database = openDatabase( join(await getDatabasesPath(), 'app_database.db'), onCreate: (db, version) { return db.execute( 'CREATE TABLE data(id INTEGER PRIMARY KEY, value TEXT)', ); }, version: 1, ); final db = await database; await db.insert( 'data', {'id': data['id'], 'value': data['value']}, conflictAlgorithm: ConflictAlgorithm.replace, ); // Save data to shared preferences final prefs = await SharedPreferences.getInstance(); await prefs.setString('data', jsonEncode(data)); // Perform some complex logic if (data['value'] == 'special') { // ...existing code... print('Special value found!'); // ...existing code... } else { // ...existing code... print('Regular value found.'); // ...existing code... } } } :::: :::details Code refactored using SOLID principles class DataFetcher { final http.Client client; DataFetcher(this.client); Future<Map<String, dynamic>> fetchData(String url) async { final response = await client.get(Uri.parse(url)); if (response.statusCode != 200) { throw Exception('Failed to load data'); } return jsonDecode(response.body); } } class DatabaseHelper { Future<Database> getDatabase() async { return openDatabase( join(await getDatabasesPath(), 'app_database.db'), onCreate: (db, version) { return db.execute( 'CREATE TABLE data(id INTEGER PRIMARY KEY, value TEXT)', ); }, version: 1, ); } Future<void> saveData(Database db, Map<String, dynamic> data) async { await db.insert( 'data', {'id': data['id'], 'value': data['value']}, conflictAlgorithm: ConflictAlgorithm.replace, ); } } class SharedPreferencesHelper { Future<void> saveData(Map<String, dynamic> data) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('data', jsonEncode(data)); } } class SomethingLogic { final DataFetcher dataFetcher; final DatabaseHelper databaseHelper; final SharedPreferencesHelper sharedPreferencesHelper; SomethingLogic(this.dataFetcher, this.databaseHelper, this.sharedPreferencesHelper); Future<void> performComplexOperation() async { final data = await dataFetcher.fetchData('https://example.com/data'); final db = await databaseHelper.getDatabase(); await databaseHelper.saveData(db, data); await sharedPreferencesHelper.saveData(data); if (data['value'] == 'special') { // ...existing code... print('Special value found!'); // ...existing code... } else { // ...existing code... print('Regular value found.'); // ...existing code... } } } :::: Doing this level of refactor manually would take quite a bit of time, but with Copilot Edits, you can get it done much faster. The code is now much easier to read, so you can build on that and refactor it further based on your own experience. Others Besides that, the basic Suggestions feature is surprisingly powerful. Normally, when I run into implementation issues, I end up switching back and forth between the browser and the IDE, but now, most problems can be solved just by consulting Copilot. That means fewer distractions and better focus during development. This might seem minor, but it makes a big difference. Tips for Giving Instructions Working with AI has led to a lot of new discoveries, but I've come to realize that giving clear instructions is one of the most important parts. Many engineers I know still find AI hard to use,but once you get used to giving it specific instructions, collaborating with AI can actually be pretty fun. Here are a few instruction tips I've picked up: Keep it simple Be specific Mention which file Say what to do Say how to do it Don't give multiple instructions at once I especially feel that it's important for the person giving instructions to have a solid grasp of programming principles and design concepts. Summary In this post, I introduced some of the things you can do by combining VSCode and Copilot. With Copilot Chat and Edits, tasks like summarizing code, writing comments, generating test code, formatting, splitting, and refactoring become significantly easier; all through a few simple prompts. I hope that at least some of that came across. In the engineering world, opinions on AI are still divided, and many of the engineers around me are still hesitant to embrace it. But it's clear that the world is steadily moving toward AI, and it's only going to keep evolving and expanding what it can do. Feels like we've entered an era where engineers need to seriously think about how we'll use AI going forward. If this article got you even a little curious about collaborating with AI, I'd be glad.
アバター
はじめに はじめまして。KINTOテクノロジーズでAndroidアプリ開発を担当しているYenaです。 キャリアはAndroid開発から始まり、スマートテレビアプリやWebのバックエンド・フロントエンド、APIの開発など、幅広い領域に携わってきました。 現在はAndroid開発に取り組む傍ら、チームと自身の成長を目指して、社内勉強会「Droid Lab」の企画・運営も行っています。 この勉強会で取り上げた技術内容をより広くチーム外にも共有するため、資料をテックブログとして公開する取り組みを進めて行こうと考えましたが、以下のような課題がありました。 資料は主にConfluenceやPPT形式で作成されているため、ブログに投稿するにはMarkdown形式への変換が必要であり、そのまま公開ができず、作業手間がかかることです。 この変換作業の負担が大きく、ブログ執筆に十分な時間を確保することが難しく、情報発信が思うように進まない状況が続いていました。 こうした課題を解決するため、生成AIであるChatGPTの カスタムGPT を活用し、ConfluenceやPPTなどの元資料を自動的にMarkdown形式へ変換できる仕組みを導入しました。 現在は試験運用を進めており、変換作業の負担軽減や情報共有の効率化といった効果が期待されています。 ここでは、私たちが実際に導入したGPTの作成手順と設定内容についてご紹介します。 GPTを作成する方法 1. GPT作成 ログイン後、左上の「Explore」をクリック My GPTカテゴリから「Create GPT」を選択 GPTビルダーでNameとプロフィール画像を設定 DALL·Eで名前に合う画像も自動生成可能(下記のイメージはDALL·Eで作成したNameを考えてAIが作成してくれたイメージです) GPT詳細情報の設定 ① Description(概要説明) このGPTが何をするものかを、1〜2行で簡潔に説明します。 例: Droid Lab資料を元にMarkdown形式の技術ブログを自動作成します。ブログ記事作成用のブランチは以下の形式に従ってください(ブランチ名:sample/YYYY-MM-DD-<テーマ>) ② Instructions(動作したいルール) GPTがどのように振る舞うべきか、どんな出力をするか、制約などを細かく記述します。ここがプロンプトの核になります。 以下は本GPTが従うべき出力ルールです YAMLの下にMarkdown本文を出力(※うちの場合、決まった形式があるのでそれをYAMLで定義) 見出し → ## 見出し リスト → - 項目 インラインコード → コード コードブロック → kotlin など、開閉セットで記述 画像 → ![説明](URL) ⚠️ 文の構成や文体、順番は変更しないこと 出力は必ず Markdown で始まり、 で終わるコードブロックで包むこと 社内API URLや機密名称が含まれる場合は「【非公開情報の可能性あり】」と明記し、修正案を提示すること 出力が長くても途中で止めず、すべてを1回で返すこと ③ Conversation starters(使い始めの例) ユーザーがどう使えばよいかを示す例文を登録します。 例:ConfluenceメモをMarkdown形式の技術ブログに変換してください。 ④ Knowledge(知識ファイル) GPTにアップロードしておく補助資料(スタイルガイド、サンプル記事など)を指定します。 社内ブログスタイルガイド 過去の公開記事サンプルなど ※ 機密情報が含まれないことを確認してアップロード ⑤ Capabilities(機能設定) Web Search Canvas DALL·E Code Interpreter → 必要に応じて機能のオン・オフが可能! GPT詳細情報の設定 全部入力したら、右上の「Create」ボタンをClickしてGPT作成は 完了 です。 2. GPTの設定 ここでは、GPTに対してどのような動作ルールや制約を設定しているかを紹介します。 以下は、社内ブログフォーマットに準拠し、GPTによるMarkdown変換を正しく行うために設定した主な機能です。 機能 説明 ✍️ Markdown形式への変換 貼り付けた文章の文体や構成を変えずに、そのままMarkdown構文へ変換します 📄 YAMLメタ情報の自動付与 自社ブログ形式に合わせて postId、title、excerpt を自動生成します 🧱 構文保持&出力形式の統一 Markdown構文が壊れないよう、すべてを1つのコードブロックで出力します 🔐 セキュリティーCheck機能 社内APIや内部コード名を検出し、「【非公開情報の可能性あり】」としてマーク+修正案を提示します ⚠️ 出力の中断防止ロジック 長文でも途中で止まらず、構文が破損しないようにすべてを1回で出力します ⚠️ 日本語・英語Check 表記ゆれや誤字、不自然な表現を検出し、必要に応じて修正案を提示します 2-1. 🧠 GPTの詳細仕様(プロンプト設定内容) このGPTは、プロの技術ブログライター兼Markdown変換ツールとして機能します。ユーザーがConfluenceや社内メモの文章を貼り付けた際、元の構成・順番・文体を一切変更せずに、以下のフォーマットに従って出力します。 1. YAMLメタ情報の出力ルール ブログ記事として公開するためには、YAMLメタ情報(タイトル、日付、カテゴリなど)を冒頭に定義する必要があります。 このGPTでは、以下のルールに従って、貼り付けた文章から自動的にYAMLヘッダーを生成します。 YAMLは、あらかじめ決められた形式で yaml コードブロック内に出力してください。 「title」や「excerpt」は、本文中から推測・抽出して自動補完してください。 タイトルがない場合は '記事タイトルをここに' のまま出力してください。 記事が非常に長い場合は、 Markdown コードブロックを複数に自動分割し、ユーザーが「続けて」と言わなくても完了まで出力を続けてください。 カテゴリの自動判定ルール 以下のキーワードが含まれる場合、 category を対応するものに自動で置き換えてください: Kotlin, Compose, MVVM, KMP → "Android" GitHub, CI/CD, CodeBuild → "DevOps" Lint, アーキテクチャ, コーディング規約 → "Architecture" Confluence, Markdown, GPT → "Tooling" Firebase, AWS, S3 → "Cloud" 勉強会, 社内共有, ナレッジ → "Team" AI, ChatGPT, Prompt, 自然言語処理 → "Generative AI" 複数に該当する場合は、 最も出現頻度が高いカテゴリを優先 してください。 💡 以下は、社内ブログで使用しているYAMLヘッダー形式の例です(社外環境ではそのまま使用できない場合があります) [例] --- postId: "<自動生成されたID>" title: "<記事タイトル>" excerpt: "<要約文>" coverTitle: "<表紙用の見出し>" coverImage: "<画像パス(社内ブログ用)>" date: "<ISO形式の日付>" category: "<カテゴリ名>" .... --- 2. Markdown本文の出力ルール Markdown変換のルール: 見出し → ## 見出し リスト → - 項目 インラインコード → コード コードブロック → 例: kotlin (※開いたら必ず閉じる) 画像 → ![説明](画像URL) ⚠️ 文の構成、順番、文体は変更しないこと ⚠️ Markdown構文を壊さないよう、すべて閉じタグまで正確に出力すること 3. 出力後の自動チェック機能 すべての出力(YAML + Markdown本文)を1つのコードブロック内( Markdown )にまとめてください 出力の最初は Markdown で開始し、 最後には対応するコードブロック閉じタグで終了 すること 長文であっても、出力が途中で止まることなく、 1回で全文が返されること 3-1. 🔐セキュリティーCheck 以下の内容が含まれていないかを検査してください: 社内APIのURL 内部ライブラリ名 プロジェクトコード名 顧客IDなど機密情報 検出された場合は、「【非公開情報の可能性あり】」とマークし、 公開用の修正案 をあわせて提示します。 検出例(スクリーンショット) 3-2.⚠️ 日本語・英語Check 日本語の誤字、助詞の誤用、不自然な表現、文末の統一性など 英語のスペルミス、文法エラー、不自然な言い回しなど 必要に応じて、「⚠️ 文章チェック:」の見出しの下に 修正案 を出力してください。 ただし、文章の順番・構成・文体は一切変更せず、 指摘のみを行うこと 。 検出例(スクリーンショット) 4. 使用方法のデモ 4-1. 実行ステップ 💬 ステップ1 :変換したいTEXTを入力 💬 ステップ2 :カスタムGPTに貼り付けて送信 💬 ステップ3 :Markdown形式で出力 5. 導入の結果、得られた効果 このGPTを導入したことで、Markdown変換の効率化や情報発信の品質向上など、さまざまな効果が得られました。 ちなみに、 この記事も本GPTを使ってMarkdown形式に自動変換しています。 項目 Before After 効果 Markdown変換作業 30分〜2時間以上 数十秒〜数分 約80%以上の工数削減 フォーマット統一 個人差あり 自動で安定出力 品質と読みやすさ向上 セキュリティ確認 手動確認 自動検出とマーク 安心して公開可能 文章確認 手動確認 自動検出とマーク 安心して公開可能 利用者 Markdown形式になれた方中心 Markdown形式に不慣れなメンバーも利用可 活用範囲が拡大 6. まとめ Droid Labで得た知見をもっと気軽に、広くチーム内外にシェアできるように そんな思いから、Markdown変換の手間を減らすためにこのGPTを導入しました。 生成AIを活用することで、これまで時間がかかっていた変換作業が一気に効率化され、品質やセキュリティの面でも安心して発信できるようになりました。 今後は、PPTの直接アップロードや会議要約機能の追加など、さらに便利にしていく予定です。 開発チーム全体のナレッジ共有が、もっとスムーズになる未来を目指していきます! 🚀 今後の活用拡大 日本語から英語への変換対応機能の追加 グローバル発信や海外メンバーとの共有に対応 PPTアップロード対応 手動でのコピーが不要となり、ファイルをアップロードするだけで変換が可能な仕組みを開発中 会議要約GPTの導入 会議ログや議事録を貼り付けるだけで、自動的にサマリやToDoを抽出できるよう最適化
アバター
Hello, I'm Xu Huang from the KINTO ID Platform team. For the past few years now, we have been providing user authentication and authorization systems (known internally as UserPool) across multiple countries. To support this, we adopted a broker model that connects Userpools across multiple regions, building and operating an architecture that allows them to share authentication and authorization information with each other. Last year, as part of our cost optimization efforts, we redesigned and migrated this architecture. In this post, I’ll walk you through what changed and why. In our initial deployment, we used AWS Aurora Global Database (referred to as Global DB) as part of our global deployment strategy. To minimize access load and latency, we deployed Slave DBs in close proximity to each UserPool and placed Broker servers in the same regions as the corresponding Slave DBs. (Due to Global DB limitations, only one Master DB is allowed, and it supports up to five Slave DBs.) As shown in the diagram above, we gradually rolled out the UserPool service to the regions outlined in blue. To enable centralized user management, we designed the system so that unique IDs would be issued from a central aggregation point and synchronized this information to each region’s sub-DB for local management. Phase 1: Migrating from Global DB to a Normal DB and Removing Write-Only Applications The original architecture prioritized minimizing access load by deploying servers across multiple regions. However, in reality, the system had not yet reached a scale that required such complexity, leading to unnecessary operational costs. To optimize the setup, we conducted a thorough evaluation and concluded that a Global DB setup was not essential for our current usage. We then redesigned the system to allow direct R&W access from the Broker to a shared common DB. The diagram below illustrates the updated architecture: Phase 2: Consolidating the Broker While Phase 1 significantly delivered cost savings, we looked for further optimization opportunities. This led us to consider whether we could consolidate the system into a single Broker instance. However, there was one challenge: as an identity provider, we also offer redirect URLs to external third party services. If those URLs were to change, it would require the third parties to update their configurations as well. So we started thinking about how we might migrate without changing the domain. With support from our infrastructure team, we realized that by updating DNS settings in Route53 and routing traffic through CloudFront to the new unified server, we could avoid changing the domain altogether and transition to a unified Broker. When implementing the design as shown above, we were concerned about the impact on latency caused by the increased physical distance between servers, particularly from the UserPool to the now-centralized Broker. So, we measured it. The results showed that communication between the UserPool and the Broker became about 10% slower, but since the Broker was now located in the same region as the database, DB communication became faster. Overall, there was no significant impact in end-to-end performance before and after the architecture change, so we proceeded with planning for the Phase 2 migration. Results Through these two phases, we optimized the system architecture to better align with the actual usage patterns of our business operations. Going forward, we will continue reviewing system functionality and regularly working on cost-efficiency efforts.
アバター
Introduction Hello! I am Ren.M, working on the front-end development of KINTO ONE (Used Vehicles) . I am pleased to announce that KINTO Technologies Corporation will be a Gold Sponsor at TSKaigi 2025, which will be held on Friday, May 23, and Saturday, May 24, 2025. What is TSKaigi 2025 TSKaigi is Japan's largest technology conference themed around TypeScript. Event Dates: May 23 (Fri) and 24 (Sat), 2025 Venue: Bellesalle Kanda (Chiyoda-ku, Tokyo) Official Website: https://2025.tskaigi.org/ Sponsored LT On the second day, from 11:20 to 11:30, our company's Torii( @yu_torii ) will be holding a sponsored LT! He is scheduled to talk on the theme of Backend Code-First OpenAPI Schema-Driven Development so please look forward to it! Sponsored Booth We have prepared a survey about TypeScript at our booth! Those who complete the survey can try their luck at our capsule toy machine and receive original novelty items as a gift! We Are Hiring! At KINTO Technologies, we are looking for new team members to work with us! We are open to casual interviews to start with. If you are even slightly interested, please apply through the link below! https://hrmos.co/pages/kinto-technologies/jobs/0000127 Conclusion If you are interested, please visit our booth! We look forward to meeting you at the event!
アバター
はじめに こんにちは! KINTO ONE(中古車) のフロントエンド開発をしていますRen.Mです。 この度、KINTOテクノロジーズ株式会社は 2025年5月23日(金)・24(土)にて開催されるTSKaigi 2025ゴールドスポンサーを務めます。 TSKaigi 2025とは TSKaigiは、日本最大級のTypeScriptをテーマとした技術カンファレンスです。 開催日程:2025年5月23日(金)・24日(土) 会場:ベルサール神田(東京都千代田区) 公式サイト: https://2025.tskaigi.org/ スポンサーLT 2日目の11:20〜11:30に弊社の鳥居( @yu_torii )によるスポンサーLTを行います! 「バックエンドのコードファーストなOpenAPIスキーマ駆動開発」 というテーマでトークを予定していますのでお楽しみに! スポンサーブース ブースではTypeScriptにまつわるアンケートを用意しています! 回答いただけた方にはガチャガチャを回していただき、オリジナルノベルティをプレゼントします! We Are Hiring! KINTOテクノロジーズでは一緒に働く仲間を探しています! まずは気軽にカジュアル面談からの対応も可能です。少しでも興味のある方は以下のリンクからご応募ください! https://hrmos.co/pages/kinto-technologies/jobs/0000127 おわりに 興味をお持ちの方はぜひブースまでお越しください! 当日みなさまに会場でお会いできるのを楽しみしています!
アバター
はじめに こんにちは!KINTOテクノロジーズでデザイナーをしているKです。 普段はECサイトのUI/UXデザインをメインで担当していますが、時々コミュニケーションデザインも担当させてもらう機会があります。 2024年11月に開催された社内イベント「超本部会」で、そのイベントの顔となるロゴの制作を担当することになりました!せっかくなので、今回はその制作の裏側やこだわったポイントをゆるっとご紹介したいと思います。 ロゴって何? ロゴって、ただの飾りじゃなくて、そのブランドやイベントの「顔」になるものですよね。 パッと見ただけで「これはあのイベントだな!」「これみたことある!」ってわかるし、見た人にどんな印象を持ってもらうかを大きく左右します。 「なんとなくカッコいいから」という理由だけで作るのではなく、「このイベントってどんな雰囲気?」「どんなメッセージを伝えたい?」「見た人にどんな印象を持ってもらいたい?」を考えながらデザインしていくことが大切だなと、改めて実感しました。 コンセプトを固める:イベントの核を探る まずはイベント全体のアートワークを監修するアートディレクターの方にヒアリング。 イベントの目的や伝えたいメッセージを整理しながら、ロゴに込めるコンセプトを考えていきました。 超本部会イベントコンセプトは「主体性」と「交流」。 仲間と主体的につながる場であること 自分たちが「主体的に行動できる会社だ」と実感できること 仲間とワイワイ楽しむエネルギーが、次の挑戦への活力になること こうした思いを、「自由に楽しめるデザイン」「仲間と盛り上がれるエネルギッシュな雰囲気」で表現したいと考えました。 デザインの方向性を探る 次は、コンセプトをもとに、どんなビジュアルが合うかを探るフェーズ。 「自由に楽しめるデザイン」「仲間と盛り上がれるエネルギッシュな雰囲気」をどう表現するか?を考えたときに浮かんできたのが、「オタク文化×テクノロジー」というテーマでした。 イベントには、開発やクリエイティブに関わるメンバーが多く参加します。そういった参加者たちにとって、アニメやゲーム、メカ、マンガといった“オタク的”なカルチャーは、親しみがあってワクワクする要素のひとつ。そこにテクノロジーの未来感を掛け合わせることで、より自由で、ポジティブな熱量を持った世界観をつくれると考えました。 検討したビジュアル要素はこんな感じ: メカ・ロボット・特撮の要素 :無機質な硬さやメカっぽさを取り入れる 漫画・コミック的な要素 :勢いのある文字や吹き出しのようなシェイプを試す デジタル感のあるタイポグラフィ :少し未来感のある雰囲気に まずは手描きでラフスケッチを描きながら、アイデアをどんどん出していきました。 ラフ案を選定して、データ化へ スケッチから方向性が見えてきたところで、Illustratorを使って本格的にデータ化。 ラフを整理しながら、ベースとなる形を作成 微妙なニュアンスの違いで複数バリエーションを制作 アートディレクターと「どれが一番コンセプトを体現できているか」を検討 もちろんボツ案もたくさん出ましたが、この試行錯誤のプロセスこそが、いいデザインを生むためには欠かせないと改めて感じました。 ディテールの磨き込み ラフが固まったら、仕上げフェーズです。ここでは、細かい部分まで納得がいくように調整を重ねていきました。 そして、 ロゴの印象を決定づける大きな要素のひとつが「フォント」。 例えば、丸みを帯びたフォントは柔らかさや親しみやすさを感じさせ、シャープなフォントは洗練された印象を与えます。ちょっとした違いが、ロゴ全体の雰囲気を大きく左右するんですよね。 今回は既存のフォントに頼らず、オリジナルでフォントを書き起こしました。イベントのキーワードである「主体性」と「交流」をイメージしながら、以下の点を意識して調整: 視認性の向上 :読みやすく、文字の幅や縦横比、余白を整えることで全体にまとまりを持たせる 曲線の調整 :パスの数を減らして、滑らかで整った印象に 漢字とカタカナの調和 :並んだ時に違和感が出ないよう、形状の統一感を意識 赤い基準線と見比べると、最終的な形は大きく変化しました。フォント選びや細部の形の違いが、ロゴの印象を大きく左右することを、改めて体感したプロセスでした。 ロゴの完成:遊び心と汎用性のバランス そしてついにロゴが完成しました! 遊び心を取り入れつつ、いろんな場面で使いやすい汎用性をキープ サブカル×テクノロジーのミックス感が自然に表現できた シェイプやフォントにこだわることで、全体の完成度がUP! まとめ ロゴデザインって、本当にちょっとした差で印象が大きく変わるものなので、「これだ!」と思えるまでやりきることが大事だなと、今回改めて思いました。 今回は「なんとなくカッコいい」だけじゃなく、「このイベントらしさがちゃんと伝わって、いろんな場所で使えるデザイン」に仕上げられたかなと思っています。 この記事が、誰かのデザインのヒントや気づきになればうれしいです!
アバター
久しぶりのブログにどきどき。KINTOテクノロジーズ(以下KTC略)・クリエイティブ室の杉本です。 弊社は会社設立から3年目にあたる2024年、コーポレートサイトをリニューアルしました。設立から3年、今後もいっしょに働く仲間を増やすため、採用活動にフォーカスしたコーポレートサイトにしたいと人事部からリクエストがあり、プロジェクトがはじまりました。 採用にフォーカスしたコーポレートサイトということで、人事部はもちろんですが、会社の進むべき方向性を経営者から、現場の声を拾い上げるために、エンジニアでつくられた技術広報部のメンバーへヒアリングを行いました。 「会社が欲しい人材は、そもそもどんな人だ?」、「我々はどんな仲間といっしょに働きたいのか」など、それぞれの視点から、課題感や希望をヒアリングすると、コーポレートサイトが果たす役割が明確になっていきました。 「常にテクノロジーへの興味を持ち、最新の技術への感度が高く、 自発的に動くエンジニア&クリエイターへ、KTCらしさを伝えるサイトにしていこう」。この目的をもとに、コンセプトを打ち出しました。 コンセプトは「The Power of Technology & Creativity」。トヨタのモビリティサービスをテクノロジーとクリエイティビティでリードしていこうという気持ちを込めたワードにしました。 コンセプトを立てておくのは、ひと手間なのかもしれませんが、制作過程で迷うときに、立ち戻る場所として、様々な職種の人が関わる案件ではとくに重要です。 「そんな機能はいるのだろうか?」「もっと、おもしろく魅せることはできないか?」視点の違う問いにも、このコンセプトがあれば、「だから、やる」「だから、やらない」の判断がしやすくなるからです。 パーソナリティの設定 次にクリエイティブ室として手がけたのは、会社を人として例えたら、どんな人で、どんなふるまいをするのかを明確にする「ブランドパーソナリティ」を設定。(※ブランドパーソナリティについては 後述 ) 「ブランドパーソナリティ」は、何もないところからはじめると、全社を巻き込むレベルの開発になるので時間とカロリーを使うのですが、コーポレートサイトのローンチは、採用が目的なだけにスピードが重要。そこで、弊社ですでに明文化していた「ビジョン」、「バリュー」、「カルチャー」、「働く姿勢」をもとに進めました。 導き出したKTCのパーソナリティは、ずばり「クリエイター」。創造者という役割で、私たちは「テクノロジーやクリエイティブの力でお客様にとって、最高の(使いやすく、分かりやすく、人に寄り添って、便利な)プロダクトを作る存在である」と、定義しました。 盛り上がるムードボードづくり ブランドパーソナリティが決まったので、次は具体的にコーポレートサイトの表現デザインをどう落としていくかになります。そこで、もうひと手間!担当デザイナーが手を動かす前に、クリエイティブ室全員で、ムードボードをつくりました。 この作業をすることで、コンセプト同様、ビジュアル面でも立ち戻る場があるので、迷走することがなくなるので、アウトプットまでがスムーズになります。 自分たちが思うKTCらしいビジュアルなどを持ち寄り、デザイナーどうし、ムードボードづくりはとても盛り上がりました。 ムードボードをつくることで、新たな発見もありました。それまでは、いわゆるカリフォルニアのキラキラしたテックカンパニーの勢いで制作したアウトプットになるかなと想定していたのですが、会社の存在を「我々は〜である」という視点で取り組むと、トヨタグループの現場主義を根底に据えた、日本のモノづくりのスピリットを尊重したプロフェッショナルエンジニアリング集団である(ありたい)という点が見えてきました。 ムードボードは、世界基準のモダンなシステムと、ブランドパーソナリティをベースとし、使いやすさと企業ブランドのうえに、表現を載せたアウトプットを目指しました。 クリエイティブのジャンプアップと効率化が実現 「パーソナリティ」「ムード」「サイトの目的」をクリアにしたことで、撮影のトーン、インタビュー内容、コピー、実装、すべてが一貫したつながりでつくれたので、結果的にクリエイティブのジャンプアップと効率化が叶うなと改めて思いました。デザイナー以外の関係者と話すときも、ロジカルに説明ができ、デザインの言語化までが叶いました。 おかげさまで海外アワードを受賞 こうして、リニューアルができたコーポレートサイトですが、おかげさまで国際的なWebデザインアワードである「CSS Design Awards」をはじめとする、複数の海外Webデザインアワードを受賞することができました。 みなさんもご覧になって、もしよければ、私たちに興味をもっていただければと思います! コーポレートサイトはこちら! https://www.kinto-technologies.com/ ※ブランドパーソナリティとは ブランド=企業を人間に例えるとどんな要素、性格で構成されているかを示したものです(アーキタイプ)。一般的に「人柄」を12の属性に分けたフレームワークを活用し、企業の性格、思考、行動、振る舞い、持ち味などを探求していきます。これを持っていると、統一されたブランドイメージを常に発信することができるので、to Cでなくても、今回のようなコーポレートサイト制作やイベントで配るグッズまで、ターゲットとなる人に同じ印象でアピールすることができます。
アバター
Introduction Hello, this is Matsuo from the Cloud Infrastructure Group. Our team is responsible for taking care of a wide range of infrastructure-related tasks across the company, from design to operations. This time, I would like to introduce the AWS Transfer Family web apps , which were announced at re:Invent. https://aws.amazon.com/jp/about-aws/whats-new/2024/12/aws-transfer-family-web-apps/ In this article, I will give an overview of the web apps, the steps to create them, how to set them up, and share my impressions after trying them out. I hope you will find this helpful. Overview To put it simply AWS Transfer Family web apps let you build applications to manage files in S3 buckets directly from a browser without writing any code. Previously, accessing S3 through a GUI required dedicated tools like the AWS Console or WinSCP, both of which also needed configuration. This created challenges for non-technical and casual users as it made operation difficult. The new AWS Transfer Family web apps feature an intuitive interface that is easy to use, even without technical knowledge. Additionally, they are integrated with IAM Identity Center and S3 Access Grants, enabling fine-grained access controls. Pricing AWS Transfer Family web apps are billed hourly based on the number of units (each support up to 250 sessions for 5 minutes per session). Region Price Tokyo Number of units x 0.5 USD/hour For example, running one unit 24 hours a day will cost 12 USD/day , meaning it will cost 360 USD a month; so using it for long periods of time can be quite costly. That's a little pricey for such a simple service. Depending on the usage, the cost may outweigh the benefit, so it is important to use the service according to your needs. How to Create a Web App Now let's create a web app. (Note: Terraform is not supported at the time of writing this article, so I will use the AWS Management Console.) Log in to the AWS Management Console, select "Web Apps" from the AWS Transfer Family navigation pane, and click Create Web App. For now, just set the Name tag and click "Next." * IAM Identity Center configuration is required in advance . If you haven’t set it up yet, please make sure to prepare it in advance. Set the page title, logo, and favicon, then click "Create." This time, I will skip the logo and favicon.. This completes the creation of the web app! It's that easy! Configuring Users/Groups and S3 Access Grants Next, let's set up group assignments and S3 Access Grants for the web app. Group assignment Click "User and group assignment" on the web app details screen. Since I have already created groups, I will select an existing group to assign. Setting up S3 access grants Next is setting up Access Grants. There are two things to set: Location and Permissions. If you go to Access Grants from the S3 navigation pane, you will see the Permissions and Location tabs, from which you can use to configure access. Start by setting the Location. This defines the S3 bucket to be accessed, along with the IAM role that has the necessary permissions for that bucket. For testing purposes, I have granted the AWS managed policy "AmazonS3FullAccess" this time. Then move to Permissions. Specify the location you configured previously, then set the sub-prefix, permission level, grantee type, IAM principal type, and the IAM principal user, and create the permission. Authentication will be done through IAM Identity Center, and it is set up as shown in the image below. Although I have not set it this time, it seems possible to set app-specific access restrictions. Setting CORS Add CORS settings from Cross-Origin Resource Sharing (CORS) to the target S3 bucket so that you can view the contents of the bucket. Here’s the configuration I used: [ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "GET", "PUT", "POST", "DELETE", "HEAD" ], "AllowedOrigins": [ "https://${ウェブアプリID}.transfer-webapp.ap-northeast-1.on.aws" ], "ExposeHeaders": [ "Access-Control-Allow-Origin" ] } ] Try It Out If you made it this far, you're ready to go. After accessing the web app URL and completing authentication, the S3 management screen appears! You will see the S3 bucket you configured in Location settingss. Now let's actually try deleting an S3 file from the target bucket. I tried to access an object from a folder link, but... It didn't work. Turns out the IAM role used for Access Grants was missing the sts:SetContext permission. This is also mentioned in the User Guide as well. I added the settings and tried again, and was able to access the object successfully. By the way, if CORS is not configured properly, a Network Error will appear here. Now, let's select the object here and delete it. Simply select the file you want to delete (in this case, test1.txt) click the ellipsis, and choose Delete. The file has been deleted from the web app. I also confirmed that it was removed from the console. Impressions Although setting up IAM Identity Center and Access Grants was required, I was impressed by how easy it was to be able to build an S3 management app without writing any code. There were a few confusing aspects due to the numerous configuration settings, but I believe that support for Infrastructure as Code (IaC) will likely make it even more user-friendly in the future. This service is built on top of the Storage Browser for Amazon S3 , which was also announced at re:Invent, so if you are comfortable with programming, you can use that service to create your own customizations. https://aws.amazon.com/jp/about-aws/whats-new/2024/12/storage-browser-amazon-s3/ I hope this blog post was helpful to you.
アバター
自己紹介 2025年3月からKTCに入社したtetsuと申します。 前職ではインフラエンジニア(オンプレ・クラウド)をしており、KTCではPlatformエンジニアとしてジョインしました。 旅行と自然が好きで大きな休みのたびにどこか遠出にしています。 概要 本記事では、Github Actionsのワークフローにて、Docker Hubからパブリックコンテナイメージ(JDK, GO, nginxなど)をPullしていた設定を、ECR Public GalleryからPullするように移行する手順や設定を紹介します。 2025年4月1日から、未認証ユーザによるDocker HubのパブリックコンテナイメージPullに対して制限が厳しくなるという話でした。 具体的には、認証されていないユーザによるPullは、ソースIPアドレスあたり10回のPull/時間に制限されることになります。 詳しくは こちら 。 Github Actionsのワークフローを実行する仮想マシンは全ユーザが共有されるため、Docker HubからみたソースIPアドレスも限られたものになります。よって上記の制限により、Github Actionsを使ってコンテナのBuildを行うにあたりネックとなるため、対応策を練る必要がありました。 前提構成 弊社では以下のような構成でGithub Actionsを利用し、コンテナのBuildを自動化していました(ざっくり抽象化した構成になります)。 対応策の検討 Pull制限問題への対応策をいくつか検討しました。 Personal Access Token(PAT)を使用してDocker HubにログインしたうえでPull 「そもそもDocker Hubに認証すればいいじゃん」という声が聞こえてきます。 Docker HubのPATを発行して、Github ActionsのワークフローでそのTokenを利用してdocker loginすることで認証できます。 それによりPull制限を回避することができます。 ただし、PATは個人に紐づきます。 弊社ではGithub Actionsをチームで共用して使用するため、個人にTokenが紐づいてしまうと、ライセンス管理の面で好ましくないと考えています。 Organization Access Token(OAT)を使用してDocker HubにログインしたうえでPull 上記の方法と同じになるのですが、異なる点はOATという組織に紐づいた共有Tokenで認証するという点になります。 この共有Tokenを利用するには、Docker DesktopのライセンスをTeamもしくはBusinessにする必要があります。 Github Container Registry(GHCR)へ移行 Githubが提供するGithub Container Registry(GHCR)からコンテナイメージをPullする方法です。 Github Actionsのワークフローで{{ secrets.GITHUB_TOKEN }}を使用して認証することで、コンテナイメージをPullすることができます。 ただし、コンテナイメージの検索をするのが少し癖があり、検索しづらいです(Docker Hubで提供されているバージョンと比較するのが難しい印象です)。 ECR Public Galleryへ移行 AWSが提供するECR Public GalleryからコンテナイメージをPullする方法です。 ECR Public GalleryにIAMを利用して認証するか、認証しないかで制限が異なりますが、基本的には無料で使うことができます。 ECR Public Galleryに未認証ユーザはソースIPアドレスあたり以下のような制限になります。 1回/秒のPull 500GB/月のPull 一方で認証ユーザについてはアカウント単位で以下のような制限になります。 10回/秒のPull 5TB/月を超える転送については0.09USD/GB(5TBまでは無料) 以下ドキュメントにて詳細な上限が記載されています。 https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/public/public-service-quotas.html https://aws.amazon.com/jp/ecr/pricing/ AWS アカウントを利用していない場合、パブリックリポジトリから転送されるデータはソース IP によって制限されます。 ECR Public GalleryにはDocker公式のコンテナイメージがあり、それがDocker Hubのコンテナイメージと対応しています。 そのため運用上利用しやすく、容易に移行がしやすいです。 案比較 上記の案をまとめてQCD評価しました。 比較表は以下の通りです。 案 Quality Cost Delivery PATを使用してDocker Hubにログイン × - 個人トークンに依存する状態のため組織としては好ましくない - 利便性については現状と変わりなし 〇 追加費用なし 〇 対応が工数が少ないためすぐ実装可能 OATを使用してDocker Hubにログイン 〇 現状から変わりなし × 利用ユーザに応じてライセンス費用が増える × ライセンス変更にリードタイムがかかる GHCRへ移行 △ Docker Hubで利用しているイメージとの対応が検索しづらい 〇 追加費用なし 〇 対応が工数少ないためすぐ実装可能 ECR Public Galleryへ移行 〇 Docker Hubで利用しているイメージとの対応が検索がしやすい 〇 追加費用なし 〇 対応工数が少ないためすぐ実装可能 PATとOATを利用する案は現状から利便性が変わらない点は優位である GHCRはGithubの{{ secrets.GITHUB_TOKEN }} を利用することで容易に実装ができるが、ECR Public Galleryと比べてコンテナイメージの検索がしづらい ECR Public GalleryはIAMポリシーで設定変更が必要であるが、軽微な修正であるので対応工数はそこまで増えない 上記を踏まえて、弊社では、対応工数が少なく、追加費用がかからない、かつ利便性の高い「ECR Public Galleryへ移行」案を採用することにしました。 ※ 各個人・各社によって環境は変わるので、必ずしもこの選択がよいとは限りません。 ECR Public Galleryへ移行するための設定 コンテナイメージの取得元修正、Github Actionsのワークフローを定義するYAMLファイル、AWSでの設定が必要になるためそれらを設定します。 構成図 コンテナイメージの取得元修正 コンテナイメージの検索 Dockerfileやdocker-compose.ymlなどでどこからコンテナイメージをPullするかを指定しているかと思います。今回はDockerfileでJDKのコンテナイメージの取得元をDocker HubからECR Public Galleryに移行するケースで説明します。 以下のようにDockerfileのFROM句があるとします。 FROM eclipse-temurin:17.0.12_7-jdk-alpine ECR Public Galleryにこのイメージが存在するかを こちら で検索します。 今回だと:の前のDocker Hubの公式コンテナイメージ(今回は eclipse-temurin )を検索して、by Dockerになっているものを選択します。 「image tags」を選択して、イメージ一覧を表示します。 Docker Hubの公式コンテナイメージのタグ(今回は 17.0.12_7-jdk-alpine )をimage tagsの検索欄に入力し、対象イメージを検索します。そして、「Image URI」をコピーします。 コンテナイメージの取得元修正 FROM句に修正後のコンテナイメージのURIをペーストします。 今回だと、以下のように修正になります(当初のURIと比べてpublic.ecr.aws/docker/library/が追加されています)。 FROM public.ecr.aws/docker/library/eclipse-temurin:17.0.12_7-jdk-alpine これでECR Public GalleryからコンテナイメージをPullするように設定ができました。 AWSの設定 ECR Public Galleryに認証してログインした状態でPullできるようにするため、IAMロールとIAMポリシーを作成します。 IAMロール Github公式ドキュメントで手順の案内があるので、こちらを参考にしてください。 https://docs.github.com/ja/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services IDプロバイダの構築 -> IAMロールの構築の順に対応となります。 IAMポリシー ECR Public GalleryからPullするためのアクションを許可するIAMポリシーを作成します。 以下ドキュメントを参考にしています。 https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/public/docker-pull-ecr-image.html { "Version": "2012-10-17", "Statement": [ { "Sid": "GetAuthorizationToken", "Effect": "Allow", "Action": [ "ecr-public:GetAuthorizationToken", "sts:GetServiceBearerToken" ], "Resource": "*" } ] } このIAMポリシーを上記で作成したIAMロールにアタッチをします。 Github ActionsにECR Public Galleryへのログイン処理の追加 ECR Public Galleryに認証した状態でログインするよう、Github Actionsのワークフローを定義するYAMLファイルでログイン処理を追加します。 弊社の環境ですと、Docker Buildのステップの前に以下の記載を追加します。 ## ECR Public Galleryへログイン - name: Login to ECR Public Gallery id: login-ecr-public run: | aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws ※ ECR Public Galleryがus-east-1リージョンに存在するため、 --region us-east-1 で明示的に指定します。 さいごに Github Actionsのワークフローにて、Docker Hubからパブリックコンテナイメージ(JDK, GO, nginxなど)をPullしていた設定を、ECR Public GalleryからPullするように移行する手順や設定を紹介しました。 この記事が皆様の開発や業務に役立てば幸いです!
アバター
This article is the entry for day 19 in the [KINTO Technologies Advent Calendar 2024](https://qiita.com/advent-calendar/2024/kinto-technologies)🎅🎄 1. Tech Blog Debut Hello! I'm Shiori ( @shor_t8q ) from the Generative AI Development Project. I am currently in charge of training, use case development, and technical support for generative AI! (Though I chose Web3 as the topic for my first Tech Blog post.) This blog is about how we used NFTs at a team activity during the CHO All-Hands Meeting (an in-person meeting event that brought together all employees across all offices) held on November 28, 2024. This is the perfect content for anyone interested in the in-house planning and deployment of large-scale company events, incorporating NFTs into internal activities, or learning more about the company culture at KINTO Technologies. Premise The NFT initiative introduced in this blog was made possible through the cooperation and dedication of all the organizers of the CHO All-Hands Meeting, the activities team, the novelty team, and the Creative Office. Furthermore, this blog is not sponsored by any of the companies providing the NFT services discussed here. The purpose of this blog is solely to share the experiences, creativity, insights, and lessons learned by those in charge of the activities and novelties. 2. About the CHO All-Hands Meeting ![01_chohonbukai](/assets/blog/authors/shiori/2024-12-19/01_chohonbukai.png =750x) 2-1. What is a CHO All-Hands Meeting? A CHO All-Hands Meeting is a company-wide event held by KINTO Technologies approximately once or twice a year. The CHO All-Hands Meeting covered in this blog was held on November 28, 2024, with approximately 300 attendees in person and around 50 attendees online. The meeting took place from 3:00 PM to 9:00 PM and was a highly exciting event with a wide variety of content. 2-2. Being Part of Organizing the activities and novelties About a month and a half before the CHO All-Hands Meeting, members from various departments came together to form the organizing team. I was assigned to be part of the team in charge of activities and novelties. ![02_novelty](/assets/blog/authors/shiori/2024-12-19/02_novelty.png =750x) To promote communication across the company, we decided to create desk nameplates as novelty items. The design was handled by J-san from the Creative Office. 2-3. Concept of the CHO All-Hands Meeting The event's concept was "KTC is Made by You”, which was shaped by gathering input from executives, department heads, and managers about their thoughts on teamwork, company culture, and their vision for the future. ![03_concept](/assets/blog/authors/shiori/2024-12-19/03_concept.png =750x) 3. Activities at the CHO All-Hands Meeting 3-1. What is a team activity? It was the final section of the event, held at the end of the meeting from 7:00 p.m. to 9:00 p.m. Based on the concept of the CHO All-Hands Meeting, the activities team set the following two goals: To promote communication among participants and between members of different departments. To deliver an experience that leaves participants feeling grateful they joined. 3-2. What led to the use of NFTs in the team activity? The activity featured an NFT stamp rally, but why choose that format? I was originally in charge of novelties, but the idea started when I wondered, "What if the novelty items were NFTs?" and "Could this serve as inspiration for future NFT and Web3 projects?" I was also motivated by the desire to try something new and different. With that in mind, I began exploring ways to incorporate NFTs that aligned with the theme of the CHO All-Hands Meeting. Through online research, I discovered the concept of an "NFT stamp rally." Around the same time, members of the organizing team shared that a digital stamp rally had been used at the previous CHO All-Hands Meeting. That inspired us to take it a step further and evolve the concept into an NFT stamp rally. From that point on, I joined the team activity planning discussions, and we began exploring how to bring the NFT stamp rally to life. ![04_nft_idea](/assets/blog/authors/shiori/2024-12-19/04_nft_idea.png =400x) 4. What Is an NFT? 4-1. NFTs Are Unique Digital Assets NFT stands for "Non-Fungible Token." NFTs are one-of-a-kind digital assets that cannot be exchanged for other tokens due to their uniqueness and characteristics. In addition, NFTs use blockchain technology to ensure transparency in transactions. For example, Bitcoin is a fungible token, meaning one Bitcoin holds the same value as another, whereas NFTs are non-fungible because each NFT holds its own unique value. ![05_nft](/assets/blog/authors/shiori/2024-12-19/05_nft.png =400x) Because of their non-fungible nature, NFTs have become a new tool to enhance fan engagement in art, games, music, movies, sports, entertainment, and corporate marketing activities, and their application in other industries is expanding as well. While NFTs provide a means of monetization for creators and a new marketing tool for companies, improving the transparency and traceability of transactions, they also come with challenges such as the environmental impact from the large amount of electricity it requires during mining, legal risks, and price volatility due to market fluctuations. 5. NFT Stamp Rally 5-1. Is it feasible to hold an NFT stamp rally at the team activity? Conducting a survey To explore whether it was feasible to distribute and exchange NFTs as part of the team activity, we began by conducting some research. Through this process, we came across a company called Sushi Top Marketing which has an extensive track record with NFT use cases including organizing NFT stamp rallies. They are also promoting a new concept called “Token Graph Marketing.” What is Token Graph Marketing? Token Graph Marketing is a new marketing approach that uses blockchain technology to reach users while protecting their privacy. Users' hobbies, preferences, and behavioral history can be analyzed based on their NFTs and other token information. ![06_token_graph_marketing](/assets/blog/authors/shiori/2024-12-19/06_token_graph_marketing.png =750x) Source: What is Token Graph Marketing? Initial Ideas I had several discussions with the vendor based on the following initial ideas: Content Description Novelty Concept Activating communication among members who rarely interact with each other, stimulate communication and promote innovation, fostering a sense of unity, and provide novelties that appeal across age and gender. The solution should not deviate from this core concept. Accessibility Since the stamp rally would be held on a single day, it needed to be intuitive and easy to use Must be supported for both app and via QR code scanning. Value as a Novelty Showcase NFTs as a new type of novelty item, something participants can transfer to their own wallet and keep as a digital asset. Innovation Reflect the company’s emphasis on creativity and technology by trying something that hasn’t been done before. Brand Alignment Customize the UI to reflect the company’s brand identity, including its colors and character. Concept Visualization For example: “Each department has a different NFT stamp. When Employee A speaks with Employee B from another department, A receives a stamp from B’s department.” This encourages interdepartmental interaction. 5-2. Blockchain Technology Behind the NFT Stamp Rally For the NFT stamp rally, we chose to use Astar, a next-generation blockchain platform known for its compatibility with smart contract and dApps (decentralized apps). Astar is part of the Polkadot ecosystem, enabling interoperability between different blockchains. ![07_astar](/assets/blog/authors/shiori/2024-12-19/07_astar.png =750x) 5-3. NFT Stamp Rally Concept Idea brainstorming We received four initial proposals for the NFT stamp rally: Proposal Description NFT Card Exchange Participants collect NFTs by exchanging digital cards. Additional NFTs can be unlocked upon exchange. Dynamic NFT Stamp Rally Collecting specific NFT pairs unlocks special NFTs. Different combinations yield different results. NFT Distribution via LINE Commemorative NFTs are distributed through an official LINE account. Those who hold them receive a gift. NFT Business Cards & Stamp Rally NFC or QR-enabled cards are handed out before the event. These cards serve as novelties and as tools for collecting NFTs during the rally. We discussed and refined the proposals based on the following criteria: Criteria Criteria Description Workload Can everything be prepared in about one month? Usability Is it intuitive, with little to no manuals or explanations? Operability Can it run smoothly, in a relaxed atmosphere in an event with 300 participants? Simplicity Can it be used without complex operations or steps? Accessibility Can it be accessed without restrictions, needing third-party services? Innovation Does it offer an interesting NFT experience? Security Does it ensure data privacy and protection? Scalability Can it handle simultaneous access from a large number of users? Compatibility Is it mobile-friendly and Web3-compatible? Budget Alignment Is it achievable within the budget? Combining the ideas and our requirements, we finalized the following plan: 5-4. NFT Stamp Rally Planning Details Overview of the NFT stamp rally We issued 14 NFTs, covering each department, management team, and a completion certificate. Participants would visit different zones during the activity (such as spots where the management and award recipients are present), collect NFTs that are different from the ones they already hold, and engage in communication with members from other departments or the management team, whom they don't often have the chance to interact with. This promotes the start of new projects and fosters relationship-building. A gamified element was added, in which participants who collected all 13 NFTs could earn a final “completion” NFT, which was redeemable for a prize. NFT Collection Points Each participant’s name tags (distributed at check-in) would contain an NFC tag -explained later- and a QR code, allowing participants to collect NFTs through either NFC tapping or QR scanning. Providing both options ensured accessibility for participants who couldn’t use NFC. NFT Stamp Rally Flow Participants visit each zone. Interact with members from other departments and management. Post what they discussed in the chat linked to the department's NFT (sharing the conversations in the NFT-linked chat adds unique value to each department's NFT). Exchange NFTs with the members they interacted with and collect 13 NFTs. Earn the completion NFT. Post their Slack name in the completion NFT chat. The event staff later award prizes via Slack. NFT Design Since this was a company-wide event, we incorporated KINTO's brand character, Kumobii , into the NFT designs to strengthen the sense of unity and identity. ![nft_collections](/assets/blog/authors/shiori/2024-12-19/08_nft_collections.png =750x) The NFT artwork was created by Momoi-san from the Creative Office. NTF Innovations We added original value to NFTs by: Each department having its own unique design. NFT names were written in both Japanese and English to accommodate global members. A unique collection name and event date attribute were added to each NFT. All NFTs included the keyword "KTC is Made by You," the theme of the CHO All-Hands Meeting. When combined, the NFTs formed the full theme of the activity. 6. Challenges in Realizing an NFT Stamp Rally 6-1. How Should NFTs Be Exchanged? What channel should be used? What technology should be adopted? Using NFT x NFC tags As an element of this get-together, we placed importance on adding small surprises and discoveries, such as "Oh, I didn't know that was possible!". By combining ideas from service providers and the organizing team members, we made it possible to receive an NFT simply by tapping a smartphone on an NFC chip embedded in a name tag. *NFC (Near Field Communication) is a technology and standard that enables wireless communication between devices in close proximity. . It's used in a wide range of applications, including smartphones, IC transit cards, credit cards, and smart appliances. How to write NFT information ito NFC tags? NFC tag: www.amazon.co.jp/dp/B0DFW9WTRW NFC writing app: https://apps.apple.com/jp/app/nfc-tools/id1252962749 We procured NFC tags from Amazon manually wrote NFT URLs for 13 types and approximately 300 people. To cover potential failures, we also prepared NFT QR codes for all participants. This process was carried out manually (the organizers, thyt-san and Oka-san, did the writing.) The completed tags were inserted into name holders. ![09_nfctag](/assets/blog/authors/shiori/2024-12-19/09_nfctag.png =400x) 6-2. How were the rules communicated to all participants? During the host's introduction before the start of the NFT stamp rally, the “NFT Stamp Rally Guide” was projected on screen, while the host and I worked together to make sure everyone was aware of the rules of the NFT stamp rally. ![10_guide](/assets/blog/authors/shiori/2024-12-19/10_guide.png =750x) 6-3. Since NFT exchange is done on a browser-based web app, how can participants avoid losing track of the NFTs they have acquired? I worked with the event MCs to provide the following information through the projected materials: The web app runs in a browser. Don’t use incognito mode. After acquiring your first NFT, add a NFT list shortcut to your home screen. Take a screenshot of your NFT backup code displayed during the NFT exchange. 6-4. How to issue completion NFTs Participants who collected all NFTs could show their NFT list to staff to receive a special completion NFT. ![11_nft_list](/assets/blog/authors/shiori/2024-12-19/11_nft_list.png =400x) 7. Lessons Learned 7-1. NFT exchange became the only activity everyone had time for Although we got to meet many team members we don't usually talk to, it was difficult to even find time to eat. It was difficult to share conversations with members in the chats linked to NFTs as originally envisioned, and achieving the goal of "accumulating the insights and ideas of department members in each department's NFTs and turning them into unique value for each department's NFT" proved challenging. In addition, the original plan envisioning people exchanging NFTs across zones (spots where management, honored members, awarded members, would stay) didn’t pan out either. At an activity that encourages free communication, there was no need to set up zones. 7-2. We should have supported NFT type-checking Participants commented that, since it was possible to obtain multiple NFTs from any member of the same Department A, participants often ended up with similar designs, such as multiple NFTs from Department A. This made it difficult to check which types of NFTs were still missing. This should have been considered in advance and addressed. 7-3. The completion process should've been simpler. As mentioned in 5-4, things didn’t go as smoothly as expected. Asking participants to post a screenshot of their completed NFT list in Slack could have helped. It would have made it easier for staff to confirm completions. Also, by reporting completion in an open space such as a Slack channel, "My colleague, so and so, has completed it!" would have motivated others and encourage more participation. 7-4. More flexibikity in choosing channels for NFT touchpoints. We manually wrote NFT URLs for 300 people onto the NFC tags. However, considering the potential for human error and the amount of workload involved, it may be better to explore other touchpoints and channels for larger events. 7-5. Provide more proactive English support About 25% of KINTO Technologies' employees are international. Although presentation slides were prepared in both Japanese and English, but when speaking with several international members at the activities, we found ourselves giving additional explanations in English during the event. Things would have gone even more smoothly if we had shared the presentation materials on the Slack channel beforehand and provided explanations in English at the start of the stamp rally. 8. NFT Stamp Rally Results 8-1. 10% of Participants Completed the Rally!!! Out of approximately 300 participants, 30 people, or 10% of the participants completed the NFT stamp rally . ![12_nft_complete](/assets/blog/authors/shiori/2024-12-19/12_nft_complete.png =400x) 8-2. Overall results A total of 1,734 NFTs were distributed. On average, participants exchanged 6.6 NFTs per person , with a median of 6 . That means each participant talked to members from around 6 different departments . One of the goals was to interact with members from other departments at the team activity, so it can be said that the NFT stamp rally fulfilled that goal. Metric Result Completed participants 30 Total NFTs issued 1734 Average NFTs exchanged 6.6 Median NFTs exchanged 6 9. Future Posibilities for NFTs We learned that NFT stamp rallies can visualize movement and engagement at in-person networking events. Interestingly, it allowed us to see how many NFTs each department issued, which enabled us to identify which departments were most active in communicating with other departments. This experience expanded our vision on how NFTs could be used both online and offline in KINTO Technologies' KINTO product offerings, such as MaaS-related apps and member services. For instance, I thought that NFTs could be effective for approaching customers based on their hobbies and preferences, rather than traditional attributes such as age and gender, and for visualizing customer communication and behavior. ![13_products.jpeg](/assets/blog/authors/shiori/2024-12-19/13_products.png =750x) 10. Conclusion Through the NFT stamp rally initiative, we realized the potential that can arise from the fusion of new technologies and ideas. It was a valuable experience to create an opportunity for members from different departments to interact and engage with technology in a fun way during a team activity. We’ll keep exploring how to integrate new technologies in engaging ways and share our findings along the way. If you're thinking about trying a project involving NFTs, AI, or Web3, go for it! I'm sure you'll discover something interesting! Thank you for reading until the end!
アバター
こんにちは。 DBRE チーム所属の @p2sk です。 DBRE(Database Reliability Engineering)チームでは、横断組織としてデータベースに関する課題解決やプラットフォーム開発に取り組んでいます。 先日、OSS のリポジトリ terraform-provider-aws に対してコントリビュートする機会がありました。具体的には、AWSが 2024 年 10 月に一般提供を開始した DynamoDB or S3 と Redshift との マネージドなデータ連携を Terraform で管理できるようにする「 aws_redshift_integration 」というリソースを新規実装しました。 PR は既にマージ されており、 v5.95.0でリリース され、機能が使えるようになりました。 私は今回が初めての OSS 貢献だったので、完走できるか不安な部分もありましたが、生成 AI の力も借りながら PR の作成までやり切ることができました。 新機能が AWS で GA されてから、Terraform で管理できるようになるまで(=terraform-provider-aws に新規リソースとして実装されるまで)、数ヶ月かかる場合もあります。そのような場合に、実装されるのを待つ代わりに自分で実装する選択肢を取れるようになったことは、大きなアドバンテージだと感じました。そこで本記事では、私と同じように初めて Terraform の AWS Provider に新規リソースを追加するコントリビューションに取り組みたいと考えている方に向けて、初回から効率的に取り組んでもらえるような情報を提供することを目指します。 いずれはコーディングエージェントに issue を渡すだけで PR 作成まで行ってくれる未来になっているかもしれませんが、現時点ではそこまでは難しい印象で、同じような境遇の方の参考になれば幸いです。 今回追加したリソースについて 今回は以下の 2 つの機能を管理できるリソースを追加しました。それぞれ簡単に説明します。 DynamoDB から Redshift への zero-ETL 統合 S3 から Redshift への event integration zero-ETL 統合は、ETL パイプラインの構築が不要な、マネージドなデータ連携機能です。「zero-ETL 統合」という機能は、最初は Aurora MySQL と Redshift 間のデータ連携として提供が開始され、その後複数のデータソースとターゲットに対象が拡大しています。アーキテクチャ図を以下に示します。 ![DynamoDB から Redshift への zero-ETL 統合のアーキテクチャ図](/assets/blog/authors/m.hirose/2025-04-23-11-13-17.png =700x) 出展:AWS - Amazon Redshift との Amazon DynamoDB ゼロ ETL 統合の始め方 S3 から Redshift への event integration も同様に、S3 バケットに追加されたファイルを自動かつ高速に Redshift に連携する機能です。 これらは機能としては別々ですが、 Integration を作成する API は同一 です。terraform-provider-aws のリソースは API にマップされるため、この API を Terraform 対応させることで、上記 2 つの機能が同時に実装されることになります。したがって、追加したリソース自体は 1 つだけです。 リソース追加の判断基準 公式ドキュメント に以下の記載があります。 New resources are required when AWS adds a new service, or adds new features within an existing service which would require a new resource to manage in Terraform. Typically anything with a new set of CRUD API endpoints is a great candidate for a new resource. 和訳: AWS が新しいサービスを追加したり、既存のサービスに新しい機能を追加したりする場合、Terraform で管理するための新しいリソースが必要になります。一般的に、新しい CRUD API エンドポイントセットを持つものは、新しいリソースの候補として最適です。 ということで、 新しい CRUD API エンドポイントセットを持つかどうか が大きな判断基準となりそうです。今回はこれを満たしており、新規リソース追加の実装を行いました。 Contribution の流れ 流れは 公式のドキュメント に非常によくまとまっています。 開発環境を準備 コードのデバッグ(今回は新規リソース追加のため、スキップ) コードを変更 テストを書く 継続的インテグレーション 変更ログを更新 プルリクエストを作成 上記の項目をベースにしつつ、本記事で推奨する手順を以下に整理します。また、各項目でかかる労力を個人の実体験をベースに「★」の数で示します。詳細な手順は公式のドキュメントの確認が必要ですが、実際に取り組んで得られた知見をまとめているため、ぜひ参考にしてください。 関連 issue の調査または作成 ★ 対応する AWS API と SDK の事前調査 ★ 開発環境を準備 ★ 対象リソースの動作検証・依存リソースのコード化 ★★★ scaffolding ツールでベースとなるコードを生成 ★ コード修正と動作確認 ★★★★★ テストを書く ★★★ 継続的インテグレーション用のテストのローカル実行 ★★ ドキュメント修正 ★ プルリクエストを作成 ★ 変更ログを作成して push ★ 以降は各手順の詳細について触れていきますが、開発をスタートする前に知っておくと良さそうなことを先にまとめます。 留意事項 複数種類の SDK による書き方が混在 terraform-provider-aws では、リポジトリ内で異なる SDK を用いた 2 パターンの書き方が混在しています。 Terraform plugin framework 現時点で使用が推奨されている、新しい SDK Terraform Plugin SDKv2 旧 SDK のため新規利用は非推奨。ただし、この SDK で実装されたリソースのバグ修正などで使うこともある サポート終了の v1 でのコードもまだ存在している可能性もあるため、正確には 3 パターンかも 従って、生成 AI に調査やコーディングを依頼する場合は Terraform plugin framework を対象にすることをプロンプトに含める方が良いです。 この辺りの歴史的経緯などに興味のある方は、 ChatGPT Deep Research のリサーチ結果 を、ハルシネーション混入の可能性に留意いただきつつご確認ください。 ライセンスについて Terraform 本体は 2023年に ライセンスが BSL に変更 され、OSS の定義からは外れていますが、terraform-provider-aws は引き続き MPL 2.0 で、OSS のままになっています。 各種プロバイダは Terraform から fork された opentofu でも使われているようです。 opentofu 用の AWS Provider も terraform-provider-aws から fork されているため、プロバイダーにコントリビュートすると、間接的に Terraform と opentofu 両方に貢献できることになりそうです。 この辺りの経緯に興味のある方は ChatGPT Deep Research のリサーチ結果 をご覧ください。(ハルシネーションに関して同様にご留意ください) 以降では、実際の手順について解説します。なお、記事内でのテストの実行時間などについては、以下の環境におけるおおまかな体感の値です。 マシン : MacBook Pro チップ : Apple M2 Pro メモリ : 32 GB 1. 関連 issue の調査または作成 PR の作成時は、関連 issue へのリンクを記載します(例:下図「Relations」)。そのため、関連する issue を最初に探して、なければ作成します。 ![関連 issue の記載](/assets/blog/authors/m.hirose/2025-04-17-12-45-46.png =700x) 既に issue が作成されている場合は、他の誰かが取り組んでいるケースもあります。issue のコメントを一読し、「まだ誰も着手していなさそうか」などは確認しておくと良さそうです。 今回は既に issue が作成されていたため、PR 作成時は既存 issue へのリンクを記載しました。 2. 対応する AWS API と SDK の事前調査 リソースを新規実装するためには、go の SDK(aws-sdk-go-v2)が該当リソースの CRUD 操作に対応している必要があります。基本的には GA されたタイミングで SDK も提供されると推測しますが、多少のラグはあるかもしれません。terraform-provider-aws の go.mod も、該当リソースに対応したバージョンにアップデートされている必要がありますが、 メンテナーにより頻繁に更新されている印象 なので、自分でアップデートしなくても、メンテナーにより最新化されている可能性が高い、という認識で良さそうです。 今回は、以下のリファレンスをブックマークに登録しておくことで、開発途中に都度参照できて便利でした。生成 AI に参照させる場合も重宝すると思います。 API リファレンス https://docs.aws.amazon.com/ja_jp/redshift/latest/APIReference/API_CreateIntegration.html https://docs.aws.amazon.com/ja_jp/redshift/latest/APIReference/API_ModifyIntegration.html https://docs.aws.amazon.com/ja_jp/redshift/latest/APIReference/API_DeleteIntegration.html https://docs.aws.amazon.com/ja_jp/redshift/latest/APIReference/API_DescribeIntegrations.html SDK リファレンス https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/redshift#Client.CreateIntegration https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/redshift#Client.ModifyIntegration https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/redshift#Client.DeleteIntegration https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/redshift#Client.DescribeIntegrations 当初は DynamoDB の zero-ETL 統合を Terraform 対応させるのがモチベーションだったのですが、リファレンスを見ると API の SourceARN パラメータのパターンが下図の通り S3 にも対応していることがわかり、S3 の integration も同時に検証しなければいけないことに気づけました。このように、検証のスコープが想定より広い場合もあるため、リファレンスの入出力は最初に一通り確認しておくと良さそうです。 ![CreateIntegration()のSourceARN](/assets/blog/authors/m.hirose/2025-04-17-15-43-29.png =700x) 出展:AWS - Redshift CreateIntegration API Reference また、リソースの種類によっては Delete が存在しないものや、Modify が存在しない場合もあるかもしれませんので、その場合は提供されている API だけ実装すれば OK です。例えば、Aurora MySQL と Redshift 間の zero-ETL 統合は、GA 時点では Create / Delete / Describe のみ提供され、後で Modify が提供されたようです。 Redshift は SDK のディレクトリとして redshift と redshiftserverless が存在し、片方でいいのか両方実装すべきなのか迷いましたが、 redshiftserverless 側には該当の API が存在しなかったのと、redshift 側の関数で serverless 用の Integration も作成できたことから、redshift 側だけ実装すれば良いと判断しました。 3. 開発環境を準備 公式のドキュメント に記載の手順通りに実行すれば OK です。ただし、実際のリソースを作成して動作確認を行う make testacc はこの時点では不要です。 make test も実行しなくても良いかもしれませんが、私の環境では 3-40 分ほどかかりました。 Using the Provider に記載の手順を実行することで、手元で build した Provider を使って Terraform コマンドを実行できるようになります。実行時に以下のような warning が表示されることを確認できれば OK です。 これで、自分で build した Provider が Terraform 実行時に使われていることが確認できます。なお、後述の「受け入れテスト」というテスト経由でも動作確認自体はできるのですが、build と動作確認のサイクルを高速に回すためには、自分で build した Provider を使って Terraform コマンドを実行するのが良いと思います。個人的には、この手順で動作確認することで、普段と同じ Terraform の使い方の中で動作が確認できてイメージしやすかったです。 詳細にデバッグしたい場合は delve を使うと良さそう です。 4. 対象リソースの動作検証・依存リソースのコード化 コーディングを開始する前に、まずは追加しようとしている新規 AWS リソースの動作確認を手元で行っておくと理解が深まります。この時、大抵は新規の AWS リソースを作成する前に、依存しているリソースを作成する必要があると思います。例えば、今回は以下の AWS リソースに依存しています。(正確には、Source は プロビジョニングされた Redshift / Redshift Serverless / S3 のいずれかだけで OK) aws_vpc aws_subnet aws_security_group aws_dynamodb_table aws_dynamodb_resource_policy aws_redshift_subnet_group aws_redshift_parameter_group aws_redshift_cluster aws_redshift_resource_policy aws_kms_key aws_kms_alias aws_kms_key_policy aws_redshiftserverless_namespace aws_redshiftserverless_workgroup aws_s3_bucket aws_s3_bucket_public_access_block aws_s3_bucket_policy aws_iam_role aws_iam_role_policy aws_redshift_cluster_iam_roles このような依存リソースは、この時点で tf ファイルとしてコード化しておくことを強くお勧めします。理由は以下の通りです。 検証、開発が 1 日で終わらない場合はコストがかかるため、都度 apply & destroy したい 後述の「受け入れテスト」でほぼ同様の Configuration を用意する必要があるので、最初に用意しておくと後で楽 terraform fmt でフォーマットもしておくと後述の CI テストのローカル実行もより楽に 生成 AI を活用することで HCL のコーディングはかなり時短できると思います。依存リソースのコード化が完了したら、あとはコンソールか AWS CLI を使って手動で対象リソースを作成して動作検証します。 5. scaffolding ツールでベースとなるコードを生成 新しいリソースを追加する場合 は、 Skaff という scaffolding ツールを使ってベースとなるコードを生成することが推奨されています。 リソースタイプ名は 命名規則 が決まっており、 aws_${サービス名}_${AWSリソース名} となります。AWS リソース名は、sdk の関数名に従う必要があります。例えば今回は「CreateIntegration」関数が提供されているため、AWS リソース名は「Integration」となります。サービス名は リポジトリの service ディレクトリ の値を使えば良さそうです。 したがって、今回のリソースタイプ名は aws_redshift_integration となります。この名前はブランチ名にも反映する必要があり、 f-aws_redshift_integration としました。skaff では AWS リソース名を指定すれば良いので、該当サービスのディレクトリへ移動した後に、以下のコマンドを実行しました。 $ pwd /Users/masaki.hirose/workspace/terraform-provider-aws/internal/service/redshift $ skaff resource --name Integration Skaff を実行することで、リソース用のコード、テストコード、ドキュメントの 3 ファイルが生成されるようです。生成されたファイルは こちら からご確認いただけますが、コメントが手厚く記載された親切なファイルになっています。また、これらの初期状態のファイル達と、 最終的にマージされたコード を比較すると、どこを修正すべきかイメージがつきやすいと思います。 6. コード修正と動作確認 生成されたコードをベースに、動作するように修正していきます。 ドキュメントに記載の通り 、Resource Schema をまずはコーディングして、その次に CRUD ハンドラを実装していきます。 Terraform plugin framework では、CRUD ハンドラがそれぞれ「Create」「Read」「Update」「Delete」という直感的な関数名になっています。例えば、初めて terraform apply して新規リソースが作られる際に、ここで実装した Create() 関数が呼ばれます。その中で go の SDK の対応する関数(この場合は CreateIntegration )が実行され、内部的には対応する AWS API(この場合は CreateIntegration )が実行され、リソースが作成される、という流れになります。 terraform apply で Replace を伴わない修正のみが実行される場合は Update() 関数が、 terraform destroy でリソースを削除する場合は Delete() 関数が実行されます。リソース情報を読み取る必要がある場面では都度 Read() 関数が呼ばれます。 Resource Schema の実装 Schema() 関数の中で、Terraform が受け付ける引数(arguments)および出力する属性(attributes)をスキーマ情報として定義します。以下のコードのように、Attributes マップに各フィールドを定義します。各属性はキーが Terraform 上の名前(snake case)、値が schema.Attribute インタフェースを実装した構造体で、schema.MapAttribute や schema.StringAttribute などから適切なものを用います。 // 修正後の Schema() 関数の一部を抜粋 func (r *integrationResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ "additional_encryption_context": schema.MapAttribute{ CustomType: fwtypes.MapOfStringType, ElementType: types.StringType, Optional: true, PlanModifiers: []planmodifier.Map{ mapplanmodifier.RequiresReplace(), }, }, names.AttrARN: framework.ARNAttributeComputedOnly(), names.AttrDescription: schema.StringAttribute{ Optional: true, }, "integration_name": schema.StringAttribute{ Required: true, }, 上記のように、SDK のリファレンスで必須になっているパラメータには Required: true を指定し、変更時にリソース置き換えが必要な場合は RequiresReplace() modifier を付与します。適切な modifier を使い分けるのが個人的には難しかったです。modifier は自分でも実装でき、1 つだけどうしても自前で実装が必要と判断して実装したのですが、PR 作成後にメンテナーによって既存の modifier に置き換えられていました。迷った場合は stringplanmodifier など、対象の型に対応する modifier で提供されている関数を最初に理解して、使えないか確認するのが良いと思います。PR 作成後のメンテナーからのフィードバックを通して、基本的には既存の modifier でカバーできるのだなという学びがありました。 合わせて、ResourceModel 構造体も定義します。 type integrationResourceModel struct { AdditionalEncryptionContext fwtypes.MapValueOf[types.String] `tfsdk:"additional_encryption_context"` Description types.String `tfsdk:"description"` IntegrationARN types.String `tfsdk:"arn"` IntegrationName types.String `tfsdk:"integration_name"` KMSKeyID types.String `tfsdk:"kms_key_id"` SourceARN fwtypes.ARN `tfsdk:"source_arn"` Tags tftags.Map `tfsdk:"tags"` TagsAll tftags.Map `tfsdk:"tags_all"` TargetARN fwtypes.ARN `tfsdk:"target_arn"` Timeouts timeouts.Value `tfsdk:"timeouts"` } CRUD ハンドラと関連処理の実装 CRUD ハンドラはいずれも、SDK への入力構造体を組み立てて、SDK の関数を呼び出す流れで実装します。また、CRUD ハンドラ内で利用する関数も合わせて実装します。これには、以下のようなものがあります。 該当リソースの情報を取得するための finder 関数 リソースの作成、修正、削除が完了するまで待つ waiter 関数 リソースのステータスを取得する status 関数 リソースを全削除する sweeper 関数(テスト向けの機能であり、必須ではない模様) 注意点として、service によっては wait.go / find.go など専用の go ファイルが用意されており、その場合はそのファイルに処理を追記する必要があります。そうでない場合は、実装中のファイルに全て処理を記述して問題ないようです。今回対象となった redshift サービスでは wait.go などが存在しており、そちらに追記する形をとりました。 リソースの登録 実装が完了したあとは、Terraform Provider にそのリソースを認識させる登録処理を行います。以下のようなアノテーションが必要ですが、skaff で生成されたコードにすでに入っているので自分で記述する必要はありません。削除しないようにだけ注意しておけば OK です。 // @FrameworkResource("aws_redshift_integration", name="Integration") func newIntegrationResource(context.Context) 上記アノテーションを記述したら、プロジェクトルートディレクトリで make gen を実行します。これにより、各サービスパッケージ内の service_package_gen.go が再生成され、新規実装したリソースも Provider 登録されます。ここまできたら、 make build でビルドし、通れば実際に terraform apply などで動作を確認できる状態になります。 動作確認 新規実装したリソースを HCL で記述し、 terraform apply して動作確認します。手順「# 4. 対象リソースの動作検証・依存リソースのコード化」において、すでに依存リソースはコード化が終わっているので、ここでは新規実装したリソースだけを、別のディレクトリの新規ファイルに記述し、別の state で管理します。これにより、動作確認したい新規リソースだけを apply & destroy できるので確認スピードが上がります。もしくは以下のようにターゲットを指定することで、1 ファイルに全て記載している場合でも個別に apply する方法を取るのでもいいと思います。 terraform plan -target=new_resource_type.hoge -out=myplan terraform apply myplan 7. テストを書く terraform-provider-aws では、以下の 3 つのテストがあります。 受け入れテスト (Acceptance Tests) Terraform を実行し、AWS 上にリソースを作成したり、更新、削除できることを確認するテスト。実際にリソースを操作するので金銭的費用が発生。そのため「実行は任意」とドキュメントに書かれている。 ユニットテスト 関数レベルのテスト。今回は不要と判断し、未作成。 CI テスト PR 作成後に実行される、lint / format などを含む包括的なテスト。 CI テストはすでに用意されているものを実行するだけなので、受け入れテストとユニットテストが、コントリビューターが書くべきテストになります。ユニットテストは複雑な処理などを実装した場合に書くことが推奨されており、今回は不要と判断し、受け入れテストだけを書きました。受け入れテストでは、以下のコードのように、テストに必要な AWS リソースを HCL で記述する必要があります。 func testAccIntegrationConfig_base(rName string) string { return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 3), fmt.Sprintf(` data "aws_caller_identity" "current" {} data "aws_partition" "current" {} resource "aws_security_group" "test" { name = %[1]q vpc_id = aws_vpc.test.id ingress { protocol = -1 self = true from_port = 0 to_port = 0 } ... ステップ「4. 対象リソースの動作検証・依存リソースのコード化」で既にコード化が完了していると、ここはほぼコピペで行けるので非常に楽でした。テストを実行する場合は、以下のように関数名を指定すると関数単位で実行できます。 make testacc TESTS=TestAccRedshiftIntegration_basic PKG=redshift リソース単位で一気にテストするには、以下のように「_」以降を削除して実行します。 make testacc TESTS=TestAccRedshiftIntegration PKG=redshift 8. 継続的インテグレーション用のテストのローカル実行 terraform-provider-aws リポジトリは、コードの品質を確保するための厳格な CI パイプラインを持っています。PR 作成後に実行されるものですが、ローカルでこれらのチェックを実行できる機能が提供されているので、できる限りローカル上でパスするように修正しておくと親切かと思います。 完全なチェックは make ci で実行できますが、私の環境だと数時間かかったので、まずは make ci-quick で検出された問題を修正してから make ci を実行するのが、待ち時間を最小化できると思います。 私の場合は何度か修正を行い、ローカル環境で make ci-quick を実行した際に全てのチェックをパスできましたが、 make ci 実行時は一箇所だけ GNUmakefile を修正しないとエラーになる箇所がありました。これは自分の環境特有の問題かもしれないため、PR に含めずローカルだけの修正で回避しました。 ドキュメント に記載がありますが、 make testacc-lint-fix を最初に実行すると、 terrafmt 関連の問題だけは自動で修正してくれるようなので、最初に実行しておくのも一手かと思います。 9. ドキュメント修正 skaff で生成されたドキュメントを修正します。ここで書いた内容が、 よく見るドキュメント として反映されます。既存のドキュメントを参考に書いていけば問題ないと思います。 10. プルリクエストを作成 こちらは特に迷うことはないと思います。 11. 変更ログを作成して push 公式のドキュメント に沿って問題なく作成できると思います。ファイルの命名規則的に PR の番号が必要なので、まず PR を出して、その後に変更ログを作成して push すれば OK です。 ここまでで、PR を作成するまでの流れをお伝えしました。以降では、本取り組みにより得た知見をシェアします。 メンテナーによる修正内容 先日、PR は無事にマージされ、 v5.95.0でリリース され、機能が使えるようになりました。マージまでに、メンテナーによりコードが修正されていたので、どのような修正が行われたかをご紹介します。 schema.Attribute から ID の削除 skaff で生成されたコードにも以下のコメントが記述されていましたが、気づけずに ID 属性を残していたところ、不要とのことで削除されていました。AWS API のリファレンスを見て残すか決めた方が良さそうです。 // Only include an "id" attribute if the AWS API has an "Id" field, such as "IntegrationId" names.AttrID: framework.IDAttribute(), 変数名などの変更 この修正がもっとも多く、自分の命名規則の確認が甘かったと思われます。一方で、「resourceIntegrationModel」という構造体名は skaff によって自動で生成されたものですが、「integrationResourceModel」という修正が加えられており、この辺りは skaff による命名規則の実装に若干の不備があるのかもしれません。 自作の modifier を既存の modifier へ置き換え ある問題を解決するために、自分で plan modifier を実装したのですが、 既存の modifier に修正 されていました。 ここは自分でも自信がない箇所だったので、 手厚めに PR にコメントを残しておいた ところ、以下のコメントもいただき、既存の modifier をもっとよく調べておくべきだったと反省しました。しかし、「なぜこの実装にしたのか」を詳細に示しておいたことで、メンテナーが修正の判断を行いやすい状態にはできたかなと思います。 This can be accomplished with the RequiresReplaceIfConfigured plan modifier. この修正は LLM の力を借りて導き出せなかったかを確認するために、 実装中に使っていたプロンプトを修正して LLM に渡した ところ、上記の既存 modifier での修正案を提案してくれました。開発時は modifier を自作するしかないと判断して LLM を使っていたためプロンプトの指示が具体的になりすぎていたのが良くなかったようです。LLM の使い方の改善余地もあるという学びを得ました。 受け入れテスト時のチェック項目の追加 こちらのコミット にあるように、受け入れテスト時は、そのテストシナリオによって「リソースの作成」を期待するのか、「リソースの更新」を期待するのかまで記述できることを知りました。これにより、意図しないリソースの再作成が発生した場合に気づける、といった効果が期待できそうです。 AWS リソース作成にかかったコスト 今回は受け入れテストも自分で実行し、かつ個別に動作検証も行ったため、AWS リソースの作成による金銭的コストが発生しました。Terraform で IaC 化して、使わないときはこまめに destroy していましたが、合計で約 50$ ほどかかりました。大半は Redshift のコストであり、ここは実装しようとするリソース次第で大きく変わってきそうです。 その他の所感 学び:標準化のために膨大なエネルギーが注がれている Terraform 関連のような、数千人規模のコントリビューターが関わっているリポジトリでは、「誰が走っても同じゴールにたどり着くためのレール」の整備が欠かせません。標準化が甘いと、メンテナー(レビュワー)の負担が大きくなり、機能のリリーススピードが落ちてしまいます。そのような背景から、以下のような様々な情報やツールの提供によってコードの標準化を強く推進する意思を感じました。 豊富なドキュメントの提供 貢献種別(バグ修正、新規リソース追加など)ごとの詳細な手順の整理 命名規則などのルールの記載 専用ツール「skaff」による scaffolding 「これを修正していけばOK」なベースとなるコードを自動生成 ローカルで実行可能な CI テスト lint / format / test など、様々な観点で徹底的にチェック可能 ローカルでパスしておけば、PR 時の CI も全てパスする可能性が高く、メンテナーの負担が下がる 特に、CI テストと同等なものをローカルで実行できるようにするためにエネルギーを注いでいるのは、下記の通り ドキュメント からも伝わってきます。 NOTE: We've made a great effort to ensure that tests running on GitHub have a close-as-possible equivalent in the Makefile. 和訳 注: GitHub で実行されるテストについては、Makefile に可能な限り同等のコードが含まれるよう最大限の努力を払っています。 これにより、例えば const で定義している定数 については、以下のように値をハードコーディングしていると定数を使うように促されるなど、細かい点までコード内の記述の揺らぎが最小化される力が働きます。 このように、テスト項目は非常に細かく多岐に渡りますが、逆にいうと、受け入れテストとローカルでの CI テストをパスした状態であれば、初めての PR であっても自信を持って作成できました。 私が所属する DBRE チームでは、 DevOps のスペシャリスト により上記のような scaffolding から format, lint, test までの開発フローを一通り整理してくれていたため、今回の開発の流れにも違和感なく取り組むことができ感謝しています。 反省点:生成 AI の活用方法に改善の余地あり 初見のリポジトリに対する理解速度を上げるために、Copilot などでリポジトリをインデックス化しておけば、コード理解がより速くなったと反省しています。一方で、今回のように異なる SDK によるコードが混在するリポジトリの場合は、前提として現在推奨されている SDK を指定した上で質問するなどの工夫も必要だと感じました。実際、Plan Modifier 周辺を Deep Research で調べて Web 上の Issue に書かれていた解決策を試したものの、旧 SDK での解決方法だったため、動作しませんでした。代わりに、関連ソース一式を LLM に渡したところ、ほぼ修正不要のコードが提案されて問題を解決できました。LLM をもっとうまく活用してキャッチアップや開発速度を上げていきたいです。 苦労した点:異なる種類の SDK によるコードの混在 前述の通り、異なる種類の SDK によるコードが混在しているため、「既存コードが全て参考になるわけではない」という状況で、これに気づくのに少し時間がかかりました。例えば、sweeper 関数の実装では、現在の SDK(Terraform plugin framework) と 以前の SDK とで実装方法が異なります。今回の実装対象サービスは redshift ですが、 redshift の sweeper 関数を実装するファイル ではまだ現在の SDK での実装が行われておらず、旧 SDK での実装を参考にしてコードを書いたけど動かない、といった問題に遭遇しました。現在の SDK で実装されている関数を別サービスから探して参照することで解決しましたが、参考にする既存コードが現在の推奨 SDK による記法かどうかは気をつけると良さそうです。 手順別の AI と人力の使いわけ 最後に、各手順を AI と人力どちらで行った方がいいのか、主観ですが現時点での見解を表にまとめます。今回の開発完了後に、検証目的で同じタスクを AI エンジニアの Devin にも実施させてみましたが、公式ドキュメントにも書いてある通り、細かくタスクを分解して渡す必要がありそうでした。もちろん、現時点での見解なので、AI の進化によって変化していくと思われます。 手順 AI / 人力 備考 1. 関連 issue の調査または作成 人力 Web検索または GitHub Issues ページを自分で調べるのが最速 2. 対応する AWS API と SDK の事前調査 人力 自分で検索するのが早い 3. 開発環境を準備 人力 自分でセットアップした方が早い 4. 対象リソースの動作検証・依存リソースのコード化 AI+人力 依存リソースのコード化は LLM 活用が有効 5. scaffoldingツールでベースとなるコードを生成 人力 自分で実行した方が早い 6. コード修正と動作確認 AI+人力 ベースを LLM に書かせ、細部は自分で仕上げる 7. テストを書く AI+人力 ベースを LLM に書かせ、細部は自分で仕上げる 8. CI用テストのローカル実行 AI or 人力 AI に任せると自動でパスするようにコードを修正してくれるかもしれないが、テスト実行時間が長いので製品によってはクレジット消費が大きくなる懸念 9. ドキュメント修正 AI+人力 マージ済みドキュメントを参考として渡して LLM に下書きを作らせると良さそう 10. プルリクエストを作成 人力 自分で行うのが早そう 11. 変更ログを作成して push 人力 自分で行うのが早そう まとめ Terraform Provider へのコントリビューションは敷居が高く感じていましたが、ガイドがしっかりと整備されており、scaffolding ツールやテストフレームワークが充実しているので、慣れればスムーズに進められると感じました。初回だったのでドキュメントの読み込みに時間がかかりましたが、次回からはより高速に開発を進められると思います。AWS の新機能リリースをいち早く Terraform 化したいという方は、ぜひ取り組んでみてください。その際に、本記事が少しでも参考になれば幸いです。 KINTO テクノロジーズ DBRE チームでは一緒に働いてくれる仲間を絶賛募集中です!カジュアルな面談も歓迎ですので、 少しでも興味を持っていただけた方はお気軽に X の DM 等でご連絡ください。併せて、 弊社の採用 Twitter もよろしければフォローお願いします!
アバター